#svg #opentype-font #opentype #font #woff #graphics

fontcore

Load fonts, select faces, shape text, and export SVG in Rust

2 releases

0.0.12 Apr 10, 2026
0.0.11 Apr 10, 2026

#2317 in Parser implementations

MIT license

1MB
31K SLoC

fontcore for Rust

fontcore is a Rust library for loading fonts, selecting a face, shaping text, and exporting SVG.

Japanese: README.ja.md

What To Use First

Most users only need these three types.

  • FontFile
    • Opens a font file, TTC, or in-memory buffer
    • Lets you choose a face
  • FontFace
    • Represents one face
    • Exposes metadata such as family(), full_name(), weight(), is_italic()
  • FontEngine
    • Shapes text, measures text, and renders SVG
    • Main entry point for direction, locale, variant, and variable-font axes

The old low-level parser surface still exists behind features = ["raw"].

Supported Formats

  • TrueType
  • OpenType / CFF
  • TTC
  • WOFF
  • WOFF2

Default features include layout and cff.

Features

  • layout
    • GSUB / GPOS shaping
    • Vertical flow, RTL, locale, and variant selection
  • cff
    • OpenType / CFF outlines
  • raw
    • Legacy low-level parser API
  • svg-fonts
    • OpenType-SVG fonts are limited implementation
    • Provisional support for converting OpenType SVG glyphs into glyph layers
    • Currently regression-tested mainly against EmojiOneColor.otf and NotoColorEmoji-Regular.ttf
    • Simple shapes are pathified, while payloads that cannot be pathified are kept as GlyphLayer::Svg
    • Full path conversion and CSS / text interpretation are not implemented yet

Install

[dependencies]
fontcore = "0.0.12"

If you need the low-level parser API:

[dependencies]
fontcore = { version = "0.0.12", features = ["raw"] }

If you also want provisional SVG emoji font support:

[dependencies]
fontcore = { version = "0.0.12", features = ["svg-fonts"] }

Quick Start

use fontcore::{FontFile, ShapingPolicy};

let face = FontFile::from_file("fonts/YourFont.ttf")?.current_face()?;
let engine = face
    .engine()
    .with_shaping_policy(ShapingPolicy::LeftToRight)
    .with_font_size(32.0)
    .with_svg_unit("px");

println!("{}", face.family());
println!("{}", engine.measure("Hello")?);
println!("{}", engine.render_svg("Hello")?);
println!("{}", engine.shape("Hello")?.glyphs.len());
# Ok::<(), Box<dyn std::error::Error>>(())

Common Tasks

  • Show metadata
    • face.family()
    • face.full_name()
    • face.weight()
    • face.is_italic()
  • Shape text
    • engine.shape(text)
  • Measure text
    • engine.measure(text)
  • Render SVG
    • engine.render_svg(text)
  • Vertical flow
    • engine.with_vertical_flow()
  • RTL shaping
    • engine.with_right_to_left()
  • GSUB variant selection
    • engine.with_font_variant(...)
  • Variable-font axes
    • face.variation_axes()
    • engine.with_variation("wght", 700.0)

More runnable examples live in doc/api-recipes.md.

About SVG Color Fonts

sbix is exposed as raster layers, COLR/CPAL as path layers, and the OpenType SVG table is pathified first under svg-fonts, falling back to Svg layers only when needed.

The current svg-fonts implementation converts simple path, rect, circle, ellipse, line, polyline, and polygon elements into PathGlyphLayer values. It includes minimal defs / use, fill / fill-rule / stroke / stroke-width, clipPath / clip-path, simple mask, translate / scale / rotate / skewX / skewY / matrix, linearGradient / radialGradient / stop, and preserved gradientUnits / gradientTransform support, and keeps a GlyphLayer::Svg fallback not only for payloads that cannot be pathified, but also for payloads that still contain unsupported constructs such as pattern, complex mask, or filter.

On the 0.0.12 line, the paintcore renderer tracks the public fontcore layer model closely enough to preserve clip_commands and gradient paint values across the fontcore -> paintcore conversion.

See doc/SVFONTSPEC.md for the exact current scope, limitations, and the paintcore handoff contract.

Examples

High-level examples that work without raw:

  • api_overview
  • fontmetadata
  • fontcore

Low-level inspection examples that require --features raw:

  • fontcmaps
  • fontcolor
  • fontgkana
  • fontgsub
  • fontheader
  • fontload
  • fontname
  • fontsbix
  • fontsvg
  • fonttest
  • fonttype
  • tategaki

Shared CLI flags:

  • -f, --font: font path
  • -d, --dir: font directory
  • -i, --index: face index inside a collection
  • -o, --output: output file path
  • -s, --string: inline text
  • -t, --text-file: text file path
  • --vertical: top-to-bottom flow
  • --variant: variant shortcut such as jp78, jp90, trad, nlck

Run a high-level example:

cargo run --example api_overview -- -f path/to/font.ttf -s "Hello"

Run a raw example:

cargo run --example fontheader --features raw -- -f path/to/font.otf

cargo doc

The crate has rustdoc on the public API surface.

cargo doc --no-deps

If you want to open it immediately:

cargo doc --no-deps --open

The crate-level docs and type docs are the best entry point for:

  • FontFile
  • FontFace
  • FontEngine
  • FontFamily
  • FontVariant
  • ShapingPolicy

WebAssembly

The crate supports wasm32-unknown-unknown.

  • Prefer load_font_from_buffer() or load_font(FontSource::Buffer(...))
  • load_font_from_file() and load_font_from_net() return ErrorKind::Unsupported on wasm32

Documentation Map

Dependencies

~8MB
~292K SLoC