COOLJAPAN
← All posts

OxiFont 0.2.0 — Pure Rust Font Discovery & Parsing, the NoFFI Replacement for fontconfig + FreeType

OxiFont is the COOLJAPAN Pure Rust font discovery, parsing, subsetting, and web-font layer for the oxi* ecosystem. It replaces the fontconfig + FreeType C/C++ pair with zero-FFI Rust: enumerate system fonts on Linux/macOS/Windows, parse TTF/OTF/TTC/WOFF/WOFF2, do CSS Level 4 family matching, and subset to WOFF2. Part of the NoFFI sovereign Rust stack.

release oxifont pure-rust cooljapan noffi fonts typography opentype text-rendering

Every program that draws text starts by answering one quiet question: where is the font, and what is inside it? For decades the answer on Linux and beyond has been two C libraries — fontconfig to find the file, freetype to read it. Today, that whole layer becomes Pure Rust.

Today we’re releasing OxiFont 0.2.0 — the COOLJAPAN Pure Rust font discovery, parsing, subsetting, and web-font encoding layer for the oxi* ecosystem.

No fontconfig. No freetype. No FFI. No -sys crates. Under default features OxiFont is 100% Rust: a single static binary that enumerates installed fonts, parses font byte streams, matches families by CSS rules, and emits web fonts — with no system libraries and no build-time C toolchain in the way.

Why OxiFont

If you have ever shipped a Rust application that renders text, you have met the font-stack tax. fontconfig wants its XML config, its cache directories, and its platform-specific quirks. freetype is a sprawling C codebase linked through freetype-sys, dragging a native build dependency into every target you care about — including the WASM and cross-compilation targets where a C toolchain is exactly what you were trying to avoid.

None of that is essential complexity. Finding a font is a filesystem scan plus a parse of a few well-specified tables. Reading a font is parsing an SFNT container. Matching a family is a documented algorithm written down in the CSS Fonts specification. OxiFont does each of these directly, in memory-safe Rust, so the font layer stops being the reason your build needs a C compiler.

OxiFont draws a deliberate line. It covers discovery, parsing, metrics, matching, subsetting, and web-font encoding. Rasterization, hinting execution, shaping, and layout are out of scope by design — those belong to oxitext. OxiFont is the layer that tells you which font and what is in it; turning glyphs into pixels is someone else’s job.

What we built

OxiFont is a workspace of focused crates, each owning one slice of the problem. The oxifont facade crate re-exports the ecosystem and gives you the convenience entry points (load_font, load_font_bytes, detect_format, decode_and_parse, and a prelude), so most code only ever needs the one dependency.

  1. oxifont-core — the vocabulary. The traits and types the whole stack speaks: FontFace, FontCatalog, FaceInfo, FontQuery, FontStyle, FontStretch, FontMetrics, GlyphOutline, KerningPair, ColorGlyphFormat, VariationAxis, and SfntTableMap.

  2. oxifont-parser — reading the bytes. TTF/OTF/TTC parsing via ttf-parser, with a full FontFace implementation: metrics, glyph outline extraction, kerning, color-glyph detection, and PostScript name. This is the part that replaces freetype’s parsing role — without inheriting its hinting interpreter, which is deliberately excluded.

  3. oxifont-discovery — finding the files. A Pure Rust OS font-directory scanner for macOS, Linux, and Windows, built on walkdir, with optional fontconfig XML config parsing for compatibility. This is fontconfig’s enumeration job done as a plain filesystem walk.

  4. oxifont-adapter-pure — the catalog. Builds a FontDatabase from a filesystem scan, resolves CSS generic-family aliases, and offers an optional disk cache so repeated startups stay fast.

  5. oxifont-db — CSS Level 4 matching. An in-memory indexed database implementing CSS Fonts Level 4 §4.5 family/weight/style/stretch matching, with 60+ BCP-47 locale mappings, a fluent Query builder, and an optional binary disk cache. This is where “give me sans-serif, weight 700” turns into a concrete face.

  6. oxifont-subset — shrinking fonts. A TrueType and CFF/CFF2 glyph subsetter: GSUB/GPOS/GDEF pruning, HVAR/VVAR rewriting, and COLR/CPAL, CBDT, SVG, sbix, and MATH subsetting, with variable-font support throughout.

  7. oxifont-webfont — shipping fonts to browsers. WOFF1 and WOFF2 decode and encode, including transformed glyf/loca/hmtx reconstruction, a streaming WOFF2 decoder, and font-format autodetection.

  8. oxifont-bundled — fonts in the binary. Compile-time embedded SIL-OFL-1.1 Noto fonts (Sans, Serif, Italic, Mono), with CJK JP/KR/SC/TC behind sub-features, so “no font installed” never has to be a failure mode.

Every default feature uses zero FFI. Native platform enumeration via CoreText (macOS) and DirectWrite (Windows) lives in a separate oxifont-adapter-native crate behind its native feature — opt-in, never on the default path. And fontconfig and freetype are permanently off-limits under any feature or adapter.

Getting Started

Add the facade crate:

[dependencies]
oxifont = "0.2"

Find a system font and read its metadata:

use oxifont::{FontDatabase, FontCatalog as _, FontQuery};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let db = FontDatabase::system()?;
    if let Some(face) = db.find(&FontQuery::new().family("Arial")) {
        println!("found: {} weight={}", face.family, face.weight);
    }
    Ok(())
}

Parse a font file directly and inspect what is inside:

use oxifont::{load_font, FontFace as _};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let face = load_font("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf")?;
    println!("family: {}", face.family_name());
    println!("units/em: {}", face.units_per_em());
    println!("glyph count: {}", face.glyph_count());
    Ok(())
}

Highlights

Tips

Part of the COOLJAPAN ecosystem

OxiFont belongs to 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. Here, that means retiring fontconfig (system enumeration and family matching) and freetype (parsing and outlines) from the dependency tree, while text shaping via harfbuzz-sys stays out of scope and lives in OxiText instead.

It is wired into the rest of the family. All DEFLATE/zlib work runs through oxiarc-deflate and all Brotli work through oxiarc-brotli — no flate2, brotli, miniz_oxide, or zip anywhere in the tree. And OxiFont is already the font foundation under OxiText (glyph metrics for layout), oxigaf (PDF CFF/Type-0 font embedding), oximedia (subtitle and OSD rendering), oxigdal-symbology (map labels), oxiphoton (image text overlay), and OxiUI (GUI text rendering).

Repository: https://github.com/cool-japan/oxifont

Star the repo if you want a font layer that finds, reads, and shrinks fonts without ever asking for a C compiler. ⭐

Pure Rust typography — sovereign, safe, and FFI-free.

KitaSan at COOLJAPAN OÜ June 22, 2026

↑ Back to all posts