Using TrueType(R)

Ron Gery

Microsoft Developer Network Technology Group

Created: March 20, 1992
Revised: April 21, 1992

ABSTRACT

This article introduces using TrueTypeÒ in an application with the MicrosoftÒ WindowsÔ version 3.1 graphical environment. It discusses issues that the introduction of TrueType raises and mechanisms for solving them. The article also explains how to use TrueType to create more accurate and device-independent output than was previously possible. New Windows version 3.1 functions covered are GetRasterizerCaps, EnumFontFamilies, GetCharABCWidths, GetOutlineTextMetrics, GetGlyphOutline, GetFontData, GetKerningPairs, and CreateScalableFontResource. This article is specific to Windows version 3.1. None of the new structures or functions discussed are available in earlier versions of Windows.

INTRODUCTION

TrueType is the scaling font technology in the MicrosoftÒ WindowsÔ version 3.1 graphical environment. It offers applications and users a variety of fonts in almost unlimited sizes and provides the potential for font-friendly applications that present a better typographical picture of the font world and that create portable documents that remain true to form across devices.

The text-handling and font-handling interface in Windows version 3.0 was designed with nonscaling font technology in mind and did not anticipate the variety and availability of typefaces or the potential for typographical accuracy. Although applications designed for Windows version 3.0 can use TrueType without requiring changes, the possibilities that TrueType opens will encourage applications to utilize TrueType explicitly when it is available. Most of the font-related limitations in Windows version 3.0 can be overcome with Windows version 3.1 functionality, thereby opening a whole new world of typographical possibilities.

SELECTING TRUETYPE FONTS

Because the new TrueType-specific functions—GetCharABCWidths, GetOutlineTextMetrics, GetGlyphOutline, and GetFontData—are meaningful only with TrueType fonts, an application should determine that a font selected into a device context (DC) is a TrueType font before calling those functions. An application can get a TrueType font either by explicit selection or through font mapping.

Is TrueType Enabled?

An application can find out whether the TrueType rasterizer is actually operating by calling the GetRasterizerCaps function:

RASTERIZER_STATUS rsStat;

GetRasterizerCaps(&rsStat, sizeof(rsStat));

if (rsStat.wFlags & (TT_ENABLED | TT_AVAILABLE) == (TT_ENABLED |

TT_AVAILABLE))

TTUsable = TRUE;

else

TTUsable = FALSE;

The GetRasterizerCaps function determines whether the TrueType rasterizer is enabled and whether any TrueType fonts are actually installed in the system. The rasterizer’s enabled status can be changed only by restarting Windows, so it remains constant in a session. The availability of TrueType fonts in the system can change during a session because fonts can be added.

Explicitly Choosing a TrueType Font

Using font enumeration, an application can determine which fonts in the system are TrueType fonts. Both the EnumFonts and the EnumFontFamilies functions return a new bit, OUTLINE_FONTTYPE, in the nFontType parameter to indicate that the font is a TrueType outline font.

To guarantee that a TrueType font is selected, set the lfOutPrecision field of the LOGFONT structure to OUT_TT_ONLY_PRECIS when creating a font. This bit tells the font mapper to choose a TrueType font rather than a non-TrueType font, overriding face name differences and similar penalties that the font mapper tabulates in selecting a physical font. If the request cannot be fulfilled (for example, no TrueType fonts are available, and OUT_DEVICE_PRECIS is set), the mapper defaults to standard behavior and searches for the closest match in the system.

The user can configure the Windows environment to essentially use only TrueType fonts by selecting the TrueType button in the Control Panel Fonts dialog box and then by selecting the Show Only TrueType Fonts In Applications check box in the TrueType dialog box. In this case, only TrueType fonts are enumerated when an application enumerates the available face names. Non-TrueType fonts can still be selected when requested explicitly by name, and enumerating by face name is also unaffected.

Is the Selected Font a TrueType Font?

After a font is selected into a DC, an application can determine whether it is a TrueType font by checking the TT_FONT bit in the tmPitchAndFamily field of the TEXTMETRIC structure. When the bit is set, the font is a TrueType font.

ENUMERATION

When the nFontType parameter has the OUTLINE_FONTTYPE bit set during font enumeration, the font being enumerated is a TrueType font. It may also be marked as a device font (DEVICE_FONTTYPE bit set) to signify that the font is being downloaded to the device; this still indicates that the font is a TrueType font and subsequently has full TrueType functionality. The SCALABLE_FONTTYPE bit is also set for each TrueType font, which indicates that enumerating for point sizes is unnecessary because the font is scalable.

