Skip to content

OxideAV/oxideav-scribe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oxideav-scribe

Pure-Rust vector font shaper + line layout for the oxideav framework. Parses TTF / OTF tables (via oxideav-ttf

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 oxideav_core::{Group, Node, VectorFrame};
use oxideav_raster::Renderer;
use oxideav_scribe::{Face, FaceChain, Shaper};

let bytes  = std::fs::read("DejaVuSans.ttf")?;
let face   = Face::from_ttf_bytes(bytes)?;
let chain  = FaceChain::new(face);

// 1. Shape: emit positioned vector glyph nodes.
let placed = Shaper::shape_to_paths(&chain, "Hello, world!", 16.0);

// 2. Wrap into a VectorFrame + render via oxideav-raster.
let mut root = Group::default();
for (_face_idx, glyph_node, transform) in placed {
    root.children.push(Node::Group(Group {
        transform,
        children: vec![glyph_node],
        ..Group::default()
    }));
}
let mut frame = VectorFrame::new(400.0, 80.0);
frame.root = root;
let rgba: oxideav_core::VideoFrame = Renderer::new(400, 80).render(&frame);

Capabilities

  • Outline accessFace::glyph_path(gid) returns a Y-up oxideav_core::Path (raw MoveTo / 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-ready Node::Path (or Node::Image for CBDT colour glyphs).
  • Shapercmap + 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.
  • Vector text APIShaper::shape_to_paths returns one (face_idx, Node, Transform2D) per visible glyph. Each node is wrapped in an oxideav_core::Group { cache_key: Some(_), .. } so the downstream rasterizer's bitmap cache memoises the rendered glyph across renders, frames, and renderer instances.
  • Italic synthesisstyle.italic synthesises 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_idx tells the consumer which face owns each glyph.
  • CBDT/CBLC colour bitmaps — Noto Color Emoji and friends decode to Node::Image carrying a VideoFrame; 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), Arabic shaping, Indic conjunct formation, variable fonts, TrueType bytecode hinting, subpixel LCD filtering — deferred.

Test fixtures

Reuses crates/oxideav-ttf/tests/fixtures/DejaVuSans.ttf plus DejaVuSansMono.ttf (Bitstream Vera license) and crates/oxideav-otf/tests/fixtures/SourceSans3-Regular.otf (SIL OFL). Network-gated emoji/CJK fixtures fetch on demand; see tests/font_fixtures/ and run with OXIDEAV_NETWORK_TESTS=1.

License

MIT — see LICENSE.

About

Pure-Rust font rasterizer + shaper + layout for the oxideav framework

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages