oxideav-ttf
Pure-Rust TrueType font parser for the oxideav framework. Implements the sfnt container, the core OpenType tables, and just enough of GSUB / GPOS to do Latin/Cyrillic/Greek/CJK shaping with ligatures and kerning.
Round-1 scope (this release)
- sfnt + table directory walker.
head,hhea,maxp,cmap(base formats 0, 4, 6, 12 + format 14 Unicode Variation Sequences as a sidecar),name,OS/2,hmtx,loca,glyf(simple + composite),post.- Legacy
kerntable (format 0). GSUBLookupType 1 (single substitution: positional forms, small-caps, vertical alternates), LookupType 2 (multiple substitution — split one input glyph into N), LookupType 3 (alternate substitution —aalt/saltper-coverage alternates), LookupType 4 (ligature substitution — exposed both as a "walk every lookup" helper and as a lookup-index-specific apply path for feature-driven shaping ofliga/rlig/dlig), LookupType 5 (contextual substitution — formats 1 / 2 / 3, predecessor of LT6 minus backtrack/lookahead), LookupType 6 (chained contexts substitution — formats 1 / 2 / 3, with recursive dispatch into nested LookupType 1 / 2 / 3 / 4 / 5 / 6 sub-lookups), and LookupType 8 (reverse chained context single substitution — used by some Arabic fonts). All sit behind a ScriptList / FeatureList walk so callers can ask "which lookup indices implement featureinitfor scriptarab?"GPOSLookupType 1 (single positioning — formats 1 + 2), LookupType 2 (pair-adjustment / kerning), LookupType 3 (cursive attachment — entry/exit anchor pairs for Arabic Nastaliq + script-font cursive chaining), LookupType 4 (mark-to-base attachment), LookupType 5 (mark-to-ligature attachment — closes thefi-ligature + above-mark gap), LookupType 6 (mark-to-mark stacking), and LookupType 8 (chained-context positioning — formats 1 / 2 / 3, with nested LT 1 / 2 / 3 / 4 / 6 / 8 dispatch). ExtensionPos (LookupType 9) is unwrapped transparently — both at the sub-table level (a LT-9 sub-table inside any lookup) and at the lookup level (a whole lookup whoselookupTypeis 9 wrapping any of the supported inner types).Font::gpos_lookup_list()+Font::gsub_lookup_list()enumerate every lookup as(index, effective_type, subtable_count)for shapers that need to find e.g. every chained-context lookup without probing each index.GDEF(glyph class definitions, used to skip mark glyphs).
The companion oxideav-scribe
crate consumes the outlines + shaping output to rasterise text to RGBA
bitmaps for subtitles and the scene compositor.
Public API
use Font;
let bytes = read?;
let font = from_bytes?;
// Metadata.
let _ = font.family_name; // Some("DejaVu Sans Mono")
let _ = font.units_per_em; // 2048
let _ = font.glyph_count;
let _ = font.ascent;
let _ = font.descent;
let _ = font.line_gap;
// Glyph lookup.
let gid_a = font.glyph_index.unwrap;
let _ = font.glyph_advance; // i16 advance width in font units
let _ = font.glyph_lsb;
let _ = font.glyph_bounding_box;
let _ = font.glyph_outline?; // contours of i16 points
// Shaping helpers.
let gid_f = font.glyph_index.unwrap;
let gid_i = font.glyph_index.unwrap;
if let Some = font.lookup_ligature
let gid_v = font.glyph_index.unwrap;
let _ = font.lookup_kerning; // negative i16 in font units
// GSUB feature-tagged lookups (Arabic positional forms, small-caps, …).
// Discover which lookup indices implement `init` for script `arab`,
// then apply LookupType 1 to a single glyph id.
for feat in font.gsub_features_for_script
// LookupType 4 — ligature substitution dispatched per-feature.
// Resolve the `liga` feature for `latn` and apply each of its
// LookupType-4 lookups to a glyph run; the apply method returns
// (replacement_gid, consumed_count) on a hit.
for feat in font.gsub_features_for_script
// LookupType 6 — chained-context substitution. Returns the rewritten
// run starting at `pos` (or None when no chain rule matches the
// (backtrack, input, lookahead) window). Formats 1 (glyph sequence),
// 2 (class-based) and 3 (coverage-based) are all supported.
for feat in font.gsub_features_for_script
// LookupType 2 — multiple substitution. Splits one input glyph into a
// sequence of replacement glyphs (e.g. some script normalisations that
// expand a precomposed glyph into base + mark cluster).
let some_gid = 42u16;
if let Some = font.gsub_apply_lookup_type_2
// LookupType 3 — alternate substitution. Each covered glyph carries an
// AlternateSet of alternates; the caller picks an index. Used by `aalt`
// / `salt` features.
for feat in font.gsub_features_for_script
// LookupType 5 — contextual substitution (LT6 minus backtrack/lookahead).
// Same return shape as LookupType 6.
for feat in font.gsub_features_for_script
// LookupType 8 — reverse chained context single substitution. Returns
// the replacement gid for `gids[pos]` when the (backtrack, input,
// lookahead) coverage triple matches. The spec mandates reverse-text
// processing: a higher-level shaper walks `pos` from right to left.
for feat in font.gsub_features_for_script
// GPOS LookupType 1 — single-glyph positioning. Returns four signed
// i16 deltas: x_placement / y_placement / x_advance / y_advance. Used
// by features like `cpsp` (capital spacing).
for in font.gpos_lookup_list
// GPOS LookupType 3 — cursive attachment. Returns a CursiveAttachment
// with (entry, exit) anchor points (each Option). Chain glyph N+1's
// entry onto glyph N's exit: per-glyph delta = prev.exit - this.entry.
if let Some = font.lookup_cursive_attachment
// GPOS LookupType 5 — mark-to-ligature attachment. Pick the ligature
// component the mark sits over (0-indexed: 0 = first component, etc.).
// Returns (dx, dy) to shift the mark's pen origin.
if let Some = font.glyph_index
// GPOS LookupType 8 — chained-context positioning. Returns a Vec of
// PosRecord(absolute glyph index, four-field PosValue). The shaper
// folds these deltas into its own glyph-position state.
for in font.gpos_lookup_list
// LookupList enumeration — find every lookup of a given (effective,
// post-extension-unwrap) type without probing each index in turn.
let chain_pos_lookups: = font
.gpos_lookup_list
.into_iter
.filter_map
.collect;
let _ = chain_pos_lookups;
// Unicode Variation Sequences (cmap format 14). Used by emoji
// presentation selectors and registered IVS for CJK.
let _ = font.lookup_variation; // grinning face + VS-16
// Colour glyphs — three families covered:
//
// COLR/CPAL: vector layer stack (Microsoft Segoe UI Emoji, Twemoji-Mozilla, …)
// CBDT/CBLC: PNG-payload bitmap strikes (Noto Color Emoji and friends)
// sbix: Apple-style PNG/JPEG bitmap strikes (Apple Color Emoji)
//
if font.has_color_layers
if font.has_color_bitmaps
if font.has_sbix
// TTC (TrueType Collection) — pick one subfont from a `.ttc` file.
let _ = is_collection;
let _ = from_collection_bytes;
// Variable fonts (fvar / avar / gvar). Pick a coord vector in
// user-space units (e.g. wght 100..900); glyph_outline() then
// returns the gvar-deltad outline.
let mut vfont = from_bytes?;
if vfont.is_variable
Out of scope (round 2+)
- CFF / Type 2 charstrings — moves to a sibling
oxideav-otfcrate. - Bidi, Arabic shaping, Indic conjuncts, complex contextual GSUB/GPOS.
- TrueType bytecode hinting (modern AA at ≥ 16 px does not need it).
- cmap formats 2, 8, 10, 13.
- All GPOS lookup types except LookupType 7 (the now-fully-handled LookupType 9 ExtensionPos wrapper plays its role) are implemented: 1 (single), 2 (pair), 3 (cursive attachment), 4 (mark-to-base), 5 (mark-to-ligature), 6 (mark-to-mark), 8 (chained context with nested LT 1/2/3/4/6/8 dispatch). All seven public GSUB lookup types (1 single, 2 multiple, 3 alternate, 4 ligature, 5 contextual, 6 chained context, 8 reverse chained context) are implemented; ExtensionSubst LookupType 7 (GSUB) and ExtensionPos LookupType 9 (GPOS) are unwrapped transparently for every type both at the sub-table and lookup level.
- COLR v1 paint graph (gradients, transforms, composites) — only the v0 flat layer stack is supported.
- sbix
'dupe'chasing (the indirection sentinel is surfaced as-is; consumers chase it with their own cycle detection). - avar v2 delta-set index map (variable-axis remap).
- HVAR / VVAR / MVAR (per-glyph horizontal-metrics / vertical-metrics / per-table metric variations).
- gvar delta propagation into composite-glyph component offsets and the four phantom points.
Test fixtures
tests/fixtures/DejaVuSansMono.ttfis the upstream DejaVu Sans Mono 2.37 under the Bitstream Vera license (seetests/fixtures/DEJAVU-LICENSE).tests/fixtures/InterVariable.ttfis Inter 4.0 (variable font,wght+opszaxes) under the SIL Open Font License 1.1 (seetests/fixtures/INTER-OFL-LICENSE.txt).tests/fixtures/NotoSansArabic-Regular.ttfis Noto Sans Arabic 2022 (used to exercise GSUB feature-tagged single substitution for thearabscript's positional joining forms) under the SIL Open Font License 1.1 (seetests/fixtures/NOTO-ARABIC-OFL-LICENSE.txt).
License
MIT — see LICENSE.