18.4.4 Creating a Logical Font

A logical font is a list of font attributes, such as height, width, character set, and typeface. An application creates a logical font to describe the font that is best suited for a given task; the font mapper uses this logical font to choose the available physical font that best matches the specified characteristics. For more information about the font mapper, see Section 18.2.5, “Font Mapper.”

An application can use either the CreateFont or the CreateFontIndirect function to create a logical font. Most applications use CreateFontIndirect, assigning values to a LOGFONT structure. These functions return a handle of a logical font, which can then be selected into a device context and used.

The following example is a function that takes a handle of a device context, the name of a font, and a nominal point size as input. It creates a logical font of the requested size and face name and selects that font into the specified device context.

BOOL FAR PASCAL CreateLogFont(hdc, pszFace, PointSize)
HDC hdc;
PSTR pszFace;
int PointSize;
{
    HFONT hfnt, hfntOld;
    PLOGFONT plf = (PLOGFONT) LocalAlloc(GPTR, sizeof(LOGFONT));

    if (GetMapMode(hdc) != MM_TEXT) {
        TextOut(hdc, 100, -200, "Mapping mode must be MM_TEXT",
            28);
        return FALSE;
    }

    plf->lfHeight = -MulDiv(PointSize,
        GetDeviceCaps(hdc, LOGPIXELSY), 72);
    lstrcpy(plf->lfFaceName, pszFace);

    hfnt = CreateFontIndirect(plf);




    hfntOld = SelectObject(hdc, hfnt);

        .
        . /* Use font for text output. */
        .
    LocalFree((LOCALHANDLE) plf);
    SelectObject(hdc, hfntOld);
    if (DeleteObject(hfnt))
        return TRUE;
    else
        return FALSE;
}

Memory for the logical font in this example is allocated and initialized to zero (by using the LocalAlloc function with the GPTR constant); this means the logical font created by the CreateFontIndirect function uses default values for all members except lfHeight and lfFaceName. (Applications should always specify values for at least these two members.) For a description of all of the members of the LOGFONT structure, see the Microsoft Windows Programmer's Reference, Volume 3.

The function in this example uses the Windows MulDiv function to convert the specified point size into a different negative value and then assigns that value to the lfHeight member. This conversion is required because logical inches are larger than physical inches. (For a description of logical inches, see Section 18.2.4.2, “Logical and Physical Inches.”) The MulDiv function multiplies the requested point size by the result of dividing the number of pixels per logical inch by the number of points in a physical inch (72). A negative value is specified for lfHeight to indicate that the system should interpret this value as the height of the character glyphs in the font; when a positive value is specified, GDI interprets it as the height of a font's character cells, including internal leading.

An application would use a positive value for the lfHeight member to choose a font that fits within a specific height. For example, to display a page in “print preview” mode, an application would retrieve the height of the printer font from the tmHeight member of the NEWTEXTMETRIC structure, scale that height to the screen resolution, and use this value for the lfHeight member. The formula in this case would look like this:

tmHeight * DPI of screen
lfHeight = ————————————
DPI of printer

The results of this calculation should always be rounded down to the nearest whole number.

When an application specifies the handle of a logical font in a call to the SelectObject function, the font mapper returns a handle of the physical font that is the best match for the requested attributes.

An application that requires a raster font can identify the available raster fonts by calling the EnumFontFamilies function and checking the RASTER_FONTTYPE bit. The application can then specify the typeface name in a LOGFONT structure. Similarly, vector fonts can be selected by checking the RASTER_FONTTYPE and TRUETYPE_FONTTYPE bits. An application can also specify a vector font by specifying OEM_CHARSET in the lfCharSet member of the LOGFONT structure, as discussed in Section 18.4.2, “Enumerating Fonts.”

An application can use TrueType fonts exclusively by specifying OUT_TT_ONLY_PRECIS in the lfOutPrecision member of the LOGFONT structure. This is important for applications that use object linking and embedding (OLE), because metafiles can be scaled much better when they use only TrueType fonts.