Skip to content

Serialized font metrics for SVG measurement, with font engine cleanup - #2496

Open
swmal wants to merge 4 commits into
develop9from
feature/i2492
Open

Serialized font metrics for SVG measurement, with font engine cleanup#2496
swmal wants to merge 4 commits into
develop9from
feature/i2492

Conversation

@swmal

@swmal swmal commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Adds a metrics-based text measurement path so SVG export can measure and line-break text even when the requested font isn't available as a font file. OpenTypeFontEngine.GetMeasurementShaper returns an ITextShaper that may be backed by serialized .fmtr metrics instead of a parsed font, and LayoutSystem now uses it.

PDF export is unaffected by design. PdfTextShaper constructs TextShaper directly from a provider and never goes through the engine's shaper resolution, so it cannot receive a metrics-only shaper. The split is enforced by return type: GetTextShaper still returns TextShaper with glyph ids, GetMeasurementShaper returns the narrower interface.

The fallback engages only after the user-configured and built-in fallback chains are exhausted, since a real metric-compatible substitute beats quantized metrics.

Configuration

// Default. Serialized metrics only when resolution falls through to the
// embedded last-resort font.
wb.ConfigureFonts(cfg =>
    cfg.MetricsFallback = MetricsFallbackMode.WhenFontMissing);

// Never use serialized metrics. Missing fonts are measured as Archivo Narrow,
// the pre-existing behaviour.
wb.ConfigureFonts(cfg =>
    cfg.MetricsFallback = MetricsFallbackMode.Disabled);

// Always measure from serialized metrics, ignoring installed fonts. Makes
// measurement machine-independent, and line breaking testable without a font
// fixture. No kerning, and widths are quantized.
wb.ConfigureFonts(cfg =>
    cfg.MetricsFallback = MetricsFallbackMode.Always);

Also in this PR

FontStore and ShaperCache extracted from OpenTypeFontEngine, FontDiscovery and FontSubFamilyConverter split out, and the OpenTypeFonts static facade removed along with GetFromBytes and GetFontSubFamily.

Breaking

Those three public removals, and the new WhenFontMissing default changes measured widths on machines lacking the requested font.

@swmal swmal added this to the EPPlus 9.0 or later milestone Sep 3, 2026
@swmal swmal self-assigned this Sep 3, 2026
@swmal swmal added the enhancement New feature or request label Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant