I'm trying to draw vertical text in win32 GDI api.
I call CreateFont() with 2700 for the angle and 900 for bold.
logPxlY = ::GetDeviceCaps (c->_hdc, LOGPIXELSY);
_hfont = ::CreateFont (-::MulDiv (point, logPxlY, 72),
0, angle, weight, 0, FALSE, FALSE, FALSE, 0, 0, 0, 0,
FIXED_PITCH | FF_MODERN, face);
where face is "Courier New", point is 9, angle is 2700 and weight is 900.
The text IS rotated correctly, but it's pretty dang faint compared to normal Courier New rendering. Is this since truetype is polishing the normal text real nice and isn't bothering with wierd rotated text or something?
Thanks for any insight :)
The font mapper can be a bit strange at times. 700 is bold, 900 is supposed to be "black". However, you probably have a Courier New Bold font file, so it can be used directly, whereas you probably do not have a Courier New Black font file, so it'll be synthesized -- probably from the normal Courier New font instead of from Courier New Bold (not sure why that is, but such is life).
If you try running through the possibilities, something like this (MFC code, for the moment, but the idea applies regardless):
CFont fonts[num];
pDC->SetBkMode(TRANSPARENT);
for (int i=0; i<num; i++) {
fonts[i].CreateFont(10, 0, 2700, 0, i*100, 0, 0, 0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, OUT_CHARACTER_PRECIS, PROOF_QUALITY, FF_MODERN, L"Courier New");
pDC->SelectObject(fonts+i);
pDC->TextOut(20+i*14, 20, L"This is some text");
}
What you'll probably see (what I get anyway) looks like this:
The 700 weight font is noticeably bolder than the 800 or 900 weight. This is not unique to Courier New either -- for example, the same code with the font name changed to Times New Roman produces output like this:
That's a bit closer, but the 700 weight still clearly looks darker than the 800 or 900. I won't bore you with screen shots, but the same effect happens when the text is horizontal.
Edit: One other minor detail: though it probably doesn't make any difference, you're currently computing the size of the font a bit incorrectly -- you're using logpixelsy, which makes sense when the font is horizontal. For a vertical font, you should use logpixelsx instead. On a typical screen, those will be identical, but on a printer (for example) they may be substantially different.
Related
This is a homework assignment. Basically, we were given some code and had to run it through Bresenham's line drawing algorithm.
Everything works fine except that the lines are cut off at the bottom (about 30 pixels). The window is big enough, but it just displays white space at the bottom.
(If I make the window 30 pixels higher, all the lines are complete so the algorithm implementation is good.)
window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0,
0, 512, 512, 5, black, white);
gc = XCreateGC(display, window, 0,0);
XClearWindow(display, window);
XMapRaised(display, window);
Am I guessing the error is somewhere in one of these lines?
I am porting an application from Windows to Mac OS X. Here, I have one confusion between the use of different terms.
On Windows, we use SetBkColor to set background color of a device context.
On Mac OS X, there is setFill to set fill color.
Is there any difference between this background color of Windows and fill color of Mac OS X?
For stroke clear (by setStroke), I think on Windows, same effect is achieved by CreatePen for lines and SetTextColor for texts. Is this concept is okay?
Both native Windows development and Core Graphics on iOS/Mac OS use the so called 'painter's model' of drawing. Just like actual painting, you select a color for your pen or brush and everything you draw, fill, what-have-you from that point until you change it will use that color. On the Mac, more specifically, you set stroke for such things as text and borders, and fills for methods that fill. You have to set each separately as each accomplishes something different.
SetBkColor would be different because it fills into the background, on Mac or iOS, you would instead set the fill color and then use a drawing method to fill a rect -- and usually this would all be done by overriding a view's drawRect method. For example, here's one way to do that:
- (void)drawRect:(NSRect)rect
{
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
// ********** Your drawing code here **********
CGContextSetRGBFillColor (myContext, 1, 0, 0, 1); // set my 'brush color'
CGContextFillRect (myContext, CGRectMake (0, 0, 200, 100 )); // fill it
CGContextSetRGBFillColor (myContext, 0, 0, 1, .5); // set my brush color
CGContextFillRect (myContext, CGRectMake (0, 0, 100, 200)); //fill it
}
Drawing is done back to front, so, if you wanted to set the background to a certain color, you would simply make that the first operation and fill the full window/view rectangle with whatever color you like.
Have a look at the Quartz 2D drawing guide for further examples. If you are coming from Windows, you will find Quartz/Core Graphics to have a very comparable, and in my mind richer, set of drawing capabilities. (The above example is from this guide)
https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_context/dq_context.html
I'm attempting to create a process manager based on QPixmaps. These pixmaps are updated via a timer callback at 20Hz, so it appears like they're spinning.
Below is a screenshot of my current window.
The pixmap is a 2D array with [20][14] elements. 20 is the amount of time slices, 14 is the process status indicator. I know, there are only 13 displayed here on the screen.
I'm currently using the painter object and composition modes to add QImages together with the following code:
QImage textImage(mapIcon.size(), QImage::Format_ARGB32);
QImage resultImage(mapIcon.size(), QImage::Format_ARGB32);
QPainter textPainter(&textImage);
textPainter.setCompositionMode(QPainter::CompositionMode_Source);
textPainter.fillRect(mapIcon.rect(), Qt::black);
textPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
textPainter.setFont(QFont("Arial", 8, QFont::Bold));
textPainter.setPen(QPen(Qt::white));
textPainter.drawText(QRectF(0, 0, mapIcon.width(), mapIcon.height()),
Qt::AlignCenter, name);
textPainter.end();
QPainter resultPainter(&resultImage);
resultPainter.setCompositionMode(QPainter::CompositionMode_Source);
resultPainter.drawImage(0, 0, mapIcon);
resultPainter.setCompositionMode(QPainter::CompositionMode_Exclusion);
resultPainter.drawImage(0, 0, textImage);
resultPainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
resultPainter.setRenderHint(QPainter::HighQualityAntialiasing, true);
runnerIcons[x][y] = QPixmap::fromImage(resultImage);
My question is this: I don't want the inverted color scheme seen on the green labels, I want that color black. The white on black is ok, but the magenta isn't my favorite.
Is this possible in Qt? Or maybe ya'll have some suggestions to alternative solutions?
Thanks in advance.
There are a couple things you can do. You might check out the QPainter::setCompositionMode (mode) method. Maybe one of the other composition modes would be useful to you? Particularly QPainter::CompositionMode_Exclusion or QPainter::RasterOp_SourceXorDestination.
You could also use a complimentary color for the text. Magenta (blue+red) is opposite green on the color wheel. If you made the text magenta, it would probably show up well against both black and green. (I'm not saying it will look great - just that it will show up well.) Or maybe you could make the text 50% gray so that there is contrast in the luminance as well as in the color?
Also, you only have 13 icons, not 14. Not sure if it makes any difference.
I'm using a fixed size font ( eg: "Courier New" ). When I initialize the CFont object by calling CFont::CreateFont function, I want to specify only the font height.
CFont Font;
Font.CreateFont( nFontHeight, 0, 0, 0, 0, false, false,
0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
FIXED_PITCH|FF_MODERN, _T("Courier New") );
As per documentation, font width will be calculated automatically. I need that automatically calculated value for some other calculation.
GetLogFont Function is useless as it seems CFont only holds the value we give that is width = 0 and it calculates the value only when it is used for first time. ( Please check the Microsoft documentation )
Another option was to use CDC::GetTextExtent using a single character. But in that case also I could see some minor differences even in the height. For example, when I give -32 as height, GetTextExtent returns 33 for y value.
Is there any way to get the correct calculated width?
First of all, if you only want to specify the font height, you normally want to use CreatePointFont. Second, Windows 95/98/SE/Me are dead and gone -- and with them, essentially all reason to use Microsoft's "text" macros like _T("whatever"). If you want wide characters, ask for them directly:
CFont font;
font.CreatePointFont(nFontHeight, L"Courier New");
Then, as suggested by #MikMik, you can use GetTextMetrics to get the width -- but only after you select the font into a DC (GetTextMetrics gets the data for a font selected into a DC, not just for the raw font -- especially at small font sizes, some things get adjusted to compensate for the resolution of the output device).
Note, however, that even for a fixed-width font, the width of a string is not necessarily char_width * num_chars. At least if I recall correctly, even a fixed-width font can still be kerned, which means the spacing is adjusted based on what pairs of characters occur together. The classic example is a pair like AV. Because the lines where they're next to each other are typically at the same angle (or at least very close to the same) the spacing will be adjusted to move them closer together -- in fact, the top of the "V" will often overlap with the bottom of the "A". The width of a string of characters can vary even though each individual character has the same width as every other.
Offhand, I'm not sure that Courier New does that, but I'm reasonably certain at least a few fixed-width fonts do.
Have you tried CDC::GetTextMetrics()? I've never used it, but it seems to be what you're looking for. You can get the average and maximum character width, which I guess should be the same for Courier New.
I am creating a custom Qt widget that mimics an A4 printed page and am having problems getting fonts to render at the correct size. My widget uses QPainter::setViewport and QPainter::setWindow to mimic the A4 page, using units of 10ths of a millimetre which enables me to draw easily. However, attempting to create a font at a specific point size doesn't seem to work and using QFont:setPixelSize isn't accurate. Here is some code:
View::View(QWidget *parent) :
QWidget(parent),
printer(new QPrinter)
{
printer->setPaperSize(QPrinter::A4);
printer->setFullPage(true);
}
void View::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setWindow(0, 0, 2100, 2970);
painter.setViewport(0, 0, printer->width(), printer->height());
// Draw a rect at x = 1cm, y = 1cm, 6cm wide and 1 inch high
painter.drawRect(100, 100, 600, 254);
// Create a 72pt (1 inch) high font
QFont font("Arial");
font.setPixelSize(254);
painter.setFont(font);
// Draw in the same box
// The font is too large
painter.drawText(QRect(100, 100, 600, 254), tr("Wg\u0102"));
// Ack - the actual font size reported by the metrics is 283 pixels!
const QFontMetrics fontMetrics = painter.fontMetrics();
qDebug() << "Font height = " << fontMetrics.height();
}
So I'm asking for a 254 high font (1 inch, 72 pts) and it's too big and sure enough when I query for the font height via QFontMetrics it is 283 high.
Does anyone else know how to use font sizes in points when using custom mapping modes like this? It must be possible. Note that I cannot see how to convert between logical/device points either (i.e. the Win32 DPtoLP/LPtoDP equivalents.)
EDIT: Well, it turns out that my code was working fine after all. I converted it to work with a printer, printed it out and then printed the same text using various word processors and the results are exactly the same. It seems that asking for a font size doesn't take the descent into account and this seems to be the norm.
QFont may or may not be able to match the exact font that you request. QFontMetrics::height() returns a size of 284 on my system, but QFontInfo::pixelSize() returns a size of 254 which is what was requested. I assume the difference is that height() includes the descent where pixelSize() returns the size in pixels of the matched font, implying that I had a match.
As for drawing, placement, and conversions, you'll need to be careful because the printer device won't be the same as the screen device nor will the resolutions match. To further exacerbate the problem, you can't get the exact printer metrics without calling setup on the print dialog. Device independence gets you close to WYSIWYG, but not always close enough.
In your sample, the paint device is this. Thus, you can get at the logical dpi through the logicalDpiX() and logicalDpiY() functions (as well as their physical equivalents).