18.4.8 TrueType Font Functions and Structures

Some of the functions and structures that allow an application to take advantage of the extra functionality of TrueType are discussed elsewhere in this chapter. This section describes some of the TrueType functions that are useful for applications that must take full advantage of the new font technology.

18.4.8.1 Retrieving Character Outlines

Applications can use the GetGlyphOutline function to retrieve the outline of a glyph from a TrueType font. GetGlyphOutline returns the outline as a bitmap or as a series of polylines and splines.

When an application retrieves a glyph outline as a series of polylines and splines, the information is returned in a TTPOLYGONHEADER structure followed by as many TTPOLYCURVE structures as are required to describe the glyph. All points are returned as POINTFX structures and represent absolute positions, not relative moves. The starting point given by the pfxStart member of the TTPOLYGONHEADER structure is the point at which the outline for a contour begins. The TTPOLYCURVE structures that follow can be either polyline records or spline records. Polyline records are a series of points; lines drawn between the points describe the outline of the character. Spline records represent the quadratic curves used by TrueType (that is, quadratic b-splines).

Each polyline and spline record contains as many sequential points as possible, to minimize the number of records returned.

The starting point given in the TTPOLYGONHEADER structure is always on the outline of the glyph. The specified point is both the starting point and the ending point for the contour.

A polyline record begins with the last point in the previous record (or with the starting point, for the first record in the contour). Each point in the record is on the glyph outline and can be connected simply by using straight lines.

A spline record begins with the last point in the previous record (or with the starting point, for the first record in the contour). For the first spline record, the starting point and the last point in the record are on the glyph outline. For all other spline records, only the last point is on the glyph outline. All other points in the spline records are off the glyph outline and must be rendered as the control points of b-splines.

The last spline or polyline record in a contour always ends with the contour's starting point. This ensures that every contour is closed.

Because b-splines require three points (one point that is off the glyph outline between two that are on the outline), applications must perform some calculations when a spline record contains more than one off-curve point.

For example, if a spline record contains three points (A, B, and C) and it is not the first record, points A and B are off the glyph outline. To interpret point A, an application can use the current position (which is always on the glyph outline) and the point on the glyph outline between points A and B. To find this point between A and B, the application can perform the following calculation:

M = A + (B – A) / 2

The midpoint between consecutive off-outline points in a spline record is a point that is on the glyph outline, according to the definition of the spline format used in TrueType fonts. In preceding formula, M is the midpoint on the line between points A and B.

If the current position is designated by P, the two quadratic splines defined by this spline record are (P, A, M) and (M, B, C).

To render a TrueType character outline in GDI, an application must use both the polyline and the spline records. GDI can render polylines easily, but it does not support any spline formats. To use the spline records, an application must convert them into a series of polylines that approximate the spline.

The glyph outline returned by the GetGlyphOutline function is for a grid-fitted glyph. (A grid-fitted glyph has been modified so that its bitmap image conforms as closely as possible to the original design of the glyph.) If an application requires an unmodified glyph outline, it should request the glyph outline for a character in a font whose size is equal to the font's em units. (To create a font with this size, an application can set the lfHeight member of the LOGFONT structure to the negative of the value of the ntmSizeEM member of the NEWTEXTMETRIC structure.)

18.4.8.2 Using Portable TrueType Metrics

Applications that use the TrueType font metrics can achieve a high degree of printer and document portability. Applications that must maintain compatibility with earlier versions of Windows can use the TrueType metrics, as can applications that are written specifically for Windows version 3.1.

Design Widths

Design widths overcome most of the problems of device-dependent text introduced by physical devices. Design widths are a kind of logical width. Independent of any rasterization problems or scaling transformations, each glyph has a logical width and height. Composed to a logical page, each character in a string has a place independent of the physical device widths. Although a logical width implies that widths can be scaled linearly at all point sizes, this is not necessarily true for either nonportable or most TrueType fonts. At smaller point sizes, some glyphs are made wider relative to their height for better readability.

The characters in TrueType core fonts are designed against a 2048-by-2048 grid. The design width is the width of a character in these grid units. (TrueType supports any integer grid size up to 16,384 by 16,384; grid sizes that are integer powers of 2 scale faster than other grid sizes.)

The outline of a font is designed in notional units. The em square is the notional grid against which the font outline is fitted. (The otmEMSquare member of OUTLINETEXTMETRIC and the ntmSizeEM member of NEWTEXTMETRIC give the size of the em square in notional units.) When a font is created that has a point size (in device units) equal to the size of its em square, the ABC widths for this font are the desired design widths. For example, if the size of an em square is 1000 and the ABC widths of a character in the font are 150, 400, and 150, a character in this font that has a height of 10 in device units would have ABC widths of 1.5, 4, and 1.5, respectively. Since the MM_TEXT mapping mode is most commonly used with fonts (and MM_TEXT is equivalent to device units), this is a simple calculation.