NEWTEXTMETRIC Structure

In Windows version 3.1, both EnumFonts and EnumFontFamilies enumerate fonts using the NEWTEXTMETRIC structure instead of the TEXTMETRIC structure used in Windows version 3.0. Because the new structure is a superset of the old one and because the graphics device interface (GDI) allocates the memory needed, applications designed for Windows version 3.0 simply ignore the new information. Applications aware of Windows version 3.1 expect this extended structure when running under version 3.1.

The four fields introduced in the NEWTEXTMETRIC structure provide basic design information about a TrueType font. The ntmFlags field describes the general style of the font. The ntmSizeEM field defines the font’s design (also called notional) units and its EM size in those units. (Design units are discussed in more detail in the “Working in Design Units” section). The maximum height of the font is given in the ntmCellHeight field, and its average width is given in the ntmAvgWidth field; both values are in design units. An application that wants to scale a font in the x direction can use the height and width values to determine the typographer’s design ratios. The default width (assuming nonzero height) calculation is as follows:

if (font->lfWidth == 0 && font->lfHeight != 0)

{

if (font->lfHeight > 0)

font->lfWidth = MulDiv(font->lfHeight, ntmAvgWidth,

ntmCellHeight);

else

font->lfWidth = MulDiv((-font->lfHeight), ntmAvgWidth,

ntmSizeEM);

}

These four additional fields are not defined if the font is not a TrueType font.

EnumFontFamilies for Better Enumeration

The EnumFontFamilies function, which allows more appropriate enumeration of fonts without changing the functionality of the EnumFonts function, is new in Windows version 3.1. Instead of enumerating fonts by their full face name (for example, ArialÒ Demi-Bold Italic), EnumFontFamilies enumerates fonts by their family name (for example, Arial is the family name of Arial, Arial Bold, and Arial Demi-Bold Italic). This enumeration scheme separates the typographic characteristics of the font, which define its family, from the styles of that family (posture and boldness).

The four standard styles of a font—Regular, Italic, Bold, and Bold Italic—are special cases as far as enumeration goes. Only a single family name is enumerated in the name pass. During the style and size pass, these fonts can be identified by being marked as italic, bold, and bold italic in the LOGFONT (lfWeight and lfItalic) and TEXTMETRIC (tmWeight and tmItalic) structures. A font with a style that is not one of the standard four (for example, Arial Demi-Bold) is still enumerated by its full face name when the EnumFonts function is used. In contrast, the EnumFontFamilies function enumerates only the family name, regardless of the style.

Similarly to the EnumFonts function, the EnumFontFamilies function can be called in two ways. If no family name is specified, representative fonts for all the family names available on the target device are enumerated. If a family name is given, all the styles (and sizes for nonscaling fonts) available for that family are enumerated. This new function also provides more information about the font names during enumeration. Instead of returning the traditional LOGFONT structure, the ENUMLOGFONT structure is returned. This is a superset of the LOGFONT structure that also contains the full face name of the font in the elfFullName field and the style name of the font in the elfStyle field.

Applications designed for Windows version 3.1 should use the EnumFontFamilies function to enumerate fonts. Simply put, this function provides a more typographically accurate way to group fonts by basing the grouping on a common family style. Because TrueType supports multilingual name strings, this function also allows localization of fonts (Gross replacing Bold in French, for example) without applications needing to recognize the style names being used.

POSITIONING TRUETYPE CHARACTERS

When an application calls the TextOut function with a TrueType font, character glyphs are placed one after the other on the target device. With less sophisticated fonts, each character cell is simply placed next to the previous cell. However, with TrueType fonts, it is possible for cells to overlap during simple output. Applications should be aware of this possibility.

Difficulties Introduced by TrueType Fonts

The widths of characters in TrueType fonts are designed and managed a bit differently than those for raster fonts. This fact is hidden as much as possible from applications. Applications that are not specifically aware of TrueType may have minor problems with fonts on the screen. Redrawing problems may appear for some glyphs when the application assumes that it is using character widths instead of advance widths (see the next section for more detail) and incorrectly calculates the end of the last glyph in a line and possibly the start of the first glyph as well. Pieces of glyphs may remain at either end of a line, depending on the specific output mechanism that the application uses. Typically, applications that explicitly clip text output or redraw complete lines do not experience any difficulties with positioning TrueType fonts.

ABC Spacing

The term overhang in Windows describes the situation where one character’s cell overlaps the next character’s cell in a text string. This effect is especially noticeable when using GDI-simulated italic fonts. The Windows model for font overhang is limiting and implicitly expects that any font with an overhang is being simulated by GDI to be italic or bold. The model also assumes that the overhang is constant on a per-font basis (the value is calculated by the GetTextMetrics function and is found in the tmOverhang field of the TEXTMETRIC structure) and does not take into account the possibility of underhang (an overhang on the left side of a character). Enter TrueType with a whole new way to place characters.

With TrueType fonts, each character has its own overhang and underhang, which are defined by the design of the glyph instead of by post-process simulations. The definition of character width changes accordingly. Gone are the concepts of the overhang and the underhang, and introduced are the concepts of ABC spacing and advance width. ABC spacing, as the name implies, has three parts: A, B, and C. The B spacing is the width of the black part (the inked area) of the glyph. The A spacing defines the distance from the current position to the glyph position. The C spacing is the distance from the end of the B width to the next character’s position. In the simple case of white space around characters, A and C widths are both positive and widen the character. In the case of overhanging and underhanging characters, A and C can be negative to account for the overlap. The advance width of a character equals A + B + C and defines the effective width of the character for multiple character placement (see Figure 1).

Figure 1. ABC Spacing Metrics

When an application calls GetTextExtent with a TrueType font selected, the extent returned is the sum of the cell widths of the characters in the string. The result is the advance width of the string. Similarly, GetCharWidth returns the advance width of the character in question (A + B + C widths of that character).

The tmOverhang field of the TEXTMETRIC structure for TrueType fonts is set to zero.

Getting a Character's ABC Spacing

The GetCharABCWidths function returns the ABC spacing of characters in a TrueType font. This function performs the same task as GetCharWidth only with more data. Because of the way TrueType font files are constructed, the ABC widths must be computed explicitly for any character that has not yet been rasterized. As a result, calling GetCharABCWidths before any characters have actually been used creates more overhead than if all characters have already been used. In light of its goals, the application should decide whether to call this function once for all characters right away or to cache the values as the characters are actually rasterized and needed.

Calling GetCharABCWidths with a non-TrueType font returns an error.

Rotating TrueType Fonts

TrueType fonts can be arbitrarily rotated. The degree of rotation is specified during creation by using the lfOrientation and lfEscapement fields of the LOGFONT structure. Only the escapement is used in Windows version 3.1 (orientation is set to the same value as the escapement); an application that wants escapement not to be equal to orientation must compute each character position itself and output one character at a time. Character widths and string extents that the various GDI functions return are based on the length of the character or the string along the escapement vector; the application must calculate bounding boxes for any rotated output.

DEVICE-INDEPENDENT PAGE LAYOUT

Applications that are more concerned with document portability across devices than with compatibility with Windows version 3.0 can use TrueType fonts and their metrics to create a device-independent document layout.

Working in Design Units

The secret behind maintaining font information in a device-independent form is the use of design units (also known as notional or portable units) in lieu of device units for calculating both line breaks and page breaks. Layout is performed at a resolution at which no accumulated error will affect the calculations. When the font is actually scaled to device resolution (display, printer, or even typesetter) for use in output, error accumulated at that resolution is handled at the device level and is not added into the document layout.

Although TrueType fonts do not scale linearly per se, a metric given in design units can be scaled to any given point size in a consistent fashion. Character hinting and pixel roundoff will cause irregularities, but these should be handled only at the final output resolution (where they appear) and not during high-level formatting. Using design units, an application can approximate to a high degree of accuracy how a certain character will appear at any point size and at any resolution. This scaling ability was not possible with Windows’ raster font technology, which necessitated contending with irregularities at all levels of formatting as well as with fonts that were sometimes not even remotely similar across devices or resolutions.

For design units to be useful on an actual device, they must first be converted to device units as follows:

DeviceValue = (DesignValue / unitsPerEM) * (PointSize / 72) *

DeviceResolution;

DeviceResolution is the logical resolution (pixels per inch) of the destination device. This is given by GetDeviceCaps using the LOGPIXELSX and LOGPIXELSY indexes.

PointSize is the size of the font in points (one point is 1/72 inch).

UnitsPerEM is the EM square size for the font; it is found in the otmEMSquare field of the OUTLINETEXTMETRIC structure and in the ntmSizeEM field of the NEWTEXTMETRIC structure.

DesignValue is the metric to be converted to device units. This could be anything from the width of a character to the ascender value for the whole font.

