TrueType outlines can carry programs, called instructions or hints, that move the
points to fit the pixel grid at small sizes, so that stems have even widths and letters
line up. The rasteriser runs them in a small stack-based virtual machine. Three tables
hold the shared parts, each glyph in glyf holds its own program, and
gasp says at which sizes to use hinting and smoothing at all. All of them
are optional.
The tables
| Tag | Contents | When it runs or is used |
|---|---|---|
cvt | The control value table: an array of FWORDs, as many as the table’s length divided by 2, with no header. Typical stem widths and heights that instructions read by index, so that related features stay equal. | Scaled to the current size before prep runs; prep and glyph programs may change the scaled values. |
fpgm | The font program: instruction bytes, usually function (FDEF) and instruction (IDEF) definitions. | Once, when the font is first used. |
prep | The control value program: instruction bytes. | Each time the size or transformation changes, before any glyph. |
gasp | Grid-fitting and scan-conversion procedure: which rendering to use at which sizes. | By the rasteriser, to choose between hinting, greyscale and ClearType modes. |
The sizes of the virtual machine (functions, instruction definitions, storage, stack
depth, twilight points) are declared in maxp.
In a variable font, cvar varies the cvt values.
gasp
| Type | Name | Description |
|---|---|---|
uint16 | version | 0 or 1; new fonts use 1. |
uint16 | numRanges | The number of ranges. |
record × numRanges | gaspRanges | 4 bytes each: rangeMaxPPEM (uint16, the largest size in pixels per em the range covers) and rangeGaspBehavior (uint16, flags). Sorted by size; the last should have 0xFFFF, meaning every larger size. |
| Mask | Name | Meaning |
|---|---|---|
0x0001 | GASP_GRIDFIT | Use hinting (grid-fitting). |
0x0002 | GASP_DOGRAY | Use greyscale rendering. |
0x0004 | GASP_SYMMETRIC_GRIDFIT | Use hinting with ClearType symmetric smoothing. Version 1 only. |
0x0008 | GASP_SYMMETRIC_SMOOTHING | Use ClearType smoothing along more than one axis. Version 1 only. |
0xFFF0 | reserved | 0. |
The first two flags apply when the system uses greyscale font smoothing, the other two
when it uses ClearType. Typical use: 0x0002 below 9 ppem,
0x0001 from 9 to 16, 0x0003 above 16;
0x0004 almost always; 0x0008 or 0x000C above
15; no flags at all for huge sizes. Without a gasp table the rasteriser
uses its own defaults. In a variable font, MVAR tags gsp0 to
gsp9 can move the thresholds of the first ten ranges, but not the
flags.
The virtual machine in brief
- Stack of 32-bit values. Push instructions take their data from the instruction stream; everything else pops its arguments and pushes its results.
- Zones: zone 1 is the glyph’s points, plus the four phantom
points; zone 0, the twilight zone, holds extra points that instructions create.
Three zone pointers (
zp0tozp2) and three reference points (rp0torp2) say which points instructions use. - Vectors: points move along the freedom vector, and distances are measured along the projection vector.
- Graphics state: rounding mode, minimum distance, control value cut-in, single width, delta base and shift, loop count, auto-flip, instruction control flags.
- Numbers: coordinates are 26.6 fixed point in pixels (64 per pixel); vectors are 2.14.
- Storage: a store of
maxStoragewords, the scaledcvt, functions and instruction definitions.
Instructions
Every instruction is one byte. Where a name has flags in brackets, the low bits of
the opcode are the flags, read as a binary number: MDRP[abcde] at
0xC0 to 0xDF has abcde = opcode − 0xC0.
| Opcode | Name | Meaning and flags |
|---|---|---|
00–01 | SVTCA[a] | Set freedom and projection vectors to an axis. a: 0 y axis, 1 x axis. |
02–03 | SPVTCA[a] | Set projection vector to an axis (a as above). |
04–05 | SFVTCA[a] | Set freedom vector to an axis. |
06–07 | SPVTL[a] | Set projection vector to a line through two points. a: 0 parallel, 1 perpendicular. |
08–09 | SFVTL[a] | Set freedom vector to a line. |
0A | SPVFS | Set projection vector from stack. |
0B | SFVFS | Set freedom vector from stack. |
0C | GPV | Get projection vector. |
0D | GFV | Get freedom vector. |
0E | SFVTPV | Set freedom vector to projection vector. |
0F | ISECT | Move point to the intersection of two lines. |
10–12 | SRP0, SRP1, SRP2 | Set reference point 0, 1, 2. |
13–15 | SZP0, SZP1, SZP2 | Set zone pointer 0, 1, 2. |
16 | SZPS | Set all three zone pointers. |
17 | SLOOP | Set loop variable. |
18 | RTG | Round to grid. |
19 | RTHG | Round to half grid. |
1A | SMD | Set minimum distance. |
1B | ELSE | Else. |
1C | JMPR | Jump relative. |
1D | SCVTCI | Set control value table cut-in. |
1E | SSWCI | Set single-width cut-in. |
1F | SSW | Set single-width value. |
20 | DUP | Duplicate top stack element. |
21 | POP | Pop top stack element. |
22 | CLEAR | Clear the stack. |
23 | SWAP | Swap the top two elements. |
24 | DEPTH | Push the stack depth. |
25 | CINDEX | Copy the indexed element to the top. |
26 | MINDEX | Move the indexed element to the top. |
27 | ALIGNPTS | Align two points. |
28 | – | Unassigned. |
29 | UTP | Untouch point. |
2A | LOOPCALL | Call a function a number of times. |
2B | CALL | Call a function. |
2C | FDEF | Start a function definition; only in fpgm or prep. |
2D | ENDF | End a function or instruction definition. |
2E–2F | MDAP[a] | Move direct absolute point. a: 0 do not round, 1 round. |
30–31 | IUP[a] | Interpolate untouched points. a: 0 in y, 1 in x. |
32–33 | SHP[a] | Shift point by the last point’s move. a: 0 uses rp2 in zp1, 1 uses rp1 in zp0. |
34–35 | SHC[a] | Shift a contour (a as SHP). |
36–37 | SHZ[a] | Shift a zone (a as SHP). |
38 | SHPIX | Shift point by a pixel amount. |
39 | IP | Interpolate point between rp1 and rp2. |
3A–3B | MSIRP[a] | Move stack indirect relative point. a: 1 also sets rp0 to the point. |
3C | ALIGNRP | Align point to rp0. |
3D | RTDG | Round to double grid. |
3E–3F | MIAP[a] | Move indirect absolute point, to a cvt value. a: 1 round, using the cut-in. |
40 | NPUSHB | Push n bytes; n is the next byte. |
41 | NPUSHW | Push n words. |
42 | WS | Write store. |
43 | RS | Read store. |
44 | WCVTP | Write a cvt value in pixels. |
45 | RCVT | Read a cvt value. |
46–47 | GC[a] | Get coordinate on the projection vector. a: 0 current position, 1 original. |
48 | SCFS | Set coordinate from stack. |
49–4A | MD[a] | Measure distance. a: 0 in the grid-fitted outline, 1 in the original. |
4B | MPPEM | Push pixels per em. |
4C | MPS | Push point size. |
4D | FLIPON | Set auto-flip on. |
4E | FLIPOFF | Set auto-flip off. |
4F | DEBUG | Debug call. |
50–55 | LT, LTEQ, GT, GTEQ, EQ, NEQ | Comparisons: pop e2 then e1, push 1 or 0 for e1 < e2, ≤, >, ≥, =, ≠. |
56–57 | ODD, EVEN | Is the rounded value odd, even. |
58 | IF | If. |
59 | EIF | End if. |
5A–5C | AND, OR, NOT | Logical operations. |
5D | DELTAP1 | Delta exception for points, sizes delta base + 0 to 15. |
5E | SDB | Set delta base. |
5F | SDS | Set delta shift. |
60–63 | ADD, SUB, DIV, MUL | Arithmetic on 26.6 values. |
64–67 | ABS, NEG, FLOOR, CEILING | Absolute value, negate, floor, ceiling. |
68–6B | ROUND[ab] | Round a value, compensating for the engine. ab: distance type, 0 grey, 1 black, 2 white. |
6C–6F | NROUND[ab] | Compensate for the engine without rounding. |
70 | WCVTF | Write a cvt value in font units. |
71–72 | DELTAP2, DELTAP3 | Delta exceptions for points, sizes delta base + 16 to 31 and + 32 to 47. |
73–75 | DELTAC1, DELTAC2, DELTAC3 | Delta exceptions for cvt values, the same three size bands. |
76 | SROUND | Super round: set a custom rounding period, phase and threshold. |
77 | S45ROUND | Super round at 45 degrees. |
78 | JROT | Jump relative if true. |
79 | JROF | Jump relative if false. |
7A | ROFF | Rounding off. |
7B | – | Unassigned. |
7C | RUTG | Round up to grid. |
7D | RDTG | Round down to grid. |
7E | SANGW | Set angle weight; no longer needed. |
7F | AA | Adjust angle; no longer supported. |
80 | FLIPPT | Flip a point on or off the curve. |
81 | FLIPRGON | Make a range of points on-curve. |
82 | FLIPRGOFF | Make a range of points off-curve. |
83–84 | – | Unassigned. |
85 | SCANCTRL | Scan conversion control (dropout control). |
86–87 | SDPVTL[a] | Set dual projection vector to a line. a: 0 parallel, 1 perpendicular. |
88 | GETINFO | Get information about the rasteriser and glyph: see GETINFO. |
89 | IDEF | Define an instruction for an unassigned opcode; only in fpgm or prep. |
8A | ROLL | Roll the top three stack elements. |
8B–8C | MAX, MIN | Maximum, minimum. |
8D | SCANTYPE | Set scan type (dropout control mode). |
8E | INSTCTRL | Instruction execution control: selector 1 turns grid-fitting off, 2 ignores changes prep made to the default graphics state, 3 enables native ClearType mode. Only allowed in prep. |
8F–90 | – | Unassigned. |
91 | GETVARIATION | Push the normalised coordinate of each variation axis (2.14). Not supported everywhere, so a font must also give an IDEF for 0x91. |
92 | GETDATA | Apple only; not in the OpenType instruction set. |
93–AF | – | Unassigned. |
B0–B7 | PUSHB[abc] | Push abc + 1 bytes (1 to 8) from the instruction stream. |
B8–BF | PUSHW[abc] | Push abc + 1 signed words. |
C0–DF | MDRP[abcde] | Move direct relative point. a: set rp0 to the point; b: keep at least the minimum distance; c: round; de: distance type (0 grey, 1 black, 2 white). |
E0–FF | MIRP[abcde] | Move indirect relative point, to a cvt distance; flags as MDRP, with c rounding and using the cut-in. |
An IDEF can give meaning to an unassigned opcode; one for an opcode that
is already defined is ignored.
GETINFO
GETINFO pops a selector and pushes a result. Each selector bit asks one
question and its answer appears in one result bit; several can be asked at once.
| Selector bit | Result bits | Question | Needs version |
|---|---|---|---|
| 0 | 0 to 7 | Rasteriser version (below) | all |
| 1 | 8 | Glyph rotated | all |
| 2 | 9 | Glyph stretched | all |
| 3 | 10 | OpenType font variations supported | 5 to 32, or 41 to 64 |
| 4 | 11 | Vertical phantom points used | 5 to 32, or 41 to 64 |
| 5 | 12 | Windows greyscale font smoothing | 34 to 64 |
| 6 | 13 | ClearType enabled | 36 to 64 |
| 7 | 14 | ClearType compatible widths | 37 to 64 |
| 8 | 15 | ClearType symmetrical smoothing (horizontal stripes) | 37 to 64 |
| 9 | 16 | ClearType BGR stripe order | 37 to 64 |
| 10 | 17 | ClearType sub-pixel positioned text | 39 to 64 |
| 11 | 18 | ClearType symmetric rendering | 40 to 64 |
| 12 | 19 | ClearType grey rendering | 40 to 64 |
| Version | Microsoft rasteriser | Platform |
|---|---|---|
| 1 | Macintosh System 6 INIT | |
| 2 | Macintosh System 7 | |
| 3 | 1.0 | 16-bit Windows 3.1 |
| 4 | Macintosh System 6.2 | |
| 5 | KIRIN printer | |
| 6 | Macintosh System 7.1 | |
| 7 | Macintosh QuickDraw GX | |
| 33 | 1.5 | 32-bit, new scan converter |
| 34 | 1.6 | Font smoothing, new SCANTYPE |
| 35 | 1.7 | Composite scaling changes |
| 36 | 1.6+ | “Classic” ClearType (Windows CE) |
| 37 | 1.8 | ClearType |
| 38 | 1.9 | Sub-pixel positioned ClearType |
| 39 | 2.0 | Sub-pixel positioned ClearType flag |
| 40 | 2.1 | Symmetric ClearType flag, ClearType grey |
| 41 | 2.2 | OpenType font variations |
| 42 | 2.3 | GETVARIATION support |
The specification lists versions 0, 4 to 32 and 43 to 255 as reserved, although its own table names Apple versions 4 to 7.
Example
KaTeX’s Size2 Regular font has all four tables. Its gasp is version 1
with one range, FFFF 000F: at every size, hinting, greyscale,
symmetric hinting and symmetric smoothing. Its cvt is 14 bytes,
seven values of 0. Its 156-byte prep starts like this, a common opening
that turns hinting off at large sizes:
00 SVTCA[0] vectors to the y axis
4B MPPEM push pixels per em
B8 00 C8 PUSHW[000] 200 push 200
52 GT ppem > 200?
58 IF
B1 01 01 PUSHB[001] 1 1 push 1, 1
8E INSTCTRL selector 1 = 1: grid-fitting off
59 EIF
Its fpgm starts B0 00 2C: push 0, then FDEF,
the start of function 0; maxp says it defines 141 functions.