Drawing text is the last thing every Rust app reaches for C for — and it shouldn’t be.
Today we’re releasing OxiText 0.2.0 — the COOLJAPAN Pure-Rust text pipeline that takes a Unicode string all the way to pixels: shape → bidi-reorder → line-break → layout → rasterize.
No HarfBuzz. No FriBidi. No ICU C library. No FreeType. No FFI, no -sys crates, not even an opt-in native escape hatch. OxiText is composed entirely from mature Pure-Rust crates, so it builds as a single static binary, needs no system libraries and no C toolchain at build time, and stays headless-testable and WASM-friendly by design.
Why OxiText
Text rendering is deceptively hard, and for decades that difficulty has been outsourced to a stack of C/C++ libraries that every GUI, document, and graphics project ends up linking:
- HarfBuzz to shape glyphs (turn characters into positioned glyph IDs with GSUB/GPOS applied),
- FriBidi to reorder right-to-left and bidirectional runs,
- ICU to find word and line break opportunities according to Unicode,
- FreeType to rasterize outlines into coverage bitmaps.
Each of those is a separate -sys crate, a separate build-time dependency, a separate surface for memory-safety bugs, and a separate reason your binary won’t cross-compile cleanly or run in the browser. OxiText replaces the whole chain. It’s the typography backbone for the COOLJAPAN ecosystem — and because it’s 100% Pure Rust, the same code path renders text on Linux, macOS, Windows, and WASM with no native libraries underneath.
What we built
OxiText is a 3-stage pipeline — shape → layout → raster — split into focused workspace crates so you only pull in what you draw with:
1. Shape (oxitext-shape)
Converts Unicode text into a ShapedRun of glyphs with advances, clusters, and GSUB/GPOS applied. The primary backend is swash; rustybuzz is opt-in for HarfBuzz test-suite parity. Shaping covers Arabic, Devanagari, Thai, CJK, and Latin, with script detection helpers (requires_arabic_shaping, requires_indic_shaping, requires_mark_positioning) driving automatic, script-based font fallback chains. It also supports OpenType variable-font axes and keeps a per-Pipeline LRU shape cache keyed on the font pointer plus the text.
2. Layout (oxitext-layout)
Reorders bidirectional text per UAX #9 (full right-to-left and mixed-direction support), breaks runs into lines per UAX #14 (word-aware greedy wrapping with mandatory breaks and hyphenation), aligns them (Left, Right, Center, Justify), and computes PositionedGlyph screen coordinates. Vertical text follows UAX #50 — upright/rotated classification and tate-chu-yoko. When you want CLDR-accurate break opportunities, oxitext-icu plugs in as an opt-in source.
3. Raster (oxitext-raster)
Renders each positioned glyph to a coverage bitmap via fontdue (primary), with ab_glyph and swash (TrueType hinting) as opt-in alternates. It does subpixel rendering (quarter-pixel positioning plus LCD 3-tap / 5-tap FIR filtering) and color glyphs: COLRv0, COLRv1 gradients, CBDT/CBLC bitmaps, and SVG via resvg.
Two more crates round out the pipeline:
oxitext-sdfgenerates GPU-ready text atlases — single-channel SDF, MSDF, MTSDF, analytic variants, and GPU descriptors — from the same bitmaps, so OxiUI/wgpu can render glyphs on the GPU.oxitext-icubrings ICU4X in (100% Pure Rust) for CLDR segmentation, Unicode collation, and NFC/NFD/NFKC/NFKD normalization.
Everything sits behind a thin facade crate, oxitext, whose Pipeline ties the layers together: measure, shape_and_layout, render_to_image, and composite_to_rgba.
Getting Started
Add the facade crate:
cargo add oxitext
Or in Cargo.toml:
[dependencies]
oxitext = "0.2.0"
Then measure a string and rasterize it to pixels:
use oxitext::{Pipeline, prelude::*};
let font_data = std::fs::read("my-font.ttf")?;
let pipeline = Pipeline::from_bytes(&font_data)?;
// Measure a string
let metrics = pipeline.measure("Hello, world!", &TextStyle::default())?;
println!("width={:.1} height={:.1}", metrics.width, metrics.height);
// Shape, lay out, and rasterize to RGBA pixels
let result = pipeline.render_to_image("Hello, OxiText!", &TextStyle::default())?;
println!("{} lines, {}x{} pixels", result.lines.len(), result.width, result.height);
That single Pipeline runs the whole shape → layout → raster chain for you — no HarfBuzz handle, no FreeType face, no ICU break iterator to wire up by hand.
Highlights
- Full pipeline in one call —
Pipeline::measure,shape_and_layout,render_to_image,composite_to_rgba. - Complex-script shaping — Arabic, Devanagari, Thai, CJK, and Latin via swash, with rustybuzz available for HarfBuzz parity.
- UAX #9 bidi — full right-to-left and bidirectional reordering.
- UAX #14 line-breaking — word-aware greedy wrapping, mandatory breaks, and hyphenation, with four alignment modes.
- Vertical text (UAX #50) — upright/rotated classification and tate-chu-yoko.
- High-quality rasterization — fontdue by default; subpixel quarter-pixel positioning with LCD 3-tap / 5-tap FIR filtering.
- Color glyphs — COLRv0, COLRv1 gradients, CBDT/CBLC bitmaps, and SVG.
- GPU atlases — SDF, MSDF, MTSDF, and analytic variants from
oxitext-sdf. - ICU4X integration — CLDR segmentation, Unicode collation, and NFC/NFD/NFKC/NFKD normalization, all Pure Rust.
- Variable fonts and a per-Pipeline LRU shape cache for fast repeated layout.
Tips
- Stay lean by default. The default
purefeature enablesoxitext-shapeandoxitext-raster— enough to shape and rasterize. Add capability features only when you need them. - Turn on
icufor CLDR-accurate word and line segmentation (and Unicode collation/normalization) when locale-correct breaking matters. - Enable
sdfwhen you’re feeding a GPU text renderer — it produces SDF/MSDF/MTSDF atlas tiles ready for OxiUI/wgpu. - Flip on
simdto take thewidef32x8 hot-loops in the rasterizer and SDF generator; pair withparallelfor Rayon-based batch shaping. - Pick a rasterizer per platform. fontdue is the default; the
swash-backendsub-feature adds TrueType hinting andab-glyph-backendcan give sharper hints on some platforms. Usesvg-backendfor SVG color glyphs. - Reach for
rustybuzz-backendif you need HarfBuzz-compatible shaping behavior (for example to match a HarfBuzz test corpus), andsystem-fontsto load installed fonts through oxifont-db for fallback.
Part of the COOLJAPAN ecosystem
OxiText is part of NoFFI — the COOLJAPAN initiative to replace every C/C++/Fortran/-sys FFI dependency in the Rust ecosystem with a clean, memory-safe, 100% Pure-Rust implementation. Where the native world reaches for HarfBuzz, FriBidi, ICU, and FreeType, OxiText offers one sovereign, FFI-free pipeline.
It pairs closely with OxiFont, which handles font parsing, OpenType-table access, glyph outlines, and font discovery that feeds OxiText’s fallback chain. And it’s consumed across the ecosystem: oximedia (subtitles and captions), oxigdal-symbology (map labels), oxiphoton (text on images), oxigaf (PDF/EPUB reflow), OxiUI (every widget, via the oxitext-sdf GPU glyph atlas), and oxirag (document rendering).
Repository: https://github.com/cool-japan/oxitext
Star the repo if you want a world where rendering a line of text no longer means linking four C libraries. ✨
Pure Rust typography — sovereign, safe, and FFI-free.
— KitaSan at COOLJAPAN OÜ June 23, 2026