DeviceValue is the metric when converted to device units.

This formula is critical for device-independent layout calculations, but it should not be used to convert from device units back to design units because device units are invariably rounded to the nearest pixel, and the propagated roundoff error could become significant in design units. Also, the destination device resolution can differ in x and y (the EGA display is an example), in which case the above calculation must be done with the x-resolution for all horizontal metric components and with the y-resolution for all vertical metric components.

A document that uses more than one TrueType font may need to contend with differing values for unitsPerEM. (Fonts included with Windows have unitsPerEM set to 2048; many fonts converted from Type 1 have unitsPerEM set to 1000.) An application that wants to be incredibly accurate and not lose information should normalize its calculations to use normalized units greater than the largest possible value, which is defined as 16,384. A suggested value for this ultra-high resolution (UHR) value is 65,536, which goes well beyond the unitsPerEM of existing fonts. An application should choose its UHR value based on the desired level of accuracy. All layout calculations are then based on this theoretical UHR device.

In reality, the device-independence part of the layout involves formatting to a theoretical device whose resolution is large enough to ensure that any actual output is scaled down to a less accurate pixel grid. Choosing a device whose resolution is higher than the design resolution of the TrueType fonts involved guarantees minimal error accumulation.

Layout Calculations

To get metrics of a font in design units, an application must first create and select a font that has a height in device units that is equal to the EM square size of the font. This can be accomplished by setting the lfHeight field of the LOGFONT structure to (–unitsPerEM). The unitsPerEm is returned in the ntmSizeEM field of the NEWTEXTMETRIC structure during font enumeration and in the otmEMSquare field of the OUTLINETEXTMETRIC structure returned by GetOutlineTextMetrics. The selected font is essentially a font that is not scaled by the rasterizer; it is at full design size. Special code in GDI ensures that a font created with this exact size is not hinted and remains true to its design.

GDI returns the metrics for the font after the font is selected into a DC. The above logical font can be selected into any DC and still maintain its design size. Functions that return useful values are GetOutlineTextMetrics, GetTextExtent, GetCharWidth, GetCharABCWidths, GetTextMetrics, and GetGlyphOutline.

All design metrics must first be normalized to the UHR value being used. The scale factor is calculated as follows:

normalizing_scale = (UHR_value / unitsPerEM)

This value is then used to scale the design units up (or down, if UHR is small) to the units of the UHR device:

design_metric_in_UHR = design_metric * normalizing_scale

Finally, the metrics for each size of the font must be scaled based on the point size of the font:

font_metric_in_UHR = design_metric_in_UHR * (point_size / 72)

Notice that for the same font at different point sizes, the design_metric_in_UHR is the same.With all critical metrics now in UHR units, the page layout can begin.

