oxideav-scribe
Pure-Rust vector font shaper + line layout for the
oxideav framework. Parses TTF / OTF
tables (via oxideav-ttf
oxideav-otf) and emits positioned glyphs asoxideav-coreNodevectors ready for the rasterizer inoxideav-raster.
Scribe contains no pixel kernel: outline flattening, scanline AA,
alpha compositing, synthetic bold and stroke dilation all live in
oxideav-raster. Producing a rasterised text run is a two-step pipeline:
use ;
use Renderer;
use ;
let bytes = read?;
let face = from_ttf_bytes?;
let chain = new;
// 1. Shape: emit positioned vector glyph nodes.
let placed = shape_to_paths;
// 2. Wrap into a VectorFrame + render via oxideav-raster.
let mut root = default;
for in placed
let mut frame = new;
frame.root = root;
let rgba: VideoFrame = new.render;
Capabilities
- Outline access —
Face::glyph_path(gid)returns a Y-upoxideav_core::Path(rawMoveTo/LineTo/QuadCurveTo/CubicCurveTo/Close). TT outlines decode quadratics; CFF charstrings decode cubics 1:1.Face::glyph_node(gid, size_px)bakes the Y-flip + scale into a render-readyNode::Path(orNode::Imagefor CBDT colour glyphs). - Shaper —
cmap+ GSUB type 4 (ligatures) + GPOS type 2 (pair kerning) + GPOS type 4/5/6 (mark-to-base, mark-to-mark stacking), enough for Latin / Cyrillic / Greek / basic CJK / Vietnamese / polytonic Greek. - Arabic contextual joining (round 7) —
shaping::arabicpicksisol/init/medi/finaper character via the Unicode joining-class state machine;FaceChain::shaperewrites Arabic letters into their Presentation Forms-B equivalents (U+FE70..U+FEFF) before cmap so cmap-only fonts render the visually-correct contextual shapes (including LAM-ALEF ligatures via the existing GSUB pass). - Indic complex-script shaping (rounds 8 + 10) —
shaping::indicclassifies Devanagari (U+0900..U+097F), Bengali (U+0980..U+09FF), and Tamil (U+0B80..U+0BFF) codepoints, segments runs into orthographic clusters, applies per-script pre-base matra reorder (Devanagari U+093F; Bengali U+09BF / U+09C7 / U+09C8; Tamil U+0BC6 / U+0BC7 / U+0BC8), and identifies reph (leading RA + halant + consonant — Devanagari + Bengali only; Tamil RA does not form a reph). When the active face publishes arphfGSUB lookup for the active script, the leading RA glyph is rewritten to its reph form viaFont::gsub_apply_lookup_type_1and the halant glyph is dropped (round 10). Per-script reorder rules are exposed asDEVANAGARI_RULES/BENGALI_RULES/TAMIL_RULESfor callers wanting to reuse the cluster machine on additional Indic scripts. - Variable fonts (round 9) —
Face::set_variation_coords/variation_axes/named_instances/is_variablesurface the font'sfvardeclarations and let callers shape against a custom axis-coord vector (e.g.wght=600 / wdth=125on Inter Variable).Shaper::with_variation_coords(vec![..]).shape_to_paths(&mut chain, text, size_px)is the per-call override path: it installs the coords on the primary face, runs the shape, then restores. Glyph outlines flow throughoxideav-ttf's gvar interpolator so the emittedPathcarries the blended deltas. CFF2 / OTF variable fonts are deferred untiloxideav-otfexposes a CFF2 variation pipeline. - Vector text API —
Shaper::shape_to_pathsreturns one(face_idx, Node, Transform2D)per visible glyph. Each node is wrapped in anoxideav_core::Group { cache_key: Some(_), .. }so the downstream rasterizer's bitmap cache memoises the rendered glyph across renders, frames, and renderer instances. - Italic synthesis —
style.italicsynthesises a 12° forward shear when the face is upright; falls back to the font's own slant when one is present. Bold synthesis is deferred to consumer code (or a real Bold face). - Face chain — multi-face fallback for missing codepoints; per-glyph
face_idxtells the consumer which face owns each glyph. - CBDT/CBLC colour bitmaps — Noto Color Emoji and friends decode to
Node::Imagecarrying aVideoFrame; the resampling to the requested size happens in scribe (bilinear, straight-alpha). - Layout — line measurement + word-wrap (no bidi; round-3 work).
Out of scope
- Pixel work — bitmap rasterisation, alpha compositing, synthetic
bold dilation, stroke dilation. All in
oxideav-raster. - Bidi (UAX #9), remaining Indic scripts (Telugu, Gujarati,
Gurmukhi, Kannada, Malayalam, Oriya — same pattern as Bengali /
Tamil with per-script categorisation tables), variable-font
metrics (
MVAR/HVAR/VVAR/STAT), CFF2 variable fonts, TrueType bytecode hinting, subpixel LCD filtering, GPOS cursive attachment — deferred.
Test fixtures
Reuses crates/oxideav-ttf/tests/fixtures/DejaVuSans.ttf plus
DejaVuSansMono.ttf (Bitstream Vera license),
crates/oxideav-otf/tests/fixtures/SourceSans3-Regular.otf (SIL OFL),
and a vendored copy of InterVariable.ttf (SIL OFL — see
tests/fixtures/INTER-OFL-LICENSE.txt) for the round-9 variable-font
suite. Network-gated emoji/CJK fixtures fetch on demand; see
tests/font_fixtures/ and run with OXIDEAV_NETWORK_TESTS=1.
License
MIT — see LICENSE.