Skip to content

[read-fonts] experimental Font API: add GlobalMetrics - #2111

Merged
dfrg merged 1 commit into
mainfrom
read/global-metrics
Sep 8, 2026
Merged

[read-fonts] experimental Font API: add GlobalMetrics#2111
dfrg merged 1 commit into
mainfrom
read/global-metrics

Conversation

@dfrg

@dfrg dfrg commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Adds font-wide metrics to Font and FontInstance. The list of metrics is slightly different here than in skrifa::metrics::Metrics because this slices the set to the values that don't require the post table (those will follow later in StyleMetrics). The reasoning is that none of those are required for shaping so we don't want to pull large post 2.0 tables unnecessarily.

Also removes any notion of size from FontInstance (that will come later as some Scaler type), so FontInstance becomes internally Arc'd and we can now create an instance at the default location for free.

Requires #2110

@dfrg
dfrg force-pushed the read/global-metrics branch 2 times, most recently from 1e8fdd9 to a6e2ec3 Compare September 7, 2026 17:04

@cmyr cmyr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, a few ignorable questions inline


#[derive(Clone)]
enum Repr {
Default(Font),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this only used for variable fonts, or also statics?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly the right question, and the motivation for this change. This allows future code to accept only FontInstance while providing a free (sans atomic counter bump) conversion from Font for both statics and variable fonts at default location.

Comment on lines +100 to +105
impl From<&Font> for FontInstance {
/// A font is an instance of itself, at the default location.
fn from(font: &Font) -> Self {
Self(Repr::Default(font.clone()))
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by-ref only?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Both conversions make sense here.

Comment thread read-fonts/src/model/metrics/global.rs Outdated
Comment on lines +15 to +17
fn widen(value: Fixed) -> F48Dot16 {
F48Dot16::from_bits(value.to_bits() as i64)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a method on Fixed? (maybe not, if it's only internal)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and it already is! Fixed (pun intended?)

@dfrg
dfrg force-pushed the read/exact-variation-deltas branch from b06b13a to 81bfe72 Compare September 8, 2026 15:35
@dfrg
dfrg force-pushed the read/global-metrics branch from a6e2ec3 to caa745c Compare September 8, 2026 15:36
@dfrg
dfrg force-pushed the read/exact-variation-deltas branch from 81bfe72 to 0b1b5a7 Compare September 8, 2026 15:40
@dfrg
dfrg force-pushed the read/global-metrics branch from caa745c to 11920c5 Compare September 8, 2026 15:40
…tion

GlobalMetrics reads head, maxp, hhea, vhea and OS/2, and applies MVAR at a
location. A font states its line metrics three times and the three disagree,
so all three are reported and choosing between them is left to the caller.
Measurements are exact, since a location can move one off a whole design
unit and rounding here would decide for every caller how that fraction is
spent.

FontInstance drops its size. Size belongs to whatever rasterizes, not to a
point in the design space, and nothing read it. What remains is a font and
a location, so an instance at the default location is now held as nothing
more than its font and building one allocates nothing. Anywhere else it
owns what the location implies, behind an Arc so that clones share a single
resolution rather than repeating it.

An instance at the default location now selects no feature variations. A
variable font is meant to keep working for a client that knows nothing of
variations, and such a client reaches the default instance without ever
consulting that table; selecting there would render the font one way for it
and another for everyone else. This changes what a font stating a universal
condition set reports at the default location, which previously matched
because conditions were evaluated against implicit zeros.

Font gains num_glyphs, units_per_em and default_instance.
@dfrg
dfrg force-pushed the read/global-metrics branch from 11920c5 to cd97907 Compare September 8, 2026 15:48
Base automatically changed from read/exact-variation-deltas to main September 8, 2026 15:52
@dfrg
dfrg merged commit e1a545c into main Sep 8, 2026
14 checks passed
@dfrg
dfrg deleted the read/global-metrics branch September 8, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants