High Fonts and Math Fonts

Math fonts differ from other fonts not only in their extensive coverage of math operators, symbols, and math alphanumerics, but also in the large number of glyph variants they have to support two sizes of sub/superscripts and many sizes of stretchable characters like parentheses and brackets. Some such glyphs can be many times as high as the normal line height. The name given to fonts that contain glyphs larger than the line height is a “high font”. Fancy fonts like Gabriola have elegant swash variants that look great on wedding invitations and the like. Some of these glyph variants have ascents and descents much bigger than the line height and hence those fonts are also high fonts.


High fonts must be handled in a special way, at least on Windows. The reason for this dates back to the early 1990s when TrueType fonts were introduced into Windows 3.1. At that time, fonts didn’t have glyphs larger than the line height, so two heights were unified: the first is how big to make the bitmap used to rasterize the glyphs and the second is the line height itself. The corresponding height information is contained in the TEXTMETRIC structure and the line height is given nominally by the sum TEXTMETRIC::tmAscent + TEXTMETRIC::tmDescent. Here tmAscent is the height above the text baseline and tmDescent is the (positive) height below the baseline. One could also add leading, but the sum of the ascent and descent sufficed to determine the height of the rasterization bitmap.


Now consider a high font with its large glyphs. Clearly the bitmap has to have tmAscent and tmDescent large enough for the largest glyph. Accordingly tmAscent and tmDescent can be considerably larger than the ascent and descent for ordinary characters such as A—Z and a—z. When these quantities are used to display a high font, the ordinary characters look very small inside a line that’s much bigger. You can see this by selecting Cambria Math or Gabriola into NotePad. At least up through Windows 7, the system edit control, which is used in NotePad, doesn’t know how to render high fonts correctly. But Word, RichEdit, PowerPoint, and other more sophisticated text programs do know how, namely they use the ascent and descent values provided by the OUTLINETEXTMETRIC structure’s otmAscent and otmDescent.


If you display text using ExtTextOut() using baseline alignment (call SetTextAlign() with TA_BASELINE), you only have to use the OUTLINETEXTMETRIC values. But if you use the default text alignment, TA_TOP, then you need to subtract tmAscent to get to the “top”. Kind of strange, since that may result in a negative y coordinate, but it works fine. RichEdit uses TA_TOP since it used to be faster than TA_BASELINE, although it may not be any longer. Word uses TA_BASELINE.


You may be wondering how to find out if a font is a high font. Officially a font is a high font if bit 7 (0x80) of OUTLINETEXTMETRIC::otmfsSelection is nonzero. This bit is named USE_TYPO_METRICS. Since fonts might not set it when they should, you might also want to conclude that a font is a high font if (unsigned)tm.tmAscent > 2*(otm.otmAscent + otm.otmLineGap).


As a last note, you may wonder how to tell if a font is a math font, since not all high fonts are math fonts. One way is to find out if the font has an OpenType “MATH” table. To do this, call GetFontData(hdc, tagMATH, 0, NULL, 0), where tagMATH is defined by


#define MakeTag(a, b, c, d) (((d)<<24) | ((c)<<16) | ((b)<<8) | a)

#define tagMATH MakeTag('M','A','T','H')


If the return value is a positive number, it is the count of bytes in the “MATH” table.


There’s a lot more to a math font than what’s given in this post. An earlier post on High Quality Editing and Display of Mathematical Text in Office 2007 has a section on the math font, although it doesn’t contain the material in the present post. A full specification is available for people interested in developing math fonts.


Thanks to Koby Kahane and Adam Twardoch for helpful comments improving this post.