Each glyph in a CFF table is
a small program, a Type 2 charstring, that draws its outline with cubic Bézier curves
and declares its hints. Type 2 charstrings are a more compact successor to Type 1
charstrings; they can be converted to and from Type 1 without loss. This page follows
Adobe Technical Note #5177 (16 March 2000). CFF2 uses the same encoding with
some changes.
How a charstring runs
A charstring is a sequence of bytes holding numbers and operators. Numbers are pushed on an argument stack; an operator takes its arguments, usually from the bottom of the stack (first argument bottom-most), and most operators then clear the stack. The arithmetic, storage, conditional and subroutine operators work at the top of the stack instead and leave results there. Drawing starts at the point (0, 0) of the glyph’s coordinate system, and every coordinate is relative to the previous point.
The parts of a charstring must come in this order:
w? {hs* vs* cm* hm* mt subpath}? {mt subpath}* endchar
- Width (
w): if the glyph’s width is not the Private DICT’sdefaultWidthX, it is the first number, stored as the difference fromnominalWidthX. It is an extra argument to the first stack-clearing operator, which must be one ofhstem,hstemhm,vstem,vstemhm,cntrmask,hintmask,hmoveto,vmoveto,rmovetoorendchar; a reader detects it by that operator having one argument more than it needs. - Hints: any of
hstem,hstemhm,vstem,vstemhm,cntrmask,hintmask, in that order. The masks may not appear if there are no stem hints. - Path: each subpath starts with a moveto. A glyph without hints must
start its path with a moveto so the width can be found.
hintmaskmay appear within the path. endcharends every glyph.
Subroutine calls may appear anywhere between whole tokens, but not inside one (such
as between a hintmask and its mask bytes).
Bytes and numbers
| Byte v | Meaning | Range | Bytes |
|---|---|---|---|
| 0–11 | Operators | – | 1 |
| 12 | Escape: the next byte is a second operator byte | – | 2 |
| 13–18 | Operators | – | 1 |
| 19, 20 | hintmask, cntrmask, followed by mask bytes | – | 2 or more |
| 21–27 | Operators | – | 1 |
| 28 | Next 2 bytes: a 16-bit signed integer, high byte first | −32768 to +32767 | 3 |
| 29–31 | Operators | – | 1 |
| 32–246 | v − 139 | −107 to +107 | 1 |
| 247–250 | (v − 247) × 256 + w + 108, w the next byte | +108 to +1131 | 2 |
| 251–254 | −(v − 251) × 256 − w − 108 | −1131 to −108 | 2 |
| 255 | Next 4 bytes: a signed 16.16 fixed-point number | ±32768 with 16 bits of fraction | 5 |
Byte 255 is read differently from Type 1, where it is a 32-bit integer. Undefined operator codes have unspecified behaviour.
Path operators
In the forms below, |- on the left means the arguments are taken from
the bottom of the stack, and on the right that the stack is cleared. Curves take six
values: dxa dya from the current point to the first control point,
dxb dyb to the second, dxc dyc to the end point. Most
operators repeat for as many argument sets as are on the stack.
| Code | Operator | Arguments | Action |
|---|---|---|---|
21 | rmoveto | |- dx1 dy1 | Move by (dx1, dy1). Closes any open subpath first. The first moveto of a glyph is relative to (0, 0). |
22 | hmoveto | |- dx1 | Move horizontally. |
4 | vmoveto | |- dy1 | Move vertically. |
5 | rlineto | |- {dxa dya}+ | A line for each pair. |
6 | hlineto | |- dx1 {dya dxb}* or |- {dxa dyb}+ | Lines alternating horizontal and vertical, starting horizontal. |
7 | vlineto | |- dy1 {dxa dyb}* or |- {dya dxb}+ | Lines alternating vertical and horizontal, starting vertical. |
8 | rrcurveto | |- {dxa dya dxb dyb dxc dyc}+ | A curve for each six values. |
27 | hhcurveto | |- dy1? {dxa dxb dyb dxc}+ | Curves that start and end horizontal; an odd first value lets the first curve start at an angle (note it comes before dxa). |
31 | hvcurveto | |- dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf? or |- {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? | Curves alternating start horizontal / end vertical and start vertical / end horizontal, starting horizontal. A final odd value lets the last curve end at an angle. |
30 | vhcurveto | |- dy1 dx2 dy2 dx3 {dxa dxb dyb dyc dyd dxe dye dxf}* dyf? or |- {dya dxb dyb dxc dxd dxe dye dyf}+ dxf? | The same, starting vertical. |
26 | vvcurveto | |- dx1? {dya dxb dyb dyc}+ | Curves that start and end vertical; an odd first value lets the first start at an angle. |
24 | rcurveline | |- {dxa dya dxb dyb dxc dyc}+ dxd dyd | Curves, then one line. |
25 | rlinecurve | |- {dxa dya}+ dxb dyb dxc dyc dxd dyd | Lines, then one curve. |
12 35 | flex | |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 dx6 dy6 fd | Two curves, drawn as a straight line when the flex depth is under fd/100 device pixels. |
12 34 | hflex | |- dx1 dx2 dy2 dx3 dx4 dx5 dx6 | Flex with depth 50 where start, end, and the first and last control points share a y, and the join and its neighbouring control points share another. |
12 36 | hflex1 | |- dx1 dy1 dx2 dy2 dx3 dx4 dx5 dy5 dx6 | Flex with depth 50 where start and end share a y, and the join and its neighbouring control points share a y. |
12 37 | flex1 | |- dx1 dy1 dx2 dy2 dx3 dy3 dx4 dy4 dx5 dy5 d6 | Flex with depth 50 where start and end share an x or a y. Sum the first ten values to (dx, dy): if |dx| > |dy|, d6 is the end point’s x change and its y is the start’s; otherwise d6 is its y change and its x is the start’s. |
Flex suits a shallow bump or dent that can be drawn as exactly two curves meeting at a joining point, whose length is greater than its depth. The flex depth is the distance from the joining point to the line from start to end.
Finishing
| Code | Operator | Arguments | Action |
|---|---|---|---|
14 | endchar | – | Ends the glyph; must be its last operator, though it may be reached in a subroutine. A glyph with no outline (a space) can be just a width and endchar, and the shortest legal charstring is endchar alone. |
Hint operators
| Code | Operator | Arguments | Action |
|---|---|---|---|
1 | hstem | |- y dy {dya dyb}* | Horizontal stem hints, in increasing order of bottom edge. The first y is from 0; each later value is from the previous edge. |
3 | vstem | |- x dx {dxa dxb}* | Vertical stem hints, in increasing order of left edge. |
18 | hstemhm | |- y dy {dya dyb}* | As hstem, but must be used instead of it when the glyph uses hintmask. |
23 | vstemhm | |- x dx {dxa dxb}* | As vstem, for glyphs with hintmask. |
19 | hintmask | |- + mask bytes | Chooses which hints are active for the path that follows; does not move the current point. Needed whenever hints overlap. |
20 | cntrmask | |- + mask bytes | Chooses stems whose counters (the spaces between them) are to be controlled; the first cntrmask has the highest priority. |
- A stem width of −20 marks an edge hint for a top (or right) edge alone, and −21 a
bottom (or left) edge; other negative widths are undefined. Edge hints replace Type 1
ghost hints. Example:
121 −21 400 −20 hstemdeclares a bottom edge at 100 and a top edge at 500. - Hints of the same direction must not overlap unless a
hintmaskstraight after the declarations picks a non-overlapping set. - A mask has one bit per declared stem, in declaration order (horizontal then vertical), starting at the most significant bit of the first byte, rounded up to whole bytes; 1 means active, unused bits are 0.
- If
hstemhints are followed directly byhintmaskorcntrmask, thevstemoperator can be left out: the values still on the stack are taken as vertical stems. So280 100 −70 40 hstemhm 400 50 hintmask 0xA0declares two horizontal stems and one vertical, and makes the first horizontal and the vertical active. - With
LanguageGroupnot 1, acntrmaskof three stems can stand in for Type 1’shstem3andvstem3.
Arithmetic, storage and conditional operators
| Code | Operator | Stack before → after | Action |
|---|---|---|---|
12 9 | abs | num → num2 | Absolute value. |
12 10 | add | num1 num2 → sum | Addition. |
12 11 | sub | num1 num2 → difference | num1 − num2. |
12 12 | div | num1 num2 → quotient | num1 ÷ num2; undefined on overflow, 0 on underflow. |
12 14 | neg | num → num2 | Negation. |
12 23 | random | → num2 | A pseudo-random number greater than 0 and at most 1. |
12 24 | mul | num1 num2 → product | Multiplication; undefined on overflow, 0 on underflow. |
12 26 | sqrt | num → num2 | Square root; undefined for negative numbers. |
12 18 | drop | num → | Removes the top element. |
12 28 | exch | num1 num2 → num2 num1 | Swaps the top two. |
12 29 | index | numX … num0 i → numX … num0 numi | Copies element i from the top; a negative i copies the top; i > X is undefined. |
12 30 | roll | num(N−1) … num0 N J → rotated | Rotates the top N elements by J (positive is upwards); N must be non-negative. |
12 27 | dup | any → any any | Duplicates the top. |
12 20 | put | val i → | Stores val in element i of the transient array. |
12 21 | get | i → val | Reads element i; undefined if not yet stored in this glyph. |
12 3 | and | num1 num2 → 1 or 0 | 1 if both non-zero. |
12 4 | or | num1 num2 → 1 or 0 | 1 if either non-zero. |
12 5 | not | num1 → 1 or 0 | 1 if zero. |
12 15 | eq | num1 num2 → 1 or 0 | 1 if equal. |
12 22 | ifelse | s1 s2 v1 v2 → s1 or s2 | s1 if v1 ≤ v2, otherwise s2 (usually biased subroutine numbers). |
The transient array is scratch storage that starts undefined for each glyph and does not persist between glyphs.
Subroutine operators
| Code | Operator | Arguments | Action |
|---|---|---|---|
10 | callsubr | subr# | Calls local subroutine subr# + bias. |
29 | callgsubr | globalsubr# | Calls global subroutine globalsubr# + bias. |
11 | return | – | Returns to the caller. A subroutine ends with return or endchar. |
The bias is 107 for fewer than 1,240 subroutines, 1131 for fewer than 33,900, and 32768 otherwise, worked out separately for the local and global INDEX; see the CFF page. Global subroutines may be used even in a set of one font. Calling a subroutine that does not exist is undefined.
Limits
| Item | Limit |
|---|---|
| Argument stack | 48 |
| Stem hints, horizontal and vertical together | 96 |
| Subroutine nesting | 10 |
| Charstring length | 65,535 bytes |
| Subroutines in one INDEX | 65,536 |
| Transient array elements | 32 |
Deprecated forms
Fonts embedded in PDF files may still use these, so readers should accept them:
dotsection(12 0,|- dotsection |-): an old form of hint substitution, always treated as doing nothing.endcharwith four extra arguments,adx ady bchar achar endchar: Type 1’sseacaccent composition. The glyph is the base characterbcharwith the accentacharplaced at (adx, ady). Both are codes in Standard Encoding, not the font’s own encoding, and the glyphs are found by the names that encoding gives them; this cannot be nested.
Earlier versions had blend (16), store (12 8)
and load (12 13) for multiple master fonts; they were removed
in 2000 and their codes are reserved. (CFF2 reuses 16 for its own
blend.)
All codes
| Code | Operator | Code | Operator |
|---|---|---|---|
0 | reserved | 16 | reserved |
1 | hstem | 17 | reserved |
2 | reserved | 18 | hstemhm |
3 | vstem | 19 | hintmask |
4 | vmoveto | 20 | cntrmask |
5 | rlineto | 21 | rmoveto |
6 | hlineto | 22 | hmoveto |
7 | vlineto | 23 | vstemhm |
8 | rrcurveto | 24 | rcurveline |
9 | reserved | 25 | rlinecurve |
10 | callsubr | 26 | vvcurveto |
11 | return | 27 | hhcurveto |
12 | escape | 28 | 16-bit number |
13 | reserved | 29 | callgsubr |
14 | endchar | 30 | vhcurveto |
15 | reserved | 31 | hvcurveto |
Two-byte operators 12 x: 0 dotsection (deprecated), 3
and, 4 or, 5 not, 9 abs, 10
add, 11 sub, 12 div, 14 neg, 15
eq, 18 drop, 20 put, 21 get, 22
ifelse, 23 random, 24 mul, 26
sqrt, 27 dup, 28 exch, 29 index,
30 roll, 34 hflex, 35 flex, 36
hflex1, 37 flex1. All others (1, 2, 6–8, 13, 16, 17, 19, 25,
31–33, 38–255) are reserved.
Example
The .notdef glyph of Noto Sans Javanese Regular, the font decoded on the
CFF page, whose Private DICT has
nominalWidthX 1309 and defaultWidthX 0. Its 23 bytes:
FD 59 E9 16 F8 2F F9 5E FC 2F 06 BE FD 2B 15 F8
F8 F7 C9 FC F8 07 0E
| Bytes | Decoded | Effect |
|---|---|---|
FD 59 E9 16 | −709 94 hmoveto | hmoveto needs one argument, so −709 is the width: 1309 − 709 = 600. Move to (94, 0). |
F8 2F F9 5E FC 2F 06 | 411 714 −411 hlineto | Lines to (505, 0), (505, 714), (94, 714); the subpath closes back to (94, 0). |
BE FD 2B 15 | 51 −663 rmoveto | Move to (145, 51). |
F8 F8 F7 C9 FC F8 07 | 612 309 −612 vlineto | Lines to (145, 663), (454, 663), (454, 51). |
0E | endchar | Closes the inner box and ends the glyph. |
The result is the usual empty rectangle, 600 units wide. The next glyph,
NULL, is the single byte 0E: no width, so
defaultWidthX (0), and no outline. The two after it, CR and
space, are each FE AD 0E: a width of 1309 − 1049 = 260 and
no outline.