A WOFF file starts with a header of 44 bytes. It says what kind of font is inside, how long the file is, how many tables follow and how big the font will be once it is unpacked, and where the two optional blocks, the extended metadata and the private data, are. All numbers in WOFF are big-endian and unsigned, as in the TrueType and OpenType fonts it wraps.
Fields
Offsets and sizes are in bytes, in decimal. The names are the ones in the W3C specification. The examples are from the header shown at the end of this page.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0 | 4 | UInt32 | signature | Always 0x774F4646, the characters wOFF. Any other value makes the file invalid. |
4 | 4 | UInt32 | flavor | The sfntVersion of the font that was wrapped: see flavour. Example: 0x00010000, TrueType outlines. |
8 | 4 | UInt32 | length | The size of the whole WOFF file. Example: 6,188. |
12 | 2 | UInt16 | numTables | The number of entries in the table directory. Example: 14. |
14 | 2 | UInt16 | reserved | Must be 0. Any other value makes the file invalid. |
16 | 4 | UInt32 | totalSfntSize | The size of the font once it is unpacked: see totalSfntSize. Example: 11,508. |
20 | 2 | UInt16 | majorVersion | The major version of the WOFF file, set by whoever made it. See version. Example: 1. |
22 | 2 | UInt16 | minorVersion | The minor version of the WOFF file. Example: 0. |
24 | 4 | UInt32 | metaOffset | Where the extended metadata block starts, from the start of the file, or 0 if there is none. |
28 | 4 | UInt32 | metaLength | The compressed length of the metadata block, or 0 if there is none. |
32 | 4 | UInt32 | metaOrigLength | The length of the metadata once it is uncompressed, or 0 if there is none. |
36 | 4 | UInt32 | privOffset | Where the private data block starts, or 0 if there is none. |
40 | 4 | UInt32 | privLength | The length of the private data block, or 0 if there is none. |
The table directory follows directly, at offset 44.
Flavour
A TrueType or OpenType font starts with a four-byte sfntVersion, and WOFF
copies it into flavor so that a reader knows what kind of outlines the
font has before it unpacks anything. The decoder writes it back as the first four bytes
of the rebuilt font.
| Value | As text | Meaning |
|---|---|---|
0x00010000 | – | TrueType outlines: a glyf and a loca table. Most .ttf fonts. |
0x4F54544F | OTTO | CFF outlines: a CFF or CFF2 table. Most .otf fonts. |
0x74727565 | true | TrueType outlines, a value the specification notes was used for some TrueType fonts on Mac OS. |
The specification does not make any other value an error, but says these are the ones
widely supported. WOFF 1.0 wraps a single font and has no way to describe a font
collection (ttcf); WOFF2 added
one.
totalSfntSize
A decoder needs to know how much memory the unpacked font takes before it starts, and
totalSfntSize tells it. The specification gives the sum:
- 12 bytes for the font’s offset table (
sfntVersion,numTables,searchRange,entrySelector,rangeShift); - 16 bytes for each table record;
- each table’s
origLength, rounded up to a multiple of 4.
The result is always a multiple of 4. A file whose totalSfntSize is
wrong, or not a multiple of 4, is invalid. It is the size of the font as it was before
it was wrapped, if that font was laid out the usual way with no gaps between tables;
the specification asks for this sum, not for the original file’s size.
For the example: 12 + 14 × 16 = 236 bytes of header and records, plus the 14 table lengths rounded up (96, 196, 16, 3,596, 8, 5,392, 56, 36, 160, 84, 32, 1,152, 292 and 156, which add up to 11,272), gives 11,508.
Version
majorVersion and minorVersion are the version of the WOFF
file, not of the format and not necessarily of the font inside. The specification lets
the maker put any version there, which need not match the version in the font’s
head or name tables, and it has no effect on how the font is
loaded. A reader should not treat any value as an error.
When a header makes the file invalid
A user agent must reject a WOFF file, and not load the font, when:
signatureis notwOFF;reservedis not 0;totalSfntSizeis not the sum above, or not a multiple of 4;length,numTablesor any offset and length put a table or block past the end of the file, or make two of them overlap;- a block that is absent does not have both its offset and its length set to 0, or one that is present has them inconsistent with the other blocks.
A metadata block that cannot be read is different: the user agent ignores it, as if it were not there, and still loads the font.
Example
The header of KaTeX’s Size2 Regular font, a TrueType font of 14 tables, as a 6,188-byte WOFF file. It has no metadata and no private data, so the last 20 bytes are zero.
00000000 77 4F 46 46 00 01 00 00 00 00 18 2C 00 0E 00 00 wOFF.......,....
00000010 00 00 2C F4 00 01 00 00 00 00 00 00 00 00 00 00 ..,.............
00000020 00 00 00 00 00 00 00 00 00 00 00 00 ............
| Bytes | Field | Value |
|---|---|---|
77 4F 46 46 | signature | wOFF |
00 01 00 00 | flavor | TrueType outlines |
00 00 18 2C | length | 6,188, the size of the file |
00 0E | numTables | 14 |
00 00 | reserved | 0 |
00 00 2C F4 | totalSfntSize | 11,508: the unpacked font is 86% bigger than the WOFF |
00 01, 00 00 | majorVersion, minorVersion | 1.0 |
| 12 zero bytes | metaOffset, metaLength, metaOrigLength | no metadata |
| 8 zero bytes | privOffset, privLength | no private data |