Skip to content

Port resvg to harfrust and fontations - #922

Merged
nicoburns merged 35 commits into
mainfrom
harfrust
Jul 29, 2026
Merged

Port resvg to harfrust and fontations#922
nicoburns merged 35 commits into
mainfrom
harfrust

Conversation

@nicoburns

@nicoburns nicoburns commented Jun 11, 2025

Copy link
Copy Markdown
Collaborator

Changes made

  • Replaces rustybuzz with harfrust
  • Replaces ttf_parser with skrifa

Notes

  • This is failing 23 tests. These probably need to be manually checked. I'm waiting on Improve the test harness #954 to investigate these.
  • This requires an MSRV bump from 1.65 to 1.85
  • This will represent a binary size bump for users of resvg.

Production profile

The analysis below uses the following "production" profile:

[profile.production]
inherits = "release"
opt-level = 3
debug = false
lto = true
codegen-units = 1
strip = true
incremental = false

Binary size analysis:

According to cargo-bloat (not the most accurate):

  • harfrust and rustybuzz are both ~250kb
  • ttf_parser and read-fonts are both ~100kb
  • However, ttf_parser includes the metrics outlining functionality of skrifa. And skrifa is another ~250kb.

Compiling the CLI (which is a much more useful test) with the production profile above (cargo build --profile production --bin resvg) I get:

  • 2.4mb for main
  • 3.0mb for this PR

So this PR causes a binary size increase of around 600kb

Compile time analysis

Compile times on an M1 Pro (8+2 cores) are shown below (cargo build):

Profile main This PR
debug 4.68s 9.09s
release 7.64s 14.84s
production 24.59s 34.00s

So this PR roughly doubles compile times at regular opt settings
(with the effect being less pronounced with LTO and other production optimisation settings enabled)

@nicoburns
nicoburns force-pushed the harfrust branch 2 times, most recently from 02f55d3 to 62c028b Compare June 11, 2025 01:04
@LaurenzV

Copy link
Copy Markdown
Collaborator

Yeah I think we first have to figure out how to deal with fontdb before doing anything with resvg. I don’t think RazrFalcon would want to switch it, and I’m not sure that fontique supports everything we need?

@RazrFalcon

Copy link
Copy Markdown
Collaborator

It's an interesting experiment, but I don't see a point in it. Is there a reason in switching to harfrust?
Last time I have checked it was still a beta, while rustybuzz (with all its faults) is a pretty robust solution.

PS: even if harfrust is faster, it doesn't matter either, because shaping isn't a bottleneck, lack of glyphs caching is.

@RazrFalcon

Copy link
Copy Markdown
Collaborator

Oh wait, it depends on proc-macros/syn?! Burn it with fire! No proc-macros in resvg.

@LaurenzV

Copy link
Copy Markdown
Collaborator

Last time I have checked it was still a beta, while rustybuzz (with all its faults) is a pretty robust solution.

harfrust is rustybuzz, just with ttf-parser switched out by read-fonts. It passes all the same tests, so it should be no less robust than then rustybuzz.

Is there a reason in switching to harfrust?

The reason is that going forward, (most likely) no one will be continually developing ttf-parser/rustybuzz, while harfrust will be actively maintained.

@RazrFalcon

Copy link
Copy Markdown
Collaborator

I would suggest to come back to it in a year. No rush.

And once again, proc-macros are no go. We have to figure out that one as well.

Comment thread .github/workflows/main.yml Outdated
@xStrom

xStrom commented Jun 12, 2025

Copy link
Copy Markdown
Member

Last time I have checked it was still a beta

Not sure about 'beta' type labels, but the first release (0.1.0) of HarfRust happened on June 10, marking a significant milestone.

It's an interesting experiment, but I don't see a point in it. Is there a reason in switching to harfrust?

For an immediate effect, it seems to be far more compliant when tested against the HarfBuzz test suite.

To quote Chad:

We’re still mulling over some public API changes and need to do some serious performance work but this is fully backed by fontations, up to date with HarfBuzz 11.2.1, and passes a significantly larger portion of the HB test suite than RustyBuzz: latest CI shows 5911 tests passing for HarfRust vs 2267 for RustyBuzz.

And the HarfRust introduction post by Behdad contains the following claim:

At the time of this writing, HarfRust passes most of the HarfBuzz shaping test suites, failing just 23 tests out of more than 6,000.


Moving forward, HarfRust will receive active development and continuous sync with HarfBuzz, while RustyBuzz is likely to only see critical fixes.

@RazrFalcon

Copy link
Copy Markdown
Collaborator

latest CI shows 5911 tests passing for HarfRust vs 2267 for RustyBuzz.

Apples and oranges, but sure.

Either way, proc-macros is the current major roadblock.

@mattfbacon

Copy link
Copy Markdown
Contributor

@RazrFalcon Seems like the proc-macros are coming from font-types which uses bytemuck and serde derive macros. Do we want to talk to them about converting to manual implementations?

@RazrFalcon

Copy link
Copy Markdown
Collaborator

@mattfbacon if it's an easy fix - sure.

@mattfbacon

Copy link
Copy Markdown
Contributor

No it wouldn't be at all, since the bytemuck derive macros generate unsafe code so they would need to allow unsafe code back into the codebase.

But what is your plan here? Earlier you said wait, but for what?

@RazrFalcon

Copy link
Copy Markdown
Collaborator

No it wouldn't be at all, since the bytemuck derive macros generate unsafe code so they would need to allow unsafe code back into the codebase.

I would call it easy. It's not like the code deeply depends on proc-macros.

But what is your plan here? Earlier you said wait, but for what?

Adoption, etc. I don't see a point/reason in switching to 0.1. Especially if we would keep ttf-parser around. It just doesn't make any sense.

@Shnatsel

Copy link
Copy Markdown
Contributor

There are derive helpers based on macro_rules! rather than proc macros: https://matx.com/research/rules_derive

It is likely possible to implement an alternative derive for bytemuck traits using such helpers. These can then be published as a separate crate such as bytemuck_derive_lite to avoid any potential backward compatibility issues with the proc macro implementation.

@nicoburns
nicoburns force-pushed the harfrust branch 4 times, most recently from e29cfbe to 0973b97 Compare August 31, 2025 11:18
@nicoburns nicoburns changed the title Port resvg to harfrust Port resvg to harfrust and fontations Aug 31, 2025
@nicoburns
nicoburns force-pushed the harfrust branch 3 times, most recently from 3c5c998 to c05e2fd Compare August 31, 2025 19:20
@xStrom

xStrom commented Sep 4, 2025

Copy link
Copy Markdown
Member

Is there a reason in switching to harfrust?

As some months have passed another benefit has appeared - performance. In the last month the HarfRust vs HarfBuzz OpenType shaping performance difference has gone from ~4x to ~1.2x, which is a massive boost. Not quite on par with HarfBuzz yet, but getting a lot closer. More importantly for this PR here though, HarfRust is now a lot faster than RustyBuzz.

@Enivex

Enivex commented Sep 10, 2025

Copy link
Copy Markdown

The geometric mean of the last result is ~1.16, meaning Harfrust is now only 16% slower than Harfbuzz.

@behdad

behdad commented Sep 10, 2025

Copy link
Copy Markdown

The geometric mean of the last result is ~1.16, meaning Harfrust is now only 16% slower than Harfbuzz.

It's even better than that. See the comment:
harfbuzz/harfrust#257 (comment)

In short, there's some hb-harfrust overhead included in the spreadsheet number.

@nicoburns
nicoburns force-pushed the harfrust branch 2 times, most recently from da2754d to 7e549e1 Compare September 13, 2025 12:17
nicoburns and others added 18 commits July 29, 2026 11:30
Skrifa's Matrix multiplication chains right-to-left (C = A * B applies B
then A), so nested paint transforms must be pre-concatenated onto the
current transform, matching the previous ttf-parser
Transform::combine(self.transform, transform) behaviour and skrifa's own
CollectFillGlyphPainter.
The single-glyph vs multi-glyph document heuristic was checking the
first record in the SVG table instead of the record that actually
contains the requested glyph, picking the wrong branch for fonts whose
records differ (e.g. Noto Color Emoji).
Replace unwraps and direct slice indexing with graceful fallbacks:
- palette lookups fall back to the foreground color instead of
  panicking on a missing/malformed CPAL table or an out-of-range
  palette index
