A font can carry ready-drawn bitmaps (“sbits”) for particular sizes, used instead of
the outline at those sizes. A set of bitmaps for one size is a strike.
EBLC says which strikes and glyphs exist and where their images are,
EBDT holds the images, and EBSC says which other sizes to make
by scaling. CBLC and CBDT extend the same layout to colour
images, mostly PNG emoji; sbix, from Apple, stores whole PNG, JPEG or TIFF
images per glyph. These tables are used with TrueType and CFF outlines alike. All
numbers are big-endian; metrics are in pixels.
EBLC
| Type | Name | Description |
|---|---|---|
uint16 | majorVersion | 2 (CBLC: 3). |
uint16 | minorVersion | 0. |
uint32 | numSizes | Number of strikes. |
| BitmapSize × numSizes | bitmapSizes | One 48-byte record per strike. |
BitmapSize
| Offset | Type | Name | Description |
|---|---|---|---|
0 | Offset32 | indexSubtableListOffset | From the start of EBLC. |
4 | uint32 | indexSubtableListSize | Bytes of the list and its subtables. |
8 | uint32 | numberOfIndexSubtables | Number of glyph ranges. |
12 | uint32 | colorRef | Unused, 0. |
16 | SbitLineMetrics | hori | Line metrics for horizontal text. |
28 | SbitLineMetrics | vert | Line metrics for vertical text. |
40 | uint16 | startGlyphIndex | Lowest glyph in the strike. |
42 | uint16 | endGlyphIndex | Highest glyph (not every glyph between need have a bitmap). |
44 | uint8 | ppemX | Horizontal pixels per em. |
45 | uint8 | ppemY | Vertical pixels per em (differs only for non-square pixels). |
46 | uint8 | bitDepth | 1 (black and white), 2 (4 greys), 4 (16 greys), 8 (256 greys); in CBLC also 32 (colour). |
47 | int8 | flags | 0x01 HORIZONTAL_METRICS, 0x02 VERTICAL_METRICS: which direction small metrics describe. Other bits reserved. |
SbitLineMetrics is twelve one-byte fields: int8 ascender,
int8 descender, uint8 widthMax, int8
caretSlopeNumerator, int8 caretSlopeDenominator, int8
caretOffset, int8 minOriginSB, int8 minAdvanceSB,
int8 maxBeforeBL, int8 minAfterBL, and two pad bytes. They
are for applications; the rasteriser does not use them.
Glyph metrics
| Record | Fields |
|---|---|
| BigGlyphMetrics (8 bytes) | uint8 height, uint8 width, int8 horiBearingX, int8 horiBearingY, uint8 horiAdvance, int8 vertBearingX, int8 vertBearingY, uint8 vertAdvance |
| SmallGlyphMetrics (5 bytes) | uint8 height, uint8 width, int8 bearingX, int8 bearingY, uint8 advance, for the direction set in flags |
Bearings run from the origin to the bitmap’s left (x) and top (y) edges; height is rows, width columns.
Index subtables
Each strike’s IndexSubtableList is an array of records, sorted and not
overlapping: uint16 firstGlyphIndex, uint16 lastGlyphIndex
(inclusive), Offset32 indexSubtableOffset (from the start of the list).
Each subtable starts with a header: uint16 indexFormat, uint16
imageFormat (the EBDT format), Offset32
imageDataOffset (from the start of EBDT).
| indexFormat | After the header | Use |
|---|---|---|
| 1 | Offset32 sbitOffsets[last − first + 2] | Glyphs with their own metrics; 4-byte offsets. |
| 2 | uint32 imageSize, BigGlyphMetrics | A run of glyphs all the same size and metrics. |
| 3 | Offset16 sbitOffsets[last − first + 2] | As 1 with 2-byte offsets. |
| 4 | uint32 numGlyphs, then numGlyphs + 1 pairs of uint16 glyphID, Offset16 sbitOffset | Sparse glyphs with their own metrics. |
| 5 | uint32 imageSize, BigGlyphMetrics, uint32 numGlyphs, uint16 glyphIdArray[numGlyphs] | Sparse glyphs sharing size and metrics. |
Offsets are added to imageDataOffset; a glyph’s image runs to the next
offset, so equal offsets mean a missing glyph and the extra last entry ends the range.
Images in formats 1, 3 and 4 must be stored in glyph order. Subtables are 4-byte
aligned, so formats 3 and 5 pad an odd-length array with one more element.
EBDT
A 4-byte header, uint16 majorVersion 2 (CBDT: 3) and
uint16 minorVersion 0, then glyph images, byte aligned, in these
formats:
| Format | Contents |
|---|---|
| 1 | SmallGlyphMetrics, then image data with each row padded to a whole byte. |
| 2 | SmallGlyphMetrics, then bit-aligned image data: rows follow one another with no padding; only the end of the glyph is padded to a byte. |
| 3 | Obsolete; not supported in OpenType. |
| 4 | Apple’s compressed format for some East Asian fonts; not supported in OpenType. |
| 5 | Bit-aligned image data only; metrics come from an index subtable of format 2 or 5. |
| 6 | BigGlyphMetrics, then byte-aligned data. |
| 7 | BigGlyphMetrics, then bit-aligned data. |
| 8 | SmallGlyphMetrics, uint8 pad, uint16 numComponents, components. |
| 9 | BigGlyphMetrics, uint16 numComponents, components. |
A component is uint16 glyphID, int8 xOffset, int8
yOffset: another bitmap glyph placed with its top-left corner at that offset.
Composites may nest. Pixels run from the top-left, most significant bit first, left to
right then down; with bitDepth above 1 each pixel’s bits are together. A set bit is
black. Windows works out tight metrics itself for format 5, so fixed-size padded
bitmaps still report correct widths.
EBSC
Defines extra strikes that are made by scaling a strike that exists in
EBLC and EBDT; useful where a scaled bitmap reads better than
a rasterised outline, as with small kanji. The first version is 2.0.
| Offset | Type | Name | Meaning |
|---|---|---|---|
0 | uint16 | majorVersion | 2. |
2 | uint16 | minorVersion | 0. |
4 | uint32 | numSizes | Number of BitmapScale records. |
8 | BitmapScale × count | strikes | One 28-byte record per scaled strike. |
| Offset | Type | Name | Meaning |
|---|---|---|---|
0 | SbitLineMetrics | hori | Horizontal line metrics of the strike after scaling, as in the EBLC BitmapSize record. |
12 | SbitLineMetrics | vert | Vertical line metrics after scaling. |
24 | uint8 | ppemX | Horizontal pixels per em of the strike to make. |
25 | uint8 | ppemY | Vertical pixels per em of the strike to make. |
26 | uint8 | substitutePpemX | Horizontal size of the existing strike to scale from. |
27 | uint8 | substitutePpemY | Vertical size of the existing strike to scale from. |
The two directions scale independently, so a square strike can become a non-square one. Each glyph’s metrics are scaled by the same factor as the size in that direction and rounded to the nearest whole pixel.
CBLC and CBDT
The colour versions have the same layout as EBLC and
EBDT, with version 3.0, and every EBDT format remains valid. bitDepth 32
means uncompressed pixels of blue, green, red and alpha bytes, premultiplied, in sRGB.
Three formats add PNG images:
| Format | Contents |
|---|---|
| 17 | SmallGlyphMetrics, uint32 dataLen, PNG data. |
| 18 | BigGlyphMetrics, uint32 dataLen, PNG data. |
| 19 | uint32 dataLen, PNG data; metrics from the index subtable. |
The PNG may contain only the IHDR, PLTE, tRNS, sRGB, IDAT and IEND chunks, is always treated as sRGB, and must be the size the metrics say. Where a size is missing, scaling down the nearest larger strike is recommended.
sbix
| Structure | Fields | Meaning |
|---|---|---|
| Header | uint16 version (1), uint16 flags, uint32 numStrikes, Offset32 strikeOffsets[numStrikes] | Flags: bit 0 always 1; bit 1 draw the outline over the bitmap (best left 0); others reserved. Offsets from the start of sbix. |
| Strike | uint16 ppem, uint16 ppi, Offset32 glyphDataOffsets[numGlyphs + 1] | The size and pixel density (such as 72 or 144) it was made for; offsets from the start of the strike, a zero length meaning no bitmap. |
| Glyph data | int16 originOffsetX, int16 originOffsetY, Tag graphicType, image bytes | Where the image’s left and bottom edges sit relative to the glyph origin (or, if the glyph has an outline, its bounding box corner), and the image. |
| graphicType | Meaning |
|---|---|
png | PNG image. |
jpg | JPEG image. |
tiff | TIFF image. |
dupe | The data is a uint16 glyph ID whose image to reuse. |
pdf , mask | Allowed by Apple’s TrueType specification; not supported in OpenType. |
If any strike has a bitmap for a glyph, that glyph is always drawn from some strike
when bitmaps are in use. Metrics still come from hmtx and
vmtx.
Example
Courier New (Courier New.ttf, macOS) has 18 strikes. The start of its
EBLC:
000A157C 00 02 00 00 00 00 00 12 00 00 03 68 00 00 00 18
000A158C 00 00 00 01 00 00 00 00 03 01 02 00 00 00 00 00
000A159C 03 FF 00 00 03 01 00 00 00 00 00 00 00 00 00 00
000A15AC 01 73 01 75 04 04 01 01 …
| Bytes | Meaning |
|---|---|
00 02 00 00 00 00 00 12 | Version 2.0; 18 strikes. |
00 00 03 68 00 00 00 18 00 00 00 01 | Strike 0: index list at 872, 24 bytes, one range. |
03 01 02 00 00 00 00 00 03 FF 00 00 | Horizontal line metrics: ascender 3, descender 1, widest glyph 2, max before baseline 3, min after −1. |
01 73 01 75 04 04 01 01 | Glyphs 371 to 373, 4 × 4 pixels per em, 1 bit per pixel, horizontal metrics. |
The index list at 872 is 01 73 01 75 00 00 00 08, then a subtable
00 03 00 02 00 00 00 04: index format 3, image format 2, images at
EBDT offset 4, with 2-byte offsets 0, 6, 12, 18, so 6 bytes per glyph.
In EBDT, glyph 371 is 03 01 01 03 02 A0: 3 rows, 1 column,
bearings 1 and 3, advance 2, then A0 = 1010 0000, bit-aligned
pixels on, off, on: a tiny colon. Glyph 372 is 04 02 00 03 02 66: 4 rows of
2 pixels from 0110 0110, alternating 01 and
10.