Because of the high resolution of TrueType design widths, applications that use them must take into account the large numeric values that can be created.

Device vs. Design Units

Portable metrics in fonts are known as design units. To apply to a given device, design units must be converted to device units. An application can use the following formula to convert design units to device units:

DeviceUnits = (DesignUnits/unitsPerEm) * (PointSize/72) * DeviceResolution

The variables in this formula have the following meanings:

Variable Description

DeviceUnits Specifies the DesignUnits font metric converted to device units. This value is in the same units as the value given for DeviceResolution.
DesignUnits Specifies the font metric to be converted to device units. This value could be any font metric, including the width of a character or the ascender value for an entire font.
unitsPerEm Specifies the em square size for the font.
PointSize Specifies size of the font in points. (One point equals 1/72 of an inch.)
DeviceResolution Specifies number of device units (pixels) per inch. Typical values might be 300 for a laser printer or 96 for a VGA screen.

Note:

This formula should not be used to convert device units back to design units. Device units are always rounded to the nearest pixel. The propagated round-off error can become very large, especially when an application is working with screen sizes.

Requesting Design-Unit Metrics

Font metrics for a physical font can be retrieved only after a font has been selected into a device context. When a font is selected into a device context, it is scaled for the device, which makes the font metrics specific to the device. To request design units, an application should create a logical font whose height is specified as –unitsPerEm. Applications can retrieve the value for unitsPerEm by calling the EnumFontFamilies function and checking the ntmSizeEM member of the NEWTEXTMETRIC structure.

Metrics for Portable Documents

The following table specifies the most important font metrics for applications that require portable documents and the functions that allow an application to retrieve them:

Function Metric Use

EnumFontFamilies ntmSizeEM Retrieving design metrics; conversion to device metrics
GetCharABCWidths ABCWidths Accurate placement of characters at the start and end of margins, picture boundaries, and other text breaks
GetCharWidth AdvanceWidths Placement of characters on a line. (This function is not new for Windows 3.1.)
GetOutlineTextMetrics otmfsType Font-embedding bits
  otmsCharSlopeRise Y-component for slope of cursor for italic fonts
  otmsCharSlopeRun X-component for slope of cursor for italic fonts
  otmAscent Line spacing
  otmDescent Line spacing
  otmLineGap Line spacing
  otmpFamilyName Font identification
  otmpStyleName Font identification
  otmpFullName Font identification (typically, family and style name)

The otmsCharSlopeRise, otmsCharSlopeRun, otmAscent, otmDescent, and otmLineGap members of the OUTLINETEXTMETRIC structure are scaled or transformed to correspond to the current device mode and physical height (as given in the tmHeight member of the NEWTEXTMETRIC structure).

Font identification is important if the same font must be selected when a document is reopened or moved to a different system. The font mapper always selects the correct font when it is asked for by full name. The family and style names are needed in order to provide input to the standard font dialog box for proper placement of the selection bars.

The otmsCharSlopeRise and otmsCharSlopeRun values are used to produce a close approximation of the main italic angle of the font. For typical roman fonts, otmsCharSlopeRise is 1 and otmsCharSlopeRun is 0. For italic fonts, the values attempt to approximate the sine and cosine of the main italic angle of the font (in counterclockwise degrees past vertical); note that the italic angle for upright fonts is 0. Because these values are not expressed in design units, they should not be converted into device units.

The character placement and line spacing metrics allow an application to compute device-independent line breaks that are portable across screens, printers, typesetters, and even platforms. If all applications adopt these techniques, documents moved from one application to another will not reflow.

Device-independent page layout requires seven basic steps:

1.Normalize all design metrics to a common ultra-high resolution (UHR) value (for example, 65,536 DPI); this prevents round-off errors.

2.Compute line breaks based on UHR metrics and physical page width; this yields a starting point and an ending point of a line within the text stream.

3.Compute the device page width in device units (for example, pixels).

4.Fit each line of text into the device page width, using the line breaks computed in step 2.

5.Compute page breaks by using UHR metrics and the physical page length; this yields the number of lines per page.

6.Compute the line heights in device units.

7.Fit the lines of text onto the page, using the lines per page from step 5 and the line heights from step 6.

18.4.8.3 Panose Numbers

TrueType font files include Panose numbers, which applications can use to choose a font that closely matches their specifications. The Panose system classifies faces by 10 different attributes. These attributes are each rated on a scale. The resulting values are concatenated to produce a number. Given this number for a font and a mathematical metric to measure distances in the Panose space, an application can determine nearest neighbors. A PANOSE structure is part of the OUTLINETEXTMETRIC structure (whose values are filled in by calling the GetOutlineTextMetrics function).