Chinese, Japanese, Korean and other ideographic text can be set in vertical lines.
Fonts that support this carry a vertical header, vhea, and vertical
metrics, vmtx, which mirror the horizontal
hhea and
hmtx; both are required for vertical writing. Fonts with CFF or CFF2
outlines may add VORG. These tables work the same in TrueType and
OpenType fonts. All numbers are big-endian.
vhea
Version 1.1 renamed and redefined the first three metrics; the layout is the same, 36 bytes in both versions.
| Offset | Type | Name (1.0 / 1.1) | Description |
|---|---|---|---|
0 | Version16Dot16 | version | 0x00010000 (1.0) or 0x00011000 (1.1). |
4 | FWORD | ascent / vertTypoAscender | 1.0: distance from the centre line to the previous line’s descent. 1.1: distance from the vertical centre baseline to the right edge of the ideographic em box, usually unitsPerEm/2. |
6 | FWORD | descent / vertTypoDescender | 1.0: distance from the centre line to the next line’s ascent. 1.1: distance to the left edge of the em box, usually −unitsPerEm/2. |
8 | FWORD | lineGap / vertTypoLineGap | 1.0: reserved, 0. 1.1: the gap between vertical lines; line spacing is the em box width plus this. |
10 | UFWORD | advanceHeightMax | Largest advance height in vmtx. |
12 | FWORD | minTopSideBearing | Smallest top side bearing. |
14 | FWORD | minBottomSideBearing | Smallest bottom side bearing. |
16 | FWORD | yMaxExtent | max(tsb + (yMax − yMin)) over all glyphs. |
18 | int16 | caretSlopeRise | Caret slope is rise/run: 0/1 is a horizontal caret, the best for vertical text; 1/0 a vertical one. |
20 | int16 | caretSlopeRun | 1 for fonts that are not slanted. |
22 | int16 | caretOffset | Shift of the highlight for slanted glyphs; 0 otherwise. |
24 | int16 × 4 | reserved | 0. |
32 | int16 | metricDataFormat | 0. |
34 | uint16 | numOfLongVerMetrics | Number of advance height and side bearing pairs in vmtx. |
The maximum and minimum values must agree with vmtx. In a variable font
the MVAR table varies these fields by tag: vasc for
ascent/vertTypoAscender, vdsc for
descent/vertTypoDescender, vlgp for the line gap,
vcrs for caretSlopeRise, vcrn for
caretSlopeRun and vcof for caretOffset.
vmtx
The table has no header: two arrays that together cover every glyph.
| Type | Name | Description |
|---|---|---|
record × numOfLongVerMetrics | vMetrics | Each a UFWORD advanceHeight and an FWORD topSideBearing. At least one is required. |
FWORD × (numGlyphs − numOfLongVerMetrics) | topSideBearing | Top side bearings for the remaining glyphs, which all share the last advance height in vMetrics. Optional; meant for one run of same-height glyphs at the end of the font. |
A monospaced font can have a single vMetrics entry and every other glyph
in the second array. numGlyphs comes from maxp.
Vertical origin and advance
- The y coordinate of a glyph’s vertical origin is its top side bearing plus the top
(yMax) of its bounding box. TrueType glyphs carry their bounding box in
glyf; for CFF and CFF2 glyphs it has to be worked out from the charstring, or read directly fromVORG. - The x coordinate of the vertical origin is not given; software may use the
BASEtable’s baselines to place glyphs across the line. - The advance height runs downwards from the vertical origin to the next glyph’s
origin. Layout features such as
vkrncan adjust it. - In variable fonts, advance heights and vertical origins vary through
VVAR(withgvarphantom points as the alternative for TrueType outlines).
VORG
An optional table, only for fonts with CFF or
CFF2 outlines (TrueType fonts must have it
ignored), that gives each glyph’s vertical origin y directly. It adds no new metric:
software may use it or compute the same value from the charstring’s bounding box and
vmtx, but it avoids rounding differences between bounding-box methods.
Advance heights still come only from vmtx.
| Offset | Type | Name | Description |
|---|---|---|---|
0 | uint16 | majorVersion | 1. |
2 | uint16 | minorVersion | 0. |
4 | int16 | defaultVertOriginY | Vertical origin y for every glyph not listed. |
6 | uint16 | numVertOriginYMetrics | Number of records. |
8 | record × count | vertOriginYMetrics | Each a uint16 glyphIndex and an int16 vertOriginY, sorted by glyph index, no glyph twice. |
Usually only full-width Latin glyphs need records, so a table where every glyph uses the default is 8 bytes. The specification’s example for a 1000-unit font has default 880 and three records: glyph 10 at 889, 12 at 861 and 13 at 849.
Example
The first font in CJKSymbolsFallback.ttc (macOS) has 1,103 glyphs and
unitsPerEm 2048. Its 36-byte vhea:
00009268 00 01 10 00 04 00 FC 00 00 00 08 00 FC 7D F6 74
00009278 0A 5A 00 00 00 01 00 00 00 00 00 00 00 00 00 00
00009288 00 00 04 4E
| Offset | Bytes | Field | Value |
|---|---|---|---|
0 | 00 01 10 00 | version | 1.1 |
4 | 04 00 | vertTypoAscender | 1024, half the em |
6 | FC 00 | vertTypoDescender | −1024 |
8 | 00 00 | vertTypoLineGap | 0 |
10 | 08 00 | advanceHeightMax | 2048 |
12 | FC 7D | minTopSideBearing | −899 |
14 | F6 74 | minBottomSideBearing | −2444 |
16 | 0A 5A | yMaxExtent | 2650 |
18 | 00 00 00 01 00 00 | caret rise, run, offset | 0, 1, 0: horizontal caret |
24 | 10 zero bytes | reserved, metricDataFormat | 0 |
34 | 04 4E | numOfLongVerMetrics | 1102 |
The vmtx table is 4,410 bytes: 1,102 four-byte pairs and one more
two-byte top side bearing, for the 1,103rd glyph. It starts
08 00 08 1A 08 00 05 8E: glyph 0 has advance height 2048 and top side
bearing 2074, glyph 1 advance 2048 and top side bearing 1422. It ends
08 00 04 2F 04 79: the last pair (2048, 1071), then 1145 for the last
glyph, whose advance is also 2048.