First, line breaks based on the UHR metrics and the physical page size are calculated. The page width in UHR units for a standard 8.5-by-11-inch page with 1-inch margins is ((UHR_value * (8.5 - (0.5 + 0.5)). This yields the start and the end of a line within a stream of text. Next, page breaks are computed using the UHR metrics (preferably otmAscent, otmDescent, and otmLineGap) and the length of the physical page. The result is a document formatted for the UHR device and hence for the device-independent layout.

The next step is fitting the layout to the target device. Metrics must be converted from UHR units to device units. Assuming the metrics are already font specific (based on point size):

font_metric_in_device = font_metric_in_UHR * (device_resolution /

UHR_value)

This results in a linearly scaled metric that is device independent. The various inquiry functions return the device-specific metrics after the font to be used is selected into the DC. The line heights are converted to device units. If a roundoff error results here (the sum of the device line heights does not match the sum of the UHR heights converted to device units), it must be absorbed somewhere for proper fitting. Probably the simplest way is to use the line placing values calculated in UHR and convert them to device units; this spreads any roundoff error nicely. Increasing or decreasing the line spacing as needed is another alternative, but the results may not be as pleasing visually.

Fitting the characters to a line (using the line breaks calculated above) is the last step. The most accurate method for doing this is to calculate, in UHR units, exactly where each line starts and ends. When device widths are used for the characters, this calculation invariably has an error in it. This error is then accumulated and spread in the interword spacing. If the line is too long (the most common case), the interword spacing is tightened. If the line is too short, the interword spacing is spread, as is commonly seen with justified paragraphs. Placing one character at a time based on UHR width metrics also accomplishes the task of error diffusion, but changes in intercharacter spacing are not pleasing visually. The exact method used by an application for this fitting depends on the desired level of accuracy.

MORE NEW FUNCTIONS

TrueType fonts differ from Windows raster and vector fonts in that they contain more typographical information and are stored in a data file that is not directly compatible with the Windows font interface. New Windows version 3.1 functions allow an application to access the TrueType-specific data and to add TrueType fonts to the system.

GetOutlineTextMetrics

The GetOutlineTextMetrics function provides access to font data that is available for TrueType fonts. This is an extension to the GetTextMetrics function and, in fact, the TEXTMETRIC structure is included in the OUTLINETEXTMETRIC structure. The metrics of special interest (not including any of those in the TEXTMETRIC structure) are the following:

otmfsType—The embedding bits are useful for an application that wants to support font embedding. Unless bit 1 of otmfsType is clear, the font cannot be embedded. If bit 2 is not clear, the embedding is read-only. (The font may be bundled with a document but cannot be unbundled and permanently installed on the receiving system.) The proper mechanism for an application handling read-only embedding is not to allow the user to edit the document unless the read-only fonts are stripped out first. Also, the application should encrypt read-only fonts in the document to hinder extraction attempts.

otmCharSlopeRise and otmCharSlopeRun—These values closely approximate the main italic angle of the font. For normal, nonitalic fonts, otmCharSlopeRise = 1 and otmCharSlopeRun = 0. For italic fonts, the values attempt to approximate the sine and cosine of the main italic angle of the font (in counterclockwise degrees from the vertical). Using these values, an application can create a sloping caret for showing the current position within an italic string. These values are not in logical units.

otmEMSquare—Defines the design units of the font. The same value is also in the ntmSizeEM field of the NEWTEXTMETRIC structure during enumeration. When the negative of this value is used as the lfHeight field during font creation, a “design resolution” font is created that can be used for device-independent page layout. (This was discussed in more detail in the “Layout Calculations” section.) This value is never scaled to logical units; it is an absolute.

otmAscent, otmDescent, and otmLineGap—These values are typographic metrics that can be used for line spacing calculations. They are in logical units.

A collection of values define the typographic location and size of subscripts, superscripts, underlines, and strikeouts. These values are designed into the TrueType font and are therefore more appropriate than the rule-of-thumb calculated values that applications commonly use.

otmpFamilyName, otmpFaceName, and otmpStyleName—These strings provide a breakdown of the font’s name. For example, the Arial Bold Italic font has Arial as the otmpFamilyName, Bold Italic as the otmpStyleName, and Arial Bold Italic as the otmpFaceName. The otmpFaceName is not always a concatenation of the otmpFamilyName and otmpStyleName.

An error is returned when GetOutlineTextMetrics is called for a non-TrueType font.

Getting Kerning Information

In Windows version 3.0, the only fonts that had kerning information were device fonts and the only mechanism for retrieving the data was the GETPAIRKERNTABLE escape. Now that kerning information is also available in many TrueType fonts, it is no longer confined to the realm of devices. GetKerningPairs is a Windows version 3.1 function that can retrieve the kerning information of TrueType fonts. This function returns an array of KERNPAIR structures that identify all of the kerning pairs and their corresponding amounts of kerning. This function differs slightly from the GETPAIRKERNTABLE escape in that it lists the pairs based on the left character and specifies the kerning amounts in logical units. If a font has no kerning information (for example, a standard raster font), the GetKerningPairs function returns zero.

Getting TrueType Font Data

The TrueType font format is public and contains information that may not be accessible using the standard Windows interface. The TrueType specification currently lists 10 required tables and 7 optional tables. These (and the other tables in the font) can be accessed using the GetFontData function. The GetFontData function can also be used to capture the entire font for embedding purposes.

Applications that want to directly manipulate character glyphs generated by TrueType can use the GetGlyphOutline function. This function returns either the bitmap or the curve representation of a glyph. An application at this point “owns” the character glyph and can output it using special effects or accomplish any transformation that GDI does not provide.

Building TrueType Font Resources

The CreateScalableFontResource function allows applications to create a font resource file from a TrueType data file (with the TTF file extension). The resulting font resource file has a file extension of FOT. The font resource file can be added to the system using AddFontResource and removed using RemoveFontResource just like a standard FON file. When a TTF file is added to Windows through the Control Panel, the TTF file is copied to the SYSTEM subdirectory of the WINDOWS directory (unless the user chooses to install in place), a corresponding FOT file is created using CreateScalableFontResource, and an entry with the FOT file name is added to WIN.INI under the [fonts] subheader.