TTF Byte Layout Reference

TrueType (TTF) Byte Layout Reference

A minimal, quick-reference for the byte offsets and field layouts of every core TTF table. Big-endian throughout. For parsing strategy and walkthroughs, see Parse a Font.

Contents

  1. File header
  2. Tables

File header

Offset table (sfnt header) — 12 bytes at byte 0:

offsettypefieldnotes
0u32sfntVersion0x00010000 (TrueType) or 0x4F54544F (OTTO)
4u16numTablescount of tables that follow
6u16searchRangebinary-search hint; recompute if modifying
8u16entrySelectorbinary-search hint
10u16rangeShiftbinary-search hint

Table directory — numTables records of 16 bytes each, starting at byte 12:

offsettypefieldnotes
0tag[4]tableTage.g. head, glyf (ASCII)
4u32checksumtable checksum
8u32offsetfrom file start
12u32lengthreal length; table padded to 4-byte bound

Record i starts at byte 12 + i×16.


Tables

head — Font header (54 bytes, fixed)

Global font metrics and configuration.

offsettypefieldnotes
0u16majorVersion1
2u16minorVersion0
4i32fontRevision16.16 fixed-point
8u32checksumAdjustmentwhole-file sum
12u32magicNumbermust be 0x5F0F3CF5
16u16flagsbit field
18u16unitsPerEmdesign grid (e.g. 1000, 2048)
20i64createdseconds since 1904-01-01 00:00 UTC
28i64modifiedsame epoch
36i16xMinfont bbox
38i16yMin
40i16xMax
42i16yMax
44u16macStylebit field
46u16lowestRecPPEMsmallest readable size in pixels
48i16fontDirectionHint
50i16indexToLocFormat0 = short loca, 1 = long loca
52i16glyphDataFormat0

maxp — Maximum profile

Memory requirements. Version 0.5 (CFF, 6 bytes):

offsettypefieldnotes
0u32version0x00005000
4u16numGlyphscritical

Version 1.0 (TrueType, 32 bytes):

offsettypefieldnotes
0u32version0x00010000
4u16numGlyphsglyph count
6u16maxPointsmax in simple glyph
8u16maxContoursmax in simple glyph
10u16maxCompositePointsmax in composite glyph
12u16maxCompositeContoursmax in composite glyph
14u16maxZones1 or 2
16u16maxTwilightPoints
18u16maxStorage
20u16maxFunctionDefs
22u16maxInstructionDefs
24u16maxStackElements
26u16maxSizeOfInstructions
28u16maxComponentElements
30u16maxComponentDepth

hhea — Horizontal header (36 bytes, fixed)

Metrics for horizontal layout.

offsettypefieldnotes
0u16majorVersion1
2u16minorVersion0
4i16ascender
6i16descenderusually negative
8i16lineGap
10u16advanceWidthMax
12i16minLeftSideBearing
14i16minRightSideBearing
16i16xMaxExtent
18i16caretSlopeRise1 for vertical
20i16caretSlopeRun0 for vertical
22i16caretOffset0 for non-slanted
24i16reserved[4]zero
32i16metricDataFormat0
34u16numberOfHMetricssizes hmtx table

hmtx — Horizontal metrics (variable)

No header. Two back-to-back arrays:

Part 1: numberOfHMetrics (from hhea) entries of:

offsettypefieldnotes
0u16advanceWidth
2i16lsbleft side bearing

Part 2: numGlyphs − numberOfHMetrics entries of:

offsettypefieldnotes
0i16lsbreuses last advance width

loca — Location index (variable)

Maps glyph index → byte offset in glyf table. numGlyphs + 1 offsets (the +1 marks end of last glyph).

Short format (head.indexToLocFormat == 0): uint16 offsets (multiply by 2 to get real byte offset).

Long format (head.indexToLocFormat == 1): uint32 offsets (use directly).

If loca[i] == loca[i+1], glyph i is empty (e.g. space character).

glyf — Glyph data (variable)

No header. Glyph blocks back to back, located by loca.

Glyph header (10 bytes):

offsettypefieldnotes
0i16numberOfContours≥ 0 = simple; < 0 = composite
2i16xMinglyph bbox
4i16yMin
6i16xMax
8i16yMax

Simple glyph (numberOfContours ≥ 0):

offsettypefieldnotes
10u16[numberOfContours]endPtsOfContourslast+1 = point count
…u16instructionLengthbytes of hinting
…u8[instructionLength]instructionsTrueType bytecode
…u8[…]flagsone logical flag per point, compressed
…—xCoordinatesdelta-encoded
…—yCoordinatesdelta-encoded

Flag bits (each point):

bitnamemeaning
0x01ON_CURVE_POINTon curve (else off-curve control point)
0x02X_SHORT_VECTORx delta is 1 byte
0x04Y_SHORT_VECTORy delta is 1 byte
0x08REPEAT_FLAGnext byte = repeat count for this flag
0x10X_IS_SAME_OR_POSITIVE(see spec)
0x20Y_IS_SAME_OR_POSITIVE(see spec)
0x40OVERLAP_SIMPLEcontours may overlap
0x80reserved0

Composite glyph (numberOfContours < 0):

Loop of components. Each:

offsettypefieldnotes
0u16flagscomponent flags (below)
2u16glyphIndexwhich glyph to reference
4—arg1, arg2int8/uint8 or int16/uint16 per ARG_1_AND_2_ARE_WORDS
…—transform0, 1, 2, or 4 × F2Dot14 per scale flags

Component flag bits:

