Note
This document is now superceded by VARC.md
The glyf data table (glyf
) stores the glyph outline data. The format number for this table is stored in the head
table's glyphDataFormat
field. The only currently defined format of the glyf
table is format 0. We propose format 1 of the glyf
table to add multiple features. See full proposal for all features. In this proposal we cover: Variable Composites / Components.
In glyf
table format 0, there exist two types of glyphs: Simple glyphs which have a numberOfContours
of >= 0, and Composite glyphs that have a numberOfContours
of < 0, with a recommended value of -1.
In glyf
table format 1, the old-style Simple and Composite glyphs exist as well. The old-style Composite glyphs shall always use a numberOfContours
of -1. A new composite glyph type call VariableComposite will be introduced which uses numberOfContours
of -2. A VariableComposite glyph has the ability to refer to variable components.
A Variable Composite glyph starts with the standard glyph header with a numberOfContours
of -2, followed by a number of Variable Component records. Each Variable Component record is at least five bytes long.
type | name | notes |
---|---|---|
uint16 | flags | see below |
uint8 | numAxes | Number of axes to follow |
GlyphID16 or GlyphID24 | gid | This is a GlyphID16 if bit 12 of flags is clear, else GlyphID24 |
uint8 or uint16 | axisIndices[numAxes] | This is a uint16 if bit 1 of flags is set, else a uint8 |
F2DOT14 | axisValues[numAxes] | The axis value for each axis |
FWORD | TranslateX | Optional, only present if bit 3 of flags is set |
FWORD | TranslateY | Optional, only present if bit 4 of flags is set |
F4DOT12 | Rotation | Optional, only present if bit 5 of flags is set |
F6DOT10 | ScaleX | Optional, only present if bit 6 of flags is set |
F6DOT10 | ScaleY | Optional, only present if bit 7 of flags is set |
F4DOT12 | SkewX | Optional, only present if bit 8 of flags is set |
F4DOT12 | SkewY | Optional, only present if bit 9 of flags is set |
FWORD | TCenterX | Optional, only present if bit 10 of flags is set |
FWORD | TCenterY | Optional, only present if bit 11 of flags is set |
The transformation data consists of individual optional fields, which can be used to construct a transformation matrix.
Transformation fields:
name | default value |
---|---|
TranslateX | 0 |
TranslateY | 0 |
Rotation | 0 |
ScaleX | 1 |
ScaleY | 1 |
SkewX | 0 |
SkewY | 0 |
TCenterX | 0 |
TCenterY | 0 |
The TCenterX
and TCenterY
values represent the “center of transformation”.
Details of how to build a transformation matrix, as pseudo-Python code:
# Using fontTools.misc.transform.Transform
t = Transform() # Identity
t = t.translate(TranslateX + TCenterX, TranslateY + TCenterY)
t = t.rotate(Rotation * math.pi)
t = t.scale(ScaleX, ScaleY)
t = t.skew(-SkewX * math.pi, SkewY * math.pi)
t = t.translate(-TCenterX, -TCenterY)
bit number | meaning |
---|---|
0 | Use my metrics |
1 | axis indices are shorts (clear = bytes, set = shorts) |
2 | if ScaleY is missing: take value from ScaleX |
3 | have TranslateX |
4 | have TranslateY |
5 | have Rotation |
6 | have ScaleX |
7 | have ScaleY |
8 | have SkewX |
9 | have SkewY |
10 | have TCenterX |
11 | have TCenterY |
12 | gid is 24 bit |
13 | axis indices have variation |
14 | reset unspecified axes |
15 | (reserved, set to 0) |
Variations of composite glyphs are processed this way: For each composite glyph, a vector of coordinate points is prepared, and its variation applied from the gvar
table. The coordinate points for the composite glyph are a concatenation of those for each variable component in order. For the purposes of gvar
delta IUP calculations, each point is considered to be in its own contour.
The coordinate points for each variable component consist of those for each axis value if flag bit 13 is set, represented as the X value of a coordinate point; followed by up to five points representing the transformation. The five possible points encode, in order, in their X,Y components, the following transformation components: (TranslateX
,TranslateY
), (Rotation
,0), (ScaleX
,ScaleY
), (SkewX
,SkewY
), (TCenterX
,TCenterY
). Only the transformation components present according to the flag bits are encoded. For example, the point (TranslateX
,TranslateY
) is encoded if and only if either of flag 3 or 4 is set. If that point is encoded, the variations from it will be applied to the transformation components even if a specific component has its flag bit off. For example, if only flag 3 is set (TranslateX
), any variations for TranslateY
are still applied to the TranslateY
of the transformation.
The component glyphs to be loaded use the coordinate values specified (with any variations applied if present). For any unspecified axis, the value used depends on flag bit 14. If the flag is set, then the normalized value zero is used. If the flag is clear the axis values from current glyph being processed (which itself might recursively come from the font or its own parent glyphs) are used. For example, if the font variations have wght
=.25 (normalized), and current glyph being processed is using wght
=.5 because it was referenced from another VarComposite glyph itself, when referring to a component that does not specify the wght
axis, if flag bit 14 is set, then the value of wght
=0 (default) will be used. If flag bit 14 is clear, wght
=.5 (from current glyph) will be used.
Note: While it is the (undocumented?) behavior of the glyf
table that glyphs loaded are shifted to align their LSB to that specified in the hmtx
table, much like regular Composite glyphs, this does not apply to component glyphs being loaded as part of a VariableComposite glyph.
Note: A static (non-variable) font that uses VarComposite glyphs, would not have fvar
/ avar
tables but would have the gvar
table. This combination is possible because the gvar
table encodes its own number-of-axes, and the axes in this proposal are specified in the normalized space.