Skip to content

Taetype

Developer Productivity

A pure‑Rust font engine for decoding, subsetting, instancing, and shaping TTF/OTF/TTC/WOFF2 fonts that runs as WebAssembly or a native library

Rust Latest v1.0.0 · 6h ago Security brief →

Features

  • Decode full table directories of TTF, OTF, TTC (no fixed allowlist)
  • Custom WOFF2 Brotli decompression in Rust
  • Full OpenType Font Variations instance support (`fvar`, `avar`, etc.)
  • TrueType and CFF subsetting with glyph‑level precision
  • GSUB/GPOS shaping via rustybuzz for ligatures, kerning, complex scripts

Recent releases

View all 4 releases →
v1.0.0 Breaking risk
⚠ Upgrade required
  • Replace any JS usage of the former wasm‑bindgen bindings with direct calls to `native_api::Font`.
  • Update pipeline steps that pass WOFF2 files; decompress upstream or convert to OTF before feeding Taetype.
Breaking changes
  • WOFF2 input is no longer supported (removes `brotli-decompressor` dependency).
  • The wasm‑bindgen JS bindings are gone; migrate to the new pure‑Rust `native_api::Font` API.
  • Package metadata updated: description, keywords, categories no longer mention wasm or WOFF2; crate is now `rlib` only with an optional `std` feature.
Notable features
  • CFF2 variable fonts – full parsing, blend resolution, subroutine inlining and instance‑to‑CFF1 conversion.
  • COLR v1 color fonts – complete paint graph including gradients, transforms, Porter‑Duff composition and recursive glyph painting with subsetting dependency tracking.
  • MATH table support – all 56 constants, per‑glyph italics correction, top‑accent attachment, subscript/superscript kerning and growable‑glyph construction for stretchy delimiters.
Full changelog

taetype 1.0.0 is the first release built to be a complete font engine, not a subsetting utility with extras bolted on. Every table format, every table, and every code path below is real, exercised by real fixture fonts, and covered by tests — see Verification in the README for exactly how that's checked.

New

  • CFF2 variable fonts – Top DICT/FDArray/FDSelect parsing, blend/vsindex resolution against an axis location, full subroutine inlining. A CFF2 font instances to a static CFF1 table the same way a TrueType variable font instances to static glyf.
  • COLR v1 color fonts – the full paint graph: linear/radial/sweep gradients, transforms, Porter-Duff composition, recursive PaintColrGlyph/PaintGlyph, and variable paints resolved against ItemVariationStore. Subsetting chases v0 layer and v1 paint dependencies through a shared fixed-point closure with GSUB, so a color reference never gets left with a blanked-out glyph.
  • MATH table – all 56 constants, per-glyph italics correction and top-accent attachment, sub/superscript kerning, and growable-glyph construction for stretchy delimiters.
  • JSTF – extender glyphs and JstfPriority modification lists, wired into rustybuzz::Feature toggling via a feature-tag heuristic for shape_justified.
  • STAT, BASE, VORG, SVG-in-OpenType – style-linking axis/value taxonomy, script baseline positions, vertical origin (with the spec-correct vmtx+glyf derivation for glyf-outline fonts), and raw SVG document extraction.
  • taerizer::cpu – a from-scratch, zero-unsafe CPU rasterizer. Turns any outline (TrueType or CFF/CFF2, at any instanced axis position) into a grayscale anti-aliased coverage bitmap with no third-party rasterizer dependency.
  • A schema-driven GSUB/GPOS/GDEF subsetting engine – every real lookup type (GSUB 1–8, GPOS 1–9, GDEF's five subtables) now subsets through one generic parse/build engine driven by declarative shape descriptions, instead of a hand-written function per lookup type. Differentially verified against the hand-written implementations it replaced, which are kept on as a standing test oracle.
  • A plain-Rust public API (native_api::Font) – no global registry, no wasm-bindgen; a caller owns its Font values directly and it works the same whether you're targeting native or wasm32.

Breaking changes

  • WOFF2 input is no longer supported. Decompression pulled in brotli-decompressor for a format most modern pipelines already unwrap upstream; dropping it keeps the dependency tree to just rustybuzz.
  • The wasm-bindgen JS bindings are gone. native_api::Font replaces the old registry-based API. If you were calling taetype from JS through the generated bindings, this is a real migration, not a drop-in swap.
  • Package metadata changed to match: description, keywords, and categories no longer mention wasm or WOFF2; the crate is rlib only (no cdylib), with an optional std feature for no_std targets.

Verification

  • 1,400+ unit and integration tests.
  • Differential testing against real fontTools for decoding, instancing, and subsetting — variable fonts, CID-keyed CFF, COLR v0/v1, CBDT/sbix bitmaps, MATH tables — checked byte-for-byte or value-for-value.
  • Fuzzing – six cargo-fuzz targets (table extraction, TTC handling, subsetting, instancing, cmap lookup, COLR v1 paint resolution) run against real font corpora.
  • Property-based testing via proptest for invariants that need to hold across the whole input space, not just fixed cases.
  • Real sanitizer validation – demo and differential-test output fonts are checked with opentype-sanitizer (OTS), the same sanitizer Chromium uses to reject malformed fonts.
  • Mutation testing on parsing/bounds-checking logic via cargo-mutants.

#![forbid(unsafe_code)] is enforced at the crate root on every path above — a crafted or malicious font file cannot corrupt memory in this crate, full stop.

Internals

  • CFF2's blend-scalar cache switched from a HashMap to a linear-scan Vec: real charstrings only ever see a handful of distinct vsindex values, so hashing cost more than it saved.
  • gvar reuses its per-glyph delta buffers across the whole instancing pass instead of reallocating them per glyph.

Full diff: https://github.com/silly-tae/taetype/compare/v0.1.3...v1.0.0

No immediate action
v0.1.3 Bug fix

post table fix

No immediate action
v0.1.1 New feature

OpenType font engine

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

About

Stars
16
Forks
1
Languages
Rust JavaScript
Downloads/week
269
NPM Maintainers
1 Single npm maintainer
TypeScript
Types included ✓

Install & Platforms

Install via
npm cargo

Beta — feedback welcome: [email protected]