- 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.
- 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.
- 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/vsindexresolution 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 staticglyf. - COLR v1 color fonts – the full paint graph: linear/radial/sweep gradients, transforms, Porter-Duff composition, recursive
PaintColrGlyph/PaintGlyph, and variable paints resolved againstItemVariationStore. 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
JstfPrioritymodification lists, wired intorustybuzz::Featuretoggling via a feature-tag heuristic forshape_justified. - STAT, BASE, VORG, SVG-in-OpenType – style-linking axis/value taxonomy, script baseline positions, vertical origin (with the spec-correct
vmtx+glyfderivation forglyf-outline fonts), and raw SVG document extraction. taerizer::cpu– a from-scratch, zero-unsafeCPU 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 itsFontvalues 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-decompressorfor a format most modern pipelines already unwrap upstream; dropping it keeps the dependency tree to justrustybuzz. - The wasm-bindgen JS bindings are gone.
native_api::Fontreplaces 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, andcategoriesno longer mention wasm or WOFF2; the crate isrlibonly (nocdylib), with an optionalstdfeature forno_stdtargets.
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-fuzztargets (table extraction, TTC handling, subsetting, instancing, cmap lookup, COLR v1 paint resolution) run against real font corpora. - Property-based testing via
proptestfor 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 aHashMapto a linear-scanVec: real charstrings only ever see a handful of distinctvsindexvalues, so hashing cost more than it saved. gvarreuses 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