Skip to content

Font preview: coverage-accurate glyph repertoire (Font Book parity) #100

Description

@thalida

Follow-up to #99. The font specimen preview now renders a fixed Repertoire grid of common glyphs. A glyph the font lacks falls back to the browser default rather than being hidden, and glyphs the font does have beyond the fixed list aren't shown. This issue tracks making the grid coverage-accurate: show exactly the glyphs the font contains, like macOS Font Book, so nothing tofus and nothing is missing.

Approach

We already fetch the font's ArrayBuffer in FontPreview (fetchFileBytes), so the parse can happen client-side.

Core: read the font's own cmap table and render only the codepoints it maps.

  • opentype.js exposes parse(buffer).tables.cmap.glyphIndexMap (every mapped codepoint) for .ttf/.otf/.woff.
  • The catch: .woff2 (the primary format in Render a font specimen when previewing font files (.woff2/.woff/.ttf/.otf) #99, and the most common web font) is Brotli-compressed and opentype.js can't decompress it. You need either a woff2→sfnt wasm decoder (wawoff2, ~300 KB wasm) on top of opentype.js, or fontkit, which handles all formats incl. woff2 in one dependency (heavier).

Recommended shape

  • fontkit, lazy-loaded in a Web Worker. One dep covers ttf/otf/woff/woff2; lazy import() keeps it off the main bundle (previewing a font is rare); the worker keeps multi-MB parsing off the main thread (reuse the existing layout-worker pattern).
  • Extract → filter → group. From the codepoint list: drop control/whitespace/unassigned, then group by Unicode block with headers (Basic Latin, Latin-1 Supplement, ...) so it reads like Font Book's sectioned view instead of a flat wall.
  • Cap huge fonts, visibly. A CJK font can map 20k+ glyphs. Virtualize the grid, or cap with a labeled "showing N of M" note. No silent truncation.
  • Graceful fallback. On parse failure or an unsupported format, fall back to the current fixed repertoire. Strictly additive: never regresses what works today.

Edge cases (mostly free)

  • Variable / color fonts: cmap enumerates fine.
  • Ligatures / stylistic alternates reached via GSUB (not in cmap): Font Book's character view doesn't show these either, so parity holds.
  • Symbol/Mac cmap subtables: handle multiple platform/encoding records (fontkit does this).

Cost / open choices

  • Effort: ~1-1.5 days (dep + lazy-worker plumbing, cmap extraction, block grouping, virtualization/caps, fallback, tests).
  • Bundle: zero main-bundle cost; a lazy chunk (~few hundred KB) loads only when previewing a font.
  • Decisions: fontkit (all formats, heavier) vs opentype.js + woff2-wasm (modular, more glue); grouped-by-block vs flat grid; virtualize vs cap+note for giant fonts.

Recommendation: fontkit + lazy worker + block grouping + fallback — cleanest path to real Font Book parity across every format #99 names.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions