Skip to content

Conversation

@oetiker
Copy link
Contributor

@oetiker oetiker commented Dec 28, 2025

  • Parse font-variation-settings CSS property
  • Auto-map font-weight/stretch/style to variation axes
  • Apply variations during text shaping via rustybuzz
  • Add FontVariationSettings to presentation attributes for CSS cascade

oetiker and others added 3 commits December 27, 2025 07:06
- Parse font-variation-settings CSS property
- Auto-map font-weight/stretch/style to variation axes
- Apply variations during text shaping via rustybuzz
- Add FontVariationSettings to presentation attributes for CSS cascade

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@oetiker
Copy link
Contributor Author

oetiker commented Jan 1, 2026

The ``typos'' seem to be outside my PR

@Its-Just-Nans
Copy link
Contributor

The ``typos'' seem to be outside my PR

Just for info, there is already a .typos.toml (where you can add exceptions) !

@RazrFalcon
Copy link
Collaborator

Looks good, but we need some tests. Which also means we have to find and add a free variable font here.

parse_font_variation_settings should ideally be moved to svgtypes. But it's not that important.

Not sure about "auto-mapping". Afaik a font can have a variation axis with any range. Meanwhile your code sets wdth in a 50...200% range. Which is most certainly wrong.
No idea what is the expected way to handle this.

@oetiker
Copy link
Contributor Author

oetiker commented Jan 7, 2026

Thanks for the review! I've added tests using https://fonts.google.com/specimen/Roboto+Flex, a variable font with 13 axes (OFL 1.1 licensed).

Tests added (14 total):

  • Explicit font-variation-settings: wght, wdth, slnt, opsz, GRAD, XTRA, and multiple axes combined
  • Auto-mapping: font-weight → wght, font-stretch → wdth, font-style: oblique → slnt
  • Priority behavior: Verifies explicit settings override auto-mapping

Regarding the wdth auto-mapping (50-200%):

The hardcoded percentages are the CSS standard values per https://drafts.csswg.org/css-fonts-4/#font-stretch-prop. When applied to fonts with different axis ranges (Roboto Flex's wdth is 25-151), the font engine clamps to the supported range. This matches browser behavior.

For example, font-stretch: ultra-expanded (200%) on Roboto Flex gets clamped to 151 by rustybuzz/ttf-parser. This is expected - it means "as expanded as this font supports."

Moving parse_font_variation_settings to svgtypes:

Happy to do this in a follow-up if you'd like, though as you noted it's not critical.

Added 14 tests for font-variation-settings using a subsetted Roboto Flex
variable font (OFL 1.1 licensed). The font preserves all 13 variation axes
including wght, wdth, slnt, opsz, GRAD, and parametric axes.

Tests cover:
- Explicit font-variation-settings (wght, wdth, slnt, opsz, GRAD, XTRA)
- Multiple axes combined
- Auto-mapping from font-weight/stretch/style to variation axes
- Priority behavior (explicit settings override auto-mapping)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@oetiker
Copy link
Contributor Author

oetiker commented Jan 7, 2026

I compared the output with the browser output for specific axis values ... and it does not match ... investigating ...

@RazrFalcon
Copy link
Collaborator

Tests look good. Thanks!

And I guess we could iron-out auto-mapping later, if someone would fine any issues.

Matching at least the Chrome output is preferable.

@oetiker
Copy link
Contributor Author

oetiker commented Jan 7, 2026

the output difference is as of yet unresolved, I have rendering the test svgs with chrome and firefox result in narrow output while rendering them to png with rust or c harfbuzz implementations give the much less narrow output. while the paremeter definitly has an influence, it just seems to be much less pronounced than with the browsers ...

- Add `font-optical-sizing` CSS property support (auto/none)
- When `font-optical-sizing: auto` (default), automatically set the `opsz`
  axis to match font size for variable fonts that support it
- Fix variable font outline extraction to properly apply variations
- Regenerate names.rs using codegen after adding FontOpticalSizing attribute
- Update test reference images with correct variable font rendering

The key fix ensures that font variations (wdth, wght, opsz, etc.) are
applied consistently during both text shaping and glyph outline extraction,
so both letter positioning AND letter shapes reflect the variation settings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@oetiker
Copy link
Contributor Author

oetiker commented Jan 7, 2026

found and fixed ... font-optical-sizing support was missing ... this is set to auto in browsers ...

see here for demo 49771e2#diff-644028718b75197f20d9637b7b96a77a7ee893aa8505860075af643503d053e4

@RazrFalcon
Copy link
Collaborator

@LaurenzV looks good to me.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@LaurenzV
Copy link
Collaborator

LaurenzV commented Jan 8, 2026

Thanks, sorry for the delay, I'll try to take a second look very soon.

oetiker added a commit to oetiker/resvg that referenced this pull request Jan 12, 2026
Move `variations`, `font_optical_sizing`, and `hinting` fields from
`PositionedGlyph` to `Span` struct since these values are uniform for
all glyphs within a span.

Benefits:
- Reduces memory by not duplicating Vec<FontVariation> per glyph
- Cleaner data model: span-level properties at span level
- Minor perf improvement: needs_variations check once per span

Based on PR linebender#997 review feedback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
oetiker and others added 2 commits January 12, 2026 20:31
- Move variations and font_optical_sizing from PositionedGlyph to Span
  (these are uniform per span, reducing memory and simplifying the API)
- Add cached has_opsz_axis check to only bypass outline cache when needed
  (fixes issue where cache was rarely used due to auto opsz default)
- Use rb_font.tables().fvar instead of re-parsing font with ttf_parser
- Remove unnecessary log::debug! messages
- Remove empty --drop-tables flag from README

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@LaurenzV LaurenzV changed the title Add variable font support via font-variation-settings CSS property Add support for variable fonts Jan 13, 2026
@LaurenzV
Copy link
Collaborator

Thanks!

@LaurenzV LaurenzV merged commit 9876cd4 into linebender:main Jan 13, 2026
5 checks passed
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.

4 participants