The CFF2 table, added in OpenType 1.8 (2016), holds cubic outlines like
the CFF table but drops
everything other OpenType tables already provide, and adds variation data so that one
font can hold a whole design space. It is defined by the OpenType specification
itself, not by an Adobe technical note. A font has either CFF ,
CFF2 or glyf outlines, and a CFF2 font, like a
CFF one, has sfntVersion OTTO. All
numbers are big-endian and nothing is aligned.
Differences from CFF
- One font only: there is one Top DICT, stored directly, with no Top DICT INDEX.
- No Name INDEX, String INDEX, encoding or charset. Names come from the
nameandposttables, characters fromcmap. - No advance widths in charstrings: widths come only from
hmtxandvmtx, varied byHVARandVVAR. - INDEX counts are 32-bit.
- Charstrings have no
endcharorreturn, and none of the arithmetic, logic or storage operators; they gainblendandvsindex. - The argument stack holds 513 values instead of 48.
- Paths are filled with the non-zero winding rule, so contours may overlap (needed
for variable fonts, where overlaps cannot practically be removed);
CFFoutlines may not overlap. - Every Font DICT and Private DICT pair applies to a group of glyphs chosen by FontDICTSelect, as in CID-keyed CFF fonts, but any font may use it.
Layout
| Part | Where | Notes |
|---|---|---|
| Header | Offset 0 | Required. |
| TopDICT | Straight after the header (offset 5) | Required. |
| GlobalSubrINDEX | Straight after the TopDICT | Required; may be empty. |
| CharStringINDEX | CharStringINDEXOffset | One charstring per glyph; glyph 0 is .notdef. |
| FontDICTSelect | FontDICTSelectOffset | Only when there is more than one Font DICT. |
| FontDICTINDEX | FontDICTINDEXOffset | One or more Font DICTs. |
| PrivateDICTs | From each Font DICT | One per Font DICT. |
| LocalSubrINDEX | From each PrivateDICT | Optional. |
| VariationStore | VariationStoreOffset | Variable fonts only. |
The first three must be at the start in this order; the rest may be anywhere, found by offsets from the start of the table (except the local subroutines, which are found from their PrivateDICT).
Header
| Offset | Type | Name | Description |
|---|---|---|---|
0 | uint8 | majorVersion | 2. |
1 | uint8 | minorVersion | 0. |
2 | uint8 | headerSize | 5; readers use it to find the TopDICT. |
3 | uint16 | topDICTSize | Length of the TopDICT in bytes. |
INDEX
| Type | Name | Description |
|---|---|---|
uint32 | count | Number of objects. |
uint8 | offSize | Size of each offset, 1 to 4 bytes. |
Offset × (count + 1) | offset | From the byte before the data; the first is 1. |
uint8 × varies | data | The objects. |
An empty INDEX is a 4-byte zero count and nothing else.
Numbers
DICTs and charstrings use the same number forms as CFF, with this split:
| First byte | Form | In DICTs | In charstrings |
|---|---|---|---|
| 32–246 | 1 byte, −107 to +107 | Yes | Yes |
| 247–250, 251–254 | 2 bytes, ±108 to ±1131 | Yes | Yes |
| 28 | 3 bytes, 16-bit signed | Yes | Yes |
| 29 | 5 bytes, 32-bit signed | Yes | No |
| 30 | Packed decimal real | Yes | No |
| 255 | 5 bytes, 16.16 fixed | No | Yes |
Charstring coordinates therefore cannot reach 32768 or more, or below −32768. The encodings are described on the CFF page.
TopDICT
| Operator | Name | Operands | Notes |
|---|---|---|---|
17 | CharStringINDEXOffset | offset | Required. |
24 | VariationStoreOffset | offset | Variable fonts only. Without it, blend and vsindex must not be used. |
12 36 | FontDICTINDEXOffset | offset | Required. |
12 37 | FontDICTSelectOffset | offset | Required with more than one Font DICT. |
12 7 | FontMatrix | 6 numbers | Default 0.001 0 0 0.001 0 0. Must be 1/unitsPerEm 0 0 1/unitsPerEm 0 0, so it may be left out when unitsPerEm is 1000. |
Every other CFF Top DICT operator (version, Notice,
FontBBox, charset, Encoding,
Private, ROS and so on) is gone. An operator not defined for
a DICT has unspecified behaviour.
Font DICT
| Operator | Name | Operands | Notes |
|---|---|---|---|
18 | PrivateDICTOffset | size offset | Size and position of this Font DICT’s PrivateDICT, the offset from the start of the CFF2 table. 0 0 for an empty one. |
PrivateDICT
| Operator | Name | Operands | Default and notes |
|---|---|---|---|
19 | LocalSubrINDEXOffset | offset | From the start of this PrivateDICT. |
22 | vsindex | number | 0. Which ItemVariationData (list of regions) the glyphs using this PrivateDICT use. |
23 | blend | see below | Makes the preceding values variable. |
6 | BlueValues | delta | – |
7 | OtherBlues | delta | After BlueValues. |
8 | FamilyBlues | delta | – |
9 | FamilyOtherBlues | delta | After FamilyBlues. |
10 | StdHW | number | – |
11 | StdVW | number | – |
12 9 | BlueScale | number | 0.039625. |
12 10 | BlueShift | number | 7. |
12 11 | BlueFuzz | number | 1. |
12 12 | StemSnapH | delta | – |
12 13 | StemSnapV | delta | – |
12 17 | LanguageGroup | number | 0. |
12 18 | ExpansionFactor | number | 0.06. |
CFF’s ForceBold, initialRandomSeed,
defaultWidthX and nominalWidthX are gone. Note the codes:
vsindex and blend are 22 and 23 in a PrivateDICT but 15 and
16 in charstrings.
FontDICTSelect
| Format | Type | Name | Description |
|---|---|---|---|
| 0 | uint8 | format | 0 |
uint8 × numGlyphs | fontDICTIDs | The Font DICT of every glyph. | |
| 3 | uint8 | format | 3 |
uint16 | numRanges | Number of ranges. | |
Range3 × numRanges | ranges | Each uint16 first, uint8 fontDICTID; the first range starts at glyph 0. | |
uint16 | sentinel | The number of glyphs. So at most 255 Font DICTs, and glyph 65534 is the last that can be mapped. | |
| 4 | uint8 | format | 4 |
uint32 | numRanges | Number of ranges. | |
Range4 × numRanges | ranges | Each uint32 first, uint16 fontDICTID; up to 65,535 Font DICTs. | |
uint32 | sentinel | The number of glyphs. |
VariationStore
| Type | Name | Description |
|---|---|---|
uint16 | length | Length of the ItemVariationStore that follows. |
uint8 × length | data | An ItemVariationStore, the common OpenType structure (format, VariationRegionList, ItemVariationData list). |
Only the regions are used from it. The VariationRegionList lists every region used
anywhere in the table; each ItemVariationData selects a subset through its
regionIndexes, and must have itemCount and its word-delta
count 0 with no delta sets, because the deltas themselves are written inline as
blend operands. Axes are numbered in their fvar order, and a
font with a VariationStore must have an fvar table. The store is not
shared with other tables’ item variation stores, even if identical.
CharStrings
A CFF2 charstring is a Type 2 charstring (see Type 2 charstrings) with these changes:
- No width before the first operator.
- No
endchar: the glyph ends where its data ends. Noreturn: a subroutine ends where its data ends. Subroutines may nest 10 deep and may not recurse.callsubrandcallgsubrpop only the subroutine number. - None of
and,or,not,abs,add,sub,div,neg,eq,drop,put,get,ifelse,random,mul,sqrt,dup,exch,index,roll, nor the deprecateddotsectionandseacform ofendchar. - Every contour is closed by a line back to its start, implied by the next moveto
or the end of the charstring. Outer contours run anticlockwise (filled area on the
left), the opposite of
glyf.
| Code | Operator | Blendable | Clears stack |
|---|---|---|---|
1 | hstem | Yes | Yes |
3 | vstem | Yes | Yes |
4 | vmoveto | Yes | Yes |
5 | rlineto | Yes | Yes |
6 | hlineto | Yes | Yes |
7 | vlineto | Yes | Yes |
8 | rrcurveto | Yes | Yes |
10 | callsubr | No | No |
15 | vsindex | No | Yes |
16 | blend | – | No (leaves its results) |
18 | hstemhm | Yes | Yes |
19 | hintmask | No | Yes |
20 | cntrmask | No | Yes |
21 | rmoveto | Yes | Yes |
22 | hmoveto | Yes | Yes |
23 | vstemhm | Yes | Yes |
24 | rcurveline | Yes | Yes |
25 | rlinecurve | Yes | Yes |
26 | vvcurveto | Yes | Yes |
27 | hhcurveto | Yes | Yes |
29 | callgsubr | No | No |
30 | vhcurveto | Yes | Yes |
31 | hvcurveto | Yes | Yes |
12 34 | hflex | Yes | Yes |
12 35 | flex | Yes | Yes |
12 36 | hflex1 | Yes | Yes |
12 37 | flex1 | Yes | Yes |
Byte 28 and 32–255 are numbers; every other code is undefined. Blendable means the
operator’s arguments may be produced by blend.
Hints work as in Type 2, with the mask bits always referring to stems in the order
they were declared. In a variable font, blended stems may overlap in some instances
even if they do not by default, so if any stems overlap anywhere in the design space
all should be declared with hstemhm/vstemhm and selected with
hintmask. The second value of a stem pair must stay zero or more after
blending, and the edge-hint widths −20 and −21 must not be blended.
blend and vsindex
vsindex takes one operand, ivd: the index of the
ItemVariationData whose region list applies. Its default is 0 or the PrivateDICT’s
vsindex; in a charstring it may be used once, before any
blend, and overrides the PrivateDICT. The number of regions in that list
is k.
blend takes n + n × k + 1 operands:
n default values, then k deltas for the first value, k
for the second and so on, then n. It replaces them with n
results: each default value plus the sum of its deltas, each multiplied by the scalar
(from 0 to 1) that the current axis settings give its region. A blend need not cover
all of the next operator’s arguments; several blends can each cover some of them. For
example, with one region and a scalar of 0.75, 120 52 1 blend hlineto
draws a line of 120 + 52 × 0.75 = 159.
Because k changes the operand count, a subroutine that uses
blend or vsindex must agree with every glyph that calls it.
Metrics are not varied here but in HVAR and VVAR; there is
no gvar table and no inferred deltas, but moving a contour’s first
rmoveto moves the whole contour.
Other tables
maxpmust be version 0.5 (6 bytes) and itsnumGlyphsmust equal the CharStringINDEX count.head:indexToLocFormatandglyphDataFormatare 0;unitsPerEmmust agree withFontMatrix.hmtx/HVARandvmtx/VVARgive all metrics;fvaris required in a variable font;gvaris not used.
Limits
| Item | Limit |
|---|---|
| Argument stack | 513 |
| Charstring length | 65,535 bytes |
| Subroutine nesting | 10, no recursion |
| Subroutine bias | 107 below 1,240 subroutines, 1131 below 33,900, otherwise 32768 |
Example
The OpenType specification’s sample CFF2 table is 226 bytes: a variable
font with one axis, two glyphs and one local subroutine that draws a square. Its first
16 bytes and the subroutine:
0000 02 00 05 00 07 CF 0C 24 C3 11 9B 18 00 00 00 00
...
00C8 BD BD EF 8C 10 8B 15 F8 88 27 FB 5C 8C 10 06 F8
00D8 88 07 FC 88 EF F7 5C 8C 10 06
| Bytes | Meaning |
|---|---|
02 00 05 00 07 | Version 2.0, 5-byte header, 7-byte TopDICT. |
CF 0C 24 | 68 FontDICTINDEXOffset. |
C3 11 | 56 CharStringINDEXOffset. |
9B 18 | 16 VariationStoreOffset. |
00 00 00 00 | Empty GlobalSubrINDEX at 12 (a 32-bit count of 0). |
BD BD EF 8C 10 8B 15 | 50 50 100 1 blend 0 rmoveto: with k = 2 regions, x = 50 plus deltas 50 and 100; y = 0. |
F8 88 27 FB 5C 8C 10 06 | 500 −100 −200 1 blend hlineto. |
F8 88 07 | 500 vlineto. |
FC 88 EF F7 5C 8C 10 06 | −500 100 200 1 blend hlineto; the data ends, closing the contour. |
Between them, the VariationStore (length 38) defines two regions on the one axis,
from −1 to 0 peaking at −0.5, and from −1 to −0.5 peaking at −1, and one
ItemVariationData with itemCount 0 that selects both. Both glyphs are just
20 0A, −107 callsubr: with one local subroutine the bias is
107, so they call subroutine 0. At the default the square is 500 units wide; towards
−1 on the axis it narrows.