Skip to content

Request: Support On-Demand Glyph Loading (Lazy Glyph Parsing) for Large Fonts #472

@bezkma

Description

@bezkma

Summary

SixLabors.Fonts eagerly loads and parses all glyph data during Add() / LoadFont().
For many real-world applications, this creates major performance and memory problems, especially with large CJK or emoji fonts (30–100+ MB).

In many software scenarios, the application may only need 1–2 glyphs from a large font, yet the entire font’s glyph tables (glyf, CFF, loca, kerning, metrics) are parsed upfront.
This leads to unnecessary CPU work, high memory usage, and slow startup times.

I would like to request support for on-demand glyph loading (lazy glyph parsing) so that glyph outlines are only parsed when they are actually used during rendering or layout.


Problem Description

Currently:

  • FileFontMetrics and StreamFontMetrics eagerly parse all glyphs.
  • FontMetrics materializes glyph-related data for every glyph.
  • This happens at FontCollection.Add(path) or Add(stream).
  • Even if the application renders a single glyph, the entire font must be parsed.

This results in:

  • High initial loading cost
  • Increased memory consumption
  • Poor performance with large fonts (CJK, emoji, TTC collections)
  • Trouble in UI/design tools loading many fonts
  • Poor scaling in image-generation or rendering servers

Examples of real usage where only a very small subset of glyphs is needed:

  • Rendering a single icon from an icon font
  • Using one Chinese character in a design tool
  • Stamping/labeling with 2–5 glyphs
  • Rendering one emoji from a large emoji font

Yet the entire font must still be parsed, which is wasteful.


Why On-Demand Glyph Loading Is Important

Other text engines like:

  • FreeType / FreeType2
  • Skia
  • HarfBuzz (via FreeType callbacks)

perform:

  • Upfront: Parse only top-level tables (cmap, maxp, loca, metrics)
  • Lazy: Parse individual glyph outlines only when needed

This drastically improves loading time and reduces memory for large fonts.

SixLabors.Fonts currently has no mechanism such as:

  • A lazy GlyphTable
  • A glyph resolver callback
  • Deferred glyf/CFF parsing
  • A “load glyph on demand” pipeline

So performance for large fonts is significantly worse than necessary.


Proposed Feature

Support a way to load glyph outlines only when they are needed.

Option A — Lazy Glyph Table

Provide an interface such as:

interface IGlyphLoader
{
    GlyphData LoadGlyph(int glyphIndex);
}

Allow FontMetrics to use a loader instead of fully materializing glyphs.

Option B — Lazy Font Loading API

Example:

FontCollection.AddLazy(path, glyphLoader: index => LoadGlyphData(index));

Option C — Partial Font Loading Strategy

  • Parse only required global tables upfront (head, maxp, cmap, loca)
  • Defer glyf/CFF parsing until a glyph is accessed

Benefits

  • Much lower memory usage
  • Faster font loading, especially for large CJK/emoji fonts
  • More responsive UI and design tools
  • Better scaling when many fonts are loaded
  • Suitable for high-performance image-generation servers
  • Avoids unnecessary work when only a few glyphs are actually needed

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions