3.7 KiB
BinaryFontPacker
(no submodules)
Purpose
BinaryFontPacker converts a TypefaceFont (the typeface.js JSON structure) into a compact binary BTF (Binary TypeFace) buffer. It builds a shared integer dictionary from all unique coordinate values in the font and encodes every number as a 16-bit dictionary index rather than a string, dramatically reducing the payload compared to raw JSON.
The BTF format is designed for Three.js and game-engine font pipelines where fonts must be shipped as efficient binary assets rather than verbose JSON strings.
Features
- Dictionary-based compression: all unique integer values stored once in an
Int16Array; all subsequent references are 16-bit indexes - Full font round-trip: header strings, reversed flag, 9 scalar metrics, bounding box, per-glyph ha/x_min/x_max, and full outline data
- Supports all typeface.js command types:
m,l,b(cubic),q(quadratic),z - Little-endian byte layout throughout for cross-platform compatibility
- Wraps internal errors in
FontCompressErrorwith stable codePACK_FAILED
Usage: Basic Example
import { createBinaryFontPacker } from "@suaveplan/font-compress/packer/binary-font-packer";
import type { TypefaceFont } from "@suaveplan/font-convert";
const font: TypefaceFont = { /* ... */ };
const packer = createBinaryFontPacker();
const buffer: Uint8Array = packer.pack(font);
Usage: Advanced Example
import { BinaryFontPacker } from "@suaveplan/font-compress/packer/binary-font-packer";
import { FontCompressError } from "@suaveplan/font-compress";
const packer = new BinaryFontPacker();
try {
const packed = packer.pack(font);
// Write to disk, send over the wire, or store in IndexedDB
await Bun.write("font.btf", packed);
} catch (err) {
if (err instanceof FontCompressError) {
console.error("Pack failed:", err.code, err.message);
}
}
API Reference
BinaryFontPacker
pack(font: TypefaceFont): Uint8Array
Packs a TypefaceFont into a BTF binary buffer.
Parameters:
font— the typeface.js font object, as produced by@suaveplan/font-convert
Returns: Uint8Array containing the binary BTF data.
Throws: FontCompressError with code PACK_FAILED if packing fails for any reason.
createBinaryFontPacker(): BinaryFontPacker
Factory function that creates a new BinaryFontPacker instance.
Implementation Notes
BTF Binary Layout
[familyName: encodeString]
[cssFontWeight: encodeString]
[cssFontStyle: encodeString]
[reversed: uint8 (0 or 1)]
[dictLen: uint32 LE]
[dict: Int16Array × dictLen]
[metricsIdxs: Uint16Array × 9] ← ascender,descender,ulPos,ulThk,res,yMin,xMin,yMax,xMax
[glyphCount: uint32 LE]
per-glyph:
[charCode: uint32 LE]
[indexCount: uint32 LE]
[indexes: Uint16Array × indexCount] ← ha,x_min,x_max, then (cmd_byte+coord_indexes)...
encodeString format: [uint32 length LE][UTF-8 bytes].
Command bytes map to: 0=m, 1=l, 2=b, 3=q, 4=z. Coordinate counts per command: m=2, l=2, b=6, q=4, z=0.
Dictionary Construction
All unique coordinate values across the entire font (metrics, bounding box, all glyph coordinates) are collected into a sorted Int16Array. This single pass over the font data is O(n) in glyph count and produces optimal deduplication. Because typeface.js coordinates are integers in a bounded range (typically ±2048), the dictionary fits comfortably in an Int16Array.
Alignment
All multi-byte typed arrays are written via Uint8Array byte copies, not direct TypedArray buffer views, so there are no alignment requirements on the output buffer. Readers (BinaryFontUnpacker) use DataView to safely read values at arbitrary offsets.