@suaveplan/font-decompress - BTF (Binary TypeFace) binary unpacking. Reverses @suaveplan/font-compress's BinaryFontPacker output back into typeface.js JSON, ready for Three.js / R3F / game-font rendering pipelines. Universal.
BTF (Binary TypeFace) binary unpacking. Reverses
@suaveplan/font-compress's BinaryFontPacker output into a
typeface.js JSON shape ready for Three.js / R3F / game-font
rendering. Universal, store-agnostic, free of node: / bun:
imports.
Documentation tree
- error-codes — The
@suaveplan/font-decompresspackage centralises every failure mode it can produce behind a single registry built w…- error-codes — The
@suaveplan/font-decompresspackage centralises every failure mode it can produce behind a single registry built w…
- error-codes — The
- binary-font-unpacker —
BinaryFontUnpackerreverses the BTF (Binary TypeFace) wire format produced byBinaryFontPackerfrom `@suaveplan/fon…- binary-font-unpacker —
BinaryFontUnpackerreverses the BTF (Binary TypeFace) wire format produced byBinaryFontPackerfrom `@suaveplan/fon…
- binary-font-unpacker —
- utils —
decodeStringreads a length-prefixed UTF-8 string from aUint8Arrayat a given offset. The BTF wire format encodes…- decode-string —
decodeStringreads a length-prefixed UTF-8 string from aUint8Arrayat a given offset. The BTF wire format encodes…
- decode-string —
Purpose
Compressed BTF buffers ship from build-time tooling to the renderer
as compact Uint8Array blobs — they are far smaller than the
underlying typeface.js JSON for non-trivial fonts. The renderer needs
the JSON back to hand to Three.js's FontLoader.parse(...). This
package owns that reverse step; the sibling @suaveplan/font-compress
owns the forward step.
The split exists because pack and unpack are independent concerns: build tooling never unpacks, runtime renderers never pack. Shipping a unified package forces consumers to drag the other half. Splitting lets each side install only what it actually executes.
Features
BinaryFontUnpackerclass +createBinaryFontUnpacker()factory- Strict boundary validation on every read — raises
FontDecompressErrorwithFONT_DECOMPRESS.INVALID_DATA - Underlying primitive exceptions (DataView, TextDecoder) wrapped as
FontDecompressErrorwithFONT_DECOMPRESS.UNPACK_FAILEDandcausepreserved - All five BTF glyph commands (
m/l/b/q/z) round-trip byte-for-byte - Unicode glyph keys (multi-byte UTF-8) round-trip correctly
- Negative coordinates round-trip correctly
- 100% statement / branch / function / line Istanbul coverage
- 5 tree-shakeable subpath exports
Usage: Basic
import { createBinaryFontUnpacker } from "@suaveplan/font-decompress";
const unpacker = createBinaryFontUnpacker();
const font = unpacker.unpack(btfBuffer);
console.log(font.familyName); // "Inter Variable"
console.log(font.glyphs["A"]?.ha); // glyph advance width
Usage: Advanced
import {
BinaryFontUnpacker,
FONT_DECOMPRESS_CODES,
FontDecompressError,
} from "@suaveplan/font-decompress";
// Reuse a single instance — stateless and safe.
const unpacker = new BinaryFontUnpacker();
async function loadCdnFont(url: string) {
const buf = new Uint8Array(
await (await fetch(url)).arrayBuffer(),
);
try {
return unpacker.unpack(buf);
} catch (err) {
if (
err instanceof FontDecompressError &&
err.code === FONT_DECOMPRESS_CODES.INVALID_DATA
) {
console.warn("Corrupted BTF from CDN:", err.message);
return null;
}
throw err;
}
}
API Reference
Public exports
class BinaryFontUnpacker—unpack(data: Uint8Array): TypefaceFontcreateBinaryFontUnpacker(): BinaryFontUnpackerFONT_DECOMPRESS_CODES— frozen registry withUNPACK_FAILED,INVALID_DATAclass FontDecompressError extends SuaveplanError<FontDecompressErrorCode>type FontDecompressErrorCode
The TypefaceFont and PathCommand types come from
@suaveplan/font-convert; consumers import them directly from there
rather than via this package's surface.
Subpath exports
| Subpath | What |
|---|---|
. |
Root barrel (above) |
./error-codes |
FONT_DECOMPRESS_CODES, FontDecompressError |
./constants |
BTF wire-format constants |
./utils/decode-string |
decodeString helper |
./unpacker/binary-font-unpacker |
BinaryFontUnpacker, factory |
Implementation Notes
The package is universal: zero node: / bun: imports
anywhere in src/. The only platform-aware calls are DataView,
TextDecoder, and String.fromCharCode — all available in every
supported runtime (Node ≥ 18, Bun, modern browsers, Web Workers).
The BTF wire-format constants (CMD_M … CMD_Z, BYTE_TO_CMD,
CMD_COORD_COUNTS, METRICS_COUNT) are duplicated from
@suaveplan/font-compress. Duplicating 19 lines of magic numbers
avoids a third "fonts-shared" package and keeps each package
self-contained. If the BTF format ever changes — which is a
coordinated breaking event — both packages get updated in the same
commit.
@suaveplan/font-compress is a devDependency for round-trip
tests only. The runtime dependency graph is font-decompress → font-convert + error; the test surface adds font-compress solely
to generate known-vector fixtures.