Conversation
Typeface is the value every text property funnels into before font resolution, so variable-font axis values belong on it - same pattern as weight and stretch, and the only way a single settings value can flow from a style through layout to the renderer. - both ctors take an optional FontVariationSettings; Empty is coerced to null at construction so equality, hashing and cache keys never distinguish the two "design defaults" spellings - equality and hash include the settings (structural, cached hash) - Normalize() and the FormattedText per-run updaters (SetFontFamily / SetFontWeight / SetFontStyle) carry the settings over when rebuilding
FontManager is the single seam every Typeface passes through on its way to a GlyphTypeface, so the user-space settings are applied there - once, at the end, whichever resolution path produced the base typeface. - the resolution body moves to a private TryResolveGlyphTypeface (the default-family recursions target it directly); the public method resolves, then binds the variations via GlyphTypeface.WithVariations - per-variation instances are cached on the resolved typeface, so repeated lookups with equal settings return the same instance (pinned by test against the embedded Inter Variable) - font fallback carries the variations over: the matched fallback family renders at the same axis values the primary typeface requested, each font clamping to its own axes (CSS behavior)
TextElement.FontVariationsProperty is the user-facing entry point for
variable-font configuration, following the FontStretch pattern exactly:
an inherited attached property that every typeface bake site folds into
the Typeface it constructs.
- attached property on TextElement (inherits) + CLR accessors and
Get/SetFontVariations statics
- AddOwner on TemplatedControl, ContentPresenter and TextBlock
- baked into the typeface at every control bake site: TextBlock,
SelectableTextBlock, TextPresenter, TextBox line-height layouts, and
Inline run properties
- property changes invalidate like the sibling font properties
(TextBlock/TextPresenter shaping group, TextElement inline host)
- XAML attribute strings ("wght=700, wdth=85") convert through the
static Parse the XAML compiler picks up - no TypeConverter needed
(pinned by a Markup.Xaml test)
FontVariationSettings.Interpolate blends two settings the way CSS font-variation-settings does: per-axis linear interpolation when both endpoints set exactly the same axes (easing overshoot extrapolates), discrete switch at the midpoint otherwise. Discrete is the only sound fallback because a missing axis means "the font''s default", a value that is not knowable in user space. - FontVariationSettingsAnimator registered like the other value animators, so keyframe Animations on FontVariations work out of the box - FontVariationSettingsTransition for the Transitions collection, following the TransformOperationsTransition pattern - interpolation contract pinned at the value level (lerp, order independence, overshoot, discrete mismatches, null/Empty endpoints) and at the transition level through a test clock
An animated axis sweeps through arbitrary float user values; without quantization every frame produced a fresh normalized position and a fresh clone in the per-source variation cache, growing it without bound across repeated sweeps. Snap each coordinate to 1/16384 after avar correction. That is the resolution the font binary itself stores - gvar, avar and the item variation stores speak F2Dot14 - so no representable position is lost, while a swept axis lands on at most 32769 distinct cache entries and sub-resolution user values collapse to one clone (pinned by tests at the position and clone-identity level).
Gillibald
force-pushed
the
pr4h/font-variations-user-api
branch
from
September 8, 2026 07:40
325a640 to
3407fe4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 12 of 15 of the glyph-outline / variable-font workstream. Stacked on Part 11 (
pr4g/vvar-advances); please merge that one first. Parts 6 to 11 built variable-font support onGlyphTypeface; this part connects it to the properties, XAML and animations that application code actually uses.What does the pull request do?
Makes variable fonts reachable without touching
GlyphTypefaceat all.TypefacecarriesFontVariations, so a variation is part of what a typeface is rather than something applied afterwards. It arrives as a constructor overload,Typeface(family, style, weight, stretch, fontVariations), leaving the existing constructors untouched.TextElement.FontVariationsPropertyis an inherited attached property withGetFontVariations/SetFontVariations, so setting it on a container applies to the text below it.TextBlock,SelectableTextBlock,TextBox,TextPresenter,ContentPresenter,TemplatedControlandInlineall take part.FontVariationSettings.Parsegives the type a XAML-friendly string form, soFontVariations="wght 700, wdth 87.5"works in markup.FontVariationSettings.Interpolate, a registered animator andFontVariationSettingsTransitionlet a variation be animated or transitioned, per-axis, the way CSS animatesfont-variation-settings.FormattedTextandTextCharacterscarry the variation through so text drawn outside the control layer varies too.What is the updated/expected behavior with this PR?
FontVariationsanywhere in the text property chain resolves throughFontManagerto a varied typeface, and inherits down likeFontSizeorFontWeightdo.Parseaccepts a comma-separated list oftag valuepairs and round-trips withToString. Unparseable input throws rather than silently producing an empty setting.FontVariationsset behaves exactly as before, and static fonts ignore the property.How was the solution implemented (if it's not obvious)?
font-weightmaps ontowghtunlessfont-variation-settingssays otherwise.Checklist
Breaking changes
None.
Typefacegains a five-parameter constructor overload rather than an optional parameter on the existing four-parameter one, so no signature is removed and assemblies compiled against an earlier release keep working. Everything else is additive, and text that does not setFontVariationsresolves the same typeface it did before.Obsoletions / Deprecations
None.
Fixed issues
None.
🤖 Generated with Claude Code