The common way to create a font with GDI is to use the desired point size and the target device's vertical resolution (DPI) like this:
LOGFONT lf = {0};
lf.lfHeight = -MulDiv(point_size, GetDeviceCaps(hdc, LOGPIXELSY), 72);
...
HFONT hfont = CreateFontIndirect(&lf);
Assuming the default MM_TEXT
mapping mode, this converts point_size into the pixel height for the desired device. (This is a common approximation. There are actually 72.27 points in an inch, not 72.) (The minus sign means I want to specify the actual character height, not the cell height.)
If I want to create a sideways font--that is, one with an orientation and escapement of 90 degrees--do I use LOGPIXELSX
rather than LOGPIXELSY
? For some of the printers I'm targeting, the horizontal and vertical resolutions are different.
Generally, if I want an angle of theta
, do I combine LOGPIXELSX
and LOGPIXELSY
? I'm thinking of something like this:
// Given theta in degrees (e.g., theta = 45.0) ...
double theta_radians = theta * 2.0 * pi / 360.0;
int dpi = static_cast<int>(GetDeviceCaps(hdc, LOGPIXELSX) * sin(theta_radians) +
GetDeviceCaps(hdc, LOGPIXELSY) * cos(theta_radians) +
0.5);
LOGFONT lf = {0};
lf.lfHeight = -MulDiv(point_size, dpi, 72);
// Set escapement and orientation to theta in tenths of a degree.
lf.lfEscapement = lf.lfOrientation = static_cast<LONG>(theta * 10.0 + 0.5);
...
This makes intuitive sense to me, but I'm wondering if this is really how the GDI font mapper and printer drivers work.