Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

Workspace Structure

The workspace is organized into 19 crates across three layers:

LayerCratesRole
Generic frameworkfonts-rs-model, fonts-rs-generatorShared types and build pipeline
Font familiesfonts-rs-doto, fonts-rs-bravura, … (10 crates)One crate per font family
Nerd Fontsnerd-fonts-model, nerd-fonts-generator, nerd-fonts-rsNerd Fonts-specific integration
Applicationsnerd-fonts-cheat-sheet, fonts-rs-noto-emoji-cheat-sheetDemo / cheat sheet apps

Crate Dependencies

graph TD
    Model["fonts-rs-model"] --> Gen["fonts-rs-generator"]
    Model --> NFModel["nerd-fonts-model"]
    Gen --> NFGen["nerd-fonts-generator"]
    NFModel --> NFGen
    Gen --> NotoGen["fonts-rs-noto-emoji-generator"]

    Model --> Doto["fonts-rs-doto"]
    Gen --> Doto
    Model --> Bravura["fonts-rs-bravura"]
    Gen --> Bravura
    Model --> Seven["fonts-rs-seven-segment"]
    Gen --> Seven

    NotoGen --> NotoEmoji["fonts-rs-noto-emoji"]
    NFGen --> NFRs["nerd-fonts-rs"]
    Model --> NFRs

    NotoEmoji --> NotoCS["fonts-rs-noto-emoji-cheat-sheet"]
    NFRs --> NFCS["nerd-fonts-cheat-sheet"]

Build Pipeline

Each font family crate follows the same build pipeline via FontBuild:

flowchart TD
    Font["Font file (TTF/OTF)"] --> Hash["FNV-1a hash"]
    Hash --> Check{"Hash changed?"}
    Check -->|Yes| Export["Export glyphs to SVG"]
    Check -->|No| Skip["Skip export"]
    Export --> Meta["metadata.json"]
    Export --> SVGs["scalable/glyphs/*.svg"]
    Export --> XML["icons.gresource.xml"]
    Meta --> Codegen["Code generation"]
    XML --> GResource["GResource compilation"]
    Codegen --> Codemap["$OUT_DIR/codemap.rs (phf::Map)"]
    Codegen --> Icons["$OUT_DIR/icons.rs (constants)"]
    Codegen --> Variant["$OUT_DIR/variant.rs (variant info)"]
    GResource --> Compiled["icons.gresource (binary)"]
    Skip --> Codegen

Hash-Based Change Detection

FontBuild computes an FNV-1a hash of the font file and stores it in resources/.hash. On subsequent builds, the hash is compared to determine whether re-export is needed. For variable font variants, extra_hash() adds the variant name to the hash, forcing re-export when the active variant changes even if the font file is unchanged.

Code Generation

The default code generation produces three files in OUT_DIR:

  • codemap.rs - phf::Map<char, &str> (codepoint → glyph name) and phf::Map<&str, char> (glyph name → codepoint)
  • icons.rs - pub const strings for each glyph name
  • variant.rs - GRESOURCE_PREFIX and GLYPH_PREFIX constants

Custom code generation is available via FontBuild::run_with().

Font Family Crate Anatomy

Each font family crate has the following structure:

crates/fonts-rs-{name}/
├── Cargo.toml          # Features, dependencies, license-file
├── build.rs            # Build pipeline (FontBuild + ExportConfig)
├── resources/
│   ├── {font}.ttf      # Bundled font file
│   ├── {license}.txt   # Font license
│   └── icons.gresource.xml  # Generated by build.rs
└── src/
    ├── lib.rs          # Runtime API (register_glyphs, all_glyphs, GlyphNameExt)
    ├── definition.rs   # FontFamilyConfig implementation
    ├── naming.rs       # FontFamily marker enum + GlyphName<F> type alias
    ├── variant.rs      # include!(OUT_DIR/variant.rs)
    ├── codepoint_map.rs # include!(OUT_DIR/codemap.rs)
    ├── constants.rs    # include!(OUT_DIR/icons.rs)
    └── fonts.rs        # impl_font_loader! (optional, render feature)

Feature Gates

Each font family crate uses feature gates for optional functionality:

FeatureDescription
gtk (default)GResource registration, GTK4 icon name resolution
renderFont loading via ab_glyph for software rendering
embed-fontsEmbed font files via include_bytes! instead of disk
Variant featuresOne Cargo feature per font variant (e.g. bold-dot)

GResource Registration

The build.rs script compiles GResource bundles via glib-build-tools:

  1. icons.gresource from resources/icons.gresource.xml - contains all exported SVG glyph files
  2. font.gresource (optional) from resources/font.gresource.xml - contains the font file itself for GResource-based font loading

At runtime, register_glyphs() registers the GResource bundle via gio::resources_register_include!("icons.gresource").

Initialization Flow

sequenceDiagram
    participant App as Application
    participant Crate as fonts-rs-{name}
    participant GResource as GResource
    participant CSS as CssProvider

    App->>Crate: register_glyphs()
    Crate->>GResource: resources_register_include!("icons.gresource")
    GResource-->>Crate: OK
    Crate-->>App: Ready

    Note over App,CSS: For Nerd Fonts (nerd-fonts-rs only)
    App->>Crate: init(base_dir)
    Crate->>GResource: Register font + icon GResources
    Crate->>CSS: Load font_face_css() into CssProvider
    Crate->>CSS: Add provider to default display
    Crate-->>App: Ready