A maths font gives a formula engine (such as Microsoft Word’s, LuaTeX or MathML in a
browser) the measurements it needs: how far to raise superscripts, how thick to draw
fraction bars, how to kern scripts against letters, and which larger glyphs or glyph
pieces to use for growing brackets, radicals and arrows. The MATH table
holds these; the layout rules themselves are left to the engine. All numbers are
big-endian; values are in font units.
Header and MathValueRecord
| Offset | Type | Name | Description |
|---|---|---|---|
0 | uint16 × 2 | majorVersion, minorVersion | 1.0. |
4 | Offset16 | mathConstantsOffset | To MathConstants. |
6 | Offset16 | mathGlyphInfoOffset | To MathGlyphInfo. |
8 | Offset16 | mathVariantsOffset | To MathVariants. |
Most values are MathValueRecords: FWORD value and Offset16
deviceOffset, a Device
table (format 1 recommended, corrections of −1 to 1 pixel) counted from the start of
the table holding the record, or NULL. Engines may ignore device corrections so that
they do not pile up.
MathConstants
Font-wide values, 214 bytes. Names follow a pattern: Height is from the
baseline, Kern fixed space, Gap minimum space, Drop/Rise
a minimum relation between two elements, Shift an adjustment of position,
Dist between baselines. Positive shift-downs move down. Values for scripts and
limits come from the base’s font, at the base’s size. “Rule thickness” means the
engine’s default rule, typically the minus sign or OS/2.yStrikeoutSize.
| Offset | Type | Name | Meaning |
|---|---|---|---|
0 | int16 | scriptPercentScaleDown | Size of first-level scripts, per cent (about 80). |
2 | int16 | scriptScriptPercentScaleDown | Size of second-level scripts (about 60). |
4 | UFWORD | delimitedSubFormulaMinHeight | Height from which a bracketed expression counts as a sub-formula. |
6 | UFWORD | displayOperatorMinHeight | Minimum height of large operators (∑, ∫) in display formulas. |
8 | MVR | mathLeading | Space between formula lines. |
12 | MVR | axisHeight | Height of the maths axis (where minus signs and fraction bars sit). |
16 | MVR | accentBaseHeight | Base height up to which accents are not raised (about x-height). |
20 | MVR | flattenedAccentBaseHeight | Base height above which flattened accents (flac) are used. |
24 | MVR | subscriptShiftDown | Normal subscript drop. |
28 | MVR | subscriptTopMax | Highest a subscript’s top may be before it is pushed down. |
32 | MVR | subscriptBaselineDropMin | Least drop of a subscript baseline below a tall base’s bottom. |
36 | MVR | superscriptShiftUp | Normal superscript rise. |
40 | MVR | superscriptShiftUpCramped | The same in cramped style. |
44 | MVR | superscriptBottomMin | Lowest a superscript’s bottom may be before it is raised. |
48 | MVR | superscriptBaselineDropMax | Most a superscript baseline may sit below a tall base’s top. |
52 | MVR | subSuperscriptGapMin | Least gap between a superscript and a subscript. |
56 | MVR | superscriptBottomMaxWithSubscript | How high a superscript may be pushed to open that gap before the subscript moves down. |
60 | MVR | spaceAfterScript | Space after scripts (before prescripts). |
64 | MVR | upperLimitGapMin | Least gap between an upper limit and its operator. |
68 | MVR | upperLimitBaselineRiseMin | Least distance from the upper limit’s baseline to the operator’s top. |
72 | MVR | lowerLimitGapMin | Least gap between a lower limit and its operator. |
76 | MVR | lowerLimitBaselineDropMin | Least distance from the lower limit’s baseline to the operator’s bottom. |
80 | MVR | stackTopShiftUp | Rise of the top of a stack (such as a binomial). |
84 | MVR | stackTopDisplayStyleShiftUp | The same, display style. |
88 | MVR | stackBottomShiftDown | Drop of the bottom of a stack. |
92 | MVR | stackBottomDisplayStyleShiftDown | The same, display style. |
96 | MVR | stackGapMin | Least gap between stack elements (about 3 rules). |
100 | MVR | stackDisplayStyleGapMin | The same, display style (about 7 rules). |
104 | MVR | stretchStackTopShiftUp | Rise of the element over a stretched glyph (such as over an arrow). |
108 | MVR | stretchStackBottomShiftDown | Drop of the element under it. |
112 | MVR | stretchStackGapAboveMin | Least gap above the stretched glyph. |
116 | MVR | stretchStackGapBelowMin | Least gap below it. |
120 | MVR | fractionNumeratorShiftUp | Numerator rise. |
124 | MVR | fractionNumeratorDisplayStyleShiftUp | The same, display style. |
128 | MVR | fractionDenominatorShiftDown | Denominator drop. |
132 | MVR | fractionDenominatorDisplayStyleShiftDown | The same, display style. |
136 | MVR | fractionNumeratorGapMin | Least gap between numerator and bar. |
140 | MVR | fractionNumDisplayStyleGapMin | The same, display style. |
144 | MVR | fractionRuleThickness | Fraction bar thickness. |
148 | MVR | fractionDenominatorGapMin | Least gap between bar and denominator. |
152 | MVR | fractionDenomDisplayStyleGapMin | The same, display style. |
156 | MVR | skewedFractionHorizontalGap | Horizontal gap in a slashed fraction. |
160 | MVR | skewedFractionVerticalGap | Vertical gap in a slashed fraction. |
164 | MVR | overbarVerticalGap | Gap under an overbar. |
168 | MVR | overbarRuleThickness | Overbar thickness. |
172 | MVR | overbarExtraAscender | Space kept above an overbar. |
176 | MVR | underbarVerticalGap | Gap above an underbar. |
180 | MVR | underbarRuleThickness | Underbar thickness. |
184 | MVR | underbarExtraDescender | Space kept below an underbar. |
188 | MVR | radicalVerticalGap | Gap between a radicand and the radical’s bar. |
192 | MVR | radicalDisplayStyleVerticalGap | The same, display style. |
196 | MVR | radicalRuleThickness | Radical bar thickness. |
200 | MVR | radicalExtraAscender | Space kept above the radical. |
204 | MVR | radicalKernBeforeDegree | Space before a root’s degree (the 3 of ∛). |
208 | MVR | radicalKernAfterDegree | Negative kern after the degree. |
212 | int16 | radicalDegreeBottomRaisePercent | Height of the degree’s bottom, per cent of the radical’s height (about 60). |
MVR is a 4-byte MathValueRecord.
MathGlyphInfo
| Structure | Fields | Meaning |
|---|---|---|
| MathGlyphInfo | Offset16 mathItalicsCorrectionInfoOffset, Offset16 mathTopAccentAttachmentOffset, Offset16 extendedShapeCoverageOffset, Offset16 mathKernInfoOffset | Offsets from the MathGlyphInfo table. |
| MathItalicsCorrectionInfo | Offset16 italicsCorrectionCoverageOffset, uint16 italicsCorrectionCount, MVR × count | How far the top of a slanted glyph overhangs its advance; added after the last slanted glyph, splits limits on integrals, and offsets superscripts. Others are 0. |
| MathTopAccentAttachment | Offset16 topAccentCoverageOffset, uint16 topAccentAttachmentCount, MVR × count | The x position where an accent’s attachment point lines up; others use the centre of the advance. |
| Extended shape coverage | A Coverage table | Tall variants (big brackets) next to which scripts are placed by the ink box rather than the usual constants. May be NULL. |
| MathKernInfo | Offset16 mathKernCoverageOffset, uint16 mathKernCount, records × count | Per glyph, four Offset16 (from the MathKernInfo table, NULL = 0): top-right, top-left, bottom-right, bottom-left MathKern. |
| MathKern | uint16 heightCount, MVR correctionHeight[heightCount], MVR kernValues[heightCount + 1] | Kerning that depends on height: a height below the first entry uses value 0, between entries i−1 and i uses value i, at or above the last uses the last. |
For a superscript the engine adds the base’s top-right kern to the script’s bottom-left kern at two heights (the script’s bottom and the base’s top) and uses the smaller sum; for a subscript, bottom-right plus top-left at the script’s top and the base’s bottom.
MathVariants
| Structure | Fields | Meaning |
|---|---|---|
| MathVariants | UFWORD minConnectorOverlap, Offset16 vertGlyphCoverageOffset, Offset16 horizGlyphCoverageOffset, uint16 vertGlyphCount, uint16 horizGlyphCount, Offset16 vertGlyphConstructionOffsets[], Offset16 horizGlyphConstructionOffsets[] | Glyphs that can grow taller and wider; offsets from MathVariants, in coverage order. |
| MathGlyphConstruction | Offset16 glyphAssemblyOffset, uint16 variantCount, records of uint16 variantGlyph, UFWORD advanceMeasurement | Ready-made bigger glyphs with their size in the growth direction, and an assembly (or NULL) for anything bigger. |
| GlyphAssembly | MVR italicsCorrection, uint16 partCount, GlyphPart × count | Pieces from left to right, or bottom to top. |
| GlyphPart | uint16 glyphID, UFWORD startConnectorLength, UFWORD endConnectorLength, UFWORD fullAdvance, uint16 partFlags | Flag 0x0001 EXTENDER_FLAG: the piece may be repeated or left out; other bits reserved. |
To build a size: first try the variants; beyond the largest, assemble the parts with
no extenders and maximum overlap, then loosen the overlaps (never below
minConnectorOverlap or beyond a connector’s length), and if still short
add one of each extender and repeat. The assembly’s size is the last part’s offset
plus its full advance.
Example
STIX Two Math (STIXTwoMath.otf, macOS, 1000 units per em):
000BF744 00 01 00 00 00 0A 00 E0 53 5C 00 46 00 37 05 2D
000BF754 07 08 00 96 00 00 01 02 00 00 01 E0 00 00 02 90
000BF764 00 00 00 D2 00 00 01 70 00 00 00 A0 00 00 01 68
| Bytes | Meaning |
|---|---|
00 01 00 00 | Version 1.0. |
00 0A 00 E0 53 5C | Constants at 10, glyph info at 224 (10 + 214), variants at 21,340. |
00 46 00 37 | Scripts at 70 % and 55 %. |
05 2D 07 08 | Delimited sub-formula from 1325; display operators at least 1800 high. |
00 96 00 00 | mathLeading 150, no device table. |
01 02 00 00 | axisHeight 258. |
01 E0 · 02 90 | Accent base heights 480 and 656. |
00 D2 · 01 70 · 00 A0 | Subscripts: drop 210, top at most 368, baseline at least 160 below a tall base. |
01 68 | superscriptShiftUp 360. |