- clip glyph outlining returns early on a draw error, matching the
  old ttf-parser behaviour
CPAL color records for all palettes live in a single shared array;
palette entry indices must be offset by the start index of the palette
from color_record_indices rather than indexing the array directly. This
is usually 0 for the first palette, but not guaranteed to be.
Signed-off-by: Nico Burns <nico@nicoburns.com>
Signed-off-by: Nico Burns <nico@nicoburns.com>
Signed-off-by: Nico Burns <nico@nicoburns.com>
Make font metrics variation-aware

Resolve the requested font-variation-settings to a normalized location
in load_font so that skrifa applies MVAR deltas to ascent, descent,
x-height, underline and strikeout metrics, and so the manual
subscript/superscript (SBYO/SPYO) delta handling actually runs.
Metrics are cached per Font spec (which includes variations), so
caching remains correct.

Also drop the leftover commented-out ttf-parser code in outline():
with skrifa, the default (empty) location already resolves to the
default value of every axis.

Cache variable font outlines per variation set

Previously any span with explicit variations (or auto optical sizing on
a font with an opsz axis) bypassed the glyph outline cache entirely,
re-extracting the outline for every glyph occurrence.

Instead, compute the effective variation list (explicit settings plus
auto opsz) once per glyph via a shared helper, include it in the cache
key, and merge outline_with_variations into a single cached outline
function. An empty variation list resolves to the default location, so
non-variable fonts behave as before.

Apply font variations to COLR color glyphs

COLR glyphs were always painted at the default variation location,
ignoring font-variation-settings. Resolve the effective variations to a
normalized location and pass it to skrifa paint(), which resolves all
COLR ItemVariationStore deltas (paint transforms, gradient stops, clip
boxes). The GlyphPainter now also draws clip glyph outlines at the same
location so the base outlines vary too.

Color glyph trees are cached per variation set, like outlines.
Skrifa pairs push_clip_glyph with pop_clip (including via the default
fill_glyph decomposition), but push_clip_glyph never opened an XML
element while pop_clip unconditionally closed one. Each painted layer
therefore closed an ancestor element, truncating the generated SVG and
making Tree::from_data fail for color glyphs with more than a few
layers.

This went unnoticed because the Noto COLR test font also contains an
SVG table, so rendering silently fell back to the SVG glyph path.

push_clip_glyph now always opens a clip group with the glyph outline
(an empty path when outlining fails), keeping pop_clip balanced.

The colrv0/colrv1 snapshots change because COLR rendering now takes
priority over the SVG table again; the output matches main.
ColorPalettes handles per-palette record offsets internally, so the
manual color_record_indices base-offset handling is no longer needed.
Replaces the manual fvar table iteration in has_opsz_axis and the
shaping auto-opsz check, and drops the harfrust FontRef usage from
flatten.rs (skrifa and harfrust share the same underlying types).
The instance only exists to apply variation settings, so avoid the
setup cost for non-variable text (the common case).
ttf-parser enforced 16..=16384 when parsing the head table; skrifa
does not, so add the check to load_font to avoid nonsensical metrics
from malformed fonts.
skrifa reports metrics as f32; round when converting to the integer
font units used by ResolvedFont rather than truncating toward zero,
matching the integer values ttf-parser used to return. Also ignore
non-positive x-height values, like ttf-parser did.
The painter previously reused the last outlined glyph (path_buf) as the
fill geometry, which only works when exactly one clip glyph is active.
The COLR imaging model instead has a proper clip stack: a fill paints
the intersection of all currently pushed clips.

- fill() now paints a rectangle covering the intersection of the
  tracked clip bounds (in root space), shaped by the enclosing SVG clip
  groups, instead of whatever happened to be in path_buf.
- push_clip_glyph/push_clip_box track their bounds on a clip stack.
- fill_glyph() is implemented directly (fill the glyph outline with the
  brush), avoiding the default clip-then-fill decomposition. This also
  restores the exact rendering of the old ttf-parser painter for
  COLRv0, so colrv0.png reverts to the version on main.