bitnamemeaning
0x0001ARG_1_AND_2_ARE_WORDSargs are 16-bit
0x0002ARGS_ARE_XY_VALUESargs are offsets (else indices)
0x0004ROUND_XY_TO_GRID
0x0008WE_HAVE_A_SCALEone F2Dot14 follows
0x0020MORE_COMPONENTSanother component after this
0x0040WE_HAVE_AN_X_AND_Y_SCALEtwo F2Dot14 follow
0x0080WE_HAVE_A_TWO_BY_TWOfour F2Dot14 (matrix)
0x0100WE_HAVE_INSTRUCTIONSafter last component: u16 length + bytes
0x0200USE_MY_METRICS
0x0400OVERLAP_COMPOUND

cmap — Character to glyph mapping (variable)

Maps Unicode → glyph index. Multiple subtables; pick the best for your case.

Header (4 bytes):

offsettypefield
0u16version
2u16numTables

Encoding records (numTables of 8 bytes each):

offsettypefieldnotes
0u16platformID0=Unicode, 1=Mac, 3=Windows
2u16encodingIDplatform-specific
4u32subtableOffsetfrom cmap table start

Common: (3,1) → format 4 (BMP); (3,10) → format 12 (full Unicode).

Format 0 (byte encoding, 256 glyphs):

offsettypefield
0u16format
2u16length
4u16language
6u8[256]glyphIdArray

Format 4 (segment mapping, BMP):

offsettypefield
0u16format
2u16length
4u16language
6u16segCountX2
8u16searchRange
10u16entrySelector
12u16rangeShift
14+u16[segCount]endCode
…u16reserved
…u16[segCount]startCode
…i16[segCount]idDelta
…u16[segCount]idRangeOffset
…u16[…]glyphIdArray

Format 12 (full Unicode coverage):

offsettypefield
0u16format
2u16reserved
4u32length
8u32language
12u32numGroups
16+—groups (numGroups entries, 12 bytes each)

Each group: { u32 startCharCode; u32 endCharCode; u32 startGlyphID }.

name — Font names (variable)

Human-readable strings (family, style, version, etc.). Stored once in a byte pool; records point in with metadata.

Header (6 bytes):

offsettypefieldnotes
0u16version0 or 1
2u16countnumber of name records
4u16storageOffsetstart of string pool from table start

Name records (count of 12 bytes each):

offsettypefieldnotes
0u16platformID0=Unicode, 3=Windows
2u16encodingIDplatform-specific
4u16languageIDplatform/language tag
6u16nameID1=family, 2=subfamily, 4=full, 5=version
8u16lengthstring length in bytes
10u16stringOffsetfrom storageOffset

Then raw string bytes per platform (typically UTF-16BE for Windows).

post — PostScript data (variable)

Italic angle, monospace flag, PostScript names (v2.0 only).

Fixed header (32 bytes):

offsettypefieldnotes
0u32version0x00010000, 0x00020000, or 0x00030000
4i32italicAngle16.16 fixed-point
8i16underlinePosition
10i16underlineThickness
12u32isFixedPitch0 or nonzero
16u32minMemType42
20u32maxMemType42
24u32minMemType1
28u32maxMemType1

Version 2.0 only (after header):

offsettypefield
32u16numGlyphs
34u16[numGlyphs]glyphNameIndex
…—Pascal-string names for indices ≥ 258

OS/2 — OS/2 and Windows metrics (version-dependent)

Font classification, weight, width, coverage, PANOSE, embedding flags.

Version 0 (78 bytes):

offsettypefieldnotes
0u16version0–5
2i16xAvgCharWidth
4u16usWeightClass100–900
6u16usWidthClass1–9
8u16fsTypeembedding flags
10i16ySubscriptXSize
12i16ySubscriptYSize
14i16ySubscriptXOffset
16i16ySubscriptYOffset
18i16ySuperscriptXSize
20i16ySuperscriptYSize
22i16ySuperscriptXOffset
24i16ySuperscriptYOffset
26i16yStrikeoutSize
28i16yStrikeoutPosition
30i16sFamilyClass
32u8[10]panose
42u32ulUnicodeRange1bits 0–31
46u32ulUnicodeRange2bits 32–63
50u32ulUnicodeRange3bits 64–95
54u32ulUnicodeRange4bits 96–127
58tag[4]achVendID
62u16fsSelectionstyle flags
64u16usFirstCharIndex
66u16usLastCharIndex
68i16sTypoAscender
70i16sTypoDescender
72i16sTypoLineGap
74u16usWinAscent
76u16usWinDescent

Version 1 adds (86 bytes):

offsettypefield
78u32ulCodePageRange1
82u32ulCodePageRange2

Version 2/3/4 add (96 bytes):

offsettypefield
86i16sxHeight
88i16sCapHeight
90u16usDefaultChar
92u16usBreakChar
94u16usMaxContext

Version 5 adds (100 bytes):

offsettypefield
96u16usLowerOpticalPointSize
98u16usUpperOpticalPointSize

kern — Kerning pairs (optional, variable)

Spacing adjustments between glyph pairs. Optional; modern fonts use GPOS instead.

Header (4 bytes):

offsettypefieldnotes
0u16version0
2u16nTables

Per subtable header (6 bytes):

offsettypefieldnotes
0u16versionsubtable version
2u16lengthsubtable length in bytes
4u16coveragehigh byte = format; low byte = flags

Format 0 (sorted pairs):

offsettypefieldnotes
6u16nPairs
8u16searchRangebinary-search hint
10u16entrySelectorbinary-search hint
12u16rangeShiftbinary-search hint
14+—pairsnPairs entries, 6 bytes each

Each pair: { u16 left; u16 right; i16 value }.


For parsing strategy and complete walkthroughs, see Parse a Font.