The colrv1 snapshot changes slightly at glyph edges: leaf fills no
longer pass through a clip of the same shape, so edge anti-aliasing is
no longer applied twice.
Co-authored-by: Laurenz Stampfl <47084093+LaurenzV@users.noreply.github.com>
Signed-off-by: Nico Burns <nico@nicoburns.com>
@nicoburns

Copy link
Copy Markdown
Collaborator Author

I've published fontdb v0.24 (which inlines a minimal subset of ttf-parser) and updated this PR to use the version from crates.io.

Signed-off-by: Nico Burns <nico@nicoburns.com>
@nicoburns
nicoburns merged commit 4d76f92 into main Jul 29, 2026
10 checks passed
@nicoburns

Copy link
Copy Markdown
Collaborator Author

This has now been published as part of the v0.48 release

renovate Bot added a commit to gwennlbh/shapemaker that referenced this pull request Aug 9, 2026
##### [v0.48.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0480-2026-07-31)

This release has an MSRV of 1.89.0 for `usvg` and `resvg` and the C API.

The big change in this release is that text support is now backed by
[`skrifa`](https://github.com/googlefonts/fontations) and
[`harfrust`](https://github.com/harfbuzz/harfrust) rather than
[`ttf-parser`](https://github.com/harfbuzz/ttf-parser) and
[`rustybuzz`](https://github.com/harfbuzz/rustybuzz):

- Moves resvg onto an actively maintained font stack.
- Should have faster and more correct text rendering.
- Will enable further improvements to things like variable font rendering in future.
- May impact binary size (expected +\~500kb for people not otherwise including fontations dependencies in their tree).
- May result in small rendering changes compared to older versions of resvg.

##### Added

- New `svgz` and `writer` feature gates to reduce the number of required dependencies. ([#1088](linebender/resvg#1088) by [@reed-smout](https://github.com/reed-smout))
- Warnings when parsing malformed paths. ([#1011](linebender/resvg#1011))
- A `Display` implementation for `Units`. ([#986](linebender/resvg#986))

##### Changed

- MSRV bumped from 1.87 to 1.89. The requirement comes from `font-types`.
- Text shaping now uses `harfrust` instead of `rustybuzz`, and font parsing uses `skrifa` (fontations) instead of `ttf-parser`. ([#922](linebender/resvg#922) by [@nicoburns](https://github.com/nicoburns))
- Filter input dimension checks are now debug-only assertions. ([#991](linebender/resvg#991))

##### Fixed

- Glyph advances are now calculated correctly. ([#1043](linebender/resvg#1043) by [@fundon](https://github.com/fundon))
- Text nodes now inherit their absolute transform. ([#1040](linebender/resvg#1040) by [@fundon](https://github.com/fundon))
- Fixes related to non-finite values. ([#1049](linebender/resvg#1049) by [@SAY-5](https://github.com/SAY-5))
- Transforms are no longer applied twice in `abs_transform`. ([#1056](linebender/resvg#1056) by [@fundon](https://github.com/fundon))
- `fr` is now resolved for radial gradients referenced via `href`. ([#1098](linebender/resvg#1098) by [@T1mVo](https://github.com/T1mVo))
- Panic in `feComposite` with the `arithmetic` operator when the filter region is larger than the clamped layer. ([#1021](linebender/resvg#1021), [#1007](linebender/resvg#1007))
- Application of `transform` (and other group properties like `opacity`) on a nested `svg`
  element.
- The missing dimension of an `svg` with only `width` or `height` specified is now computed from its `viewBox` aspect ratio. ([#1045](linebender/resvg#1045))
- The `wght` variation coordinate is now set even when `font-weight` has its default value. ([#1099](linebender/resvg#1099))
- The unprefixed `href` attribute now takes precedence over the deprecated `xlink:href` when both are present, as required by SVG 2. ([#1015](linebender/resvg#1015))
- Incorrect y-axis offsets when transforming `feSpotLight` sources. ([#1052](linebender/resvg#1052))
- Panics caused by bounding boxes that exceed the supported integer range. ([#989](linebender/resvg#989))
##### [v0.47.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0470-2026-02-05)

This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API.

##### Added

- Focal radius (`fr`) supported for Radial Gradients. ([#1014](linebender/resvg#1014) by [@wmedrano](https://github.com/wmedrano))
- Support for variable fonts based on font-variation-settings CSS property. ([#997](linebender/resvg#997) by [@oetiker](https://github.com/oetiker))

##### Changed

- `tiny-skia` has a major version bump from 0.11 to 0.12.
renovate Bot added a commit to gwennlbh/vgvf that referenced this pull request Aug 9, 2026
##### [v0.48.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0480-2026-07-31)

This release has an MSRV of 1.89.0 for `usvg` and `resvg` and the C API.

The big change in this release is that text support is now backed by
[`skrifa`](https://github.com/googlefonts/fontations) and
[`harfrust`](https://github.com/harfbuzz/harfrust) rather than
[`ttf-parser`](https://github.com/harfbuzz/ttf-parser) and
[`rustybuzz`](https://github.com/harfbuzz/rustybuzz):

- Moves resvg onto an actively maintained font stack.
- Should have faster and more correct text rendering.
- Will enable further improvements to things like variable font rendering in future.
- May impact binary size (expected +\~500kb for people not otherwise including fontations dependencies in their tree).
- May result in small rendering changes compared to older versions of resvg.

##### Added

- New `svgz` and `writer` feature gates to reduce the number of required dependencies. ([#1088](linebender/resvg#1088) by [@reed-smout](https://github.com/reed-smout))
- Warnings when parsing malformed paths. ([#1011](linebender/resvg#1011))
- A `Display` implementation for `Units`. ([#986](linebender/resvg#986))

##### Changed

- MSRV bumped from 1.87 to 1.89. The requirement comes from `font-types`.
- Text shaping now uses `harfrust` instead of `rustybuzz`, and font parsing uses `skrifa` (fontations) instead of `ttf-parser`. ([#922](linebender/resvg#922) by [@nicoburns](https://github.com/nicoburns))
- Filter input dimension checks are now debug-only assertions. ([#991](linebender/resvg#991))

##### Fixed

- Glyph advances are now calculated correctly. ([#1043](linebender/resvg#1043) by [@fundon](https://github.com/fundon))
- Text nodes now inherit their absolute transform. ([#1040](linebender/resvg#1040) by [@fundon](https://github.com/fundon))
- Fixes related to non-finite values. ([#1049](linebender/resvg#1049) by [@SAY-5](https://github.com/SAY-5))
- Transforms are no longer applied twice in `abs_transform`. ([#1056](linebender/resvg#1056) by [@fundon](https://github.com/fundon))
- `fr` is now resolved for radial gradients referenced via `href`. ([#1098](linebender/resvg#1098) by [@T1mVo](https://github.com/T1mVo))
- Panic in `feComposite` with the `arithmetic` operator when the filter region is larger than the clamped layer. ([#1021](linebender/resvg#1021), [#1007](linebender/resvg#1007))
- Application of `transform` (and other group properties like `opacity`) on a nested `svg`
  element.
- The missing dimension of an `svg` with only `width` or `height` specified is now computed from its `viewBox` aspect ratio. ([#1045](linebender/resvg#1045))
- The `wght` variation coordinate is now set even when `font-weight` has its default value. ([#1099](linebender/resvg#1099))
- The unprefixed `href` attribute now takes precedence over the deprecated `xlink:href` when both are present, as required by SVG 2. ([#1015](linebender/resvg#1015))
- Incorrect y-axis offsets when transforming `feSpotLight` sources. ([#1052](linebender/resvg#1052))
- Panics caused by bounding boxes that exceed the supported integer range. ([#989](linebender/resvg#989))
##### [v0.47.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0470-2026-02-05)

This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API.

##### Added

- Focal radius (`fr`) supported for Radial Gradients. ([#1014](linebender/resvg#1014) by [@wmedrano](https://github.com/wmedrano))
- Support for variable fonts based on font-variation-settings CSS property. ([#997](linebender/resvg#997) by [@oetiker](https://github.com/oetiker))

##### Changed

- `tiny-skia` has a major version bump from 0.11 to 0.12.
renovate Bot added a commit to gwennlbh/shapemaker that referenced this pull request Aug 9, 2026
##### [v0.48.1](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0481-2026-08-02)

This release has an MSRV of 1.85.0 for `usvg` and `resvg` and the C API.

##### Changed

- MSRV lowered from 1.89 to 1.85. ([#1109](linebender/resvg#1109))
- Downgraded strict-num dependency to 0.1.1. This prevents duplicate versions from being included ([#1110](linebender/resvg#1110))

##### Fixed

- Fixed an `as_mut_slice` future-compatibility warning. ([#1108](linebender/resvg#1108))
##### [v0.48.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0480-2026-07-31)

This release has an MSRV of 1.89.0 for `usvg` and `resvg` and the C API.

The big change in this release is that text support is now backed by
[`skrifa`](https://github.com/googlefonts/fontations) and
[`harfrust`](https://github.com/harfbuzz/harfrust) rather than
[`ttf-parser`](https://github.com/harfbuzz/ttf-parser) and
[`rustybuzz`](https://github.com/harfbuzz/rustybuzz):

- Moves resvg onto an actively maintained font stack.
- Should have faster and more correct text rendering.
- Will enable further improvements to things like variable font rendering in future.
- May impact binary size (expected +\~500kb for people not otherwise including fontations dependencies in their tree).
- May result in small rendering changes compared to older versions of resvg.

##### Added

- New `svgz` and `writer` feature gates to reduce the number of required dependencies. ([#1088](linebender/resvg#1088) by [@reed-smout](https://github.com/reed-smout))
- Warnings when parsing malformed paths. ([#1011](linebender/resvg#1011))
- A `Display` implementation for `Units`. ([#986](linebender/resvg#986))

##### Changed

- MSRV bumped from 1.87 to 1.89. The requirement comes from `font-types`.
- Text shaping now uses `harfrust` instead of `rustybuzz`, and font parsing uses `skrifa` (fontations) instead of `ttf-parser`. ([#922](linebender/resvg#922) by [@nicoburns](https://github.com/nicoburns))
- Filter input dimension checks are now debug-only assertions. ([#991](linebender/resvg#991))

##### Fixed

- Glyph advances are now calculated correctly. ([#1043](linebender/resvg#1043) by [@fundon](https://github.com/fundon))
- Text nodes now inherit their absolute transform. ([#1040](linebender/resvg#1040) by [@fundon](https://github.com/fundon))
- Fixes related to non-finite values. ([#1049](linebender/resvg#1049) by [@SAY-5](https://github.com/SAY-5))
- Transforms are no longer applied twice in `abs_transform`. ([#1056](linebender/resvg#1056) by [@fundon](https://github.com/fundon))
- `fr` is now resolved for radial gradients referenced via `href`. ([#1098](linebender/resvg#1098) by [@T1mVo](https://github.com/T1mVo))
- Panic in `feComposite` with the `arithmetic` operator when the filter region is larger than the clamped layer. ([#1021](linebender/resvg#1021), [#1007](linebender/resvg#1007))
- Application of `transform` (and other group properties like `opacity`) on a nested `svg`
  element.
- The missing dimension of an `svg` with only `width` or `height` specified is now computed from its `viewBox` aspect ratio. ([#1045](linebender/resvg#1045))
- The `wght` variation coordinate is now set even when `font-weight` has its default value. ([#1099](linebender/resvg#1099))
- The unprefixed `href` attribute now takes precedence over the deprecated `xlink:href` when both are present, as required by SVG 2. ([#1015](linebender/resvg#1015))
- Incorrect y-axis offsets when transforming `feSpotLight` sources. ([#1052](linebender/resvg#1052))
- Panics caused by bounding boxes that exceed the supported integer range. ([#989](linebender/resvg#989))
##### [v0.47.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0470-2026-02-05)

This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API.

##### Added

- Focal radius (`fr`) supported for Radial Gradients. ([#1014](linebender/resvg#1014) by [@wmedrano](https://github.com/wmedrano))
- Support for variable fonts based on font-variation-settings CSS property. ([#997](linebender/resvg#997) by [@oetiker](https://github.com/oetiker))

##### Changed

- `tiny-skia` has a major version bump from 0.11 to 0.12.
renovate Bot added a commit to gwennlbh/vgvf that referenced this pull request Aug 9, 2026
##### [v0.48.1](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0481-2026-08-02)

This release has an MSRV of 1.85.0 for `usvg` and `resvg` and the C API.

##### Changed

- MSRV lowered from 1.89 to 1.85. ([#1109](linebender/resvg#1109))
- Downgraded strict-num dependency to 0.1.1. This prevents duplicate versions from being included ([#1110](linebender/resvg#1110))

##### Fixed

- Fixed an `as_mut_slice` future-compatibility warning. ([#1108](linebender/resvg#1108))
##### [v0.48.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0480-2026-07-31)

This release has an MSRV of 1.89.0 for `usvg` and `resvg` and the C API.

The big change in this release is that text support is now backed by
[`skrifa`](https://github.com/googlefonts/fontations) and
[`harfrust`](https://github.com/harfbuzz/harfrust) rather than
[`ttf-parser`](https://github.com/harfbuzz/ttf-parser) and
[`rustybuzz`](https://github.com/harfbuzz/rustybuzz):

- Moves resvg onto an actively maintained font stack.
- Should have faster and more correct text rendering.
- Will enable further improvements to things like variable font rendering in future.
- May impact binary size (expected +\~500kb for people not otherwise including fontations dependencies in their tree).
- May result in small rendering changes compared to older versions of resvg.

##### Added

- New `svgz` and `writer` feature gates to reduce the number of required dependencies. ([#1088](linebender/resvg#1088) by [@reed-smout](https://github.com/reed-smout))
- Warnings when parsing malformed paths. ([#1011](linebender/resvg#1011))
- A `Display` implementation for `Units`. ([#986](linebender/resvg#986))

##### Changed

- MSRV bumped from 1.87 to 1.89. The requirement comes from `font-types`.
- Text shaping now uses `harfrust` instead of `rustybuzz`, and font parsing uses `skrifa` (fontations) instead of `ttf-parser`. ([#922](linebender/resvg#922) by [@nicoburns](https://github.com/nicoburns))
- Filter input dimension checks are now debug-only assertions. ([#991](linebender/resvg#991))

##### Fixed

- Glyph advances are now calculated correctly. ([#1043](linebender/resvg#1043) by [@fundon](https://github.com/fundon))
- Text nodes now inherit their absolute transform. ([#1040](linebender/resvg#1040) by [@fundon](https://github.com/fundon))
- Fixes related to non-finite values. ([#1049](linebender/resvg#1049) by [@SAY-5](https://github.com/SAY-5))
- Transforms are no longer applied twice in `abs_transform`. ([#1056](linebender/resvg#1056) by [@fundon](https://github.com/fundon))
- `fr` is now resolved for radial gradients referenced via `href`. ([#1098](linebender/resvg#1098) by [@T1mVo](https://github.com/T1mVo))
- Panic in `feComposite` with the `arithmetic` operator when the filter region is larger than the clamped layer. ([#1021](linebender/resvg#1021), [#1007](linebender/resvg#1007))
- Application of `transform` (and other group properties like `opacity`) on a nested `svg`
  element.
- The missing dimension of an `svg` with only `width` or `height` specified is now computed from its `viewBox` aspect ratio. ([#1045](linebender/resvg#1045))
- The `wght` variation coordinate is now set even when `font-weight` has its default value. ([#1099](linebender/resvg#1099))
- The unprefixed `href` attribute now takes precedence over the deprecated `xlink:href` when both are present, as required by SVG 2. ([#1015](linebender/resvg#1015))
- Incorrect y-axis offsets when transforming `feSpotLight` sources. ([#1052](linebender/resvg#1052))
- Panics caused by bounding boxes that exceed the supported integer range. ([#989](linebender/resvg#989))
##### [v0.47.0](https://github.com/linebender/resvg/blob/HEAD/CHANGELOG.md#0470-2026-02-05)

This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API.

##### Added

- Focal radius (`fr`) supported for Radial Gradients. ([#1014](linebender/resvg#1014) by [@wmedrano](https://github.com/wmedrano))
- Support for variable fonts based on font-variation-settings CSS property. ([#997](linebender/resvg#997) by [@oetiker](https://github.com/oetiker))

##### Changed

- `tiny-skia` has a major version bump from 0.11 to 0.12.
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.