From 15334d54e8d24165368d2a009bb182020ba7f106 Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Sat, 10 Jan 2026 15:27:32 +0100 Subject: [PATCH] Port to harfrust/skrifa with hinting and variable font support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supersedes #922 (nicoburns' "Port resvg to harfrust and fontations") This patch builds upon the excellent groundwork laid out in PR #922, which identified harfrust and skrifa as the path forward for long-term maintainability. As noted in that discussion, these actively-maintained libraries offer significant advantages: harfrust passes substantially more shaping tests than rustybuzz, and skrifa provides a modern, well-designed API for font parsing. Core migration (shared with #922): - Replace rustybuzz with harfrust for OpenType text shaping - Replace ttf-parser with skrifa for font parsing and metrics - Update font metrics extraction to use skrifa's MetadataProvider Where this implementation extends #922: 1. Font Hinting Support - Add optional `hinting` feature and HintingOptions in parser options - Implement hinted outline extraction via skrifa's HintingInstance - Honor CSS text-rendering property: geometricPrecision disables hinting, optimizeLegibility/optimizeSpeed enable full hinting - Configurable DPI for ppem calculation 2. Full Variable Font Support - Parse font-variation-settings CSS property - Parse font-optical-sizing CSS property (auto/none) - Auto-map standard properties to variation axes: * font-weight → wght axis * font-stretch → wdth axis * font-style: italic → ital axis * font-style: oblique → slnt axis - Auto-set opsz axis based on font size when font-optical-sizing: auto - Store per-glyph variation context in PositionedGlyph for correct outline extraction with variations applied 3. Modular Skrifa Integration - New skrifa_metrics.rs: Font metrics via skrifa's MetadataProvider - New skrifa_colr.rs: COLR rendering via skrifa's ColorPainter trait - Delete legacy colr.rs (ttf-parser based implementation) 4. Enhanced COLR Support - Implement skrifa's ColorPainter trait for SVG output - Support COLRv1 features: transforms, clips, composite modes - Handle linear, radial gradients with proper spread methods 5. Test Infrastructure - Add tests-hinted/ directory with hinted reference images - Add font-variation-settings test suite - Include RobotoFlex variable font for variation testing We appreciate the careful analysis in #922 regarding the ecosystem trade-offs, particularly around compile times and binary size. This implementation accepts those trade-offs in exchange for the additional capabilities (hinting, variable fonts) that skrifa enables. Co-Authored-By: Claude Opus 4.5 --- .typos.toml | 1 + Cargo.lock | 133 +++- crates/resvg/Cargo.toml | 6 + .../examples/generate_hinting_comparison.rs | 78 ++ crates/resvg/src/main.rs | 2 + .../text/alignment-baseline/after-edge.png | Bin 0 -> 1252 bytes .../text/alignment-baseline/alphabetic.png | Bin 0 -> 1300 bytes .../tests/text/alignment-baseline/auto.png | Bin 0 -> 1300 bytes .../text/alignment-baseline/baseline.png | Bin 0 -> 1300 bytes .../text/alignment-baseline/before-edge.png | Bin 0 -> 1265 bytes .../tests/text/alignment-baseline/central.png | Bin 0 -> 1330 bytes ...ging-and-baseline-shift-eq-20-on-tspan.png | Bin 0 -> 2125 bytes .../alignment-baseline/hanging-on-tspan.png | Bin 0 -> 2108 bytes .../hanging-on-vertical.png | Bin 0 -> 1587 bytes .../hanging-with-underline.png | Bin 0 -> 2157 bytes .../tests/text/alignment-baseline/hanging.png | Bin 0 -> 1244 bytes .../text/alignment-baseline/ideographic.png | Bin 0 -> 1252 bytes .../tests/text/alignment-baseline/inherit.png | Bin 0 -> 1244 bytes .../text/alignment-baseline/mathematical.png | Bin 0 -> 1316 bytes .../alignment-baseline/middle-on-textPath.png | Bin 0 -> 3445 bytes .../tests/text/alignment-baseline/middle.png | Bin 0 -> 1312 bytes .../alignment-baseline/text-after-edge.png | Bin 0 -> 1252 bytes .../alignment-baseline/text-before-edge.png | Bin 0 -> 1265 bytes .../two-textPath-with-middle-on-first.png | Bin 0 -> 5701 bytes .../tests/text/baseline-shift/-10.png | Bin 0 -> 2106 bytes .../tests/text/baseline-shift/-50percent.png | Bin 0 -> 2108 bytes .../tests/text/baseline-shift/0.png | Bin 0 -> 2093 bytes .../tests/text/baseline-shift/10.png | Bin 0 -> 2059 bytes .../tests/text/baseline-shift/2mm.png | Bin 0 -> 2092 bytes .../tests/text/baseline-shift/50percent.png | Bin 0 -> 2061 bytes .../tests/text/baseline-shift/baseline.png | Bin 0 -> 2093 bytes .../baseline-shift/deeply-nested-super.png | Bin 0 -> 1573 bytes .../text/baseline-shift/inheritance-1.png | Bin 0 -> 1680 bytes .../text/baseline-shift/inheritance-2.png | Bin 0 -> 1624 bytes .../text/baseline-shift/inheritance-3.png | Bin 0 -> 1624 bytes .../text/baseline-shift/inheritance-4.png | Bin 0 -> 1624 bytes .../text/baseline-shift/inheritance-5.png | Bin 0 -> 1624 bytes .../text/baseline-shift/invalid-value.png | Bin 0 -> 2093 bytes .../text/baseline-shift/mixed-nested.png | Bin 0 -> 1781 bytes .../text/baseline-shift/nested-length.png | Bin 0 -> 2052 bytes .../text/baseline-shift/nested-super.png | Bin 0 -> 2063 bytes .../baseline-shift/nested-with-baseline-1.png | Bin 0 -> 1571 bytes .../baseline-shift/nested-with-baseline-2.png | Bin 0 -> 1571 bytes .../tests/text/baseline-shift/sub.png | Bin 0 -> 2107 bytes .../tests/text/baseline-shift/super.png | Bin 0 -> 2056 bytes .../tests/text/baseline-shift/with-rotate.png | Bin 0 -> 2304 bytes .../tests/text/color-font/cbdt.png | Bin 0 -> 10675 bytes .../tests/text/color-font/colrv0.png | Bin 0 -> 1533 bytes .../tests/text/color-font/colrv1.png | Bin 0 -> 6295 bytes .../compound-emojis-and-coordinates-list.png | Bin 0 -> 5800 bytes .../tests/text/color-font/compound-emojis.png | Bin 0 -> 822 bytes .../tests/text/color-font/mixed-text-rtl.png | Bin 0 -> 758 bytes .../tests/text/color-font/mixed-text.png | Bin 0 -> 1731 bytes .../tests/text/color-font/sbix.png | Bin 0 -> 3375 bytes .../tests/text/color-font/svg.png | Bin 0 -> 1843 bytes .../tests/text/color-font/writing-mode=tb.png | Bin 0 -> 1473 bytes .../rtl-with-vertical-writing-mode.png | Bin 0 -> 959 bytes .../tests-hinted/tests/text/direction/rtl.png | Bin 0 -> 941 bytes ...-baseline-and-baseline-shift-on-tspans.png | Bin 0 -> 1792 bytes .../alignment-baseline=baseline-on-tspan.png | Bin 0 -> 1452 bytes .../text/dominant-baseline/alphabetic.png | Bin 0 -> 1148 bytes .../tests/text/dominant-baseline/auto.png | Bin 0 -> 1148 bytes .../tests/text/dominant-baseline/central.png | Bin 0 -> 1176 bytes .../tests/text/dominant-baseline/complex.png | Bin 0 -> 1484 bytes .../different-alignment-baseline-on-tspan.png | Bin 0 -> 1809 bytes .../text/dominant-baseline/dummy-tspan.png | Bin 0 -> 1452 bytes .../equal-alignment-baseline-on-tspan.png | Bin 0 -> 1753 bytes .../tests/text/dominant-baseline/hanging.png | Bin 0 -> 840 bytes .../text/dominant-baseline/ideographic.png | Bin 0 -> 1111 bytes .../tests/text/dominant-baseline/inherit.png | Bin 0 -> 1171 bytes .../text/dominant-baseline/mathematical.png | Bin 0 -> 1204 bytes .../tests/text/dominant-baseline/middle.png | Bin 0 -> 1171 bytes .../tests/text/dominant-baseline/nested.png | Bin 0 -> 1794 bytes .../text/dominant-baseline/no-change.png | Bin 0 -> 1853 bytes .../text/dominant-baseline/reset-size.png | Bin 0 -> 1148 bytes .../text/dominant-baseline/sequential.png | Bin 0 -> 1769 bytes .../dominant-baseline/text-after-edge.png | Bin 0 -> 1111 bytes .../dominant-baseline/text-before-edge.png | Bin 0 -> 1149 bytes .../text/dominant-baseline/use-script.png | Bin 0 -> 874 bytes .../text/font-family/bold-sans-serif.png | Bin 0 -> 1166 bytes .../tests/text/font-family/cursive.png | Bin 0 -> 1404 bytes .../tests/text/font-family/double-quoted.png | Bin 0 -> 1165 bytes .../tests/text/font-family/fallback-1.png | Bin 0 -> 1265 bytes .../tests/text/font-family/fallback-2.png | Bin 0 -> 1165 bytes .../tests/text/font-family/fantasy.png | Bin 0 -> 1439 bytes .../tests/text/font-family/font-list.png | Bin 0 -> 1130 bytes .../tests/text/font-family/monospace.png | Bin 0 -> 1208 bytes .../tests/text/font-family/noto-sans.png | Bin 0 -> 1165 bytes .../tests/text/font-family/sans-serif.png | Bin 0 -> 1165 bytes .../tests/text/font-family/serif.png | Bin 0 -> 1260 bytes .../text/font-family/source-sans-pro.png | Bin 0 -> 1130 bytes .../tests/text/font-kerning/arabic-script.png | Bin 0 -> 1643 bytes .../tests/text/font-kerning/as-property.png | Bin 0 -> 1555 bytes .../tests/text/font-kerning/none.png | Bin 0 -> 2182 bytes .../text/font-size-adjust/simple-case.png | Bin 0 -> 1486 bytes .../text/font-size/em-nested-and-mixed.png | Bin 0 -> 1109 bytes .../text/font-size/em-on-the-root-element.png | Bin 0 -> 1109 bytes .../tests-hinted/tests/text/font-size/em.png | Bin 0 -> 1109 bytes .../text/font-size/ex-nested-and-mixed.png | Bin 0 -> 1018 bytes .../text/font-size/ex-on-the-root-element.png | Bin 0 -> 1072 bytes .../tests-hinted/tests/text/font-size/ex.png | Bin 0 -> 1072 bytes .../tests/text/font-size/inheritance.png | Bin 0 -> 1165 bytes .../tests/text/font-size/mixed-values.png | Bin 0 -> 1120 bytes .../named-value-without-a-parent.png | Bin 0 -> 922 bytes .../tests/text/font-size/named-value.png | Bin 0 -> 1801 bytes .../tests/text/font-size/negative-size.png | Bin 0 -> 642 bytes .../font-size/nested-percent-values-1.png | Bin 0 -> 1121 bytes .../font-size/nested-percent-values-2.png | Bin 0 -> 1121 bytes .../percent-value-without-a-parent.png | Bin 0 -> 1105 bytes .../tests/text/font-size/percent-value.png | Bin 0 -> 1121 bytes .../tests/text/font-size/simple-case.png | Bin 0 -> 1165 bytes .../text/font-size/zero-size-on-parent-1.png | Bin 0 -> 1165 bytes .../text/font-size/zero-size-on-parent-2.png | Bin 0 -> 1165 bytes .../text/font-size/zero-size-on-parent-3.png | Bin 0 -> 642 bytes .../tests/text/font-size/zero-size.png | Bin 0 -> 642 bytes .../text/font-stretch/extra-condensed.png | Bin 0 -> 1165 bytes .../tests/text/font-stretch/inherit.png | Bin 0 -> 1165 bytes .../tests/text/font-stretch/narrower.png | Bin 0 -> 1165 bytes .../tests/text/font-style/inherit.png | Bin 0 -> 1346 bytes .../tests/text/font-style/italic.png | Bin 0 -> 1346 bytes .../tests/text/font-style/oblique.png | Bin 0 -> 1346 bytes .../tests/text/font-variant/inherit.png | Bin 0 -> 1070 bytes .../tests/text/font-variant/small-caps.png | Bin 0 -> 1070 bytes .../all-axes-combined.png | Bin 0 -> 1267 bytes .../auto-font-stretch-condensed.png | Bin 0 -> 1529 bytes .../auto-font-style-oblique.png | Bin 0 -> 1520 bytes .../auto-font-weight-700.png | Bin 0 -> 1176 bytes .../explicit-overrides-auto.png | Bin 0 -> 808 bytes .../font-variation-settings/grad-negative.png | Bin 0 -> 1453 bytes .../font-variation-settings/multiple-axes.png | Bin 0 -> 1147 bytes .../text/font-variation-settings/opsz-144.png | Bin 0 -> 1613 bytes .../font-variation-settings/slnt-negative.png | Bin 0 -> 1520 bytes .../text/font-variation-settings/wdth-151.png | Bin 0 -> 1585 bytes .../text/font-variation-settings/wdth-25.png | Bin 0 -> 1439 bytes .../text/font-variation-settings/wght-100.png | Bin 0 -> 808 bytes .../text/font-variation-settings/wght-700.png | Bin 0 -> 1176 bytes .../font-variation-settings/xtra-extreme.png | Bin 0 -> 1624 bytes .../tests/text/font-weight/650.png | Bin 0 -> 1216 bytes .../tests/text/font-weight/700.png | Bin 0 -> 1166 bytes .../tests/text/font-weight/bold.png | Bin 0 -> 1211 bytes .../text/font-weight/bolder-with-clamping.png | Bin 0 -> 1210 bytes .../font-weight/bolder-without-parent.png | Bin 0 -> 1211 bytes .../tests/text/font-weight/bolder.png | Bin 0 -> 1211 bytes .../tests/text/font-weight/inherit.png | Bin 0 -> 1216 bytes .../text/font-weight/invalid-number-1.png | Bin 0 -> 1216 bytes .../font-weight/lighter-with-clamping.png | Bin 0 -> 1135 bytes .../font-weight/lighter-without-parent.png | Bin 0 -> 1135 bytes .../tests/text/font-weight/lighter.png | Bin 0 -> 1211 bytes .../tests/text/font-weight/normal.png | Bin 0 -> 1216 bytes .../tests/text/font/font-shorthand.png | Bin 0 -> 1736 bytes .../tests/text/font/simple-case.png | Bin 0 -> 905 bytes .../simple-case.png | Bin 0 -> 1205 bytes .../simple-case.png | Bin 0 -> 1267 bytes .../tests-hinted/tests/text/kerning/0.png | Bin 0 -> 2358 bytes .../tests/text/kerning/10percent.png | Bin 0 -> 1454 bytes .../text/lengthAdjust/spacingAndGlyphs.png | Bin 0 -> 1559 bytes .../tests/text/lengthAdjust/text-on-path.png | Bin 0 -> 3362 bytes .../tests/text/lengthAdjust/vertical.png | Bin 0 -> 1675 bytes .../text/lengthAdjust/with-underline.png | Bin 0 -> 1575 bytes .../tests/text/letter-spacing/-3.png | Bin 0 -> 1630 bytes .../tests/text/letter-spacing/0.png | Bin 0 -> 1670 bytes .../tests/text/letter-spacing/1mm.png | Bin 0 -> 1715 bytes .../tests/text/letter-spacing/3.png | Bin 0 -> 1681 bytes .../tests/text/letter-spacing/5percent.png | Bin 0 -> 1705 bytes .../tests/text/letter-spacing/filter-bbox.png | Bin 0 -> 1059 bytes .../text/letter-spacing/large-negative.png | Bin 0 -> 736 bytes .../text/letter-spacing/mixed-scripts.png | Bin 0 -> 1529 bytes .../text/letter-spacing/mixed-spacing.png | Bin 0 -> 1392 bytes .../letter-spacing/non-ASCII-character.png | Bin 0 -> 908 bytes .../tests/text/letter-spacing/normal.png | Bin 0 -> 1670 bytes .../tests/text/letter-spacing/on-Arabic.png | Bin 0 -> 1690 bytes .../text/text-anchor/coordinates-list.png | Bin 0 -> 1036 bytes .../tests/text/text-anchor/end-on-text.png | Bin 0 -> 1408 bytes .../text-anchor/end-with-letter-spacing.png | Bin 0 -> 1247 bytes .../tests/text/text-anchor/inheritance-1.png | Bin 0 -> 2390 bytes .../tests/text/text-anchor/inheritance-2.png | Bin 0 -> 1247 bytes .../tests/text/text-anchor/inheritance-3.png | Bin 0 -> 1644 bytes .../text-anchor/invalid-value-on-text.png | Bin 0 -> 1442 bytes .../tests/text/text-anchor/middle-on-text.png | Bin 0 -> 1454 bytes .../text/text-anchor/on-the-first-tspan.png | Bin 0 -> 1350 bytes .../text/text-anchor/on-tspan-with-arabic.png | Bin 0 -> 2405 bytes .../tests/text/text-anchor/on-tspan.png | Bin 0 -> 2518 bytes .../tests/text/text-anchor/start-on-text.png | Bin 0 -> 1442 bytes .../text-anchor-not-on-text-chunk.png | Bin 0 -> 2054 bytes .../all-types-inline-comma-separated.png | Bin 0 -> 2079 bytes .../all-types-inline-no-spaces.png | Bin 0 -> 2079 bytes .../text/text-decoration/all-types-inline.png | Bin 0 -> 2237 bytes .../text/text-decoration/all-types-nested.png | Bin 0 -> 2237 bytes .../indirect-with-multiple-colors.png | Bin 0 -> 2702 bytes .../tests/text/text-decoration/indirect.png | Bin 0 -> 1503 bytes .../text/text-decoration/line-through.png | Bin 0 -> 2163 bytes .../outside-the-text-element.png | Bin 0 -> 1503 bytes .../tests/text/text-decoration/overline.png | Bin 0 -> 2117 bytes .../text-decoration/style-resolving-1.png | Bin 0 -> 2355 bytes .../text-decoration/style-resolving-2.png | Bin 0 -> 2355 bytes .../text-decoration/style-resolving-3.png | Bin 0 -> 2278 bytes .../text-decoration/style-resolving-4.png | Bin 0 -> 2113 bytes .../text/text-decoration/tspan-decoration.png | Bin 0 -> 6396 bytes .../underline-with-dy-list-1.png | Bin 0 -> 1526 bytes .../underline-with-dy-list-2.png | Bin 0 -> 5553 bytes .../underline-with-rotate-list-3.png | Bin 0 -> 2143 bytes .../underline-with-rotate-list-4.png | Bin 0 -> 7991 bytes .../text-decoration/underline-with-y-list.png | Bin 0 -> 1490 bytes .../tests/text/text-decoration/underline.png | Bin 0 -> 2125 bytes .../with-textLength-on-a-single-character.png | Bin 0 -> 1109 bytes .../text-rendering/geometricPrecision.png | Bin 0 -> 2030 bytes .../tests/text/text-rendering/on-tspan.png | Bin 0 -> 1454 bytes .../text-rendering/optimizeLegibility.png | Bin 0 -> 1570 bytes .../text/text-rendering/optimizeSpeed.png | Bin 0 -> 1696 bytes .../text/text-rendering/with-underline.png | Bin 0 -> 830 bytes .../tests/text/text/bidi-reordering.png | Bin 0 -> 2107 bytes .../text/complex-grapheme-split-by-tspan.png | Bin 0 -> 1382 bytes ...complex-graphemes-and-coordinates-list.png | Bin 0 -> 994 bytes .../tests/text/text/complex-graphemes.png | Bin 0 -> 1035 bytes .../text/dx-and-dy-instead-of-x-and-y.png | Bin 0 -> 1673 bytes ...nd-dy-with-less-values-than-characters.png | Bin 0 -> 1674 bytes ...nd-dy-with-more-values-than-characters.png | Bin 0 -> 1681 bytes .../text/dx-and-dy-with-multiple-values.png | Bin 0 -> 1681 bytes .../tests/text/text/em-and-ex-coordinates.png | Bin 0 -> 1658 bytes .../tests/text/text/escaped-text-1.png | Bin 0 -> 1621 bytes .../tests/text/text/escaped-text-2.png | Bin 0 -> 1517 bytes .../tests/text/text/escaped-text-3.png | Bin 0 -> 2093 bytes .../tests/text/text/escaped-text-4.png | Bin 0 -> 1257 bytes .../tests/text/text/fill-rule=evenodd.png | Bin 0 -> 1702 bytes .../tests/text/text/filter-bbox.png | Bin 0 -> 1456 bytes .../tests/text/text/glyph-splitting.png | Bin 0 -> 1323 bytes .../ligatures-handling-in-mixed-fonts-1.png | Bin 0 -> 1592 bytes .../ligatures-handling-in-mixed-fonts-2.png | Bin 0 -> 1610 bytes .../tests/text/text/mm-coordinates.png | Bin 0 -> 1707 bytes .../tests-hinted/tests/text/text/nested.png | Bin 0 -> 699 bytes .../tests/text/text/no-coordinates.png | Bin 0 -> 1704 bytes .../text/text/percent-value-on-dx-and-dy.png | Bin 0 -> 1196 bytes .../text/text/percent-value-on-x-and-y.png | Bin 0 -> 1196 bytes .../tests/text/text/real-text-height.png | Bin 0 -> 1826 bytes .../tests/text/text/rotate-on-Arabic.png | Bin 0 -> 1784 bytes .../text/rotate-with-an-invalid-angle.png | Bin 0 -> 1694 bytes ...otate-with-less-values-than-characters.png | Bin 0 -> 2226 bytes ...otate-with-more-values-than-characters.png | Bin 0 -> 2198 bytes ...-with-multiple-values-and-complex-text.png | Bin 0 -> 2452 bytes ...-multiple-values-underline-and-pattern.png | Bin 0 -> 2766 bytes .../text/text/rotate-with-multiple-values.png | Bin 0 -> 2198 bytes .../tests-hinted/tests/text/text/rotate.png | Bin 0 -> 2180 bytes .../tests/text/text/simple-case.png | Bin 0 -> 1704 bytes .../tests/text/text/transform.png | Bin 0 -> 2062 bytes .../text/x-and-y-with-dx-and-dy-lists.png | Bin 0 -> 1649 bytes .../text/text/x-and-y-with-dx-and-dy.png | Bin 0 -> 1673 bytes ...and-y-with-less-values-than-characters.png | Bin 0 -> 1688 bytes ...and-y-with-more-values-than-characters.png | Bin 0 -> 1679 bytes ...y-with-multiple-values-and-arabic-text.png | Bin 0 -> 2612 bytes ...x-and-y-with-multiple-values-and-tspan.png | Bin 0 -> 1914 bytes .../text/x-and-y-with-multiple-values.png | Bin 0 -> 1679 bytes .../tests/text/text/xml-lang=ja.png | Bin 0 -> 2222 bytes .../tests/text/text/xml-space.png | Bin 0 -> 1438 bytes .../tests-hinted/tests/text/text/zalgo.png | Bin 0 -> 3017 bytes .../tests/text/textLength/150-on-parent.png | Bin 0 -> 1482 bytes .../tests/text/textLength/150-on-tspan.png | Bin 0 -> 1474 bytes .../tests/text/textLength/150.png | Bin 0 -> 1474 bytes .../tests/text/textLength/40mm.png | Bin 0 -> 1484 bytes .../tests/text/textLength/75percent.png | Bin 0 -> 1474 bytes .../textLength/arabic-with-lengthAdjust.png | Bin 0 -> 1817 bytes .../tests/text/textLength/arabic.png | Bin 0 -> 1656 bytes .../tests/text/textLength/inherit.png | Bin 0 -> 1482 bytes .../tests/text/textLength/negative.png | Bin 0 -> 1482 bytes .../text/textLength/on-a-single-tspan.png | Bin 0 -> 1348 bytes .../text/textLength/on-text-and-tspan.png | Bin 0 -> 2100 bytes .../tests/text/textLength/zero.png | Bin 0 -> 1170 bytes .../tests/text/textPath/closed-path.png | Bin 0 -> 6003 bytes .../tests/text/textPath/complex.png | Bin 0 -> 4911 bytes .../textPath/dy-with-tiny-coordinates.png | Bin 0 -> 3457 bytes .../tests/text/textPath/invalid-link.png | Bin 0 -> 642 bytes .../invalid-textPath-in-the-middle.png | Bin 0 -> 1438 bytes .../tests/text/textPath/link-to-rect.png | Bin 0 -> 2092 bytes .../tests/text/textPath/m-A-path.png | Bin 0 -> 3822 bytes .../tests/text/textPath/m-L-Z-path.png | Bin 0 -> 2534 bytes .../tests/text/textPath/method=stretch.png | Bin 0 -> 3475 bytes .../tests/text/textPath/mixed-children-1.png | Bin 0 -> 4259 bytes .../tests/text/textPath/mixed-children-2.png | Bin 0 -> 3748 bytes .../tests/text/textPath/nested.png | Bin 0 -> 3923 bytes .../tests/text/textPath/no-link.png | Bin 0 -> 1796 bytes .../text/textPath/path-with-ClosePath.png | Bin 0 -> 4848 bytes .../path-with-subpaths-and-startOffset.png | Bin 0 -> 1676 bytes .../text/textPath/path-with-subpaths.png | Bin 0 -> 3349 bytes .../tests/text/textPath/side=right.png | Bin 0 -> 3475 bytes .../tests/text/textPath/simple-case.png | Bin 0 -> 3475 bytes .../tests/text/textPath/spacing=auto.png | Bin 0 -> 3475 bytes .../tests/text/textPath/startOffset=-100.png | Bin 0 -> 2337 bytes .../text/textPath/startOffset=10percent.png | Bin 0 -> 3348 bytes .../tests/text/textPath/startOffset=30.png | Bin 0 -> 3525 bytes .../tests/text/textPath/startOffset=5mm.png | Bin 0 -> 3395 bytes .../tests/text/textPath/startOffset=9999.png | Bin 0 -> 1796 bytes .../textPath/tspan-with-absolute-position.png | Bin 0 -> 4408 bytes .../textPath/tspan-with-relative-position.png | Bin 0 -> 3795 bytes .../tests/text/textPath/two-paths.png | Bin 0 -> 3598 bytes .../tests/text/textPath/very-long-text.png | Bin 0 -> 2806 bytes .../with-baseline-shift-and-rotate.png | Bin 0 -> 4468 bytes .../text/textPath/with-baseline-shift.png | Bin 0 -> 4376 bytes .../text/textPath/with-big-letter-spacing.png | Bin 0 -> 2097 bytes .../textPath/with-coordinates-on-text.png | Bin 0 -> 3348 bytes .../textPath/with-coordinates-on-textPath.png | Bin 0 -> 3435 bytes .../tests/text/textPath/with-filter.png | Bin 0 -> 3598 bytes .../with-invalid-path-and-xlink-href.png | Bin 0 -> 1602 bytes .../text/textPath/with-letter-spacing.png | Bin 0 -> 3031 bytes .../textPath/with-path-and-xlink-href.png | Bin 0 -> 1602 bytes .../tests/text/textPath/with-path.png | Bin 0 -> 1602 bytes .../tests/text/textPath/with-rotate.png | Bin 0 -> 3114 bytes .../tests/text/textPath/with-text-anchor.png | Bin 0 -> 2521 bytes .../with-transform-on-a-referenced-path.png | Bin 0 -> 3313 bytes ...th-transform-outside-a-referenced-path.png | Bin 0 -> 3297 bytes .../tests/text/textPath/with-underline.png | Bin 0 -> 3988 bytes .../tests/text/textPath/writing-mode=tb.png | Bin 0 -> 3787 bytes .../text/tref/link-to-a-complex-text.png | Bin 0 -> 1955 bytes .../text/tref/link-to-a-non-SVG-element.png | Bin 0 -> 699 bytes .../text/tref/link-to-a-non-text-element.png | Bin 0 -> 1621 bytes .../tref/link-to-an-external-file-element.png | Bin 0 -> 1701 bytes .../tests/text/tref/link-to-text.png | Bin 0 -> 1621 bytes .../tests-hinted/tests/text/tref/nested.png | Bin 0 -> 699 bytes .../tests/text/tref/position-attributes.png | Bin 0 -> 1621 bytes .../tests/text/tref/style-attributes.png | Bin 0 -> 1621 bytes .../tests/text/tref/with-a-title-child.png | Bin 0 -> 1993 bytes .../tests/text/tref/with-text.png | Bin 0 -> 1993 bytes .../tests/text/tref/xml-space.png | Bin 0 -> 1496 bytes .../tests/text/tspan/bidi-reordering.png | Bin 0 -> 3792 bytes .../tests/text/tspan/mixed-font-size.png | Bin 0 -> 1826 bytes .../tests/text/tspan/mixed-xml-space-1.png | Bin 0 -> 1884 bytes .../tests/text/tspan/mixed-xml-space-2.png | Bin 0 -> 1839 bytes .../tests/text/tspan/mixed-xml-space-3.png | Bin 0 -> 1364 bytes .../tests-hinted/tests/text/tspan/mixed.png | Bin 0 -> 1906 bytes .../tests/text/tspan/multiple-coordinates.png | Bin 0 -> 1633 bytes .../tests/text/tspan/nested-rotate.png | Bin 0 -> 4024 bytes .../tests/text/tspan/nested-whitespaces.png | Bin 0 -> 1704 bytes .../tests-hinted/tests/text/tspan/nested.png | Bin 0 -> 1675 bytes .../tests/text/tspan/only-with-y.png | Bin 0 -> 1673 bytes .../tests/text/tspan/outside-the-text.png | Bin 0 -> 699 bytes .../tests/text/tspan/pseudo-multi-line.png | Bin 0 -> 1947 bytes .../text/tspan/rotate-and-display-none.png | Bin 0 -> 1399 bytes .../tests/text/tspan/rotate-on-child.png | Bin 0 -> 2067 bytes .../tests/text/tspan/sequential.png | Bin 0 -> 1906 bytes .../tests/text/tspan/style-override.png | Bin 0 -> 1701 bytes .../text-shaping-across-multiple-tspan-1.png | Bin 0 -> 1667 bytes .../text-shaping-across-multiple-tspan-2.png | Bin 0 -> 2823 bytes .../tests/text/tspan/transform.png | Bin 0 -> 1673 bytes .../tests/text/tspan/tspan-bbox-1.png | Bin 0 -> 3762 bytes .../tests/text/tspan/tspan-bbox-2.png | Bin 0 -> 1688 bytes .../tspan/tspan-span-and-BIDI-reordering.png | Bin 0 -> 3849 bytes .../tests/text/tspan/with-clip-path.png | Bin 0 -> 1673 bytes .../tests-hinted/tests/text/tspan/with-dy.png | Bin 0 -> 1609 bytes .../tests/text/tspan/with-filter.png | Bin 0 -> 1673 bytes .../tests/text/tspan/with-mask.png | Bin 0 -> 1673 bytes .../tests/text/tspan/with-opacity.png | Bin 0 -> 1822 bytes .../tests/text/tspan/with-x-and-y.png | Bin 0 -> 1673 bytes .../tests/text/tspan/without-attributes.png | Bin 0 -> 1673 bytes .../tests/text/tspan/xml-space-1.png | Bin 0 -> 1594 bytes .../tests/text/tspan/xml-space-2.png | Bin 0 -> 1594 bytes .../tests/text/unicode-bidi/bidi-override.png | Bin 0 -> 1776 bytes .../tests/text/word-spacing/-5.png | Bin 0 -> 1723 bytes .../tests/text/word-spacing/0.png | Bin 0 -> 1728 bytes .../tests/text/word-spacing/10.png | Bin 0 -> 1739 bytes .../tests/text/word-spacing/2mm.png | Bin 0 -> 1735 bytes .../tests/text/word-spacing/5percent.png | Bin 0 -> 1739 bytes .../text/word-spacing/large-negative.png | Bin 0 -> 699 bytes .../tests/text/word-spacing/normal.png | Bin 0 -> 1728 bytes .../text/writing-mode/arabic-with-rl.png | Bin 0 -> 1680 bytes .../tests/text/writing-mode/horizontal-tb.png | Bin 0 -> 1680 bytes .../tests/text/writing-mode/inheritance.png | Bin 0 -> 1700 bytes .../tests/text/writing-mode/invalid-value.png | Bin 0 -> 1680 bytes .../text/writing-mode/japanese-with-tb.png | Bin 0 -> 1301 bytes .../tests/text/writing-mode/lr-tb.png | Bin 0 -> 1680 bytes .../tests/text/writing-mode/lr.png | Bin 0 -> 1680 bytes .../mixed-languages-with-tb-and-underline.png | Bin 0 -> 1590 bytes .../writing-mode/mixed-languages-with-tb.png | Bin 0 -> 1868 bytes .../tests/text/writing-mode/on-tspan.png | Bin 0 -> 1680 bytes .../tests/text/writing-mode/rl-tb.png | Bin 0 -> 1680 bytes .../tests/text/writing-mode/rl.png | Bin 0 -> 1680 bytes .../text/writing-mode/tb-and-punctuation.png | Bin 0 -> 1650 bytes .../tests/text/writing-mode/tb-rl.png | Bin 0 -> 1700 bytes .../text/writing-mode/tb-with-alignment.png | Bin 0 -> 1719 bytes .../tb-with-dx-on-second-tspan.png | Bin 0 -> 2120 bytes .../text/writing-mode/tb-with-dx-on-tspan.png | Bin 0 -> 1442 bytes .../tb-with-dy-on-second-tspan.png | Bin 0 -> 2134 bytes .../tb-with-rotate-and-underline.png | Bin 0 -> 2515 bytes .../text/writing-mode/tb-with-rotate.png | Bin 0 -> 2208 bytes .../tests/text/writing-mode/tb.png | Bin 0 -> 1700 bytes .../tests/text/writing-mode/vertical-lr.png | Bin 0 -> 1700 bytes .../tests/text/writing-mode/vertical-rl.png | Bin 0 -> 1700 bytes .../tests-hinted/text/color-font/cbdt.png | Bin 0 -> 10675 bytes .../tests-hinted/text/color-font/colrv0.png | Bin 0 -> 1591 bytes .../tests-hinted/text/color-font/colrv1.png | Bin 0 -> 6152 bytes .../compound-emojis-and-coordinates-list.png | Bin 0 -> 5800 bytes .../text/color-font/compound-emojis.png | Bin 0 -> 822 bytes .../text/color-font/mixed-text-rtl.png | Bin 0 -> 764 bytes .../text/color-font/mixed-text.png | Bin 0 -> 1764 bytes .../tests-hinted/text/color-font/sbix.png | Bin 0 -> 3375 bytes .../tests-hinted/text/color-font/svg.png | Bin 0 -> 1843 bytes .../text/color-font/writing-mode=tb.png | Bin 0 -> 1473 bytes crates/resvg/tests/fonts/README.md | 7 +- .../tests/fonts/RobotoFlex-LICENSE-OFL.txt | 93 +++ .../resvg/tests/fonts/RobotoFlex.subset.ttf | Bin 0 -> 377180 bytes crates/resvg/tests/gen-tests.py | 110 ++- crates/resvg/tests/integration/hinting.rs | 279 ++++++++ crates/resvg/tests/integration/main.rs | 66 +- crates/resvg/tests/integration/render.rs | 14 + .../resvg/tests/integration/render_hinted.rs | 387 ++++++++++ .../tests/tests/text/color-font/colrv0.png | Bin 1591 -> 1561 bytes .../tests/tests/text/color-font/colrv1.png | Bin 6152 -> 6295 bytes .../all-axes-combined.png | Bin 0 -> 1262 bytes .../all-axes-combined.svg | 10 + .../auto-font-stretch-condensed.png | Bin 0 -> 1589 bytes .../auto-font-stretch-condensed.svg | 9 + .../auto-font-style-oblique.png | Bin 0 -> 1537 bytes .../auto-font-style-oblique.svg | 9 + .../auto-font-weight-700.png | Bin 0 -> 1187 bytes .../auto-font-weight-700.svg | 9 + .../explicit-overrides-auto.png | Bin 0 -> 790 bytes .../explicit-overrides-auto.svg | 10 + .../font-variation-settings/grad-negative.png | Bin 0 -> 1484 bytes .../font-variation-settings/grad-negative.svg | 10 + .../font-variation-settings/multiple-axes.png | Bin 0 -> 1143 bytes .../font-variation-settings/multiple-axes.svg | 10 + .../text/font-variation-settings/opsz-144.png | Bin 0 -> 1630 bytes .../text/font-variation-settings/opsz-144.svg | 10 + .../font-variation-settings/slnt-negative.png | Bin 0 -> 1537 bytes .../font-variation-settings/slnt-negative.svg | 10 + .../text/font-variation-settings/wdth-151.png | Bin 0 -> 1582 bytes .../text/font-variation-settings/wdth-151.svg | 10 + .../text/font-variation-settings/wdth-25.png | Bin 0 -> 1407 bytes .../text/font-variation-settings/wdth-25.svg | 10 + .../text/font-variation-settings/wght-100.png | Bin 0 -> 790 bytes .../text/font-variation-settings/wght-100.svg | 10 + .../text/font-variation-settings/wght-700.png | Bin 0 -> 1187 bytes .../text/font-variation-settings/wght-700.svg | 10 + .../font-variation-settings/xtra-extreme.png | Bin 0 -> 1672 bytes .../font-variation-settings/xtra-extreme.svg | 10 + crates/resvg/tests/tests/text/text/zalgo.png | Bin 3123 -> 3104 bytes crates/usvg/Cargo.toml | 13 +- crates/usvg/codegen/attributes.txt | 2 + crates/usvg/src/main.rs | 1 + crates/usvg/src/parser/converter.rs | 2 +- crates/usvg/src/parser/mod.rs | 4 + crates/usvg/src/parser/options.rs | 49 ++ crates/usvg/src/parser/svgtree/mod.rs | 3 + crates/usvg/src/parser/svgtree/names.rs | 447 ++++++------ crates/usvg/src/parser/text.rs | 151 +++- crates/usvg/src/text/colr.rs | 343 --------- crates/usvg/src/text/flatten.rs | 675 +++++++++++++++--- crates/usvg/src/text/layout.rs | 358 +++++++--- crates/usvg/src/text/mod.rs | 14 +- crates/usvg/src/text/skrifa_colr.rs | 396 ++++++++++ crates/usvg/src/text/skrifa_metrics.rs | 105 +++ crates/usvg/src/tree/text.rs | 67 ++ 449 files changed, 3093 insertions(+), 850 deletions(-) create mode 100644 crates/resvg/examples/generate_hinting_comparison.rs create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/after-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/alphabetic.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/auto.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/baseline.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/before-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/central.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-and-baseline-shift-eq-20-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-vertical.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-with-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/ideographic.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/mathematical.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/middle-on-textPath.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/middle.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/text-after-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/text-before-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/alignment-baseline/two-textPath-with-middle-on-first.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/-10.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/-50percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/0.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/10.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/2mm.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/50percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/baseline.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/deeply-nested-super.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-4.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-5.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/invalid-value.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/mixed-nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/nested-length.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/nested-super.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/nested-with-baseline-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/nested-with-baseline-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/sub.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/super.png create mode 100644 crates/resvg/tests-hinted/tests/text/baseline-shift/with-rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/cbdt.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/colrv0.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/colrv1.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/compound-emojis-and-coordinates-list.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/compound-emojis.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/mixed-text-rtl.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/mixed-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/sbix.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/svg.png create mode 100644 crates/resvg/tests-hinted/tests/text/color-font/writing-mode=tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/direction/rtl-with-vertical-writing-mode.png create mode 100644 crates/resvg/tests-hinted/tests/text/direction/rtl.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline-and-baseline-shift-on-tspans.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline=baseline-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/alphabetic.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/auto.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/central.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/complex.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/different-alignment-baseline-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/dummy-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/equal-alignment-baseline-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/hanging.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/ideographic.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/mathematical.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/middle.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/no-change.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/reset-size.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/sequential.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/text-after-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/text-before-edge.png create mode 100644 crates/resvg/tests-hinted/tests/text/dominant-baseline/use-script.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/bold-sans-serif.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/cursive.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/double-quoted.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/fallback-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/fallback-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/fantasy.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/font-list.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/monospace.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/noto-sans.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/sans-serif.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/serif.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-family/source-sans-pro.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-kerning/arabic-script.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-kerning/as-property.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-kerning/none.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size-adjust/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/em-nested-and-mixed.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/em-on-the-root-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/em.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/ex-nested-and-mixed.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/ex-on-the-root-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/ex.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/inheritance.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/mixed-values.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/named-value-without-a-parent.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/named-value.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/negative-size.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/nested-percent-values-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/nested-percent-values-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/percent-value-without-a-parent.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/percent-value.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/zero-size-on-parent-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/zero-size-on-parent-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/zero-size-on-parent-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-size/zero-size.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-stretch/extra-condensed.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-stretch/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-stretch/narrower.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-style/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-style/italic.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-style/oblique.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variant/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variant/small-caps.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/all-axes-combined.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-stretch-condensed.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-style-oblique.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-weight-700.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/explicit-overrides-auto.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/grad-negative.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/multiple-axes.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/opsz-144.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/slnt-negative.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-151.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-25.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-100.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-700.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-variation-settings/xtra-extreme.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/650.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/700.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/bold.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/bolder-with-clamping.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/bolder-without-parent.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/bolder.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/invalid-number-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/lighter-with-clamping.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/lighter-without-parent.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/lighter.png create mode 100644 crates/resvg/tests-hinted/tests/text/font-weight/normal.png create mode 100644 crates/resvg/tests-hinted/tests/text/font/font-shorthand.png create mode 100644 crates/resvg/tests-hinted/tests/text/font/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/glyph-orientation-horizontal/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/glyph-orientation-vertical/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/kerning/0.png create mode 100644 crates/resvg/tests-hinted/tests/text/kerning/10percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/lengthAdjust/spacingAndGlyphs.png create mode 100644 crates/resvg/tests-hinted/tests/text/lengthAdjust/text-on-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/lengthAdjust/vertical.png create mode 100644 crates/resvg/tests-hinted/tests/text/lengthAdjust/with-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/0.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/1mm.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/3.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/5percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/filter-bbox.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/large-negative.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-scripts.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-spacing.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/non-ASCII-character.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/normal.png create mode 100644 crates/resvg/tests-hinted/tests/text/letter-spacing/on-Arabic.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/coordinates-list.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/end-on-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/end-with-letter-spacing.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/invalid-value-on-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/middle-on-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/on-the-first-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan-with-arabic.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/start-on-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-anchor/text-anchor-not-on-text-chunk.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-comma-separated.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-no-spaces.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/all-types-nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/indirect-with-multiple-colors.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/indirect.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/line-through.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/outside-the-text-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/overline.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-4.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/tspan-decoration.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-dy-list-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-dy-list-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-4.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-y-list.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-decoration/with-textLength-on-a-single-character.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-rendering/geometricPrecision.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-rendering/on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-rendering/optimizeLegibility.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-rendering/optimizeSpeed.png create mode 100644 crates/resvg/tests-hinted/tests/text/text-rendering/with-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/bidi-reordering.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/complex-grapheme-split-by-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/complex-graphemes-and-coordinates-list.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/complex-graphemes.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/dx-and-dy-instead-of-x-and-y.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-less-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-more-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-multiple-values.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/em-and-ex-coordinates.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/escaped-text-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/escaped-text-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/escaped-text-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/escaped-text-4.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/fill-rule=evenodd.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/filter-bbox.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/glyph-splitting.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/mm-coordinates.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/no-coordinates.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/percent-value-on-dx-and-dy.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/percent-value-on-x-and-y.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/real-text-height.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-on-Arabic.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-an-invalid-angle.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-less-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-more-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-and-complex-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-underline-and-pattern.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/transform.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy-lists.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-less-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-more-values-than-characters.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-arabic-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/xml-lang=ja.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/xml-space.png create mode 100644 crates/resvg/tests-hinted/tests/text/text/zalgo.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/150-on-parent.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/150-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/150.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/40mm.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/75percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/arabic-with-lengthAdjust.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/arabic.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/inherit.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/negative.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/on-a-single-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/on-text-and-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/textLength/zero.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/closed-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/complex.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/dy-with-tiny-coordinates.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/invalid-link.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/invalid-textPath-in-the-middle.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/link-to-rect.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/m-A-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/m-L-Z-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/method=stretch.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/mixed-children-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/mixed-children-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/no-link.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/path-with-ClosePath.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths-and-startOffset.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/side=right.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/simple-case.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/spacing=auto.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/startOffset=-100.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/startOffset=10percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/startOffset=30.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/startOffset=5mm.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/startOffset=9999.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/tspan-with-absolute-position.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/tspan-with-relative-position.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/two-paths.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/very-long-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift-and-rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-big-letter-spacing.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-textPath.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-filter.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-invalid-path-and-xlink-href.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-letter-spacing.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-path-and-xlink-href.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-text-anchor.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-transform-on-a-referenced-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-transform-outside-a-referenced-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/with-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/textPath/writing-mode=tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/link-to-a-complex-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/link-to-a-non-SVG-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/link-to-a-non-text-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/link-to-an-external-file-element.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/link-to-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/position-attributes.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/style-attributes.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/with-a-title-child.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/with-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/tref/xml-space.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/bidi-reordering.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/mixed-font-size.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-3.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/mixed.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/multiple-coordinates.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/nested-rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/nested-whitespaces.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/nested.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/only-with-y.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/outside-the-text.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/pseudo-multi-line.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/rotate-and-display-none.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/rotate-on-child.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/sequential.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/style-override.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/transform.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/tspan-span-and-BIDI-reordering.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-clip-path.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-dy.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-filter.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-mask.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-opacity.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/with-x-and-y.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/without-attributes.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/xml-space-1.png create mode 100644 crates/resvg/tests-hinted/tests/text/tspan/xml-space-2.png create mode 100644 crates/resvg/tests-hinted/tests/text/unicode-bidi/bidi-override.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/-5.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/0.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/10.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/2mm.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/5percent.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/large-negative.png create mode 100644 crates/resvg/tests-hinted/tests/text/word-spacing/normal.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/arabic-with-rl.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/horizontal-tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/inheritance.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/invalid-value.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/japanese-with-tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/lr-tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/lr.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/mixed-languages-with-tb-and-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/mixed-languages-with-tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/rl-tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/rl.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-and-punctuation.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-rl.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-alignment.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dx-on-second-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dx-on-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dy-on-second-tspan.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-rotate-and-underline.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-rotate.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/tb.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/vertical-lr.png create mode 100644 crates/resvg/tests-hinted/tests/text/writing-mode/vertical-rl.png create mode 100644 crates/resvg/tests-hinted/text/color-font/cbdt.png create mode 100644 crates/resvg/tests-hinted/text/color-font/colrv0.png create mode 100644 crates/resvg/tests-hinted/text/color-font/colrv1.png create mode 100644 crates/resvg/tests-hinted/text/color-font/compound-emojis-and-coordinates-list.png create mode 100644 crates/resvg/tests-hinted/text/color-font/compound-emojis.png create mode 100644 crates/resvg/tests-hinted/text/color-font/mixed-text-rtl.png create mode 100644 crates/resvg/tests-hinted/text/color-font/mixed-text.png create mode 100644 crates/resvg/tests-hinted/text/color-font/sbix.png create mode 100644 crates/resvg/tests-hinted/text/color-font/svg.png create mode 100644 crates/resvg/tests-hinted/text/color-font/writing-mode=tb.png create mode 100644 crates/resvg/tests/fonts/RobotoFlex-LICENSE-OFL.txt create mode 100644 crates/resvg/tests/fonts/RobotoFlex.subset.ttf create mode 100644 crates/resvg/tests/integration/hinting.rs create mode 100644 crates/resvg/tests/integration/render_hinted.rs create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/all-axes-combined.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/all-axes-combined.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/grad-negative.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/grad-negative.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/multiple-axes.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/multiple-axes.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/opsz-144.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/opsz-144.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wdth-151.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wdth-151.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wdth-25.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wdth-25.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wght-100.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wght-100.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wght-700.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/wght-700.svg create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.png create mode 100644 crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.svg delete mode 100644 crates/usvg/src/text/colr.rs create mode 100644 crates/usvg/src/text/skrifa_colr.rs create mode 100644 crates/usvg/src/text/skrifa_metrics.rs diff --git a/.typos.toml b/.typos.toml index 389e359e0..418faf839 100644 --- a/.typos.toml +++ b/.typos.toml @@ -16,6 +16,7 @@ SVGinOT = "SVGinOT" # Match Inside a Word - Case Insensitive [default.extend-words] +wdth = "wdth" [files] # Include .github, .cargo, etc. diff --git a/Cargo.lock b/Cargo.lock index 6dcbc486d..2984b3d4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,15 +49,29 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "byteorder-lite" @@ -158,6 +172,15 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +[[package]] +name = "font-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4d2d0cf79d38430cc9dc9aadec84774bff2e1ba30ae2bf6c16cfce9385a23" +dependencies = [ + "bytemuck", +] + [[package]] name = "fontconfig-parser" version = "0.5.7" @@ -197,6 +220,19 @@ dependencies = [ "weezl", ] +[[package]] +name = "harfrust" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9f40651a03bc0f7316bd75267ff5767e93017ef3cfffe76c6aa7252cc5a31c" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "core_maths", + "read-fonts", + "smallvec", +] + [[package]] name = "image-webp" version = "0.2.0" @@ -333,12 +369,30 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "proc-macro2" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +dependencies = [ + "unicode-ident", +] + [[package]] name = "quick-error" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quote" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.6.5" @@ -454,6 +508,17 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "core_maths", + "font-types", +] + [[package]] name = "resvg" version = "0.45.1" @@ -494,24 +559,6 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" -[[package]] -name = "rustybuzz" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" -dependencies = [ - "bitflags 2.8.0", - "bytemuck", - "core_maths", - "log", - "smallvec", - "ttf-parser", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - [[package]] name = "simd-adler32" version = "0.3.7" @@ -539,6 +586,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts", +] + [[package]] name = "slotmap" version = "1.0.7" @@ -573,6 +630,17 @@ dependencies = [ "siphasher 1.0.1", ] +[[package]] +name = "syn" +version = "2.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -630,22 +698,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] -name = "unicode-bidi-mirroring" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" - -[[package]] -name = "unicode-ccc" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" - -[[package]] -name = "unicode-properties" -version = "0.1.3" +name = "unicode-ident" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-script" @@ -667,15 +723,16 @@ dependencies = [ "data-url", "flate2", "fontdb", + "harfrust", "imagesize", "kurbo", "log", "once_cell", "pico-args", "roxmltree", - "rustybuzz", "simplecss", "siphasher 1.0.1", + "skrifa", "strict-num", "svgtypes", "tiny-skia-path", diff --git a/crates/resvg/Cargo.toml b/crates/resvg/Cargo.toml index e29a4160a..cd89b1735 100644 --- a/crates/resvg/Cargo.toml +++ b/crates/resvg/Cargo.toml @@ -14,6 +14,10 @@ workspace = "../.." name = "resvg" required-features = ["text", "system-fonts", "memmap-fonts"] +[[example]] +name = "generate_hinting_comparison" +required-features = ["text", "hinting"] + [dependencies] gif = { version = "0.13", optional = true } image-webp = { version = "0.2.0", optional = true } @@ -42,3 +46,5 @@ memmap-fonts = ["usvg/memmap-fonts"] # When disabled, `image` elements with SVG data will still be rendered. # Adds around 200KiB to your binary. raster-images = ["gif", "image-webp", "dep:zune-jpeg"] +# Enables font hinting via skrifa (requires `text`). +hinting = ["usvg/hinting"] diff --git a/crates/resvg/examples/generate_hinting_comparison.rs b/crates/resvg/examples/generate_hinting_comparison.rs new file mode 100644 index 000000000..ea8a0fb4b --- /dev/null +++ b/crates/resvg/examples/generate_hinting_comparison.rs @@ -0,0 +1,78 @@ +//! Run with: cargo run --example generate_hinting_comparison --features text,hinting + +use std::sync::Arc; +use usvg::fontdb; + +fn main() { + // Load fonts + let mut fontdb = fontdb::Database::new(); + fontdb.load_fonts_dir("crates/resvg/tests/fonts"); + fontdb.set_sans_serif_family("Noto Sans"); + let fontdb = Arc::new(fontdb); + + // SVG with small text where hinting is most visible + let svg = br#" + + + The quick brown fox jumps over the lazy dog. (12px) + + + The quick brown fox jumps over the lazy dog. (14px) + + + The quick brown fox jumps over the lazy dog. (16px) + + + The quick brown fox jumps over. (20px) + + + The quick brown fox. (24px) + + + "#; + + // Render with hinting + let opt_hinted = usvg::Options { + fontdb: fontdb.clone(), + hinting: usvg::HintingOptions { + enabled: true, + dpi: Some(96.0), + }, + ..usvg::Options::default() + }; + + let tree = usvg::Tree::from_data(svg, &opt_hinted).unwrap(); + let size = tree.size().to_int_size(); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap(); + pixmap.fill(tiny_skia::Color::WHITE); + resvg::render( + &tree, + tiny_skia::Transform::identity(), + &mut pixmap.as_mut(), + ); + pixmap.save_png("hinted.png").unwrap(); + println!("Saved hinted.png"); + + // Render without hinting + let opt_unhinted = usvg::Options { + fontdb: fontdb.clone(), + hinting: usvg::HintingOptions { + enabled: false, + dpi: Some(96.0), + }, + ..usvg::Options::default() + }; + + let tree = usvg::Tree::from_data(svg, &opt_unhinted).unwrap(); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap(); + pixmap.fill(tiny_skia::Color::WHITE); + resvg::render( + &tree, + tiny_skia::Transform::identity(), + &mut pixmap.as_mut(), + ); + pixmap.save_png("unhinted.png").unwrap(); + println!("Saved unhinted.png"); + + println!("Done! Compare hinted.png and unhinted.png"); +} diff --git a/crates/resvg/src/main.rs b/crates/resvg/src/main.rs index 830eb8d4f..5b72fb772 100644 --- a/crates/resvg/src/main.rs +++ b/crates/resvg/src/main.rs @@ -577,6 +577,8 @@ fn parse_args() -> Result { image_href_resolver: usvg::ImageHrefResolver::default(), font_resolver: usvg::FontResolver::default(), fontdb: Arc::new(fontdb::Database::new()), + #[cfg(feature = "text")] + hinting: usvg::HintingOptions::default(), style_sheet, }; diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/after-edge.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/after-edge.png new file mode 100644 index 0000000000000000000000000000000000000000..0d94621160981d29a8d40014486977a9d8207b11 GIT binary patch literal 1252 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXO3I6XFV_i3faqd_cvTnwsqF z>_A3tZmx@q3q-r2p&=I+S3^TXeSJNC0~;F~fy!Rlnob3((1 z`w!O7ufLwZ>~(x*d%ypjhqLD_IDa8wL%;`v2?Fs6Qk{0E85o#9d%8G=RNQ)Vp_{Y8 zK!9~awP+(>(A|3HgN#ppbgL;Zx#o6xRgYSbq%rRqYwfEJDJLhXdQV$ZKM_dkL~fdZ zPF*WJ1yTT%f~cet(6|yi#Kw6)Y-DR7O^vAG_Cl}wT9(Ei}arQqS^bHR#(}t5e$<&!Mx=a^{rJ)09GL7`&v7H`E+){Q0L~^DouByAz+O z3ePE)KA^FtSi|+!!9|6f?T>zV{1K39Ej75(vG&vX9bueAy@Wl zby43RvmF&S+hRl1-lU${bp3()zTm?P7ezi=9qYn>yG^fMdK1s%$u=>}Jf>mf$(HWTLOe)Ud?6x{_5*@BNflmbuH%$&8pOIHg;hh11>a(Y2PznGut} ziFMze(jqHeIL$9#OicaNiWVlP{<%$?d9$0vpSYMbnJyE(_W9ECh`G^;dwIK!zU4pT z%C1PBf3-<8JYr6TXjuDPt;ZWGnBK;>PBm)S$T(qnX~}`Vt2ZdcYiVxb?p{)w9dT=g zqa82r;iB4^nhCzYIlC*$AA3ifymO85rD{aU`SVM8euvz#%;%i;_~RbkMA6fMKX>XT zgf2@cU9`nzrHGe!=#a=if_-A7A`CV2$rr^W?XdGja}0 zTIy;M%FV{7%jCSS*Yhv7-lNrW zYkJTIwrNmrw7jNy={9dQbF`%E~Jy zYyY$VUq9E%f>ENSNkhVudEVDG-|iVNi#xWYlem0WP V&=ZGO3-v%ni>Irf%Q~loCIBhG`KbT^ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/alphabetic.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/alphabetic.png new file mode 100644 index 0000000000000000000000000000000000000000..148548b8906125be7c71f735b4578837f4c1b951 GIT binary patch literal 1300 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`b-6XFV_F+pQvBT%rRp#ezd z=H}+)NH&1VGp>U|?ls1>^!%*4NiV#I>}vl$DhsY*{dXuq7lUAPhb}J|KgO z3*OXfggThX<c@A!sQ zRrfNuzC@hA{X=ez)_?Da?*2{9@};IWKZ*qGPo9r_-bj`@joVxMqsgm~JcU~==KZcYiAyKHESPbx z)ON0=r{>)!cl_6Uve`Z>#CVO#tDJp8+cPg8jruOKTISh{rR(I2`@W?`g!ZiZrlj*| z!Rpt)QmwMy<^66fotwO==b#&hP0rc6+nKsYUVpn+`hQ)Up=nm%JV%|qyTwi%-0f=N zReNk!iC$&%%O6`M_nO!rSE^b0t4Fl`v|rVA*E_OX>g3J33)H_#YG>Hpf3{5W-kCDa ztyW*9UhnjtaB7>^PYLcqf$j}&jKj*6PF=Q|?elK-(VOvWrtVo`cF1#H>EvI%r5{)$ zGN&v)E_Cg9L}*_Z%j@Jd2a7-7V9tKrJiY#~3~%DmBSCAPy|DH?xz>5Fi1xV%{lZE5 z2~Qsyttk>Jk8u1J^G!&wpKE_F*qXRu-I?#dCvOO=FKGX{ zcD3t%nframKb|b8Dcw<3_04SaPZQbrGPCY{``KqJzGwZJ_4)FTto*O;Ut%L(?_Yj- z^Vj>6?RkH+vqI84&66}RGm)BWpjx0BSs>aufq8JhCM0)e|Gq4~NH&1VGp>U|?ls1>^!%*4NiV#I>}vl$DhsY*{dXuq7lUAPhb}J|KgO z3*OXfggThX<c@A!sQ zRrfNuzC@hA{X=ez)_?Da?*2{9@};IWKZ*qGPo9r_-bj`@joVxMqsgm~JcU~==KZcYiAyKHESPbx z)ON0=r{>)!cl_6Uve`Z>#CVO#tDJp8+cPg8jruOKTISh{rR(I2`@W?`g!ZiZrlj*| z!Rpt)QmwMy<^66fotwO==b#&hP0rc6+nKsYUVpn+`hQ)Up=nm%JV%|qyTwi%-0f=N zReNk!iC$&%%O6`M_nO!rSE^b0t4Fl`v|rVA*E_OX>g3J33)H_#YG>Hpf3{5W-kCDa ztyW*9UhnjtaB7>^PYLcqf$j}&jKj*6PF=Q|?elK-(VOvWrtVo`cF1#H>EvI%r5{)$ zGN&v)E_Cg9L}*_Z%j@Jd2a7-7V9tKrJiY#~3~%DmBSCAPy|DH?xz>5Fi1xV%{lZE5 z2~Qsyttk>Jk8u1J^G!&wpKE_F*qXRu-I?#dCvOO=FKGX{ zcD3t%nframKb|b8Dcw<3_04SaPZQbrGPCY{``KqJzGwZJ_4)FTto*O;Ut%L(?_Yj- z^Vj>6?RkH+vqI84&66}RGm)BWpjx0BSs>aufq8JhCM0)e|Gq4~NH&1VGp>U|?ls1>^!%*4NiV#I>}vl$DhsY*{dXuq7lUAPhb}J|KgO z3*OXfggThX<c@A!sQ zRrfNuzC@hA{X=ez)_?Da?*2{9@};IWKZ*qGPo9r_-bj`@joVxMqsgm~JcU~==KZcYiAyKHESPbx z)ON0=r{>)!cl_6Uve`Z>#CVO#tDJp8+cPg8jruOKTISh{rR(I2`@W?`g!ZiZrlj*| z!Rpt)QmwMy<^66fotwO==b#&hP0rc6+nKsYUVpn+`hQ)Up=nm%JV%|qyTwi%-0f=N zReNk!iC$&%%O6`M_nO!rSE^b0t4Fl`v|rVA*E_OX>g3J33)H_#YG>Hpf3{5W-kCDa ztyW*9UhnjtaB7>^PYLcqf$j}&jKj*6PF=Q|?elK-(VOvWrtVo`cF1#H>EvI%r5{)$ zGN&v)E_Cg9L}*_Z%j@Jd2a7-7V9tKrJiY#~3~%DmBSCAPy|DH?xz>5Fi1xV%{lZE5 z2~Qsyttk>Jk8u1J^G!&wpKE_F*qXRu-I?#dCvOO=FKGX{ zcD3t%nframKb|b8Dcw<3_04SaPZQbrGPCY{``KqJzGwZJ_4)FTto*O;Ut%L(?_Yj- z^Vj>6?RkH+vqI84&66}RGm)BWpjx0BSs>aufq8JhCM0)e|Gq4~je!nL!SCzxwG0Af;9kmPESifQafwSi?T)+R|{fDm;_dNAuU|?bOba4!+ zxb^1BVMb?05!Zv#w>1?1mP@=%t~sljD0k`I%agZGI{HsDzGhRk=%=W*u5Dn#!6sI2 zu{CKxLMLKF0wrU!;Q^ z8TJsvsaB`0S+8}*S_kAxvmLTnH~Hzz3D-7@x#hb0N}c|F@4sNV@v6tOZwY8fPxvg~ zkTi$Ez9wRCSW1EN|NR@xbi%Kfq)Ue}$?>fIbiJzJV!Uzu!K@Dn5k|o_zVQdGaw5Jb z$C|C#y-@~4MD2|zy<58b*4hoT`l{6~)~r=r_eyAoUiz1Wo#IdYtbg}~`aYPI^l4ew zimJvl*#|eduklh#4rJDg+*QVOT_~_6NT_O8QTI&!Po_~_zmU5A}k-D|%vA#Dvqg4X-aPjl+dI9Di~ zjS!1b5Zp1@#4-E8Tu;+!jNgO06$GC(*X(L2-nH@D50#CNPj6i!efoZ*D`WA*yoB6{ zM<$I~haa8$xc=TfrK!a?aw1}?tAC~oKMPtavzoPhN3W?u`I5IU8Y-BztLHKA2s59? zT)wk4bZMn!mV1Gpsn}VzWkvdf2R6%$MaPe_}%Sd`z_@CueE9O zPsJ&HZo*=$1uG{;_^V7`oRq7zfz3DKXXC*F*A4gM?q743dU7jdpUj5qEv|gUFK@hk zwd-D~JA>qEM)Sy*wNgw zz4_|!qgi!_wto1WxllrPt@UYr1LdNJA2-B2`SvC7*l)XI527dc^O?Dv6Nx_%x|;i+ zK=S*u-|9d7-*x}(g+^8eLjjfpr8WF_C&U#<69jyGe8_5qg@qwp zLqkI#LsL@|NGgMYm6er?i%UR2Ku%7MzrTNOZZ0!3GdnxGtgI|hTuVz!LP7%BC^U9s zV`D=@!@JHi$v_Fik|4ie28aLl4F?3?pAUF2;rjaf`SoZ0<7dxb*1uu>#P-^(y3DVy zcXcd1ydYu!h6@EB3>4xMK8Mda#K6EJ>*?YcQgQ3;?asX076J_qFLo?Su`a!o{C@ZC zBh!!k_&Yz3eN#f^l>?#y$$~Ba`?cjRSlBfP9aItWo)tO8DKo7#QI>1g#f8VUTGB!q zSj8d|8d<~Q8X*iZZ1j2e4F{OGbp{tv6&$f~PY~1T&=*sgA`^Do4C~A+mbNR zV_okLzWTB@aVOW-Lu>D~F|PR;!5gu8FmjdVLGSJC6+F|dUD46+Kek&?Ll@C zACni?e)Z2h@=D!L`)Zb`(x<|;>n8ACb6%T#+akd;VD-fAZCPtwQkKtB535@S6sO^Hmwf}Z-D(YP2a(0!Acz-3U{o$hLKcDkk zmKI1CzTO}E^t)Niimm=eBHy!Wr!AZtwVHdUm(j7Vt*f?W7G3!h-IlaEOfjrTJ6`eH z=icAGYvc9Q=U@3%WLX*V`ts)s>;G>1bGmNVXYKZbpM8Jpt$E!0JACbYef9TOe^s6R z{rUL4cb`B0SS%lHd+p=0y`OR;em|cedbRga(Aq~^I2U{Lo!7B1SQ#~0_4V2)?vqm4 z3-zA~H1Vxf$zNl@?EUT5_MU`V>DAe#77h(de`j5~8~b#_tIvO#BWCBv{4>3E-DN{g z0dF_^9{G^)jlWb+$E7h&GrPXwQPkQ+``4~az7}z5)zozfe+_aDG)KMvbgXKYgwIB? z!<^Y0EKl4xXPw?~)we%DPP=dV;^n!RCU=6?g!#lpsF1XY2m173qZm-h))++z_=G99v46Z~D%X7HtHUHUP?^_~y_j`oN gW~U@a{A!M|^(Cft(R2P%F%UHx3vIVCg!09q~^E&u=k literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-and-baseline-shift-eq-20-on-tspan.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-and-baseline-shift-eq-20-on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..3dc7c0d40da6f693b1db546ce9c597f662e0dab7 GIT binary patch literal 2125 zcmchYSx}Q{7KZb&1~aW39$SLYK5 z2^9$d01$X52R8tKpuZIyx;JqyOFFTKTdpVF9ryU>Lt9&0T3Q+ggPlKrUSD5dNl8gU zLc-VA7Yc=1T3X7<$vHSUV6j*qA0H}}nw*^M>gu}p_}=hOenF$r_JlJdjz8}SurY4V zX8@aBYicWN;eu-~cPzQ4WCfcnwFHd*^Qfkbe*j}O zFc$z|=6DBN_xPb%K30KhBejp41UjF3)nXYRz}nQ2bxV|fcRMhv*%Jk=!l2r1g1YEB z1V+`1&Tl|_{ue||!P|fApgkY|%}qbjN=WNqOQfAXUOGrO7>=;B8Qh)sJ8g@LCJcRf zY3iRkYSbov%z5of1SB*Uwivki58`B}uw$3B4Hqc19;pD{T2n$jH_ee(FUt}E-j}C~ zWW!x!P$BEYsj~ZN6{Wf1vXj;b!IU_-6Al`5CNB(d6V(Kr@3~{o`_US97KqHY*{ZxY zOT)S-Gti&b#w4cIrdecqy_S`Je>*-U_KGe}sxnhl|Fy#s*fc@OrodBSTSp~ouUp*y zse^{ET%j)aW4(Dd%?b17slU+VePj69=JE8i$TqhCv%c%rMK@4YY<%_Bk);M!;-TNT zQ1oD{in_(ix~5nTMK?#nkE%n%cw^(osw!|$L!lMSWwfii{H8`(`7FSUmu?Sy*rLHG zP{~X7GO1lUiPgIm>wdIIn-4!w?#_4VP0J)XLQ710!;kh1rz@Ltz;_}U6D(V5<`ew) z1p6oUJ#6Zwka0C#qtLK3S{wL?(r%F}#<=2x))|FIII#gKmN!cM#h_)JrpNHy2)8<5 zV(16c;G%r~8%0tD2hxDS>iMo)?(=Q*UTPTGe>{X5T}KK9)qSoF^R;xy1}TT3@!|}) z3Xrg|bXw>Nechg|S05MxDVJrN8Fby}l5gtCb!CT*Yx$+!j>1D*^(ZfRPa;I+Vw8p> zYY9$*lwn2UKHPKb6o0dlRNPBx)Q6`qC5ltfL2poa@LhSd+o1w&KLqN}L zzx);C@`Qt;En5}b@&f5MrqUr^&58^q#EkO6^x0C+l1}C;`dJbw4xDD!P3&spnw1%R zR#IVxbwN z2uBu39^iwm#Jg%My5e_sN_meaCeCp6SJx*~=4Na|*Q6F*qBOs6f(pV~lZ)DO?dxGx z#~NIN_Q&2&$DGH#{&Bewt2jPx0RlWP5x}dxaILuAa72>e~YMzg*-`02=Gy$xw zm2E7l24!1G5|(y)KdsDfGqZ6@4_w}DF}d=D+W$8b7Ow zaTp&F*48I@2|VG{<$>Tg&%C}TE1=3(GYSGHnF63d;It(Nhz>`R;mGb5t#EwNYtAq9 zZWRxrJ&Ku@byf`j(=}&gA)yi7C2aKNox@N!P4a}M%+P{hDo6-eucf&_P{AWU97L;O zlu6vc^~1-}Eg20%s-~<0qn$6sjYe^bidsbJq8cuGjD2zAz0U#T@BpxH^x>~Yk$E0d z5AKSrdpK_2W!<(xgMCuJ+ReFa8Q13^WGd4t0=k48%kNU)_$m&if*B?K(S2r+kBI^+iPSt>!ZpOV~Mb)bDcix24 z%cI7>zM~|5ni+_lDTD(u`^A)gD37U0zC2tyrl>0`p8s!GO8)D{Bl(AG{V({1EbH>k euDNpb?4p65D0wy>usHtBvGI=14%K!6DgOehQK;Sk literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-tspan.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..dc99d2e1ab69ec5c29e3ddcf05a9b0162ca3642f GIT binary patch literal 2108 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-with-underline.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-with-underline.png new file mode 100644 index 0000000000000000000000000000000000000000..f6ffc42541a7302e73ab9661ef43c314e727efec GIT binary patch literal 2157 zcmcgtdo; z(f|O!ZBOGI06+x&{YpZF9s7c~Q$k=6?Hp}{C_HpJJw87E&-$;jrlzK>tSkMJ z0Reh?daA0b($doI?(Pr>#Ldl(MxzOJ3=Iv13Ro-_fj|(6L?QpL1piO}#hz=zb%7&c z4)#9*bc(0^ioqnY1L)XG`va`MK@u|sYQ-k``rurz$*O)XE*L>Gv zbM-z00HBVxI7`Q<*9-lYA{Kz6xB*dOYE2HR_%+fs!I33f2UQ?AUsBmink<)bFUj<6IM~Qu&>&G_;v9J__Cue;>G#T;q&^ zRU4>~`@8plRWG2#oEK-_lO2^b)(7zSc>{}G=*J6)$_Zy}#SryxpKNEDT?sk@1XBS> zbi|U&hHn-z#WC+jKt1rJPpWrt)=SXjeA`?Q9OeGYgznqaRpPVAl)ab=h`ks^<%!xJ z(hp93$}WOK7Yf|qmTv$?$YEe`CnNP((h=?gwDRMk4w~MaP{-4K?hD>|riIh`A(UJ) zPq~#-2fW}@2H!YG{dgLXa5LMkU39vkp+cg&{5)xK7_(QG!(Rh&0whJ*rhgtlnbl8^EEOzB87%O)*oC}z#cswdMaME&91bsr8q0yF(V>#6)vK3$f(3Gz7{bO?Z zlQ-GcS{N+nQnCPZ-(oRPhEO||S~wj{_P{20*z>Gk1$G6&%jO>KNTnsu0^xd`FA%T9 z>8mz{OUe(`c>Y{M=54zeBu9z0PqN2=j7Teqk*NLcI&!Ynsi^;vM30EzDJUb~$9`3x z-v7|uHO?4~Scg=7E5%gZr5hKuI%xP~^w8pt!7pDoW+rTHSZkJ~KTM${ey%WIA2Bhm z5zWim@a~nzE%Wf`!Ia+ZP|_WdD^evXM{YKnhNd_uS8hhz9k7Xt*n_4U^{pyW{PMkQ zO{)!x+8mU&QuRg5B{#iQ`9-xjxElM+kP9pv#GYSI7}V!G^fJMsH>|zg4i|f?Stwq5)I7e0RlMT z{>5l}vh$CkedfMXTODb%&9$b{yDXO4{6R2%@rifu4JB3E=I<}FdWT~$#w*Q|hW#A; zB!0=$wOZ65K9?3r{!ff0wXe$IXH2reYL%2$lfoIV%4|d;-{&@1r8sJg;=5$E_yhP# zK?>Aj=fOE-A++a(d;n|DvO~0SNN46kCeqx7tUVRprO_fr8gOHbI3Y@%KF@UzT8t(5 zT+;24YAdCe>aQG@XJxT7l!krzb#pJY?c^9Gmg{GEqIka!+_GYRbMCmJmoepxoIX$< z6qrQSyiuBq;waS|>2o0X=AS3z$^=h(jEZ?(?-wO_T!bcDX)TTE+sTupGP&uW6oI33 zCo9duEEF2m2q)Z1-nv~VrEe-ew4x8ssBjkd^*iBFJ#OUn`&;ozKWKAf*~Z(nE6w9IZ!GHX?!TQk)@6a$v*Hk9<2PsDQ+1A zd}hBJ)_wKENJ%Slq4wjF4qAXJJt#%UI^Z&6Dotp1N#GBLQM4zvT9(7~GTG`tLga}uRLtwRcgnBAD4fE4*xN2`!C?Mbp2^}O_0xgX~VLEICV0c VUL#3+=kndWZEfsv zAU+`>Gryp|p}l{?>^XDhFIcvI!~O&3FI>O>;Pv|t>;LOaVPIhX;_2cTQgQ3e1xH2) z1`*Z`>I5XB@QAdsd8gbXS=}) zCaHQuR1PYJx%Ib&cdR&E5@#%u-r2L}iwje@#rywVmi><*3AUY<_XcQ{$c#9CQm-+7-@Bx$!BAjhtaE!r8X<9cJIDka<1qo z7xPoYXVX5PeCT&nk*DJMwJ3hAb$O8qy~0=cEtplI5U;};@QQPd*p%LSUdiN>cKg*1uX-02k;U)zBx2Uxbx=yt$oI#uJh8d)G}X;~!qFqgJpP2Jy+yKBOJ&hpy_jSf!Y z{j{y{+&8adW+(q%Wm7bZ*z{^*$qp{>@{T7CD!-SW`gC|vN%D7zTi<<6|4GfVXjy0$ zZLd?sf9m_!`-g*?F7@A!I=b|5#hL)4w~gAX|G&Mpk&{7zhxMZW0lnYnwK=}M+)`nF zXtloGkMm8e++sQr8xjs;WnAOMBT0_A3tZmx@q3q-r2p&=I+S3^TXeSJNC0~;F~fy!Rlnob3((1 z`w!O7ufLwZ>~(x*d%ypjhqLD_IDa8wL%;`v2?Fs6Qk{0E85o#9d%8G=RNQ)Vp_{Y8 zK!9~awP+(>(A|3HgN#ppbgL;Zx#o6xRgYSbq%rRqYwfEJDJLhXdQV$ZKM_dkL~fdZ zPF*WJ1yTT%f~cet(6|yi#Kw6)Y-DR7O^vAG_Cl}wT9(Ei}arQqS^bHR#(}t5e$<&!Mx=a^{rJ)09GL7`&v7H`E+){Q0L~^DouByAz+O z3ePE)KA^FtSi|+!!9|6f?T>zV{1K39Ej75(vG&vX9bueAy@Wl zby43RvmF&S+hRl1-lU${bp3()zTm?P7ezi=9qYn>yG^fMdK1s%$u=>}Jf>mf$(HWTLOe)Ud?6x{_5*@BNflmbuH%$&8pOIHg;hh11>a(Y2PznGut} ziFMze(jqHeIL$9#OicaNiWVlP{<%$?d9$0vpSYMbnJyE(_W9ECh`G^;dwIK!zU4pT z%C1PBf3-<8JYr6TXjuDPt;ZWGnBK;>PBm)S$T(qnX~}`Vt2ZdcYiVxb?p{)w9dT=g zqa82r;iB4^nhCzYIlC*$AA3ifymO85rD{aU`SVM8euvz#%;%i;_~RbkMA6fMKX>XT zgf2@cU9`nzrHGe!=#a=if_-A7A`CV2$rr^W?XdGja}0 zTIy;M%FV{7%jCSS*Yhv7-lNrW zYkJTIwrNmrw7jNy={9dQbF`%E~Jy zYyY$VUq9E%f>ENSNkhVudEVDG-|iVNi#xWYlem0WP V&=ZGO3-v%ni>Irf%Q~loCIBhG`KbT^ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/inherit.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/inherit.png new file mode 100644 index 0000000000000000000000000000000000000000..080a0012c0d9440e84c0953677627f77420e6f50 GIT binary patch literal 1244 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOCL6XFV_v4Y0N#)gIlpj2*d zF0uj_7Z(T@C|h4&Z)j);;c9AXA}fQi`S|!C40d*Qxa@mY=V%~DwIs+d*nvSn!NA@> zAU+`>Gryp|p}l{?>^XDhFIcvI!~O&3FI>O>;Pv|t>;LOaVPIhX;_2cTQgQ3e1xH2) z1`*Z`>I5XB@QAdsd8gbXS=}) zCaHQuR1PYJx%Ib&cdR&E5@#%u-r2L}iwje@#rywVmi><*3AUY<_XcQ{$c#9CQm-+7-@Bx$!BAjhtaE!r8X<9cJIDka<1qo z7xPoYXVX5PeCT&nk*DJMwJ3hAb$O8qy~0=cEtplI5U;};@QQPd*p%LSUdiN>cKg*1uX-02k;U)zBx2Uxbx=yt$oI#uJh8d)G}X;~!qFqgJpP2Jy+yKBOJ&hpy_jSf!Y z{j{y{+&8adW+(q%Wm7bZ*z{^*$qp{>@{T7CD!-SW`gC|vN%D7zTi<<6|4GfVXjy0$ zZLd?sf9m_!`-g*?F7@A!I=b|5#hL)4w~gAX|G&Mpk&{7zhxMZW0lnYnwK=}M+)`nF zXtloGkMm8e++sQr8xjs;WnAOMBT0hA>#W)H>o$BXKD*O@&g_!I z9qX^}zp&wc!UqL|0)d41KaUbL85mfEJzX3_DsH{G;L6y*Ai%I;vPH!Ik_g6k=fx5? znmR|P7)~j_Hj8IXe%LXFpX+rZH>I4M)QXGhi=76MQuQ7jjMtZs_EoOEx#|#ugmTZ_ zmwUsxpRM^`zgu`_&uoj$clJK2cjt-wBi}i(F1;~hs%l39NS+SXIA9(DtnZT3Fbp0NirPt2_h zdw>18^zpM_+isliP}X-o*2j0}^o**{%0KiX|Nl*R*Jx2IZ-0jG!PMQ=QTJl{4+=|2 zUKie;?l7lE`kcc7{l9+y+Klcn_g~sK^&x{xbKIlLx9gaVOB8Imy#=0}T&)u}>D;a> zo4F#w?l&A3S^4rn;N~^=)-KjGW^XvBwdiV8xI=~-m!sJ9u1)Ys{*bg?p1+g*W$+;2WEQUOJo- zn!Z@SNS{5&W7C>BT+cTBsxfN1>(lpa?!gm}{y#aEH!+mSuww2$7tPfiUSj>vt>aF_ z#r?4B*<&_Uzga^d@=^S*o40!fA6IgTe~DWM4fRYw=< literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/middle-on-textPath.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/middle-on-textPath.png new file mode 100644 index 0000000000000000000000000000000000000000..69cb52bfaf42001a1e1d6af276fa1183375fb73b GIT binary patch literal 3445 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 O-yQ8-ZCkDJS^op6ni7)$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/middle.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/middle.png new file mode 100644 index 0000000000000000000000000000000000000000..1a7af58718d52a47f0915db44c0253aedf99f15b GIT binary patch literal 1312 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOLO6XFV_NdkO)d@e375)u+X zU0hsTKz43!ZftBUkZWjY$jl5fUs+ih%}h*@hK7d5#>QQzW+(!cYLx`}1v5DOw{O^g zK*8X{`+y7Q7d*J$aX9{AduFl!*{}WU^Ea%&KYzo7g!%%3gm}m6SAm*X)ID7sLn>~) zz1>>$#7clQ;Nbb}?<623HN_0eMQnAY0^@p0a-hG=;s~DCw>zVvvuZ=198P_JCd{Vt(+kcj8AA_&` zTXDO9_x0(G&o=Cn&^7}S*~SrT(s$p@DA{T4%bIPy>ulwUPd^JM)!Jt5n)0$tBjV+k zMU^K~YYupw{=YV^Wa{(n3%a|P`B{ssdAa9h`t*&vs_N!^3;2BKoxDvRTi4cHzM{H* z(Od5_L&Kh(yWPT=tUF6@bD8|(ZME~{{fxrQUami{{Pxqk3r8i2r%!uX#t~7zcB|)K z?RAxs?~G=Cl`1sS=Z`F^*#59G{8oE_?0oak?sZkZJNTK8%_^H(_(HY(QF8cP+jlpn zPjxwD&@#9KCHnR!Pl?ze0{xnN`1-3KClbGGhzs&v=%p&5^4_9fA43%#yc{#ctf z+5bVLgh`lQPg&@!rU15|cUm%UMEri%Df1=OkLU2Qtp4QCZnKBykL~(-uyXeE&v6f* zXs*e+y*#F>Jove5+;`{Cu@TqpE%ayKj`_+J9{cd>RY$wJGuf+LE90m3l>T-8EWRbN z`pr>$`^~R7OKL^5*UD|s3o@|k=}*etly28F{a}EVecROSHvZ)%-HyqvHidcfk7()l z`K8IeKB9l=^B0wCmGd^ph4=COHs<5hHeDK$Je50P<|)rx@^_YWA556~@lWxp4RLM1 zj$V9~dihnry0+%fd(}HM{`c_Dx8M6>zw^awRx5YO%sOqNvc@F)ozbp4Z_B3NeD3=G ziY|YQd4GR;`I)=hE>=iHD5f@R>7ROGH(PGUwE7QU`Yh8mB6jY7wMT35Z@Vv>R=huF zA*~SRaeK3p>An5uw?AB_aAj_J+_$yq|KH7CGx?j@$Ig1+JKNsc`N_MrUn!f}qV-?@ znCor5MduIxzQjOb@~4{iMo3mmdKI;Vst0ErYPvH$=8 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/text-after-edge.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/text-after-edge.png new file mode 100644 index 0000000000000000000000000000000000000000..0d94621160981d29a8d40014486977a9d8207b11 GIT binary patch literal 1252 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXO3I6XFV_i3faqd_cvTnwsqF z>_A3tZmx@q3q-r2p&=I+S3^TXeSJNC0~;F~fy!Rlnob3((1 z`w!O7ufLwZ>~(x*d%ypjhqLD_IDa8wL%;`v2?Fs6Qk{0E85o#9d%8G=RNQ)Vp_{Y8 zK!9~awP+(>(A|3HgN#ppbgL;Zx#o6xRgYSbq%rRqYwfEJDJLhXdQV$ZKM_dkL~fdZ zPF*WJ1yTT%f~cet(6|yi#Kw6)Y-DR7O^vAG_Cl}wT9(Ei}arQqS^bHR#(}t5e$<&!Mx=a^{rJ)09GL7`&v7H`E+){Q0L~^DouByAz+O z3ePE)KA^FtSi|+!!9|6f?T>zV{1K39Ej75(vG&vX9bueAy@Wl zby43RvmF&S+hRl1-lU${bp3()zTm?P7ezi=9qYn>yG^fMdK1s%$u=>}Jf>mf$(HWTLOe)Ud?6x{_5*@BNflmbuH%$&8pOIHg;hh11>a(Y2PznGut} ziFMze(jqHeIL$9#OicaNiWVlP{<%$?d9$0vpSYMbnJyE(_W9ECh`G^;dwIK!zU4pT z%C1PBf3-<8JYr6TXjuDPt;ZWGnBK;>PBm)S$T(qnX~}`Vt2ZdcYiVxb?p{)w9dT=g zqa82r;iB4^nhCzYIlC*$AA3ifymO85rD{aU`SVM8euvz#%;%i;_~RbkMA6fMKX>XT zgf2@cU9`nzrHGe!=#a=if_-A7A`CV2$rr^W?XdGja}0 zTIy;M%FV{7%jCSS*Yhv7-lNrW zYkJTIwrNmrw7jNy={9dQbF`%E~Jy zYyY$VUq9E%f>ENSNkhVudEVDG-|iVNi#xWYlem0WP V&=ZGO3-v%ni>Irf%Q~loCIBhG`KbT^ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/text-before-edge.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/text-before-edge.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa703e373ab08b4672156c2b1396bfedd1e3911 GIT binary patch literal 1265 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 Z1m|glGS#OzX8%14G}gC3HR*XI{TIXwUcvwX literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/-10.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/-10.png new file mode 100644 index 0000000000000000000000000000000000000000..c80578101577d3391b09dabb9ab02a5d2c1ebe19 GIT binary patch literal 2106 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 G&HM-c2ZXEu literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/0.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/0.png new file mode 100644 index 0000000000000000000000000000000000000000..56ce39d6b1f54015b85272515fda3ee484e360f2 GIT binary patch literal 2093 zcmd6oc~Dd58pZ<|5(ult5JX6km?=uwQ8q6K1Z6XXML1zi5D*Y58bJ1(1Ta8>3kp%I zQ!qjiiQxbODpEoa)UpV+BrLLe@rqJ0tqZQ)L(|SU)Bij7H|IR>`##_E&AjKYQ%s{C z(8TCt5D0{(mnS6vflwlEysAjppp+`k;oUkw7m;cyUtj35Xq zt|W7kVHBpqiQq)Q&^R=hFMSF~f!WBw4=f;PWo5-?vlXL4cY(WLh#(OjiA3TbxeYM{ z4Pm}a>VbM#EcQ!B3)F&9I2aHEHyF&u=c7S1j1EWV%PziR9=;qCy z9qnMF)X(+HYv=Oqx$IM8q8D*M?(EED*UX53QRwmw854ZCQ;uV#rEWL& zK9WAjl4&hVrkrdx$IEP-auC9klXPbPR6K=3jJTH#qPFA?fA2x5e5*Ui!iurMr-umq(2bQA3)shJtdHKLz4RX z`c;`J73<@i?d%doZB4qd1G8Eem|Q^zLrx_B*5HEv^sky4D4iUc zBgu1``Od`#E$#PtY|+-u8)x!oY`d2RH5}XeFj^)dJsDkrnqkN95JkPFTtO(K{Ri8h z8zmJji`7;y?wR6&ZCHlAwOV_~`JJ~0oCm`hX{wGUyi$6=+p=qoae(Qahu!fN-Y2$( z5(SMd+(ypNMaBoK_6y22rTagB%ARR^@Nuu4GW?v}W&22CJhKOOKARnrjl>g1i#OhzxD{S{^BJ|;c9Kxi{;qO3+3%Hd zp?!?oL5+4PO4|<|y|c{Lt_XN`Rl`FzIiH>B!#y}KyVH2(T*EdYb`*#>VsIu=zOan? zHlZ{w-8(f_=;~i&6)nQ^t8NBo@z^pj5WWL*N6t)EV22fRB zr-$S{Lgs)-vO5AAVQCj;++km`ArFjQ*mlg2^}5+GVp)vlAkc^sdOT$MwXmY2(ht0&)?k(IO7*u46>;gnbky%f^yuTd~x23ajgnTC^&OfZA3|T z^V5C<;Olo0`M!gS4*Ny6yyfwDUHATI{pogbe@(^`@l6X$j+V}D9t*Ro zmGK_?QC=-KyQ{@LFCRW}yys)lHTT(cyIK5)ZyDEI%JSaf;=12AM>y3fAy8bSjQf`z zGuFK?1ogI@rmN-4JPtc>Rn&FK0L1A1ziUW}t$Y-_@&DZL&pm74b)^K{uYCb@YyZh` XoKv7R=@!)p{^=pSJg5|r8-x2lot|u5 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/10.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/10.png new file mode 100644 index 0000000000000000000000000000000000000000..be2d2f135a08ed14f759e40d7d89cf02c6bfbc03 GIT binary patch literal 2059 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAoVuDC&U#@ z;($Q|OazV5ghL#r%*Dk8WLhIbY-22h!PmeCzJnVFfDm6d_wTwGj+hK4`}1n}|k!I-4cdF~1AKpp-i zL4Lsu3Go8|4>U{&Sa0AUFyX;@g$wrY?-wKlZ1}K${et%S@x}f5*Zt?ru7CJC^YGc7 z{;zA77H584AOCQ6eg6FG3-%{$xPSh^hk^_54HOy<*#CFwky@L>*8CO&C=-P5GaOO_ks&KHt>o`Tpy-xaIR^?Qryo?*3jsM|PVjK4^w89 zZfX0P5HW8rh&-Mh;dbxf!Gruf+}*l4Z$D=B&%ZB!>)X4=6V<0Te5*_0TQh&Z`Rm|q z+c)mczWqG<+RKT&miZFbPAVG2%xbu`?u!U>vh_EqX&W|0p8Iy-=j8d~(=xJ;Z|mnV zU*EB5^1+7qJCYrK_jK0S#=Wgh`uo*<_VH;M!ks%#w{-n_x`z7?YsQ}6ZG|#nllae@ z>MXXskPsmhusm(!eDy`?ed`hzR$A%*)|p(pB6L#A?`u+Fyo_yI=dYj8G5ycuy$TVU zS2ccDZ76#yYAI@Fv4hJyxHpb*&6Ceh^dicX*X%9coW&aU%`%(unv1y7qJ+%j*AAPi z|22t-ZlBcgbwf<9h*01PZdukky4@i~rYscw`adKJei);(o zIQ6H?KPQpvhbJ-ITGLoM@w}8-A!C)r8rO#$F-Q1n{s;)h>brQFZsFq*zWL6Pxclh(r?V{B(MSSNtysR5V z-M3tcSa|Zr1~2*NpDyj)z|#Kru2{m`h4uE@&-fKg9J+6DWIJ6by_urZT$PdID|`5s z!Zf+1mmQi;U*PIgN>-iNIC<$xHLjqGOBk|$Gv+ANS2 zc2eUEXKSp^*(8-{*jtdv?qZzm+wD^Fuz351DVm;co;xp8DtX=TUE6+uX+pC5qG$Z+ z4^F;XA@f7@#lFKkYgR?^XCDqQoRzS!$wtt4$4yzCibWfQo7zta7j~$ytSS3v$g)A; zkz$$1AJZ8VT4E13MgKUx>(j%y$Gjyx-Gx0_e@i=+YMSOAzSL{}PqQ;-HGc%l)Vo|l zf~j9B4>&0WEttozV{%4gaqMBPS&2U{Esd%@;592zRdCOH#Z6M2J5;=Wcdl_`vg_P* zFTu6S`BaUI(J0>v!9`7j6 z(wHM$rcI&128(Q*1mAoN&A!P@$^7`slbdA2Yq_V5*MEQ z{NMXXT+K(*Q!7^S+$@OyEL?HbNJlhi-OS20KbjmBq$1dE%IRqEt%`fOsprsC4aTsz zA4_hxvC0KBG~N$V{G+vD8y9y_u$HNlr0$d{%?D=qUJGyd`mR2a*)*7eb6d90 zzj#uVjay77Vnf2gCf32m@P@c*8q{r27ed{+rG=F{ES~l2@t_-Xq*|{sXHEWWdo%vS Q98k6B>FVdQ&MBb@0Pz@62LJ#7 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/2mm.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/2mm.png new file mode 100644 index 0000000000000000000000000000000000000000..6610843eda09b7c8c8216f610976fa5ecfeb26af GIT binary patch literal 2092 zcmd5-X;72b8V-a60%4OSECDOKAp?Yh6$BG7Y(^k#F|sCtEQSb_T|~aH1xQ_j3P?au zK&#|JM7^?vH7Zww0=;a*t^rg~NL7#u%8jM%On>x8e{|-)^PYL0^SsMEbN-w{qL-VZ zypB8w1XA>H$NPdnQs}Qo4lGf;YEHXJKukR3?;=3}02mC0g!~qOMEW%)cL~|9{2~4o z$^L!n&kcA0ZwMGla(fj9z(^Kq0b2HeeJ~J=0#LHDvU+-YAP`7RO)V=cOJW9(#}kP} z6bcm*5<;ib!CO_EN`Z7>->k?yD8^fM+vf`>n zJF6+Ynf}@H;`jk8pbNW&dv<<}3j#qo9(X7JwDC6s7!ANmU52M@I|_N$sheijT#0v% z3^5*=yMFOI8nfq1lQraBBl<{F#N*<;zk+86O14YJgnyVgz9~;ltUm~Um$bpaB2}^1;mU%AUYZz6675#p&sC&>X>AhVPD4iyVpF_6RnBDjaa}uSW-gJU zyufuS-hC6Unf23d`NMYdM|#7L4Nt=anV0Gv1C57BX2(wllSLO)bl!e%{aK{(*=jQ8 zWnwRMfVzk@K8^ z!vo^RxbCTg#!p7%SV23objKeJL3><7b46Q%pZu?-f`nTsK~f6-;}Gt@?cf;G+%~hG zdx9q&$NE7_q&wX9<^sg6j>uXeRq6?&@5nwEy<0yscH@I`9RsAz2f22tPm?WH<)(Z- zRXDN=d{<>$0(iLU&R+X{6B7u1@Wis>;{+JmEaSL$^hDp^h)RfV8j5Qunu3xpM zPLaBtgJA@{Sz*Fk-ib*;Ai9*W^UNgD!Q;oxn`ncg5)unVCXZHxjdhyJCr97Kp0?o{ z>#DNSp!!%@d?~?vMiIRggd+{UoGdA9OIs_CUaWs;>(q)YiFwVeL%hZyqE`}ln}ood z9IXAu4SN6HD;yoZsadi#O_g|+rhLGaP}r-D^@l0QtP!ZI=-oE|D(9VmwO-s+{-{HC^j-V8`UBR+MB7O+40_$&M>~eR5`V&@5nZCIH^){6=V6L>{Uk@ zwnarPEk!{nDtYj3zM8(P;iqMA4PG4ko>fO0`1t= z9Ehp@mCHHI`=|#NMLZ>R=u%};pUjqD?;&xMSYW`bVqP6ojvQLKC}?#$s+}$tmJxHk zsNI^i5A#3ATmB3l0`h$Hiu0->rd7yC=6Ue59N$iu58ypuhYm>>bsE;=hZzt>CB|ac zevJBlvWzs%7M&dt=(OwFnGPkg8NR5UNwwv8E;|x4#$MU>Tbj@_v^Xylo<0xv4jqk! zr!EP4x_;QRh$IConm75~LNV_>+H&!e7B=S3%f6V-j11V}ZiQ&ehcJzc{)5WEke%v& z(Fz-1rcMQ%$ap(B&+j(O@-O5MllPhyO$v%tU5)h2Z;!Hs2*z*^Ap6+!($jVjx7IyI zj&8FS-)=@RZlK)MN{wU(3w$@_ko&UdMQsq2R%COi`+t+A6y#c+g{8@=h+LZj?Vw~3 zi^-3ZeV&Gns9lJAO60 tdf=-;lv3d+*(6&G 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 XoKv7R=@!)p{^=pSJg5|r8-x2lot|u5 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/deeply-nested-super.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/deeply-nested-super.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd0e6990fd242b2ff0cf37007a17d712251e209 GIT binary patch literal 1573 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhj{TC&U#&B$I(`WNrhJ6r7Erps}$LXq4Fg`ykV;OM?7@865uG z+bb9(To5QINZ6ndu)tu#hx_jv&Og|HA^&WA{ll-b=fwA~KkuJEVZ(!f`|sy}5Li&Z z|3Jfkhxi29&8rI;7+79-x;TbZ+A* z0k`mF1zn--yB1aTiL&ilBp{{}v0+v#tM`V4gH5d5)4-&d4u}nu0g~4WSYFpaBtc4{ z^2m&(C-XL(yYl)y8~3%(8>*rY?rM12&<@nTCZ7|ca{W$fpbc{xM6V6HZfBm~3 zA-*Ek**vZEU-+EAaWf{KK7ZuwJk#d?JA%27Zen`*@ag(Tvm*jSLxVQt%*;Bf_4@y% zCw>fJakAZoT7Pe+H%{*ky}0vU0(bDUM$rvEfqVz^em`^K-N-5>=<)C^ar!8d25WA38UJdA{{?tBp!B-PxDb*aa$eJ_Kzvn&IX8ykzH6 zzcsuKPD)`+3h!&*X3k(T%R7@K5Wx6-ygcgy5`u%9ha*1wrakt zl48@@z4X@34I;5(8&(wcoMFDsXPmIJ|IL)@i(C<%%-u=P*NSdn(_3?*GMjacDZ}@Y z8G)M{mIggHoZs~F!@&?%olEN-;&!wx`g5eTuDy2tTLp3L+w-f;LOQsMmL{1@>Q2=b z&eC3$(7j$f`@|XZy5=vZyP|?UW5Yv3ukTv$`e;?sGtI#3)qhf_GFOBy+Fwc-*?Yl_IGlN>GQPhjH~yunpbl~to8k| zDe}Otls37EZ~H2xHrPepQ$H)3Be)?dYMxo-Hc4ZC=CId1w(7StpHy;1tTq1f=F^V0 zYvjeW#P7W;$j@7*f6@6;C8&Rn;lY}w8-wb_BQ1CetrG>2o$&;uX^ zDQ-5ffC`-r3D9yw2vXjtMr?43c&xjma6{Kh+r6T}{~7-~GB*A&?EVfam_1$nT-G@y GGywor9*i3R literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-1.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-2.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-2.png new file mode 100644 index 0000000000000000000000000000000000000000..830e6aee268cd7ce75cbcec83e03cc5ae0713ca2 GIT binary patch literal 1624 zcmd6nYdF+d9LLWvvx(elW@<)bqGX0YiNzvx!LTk#F8@T0Q9W)MmvO7HGqPdKhLF~! z6e%<^E;S*{5M5jfDZ3-2&_$6RE)W0$0>P$Il@W-a<>dU(=twd-&cwtA05=5%c3>cj#gg6@qNNpp!>J$; zG&DL?LqqxmSw=>BTBA_jN=i~g13)?wASD4H1^`O{lmYMnz(`vAXT2wc6QtgV;pTD> zP>+TY=a#(0^s}@1%fh7P2+7;7>p8bZN(=H|h$Nl0VGH!B7b*pn$=$ogCCyXTE4xGP zBr*U%Svc72agY6T^65?t+W?K^E4$P)lD_OvQkM_aKA-W27ss-WJl5rXmEXj3N_d#5 z<(R``9oKNofeuw4`;;=&-Wry!!n*%7Mlx_Caugc>9X9-0n_APM+o4(lnHG}cxXngAg!La(*O4Ip zHs7s3T;r=zoktkJd_3u)~Hb)6gOn z-jGWY`?i-4BH8pHS5^7T&VlOGY`&GRDHlc3-#T-@=s@WV<6OtdZ%4G^Xy=m!)P3WJ zH|I@sVk%&)@}d*-Pai))@N z>v=&s1WvTw6XZybc9-k+7e-z@^=u_AVYkClMU@u%l%X5+#iu9PK`{4W$fIh}hnhFOKo z3jx@nz^G@|{I<-u(b6t;t0C60#0%CTj&NJgd_)zY3me>dk%ChYe8SV+j9RPXGWGpM zw=}Le2eC`ixfis@U+F+K2N*?2qWz2zmVpux*q@pjRTyIxQ?0bI{nL2=SFgq5+h(KI zspf_`&ex3hK!J`A1mt>9C^zE@e-(vg2f>0GTDi8$_vjm{QBt Z5xE<=rDcQtEvrAWgRP6rt-aJUe*rx1w21%! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-3.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-3.png new file mode 100644 index 0000000000000000000000000000000000000000..830e6aee268cd7ce75cbcec83e03cc5ae0713ca2 GIT binary patch literal 1624 zcmd6nYdF+d9LLWvvx(elW@<)bqGX0YiNzvx!LTk#F8@T0Q9W)MmvO7HGqPdKhLF~! z6e%<^E;S*{5M5jfDZ3-2&_$6RE)W0$0>P$Il@W-a<>dU(=twd-&cwtA05=5%c3>cj#gg6@qNNpp!>J$; zG&DL?LqqxmSw=>BTBA_jN=i~g13)?wASD4H1^`O{lmYMnz(`vAXT2wc6QtgV;pTD> zP>+TY=a#(0^s}@1%fh7P2+7;7>p8bZN(=H|h$Nl0VGH!B7b*pn$=$ogCCyXTE4xGP zBr*U%Svc72agY6T^65?t+W?K^E4$P)lD_OvQkM_aKA-W27ss-WJl5rXmEXj3N_d#5 z<(R``9oKNofeuw4`;;=&-Wry!!n*%7Mlx_Caugc>9X9-0n_APM+o4(lnHG}cxXngAg!La(*O4Ip zHs7s3T;r=zoktkJd_3u)~Hb)6gOn z-jGWY`?i-4BH8pHS5^7T&VlOGY`&GRDHlc3-#T-@=s@WV<6OtdZ%4G^Xy=m!)P3WJ zH|I@sVk%&)@}d*-Pai))@N z>v=&s1WvTw6XZybc9-k+7e-z@^=u_AVYkClMU@u%l%X5+#iu9PK`{4W$fIh}hnhFOKo z3jx@nz^G@|{I<-u(b6t;t0C60#0%CTj&NJgd_)zY3me>dk%ChYe8SV+j9RPXGWGpM zw=}Le2eC`ixfis@U+F+K2N*?2qWz2zmVpux*q@pjRTyIxQ?0bI{nL2=SFgq5+h(KI zspf_`&ex3hK!J`A1mt>9C^zE@e-(vg2f>0GTDi8$_vjm{QBt Z5xE<=rDcQtEvrAWgRP6rt-aJUe*rx1w21%! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-4.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-4.png new file mode 100644 index 0000000000000000000000000000000000000000..830e6aee268cd7ce75cbcec83e03cc5ae0713ca2 GIT binary patch literal 1624 zcmd6nYdF+d9LLWvvx(elW@<)bqGX0YiNzvx!LTk#F8@T0Q9W)MmvO7HGqPdKhLF~! z6e%<^E;S*{5M5jfDZ3-2&_$6RE)W0$0>P$Il@W-a<>dU(=twd-&cwtA05=5%c3>cj#gg6@qNNpp!>J$; zG&DL?LqqxmSw=>BTBA_jN=i~g13)?wASD4H1^`O{lmYMnz(`vAXT2wc6QtgV;pTD> zP>+TY=a#(0^s}@1%fh7P2+7;7>p8bZN(=H|h$Nl0VGH!B7b*pn$=$ogCCyXTE4xGP zBr*U%Svc72agY6T^65?t+W?K^E4$P)lD_OvQkM_aKA-W27ss-WJl5rXmEXj3N_d#5 z<(R``9oKNofeuw4`;;=&-Wry!!n*%7Mlx_Caugc>9X9-0n_APM+o4(lnHG}cxXngAg!La(*O4Ip zHs7s3T;r=zoktkJd_3u)~Hb)6gOn z-jGWY`?i-4BH8pHS5^7T&VlOGY`&GRDHlc3-#T-@=s@WV<6OtdZ%4G^Xy=m!)P3WJ zH|I@sVk%&)@}d*-Pai))@N z>v=&s1WvTw6XZybc9-k+7e-z@^=u_AVYkClMU@u%l%X5+#iu9PK`{4W$fIh}hnhFOKo z3jx@nz^G@|{I<-u(b6t;t0C60#0%CTj&NJgd_)zY3me>dk%ChYe8SV+j9RPXGWGpM zw=}Le2eC`ixfis@U+F+K2N*?2qWz2zmVpux*q@pjRTyIxQ?0bI{nL2=SFgq5+h(KI zspf_`&ex3hK!J`A1mt>9C^zE@e-(vg2f>0GTDi8$_vjm{QBt Z5xE<=rDcQtEvrAWgRP6rt-aJUe*rx1w21%! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-5.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/inheritance-5.png new file mode 100644 index 0000000000000000000000000000000000000000..830e6aee268cd7ce75cbcec83e03cc5ae0713ca2 GIT binary patch literal 1624 zcmd6nYdF+d9LLWvvx(elW@<)bqGX0YiNzvx!LTk#F8@T0Q9W)MmvO7HGqPdKhLF~! z6e%<^E;S*{5M5jfDZ3-2&_$6RE)W0$0>P$Il@W-a<>dU(=twd-&cwtA05=5%c3>cj#gg6@qNNpp!>J$; zG&DL?LqqxmSw=>BTBA_jN=i~g13)?wASD4H1^`O{lmYMnz(`vAXT2wc6QtgV;pTD> zP>+TY=a#(0^s}@1%fh7P2+7;7>p8bZN(=H|h$Nl0VGH!B7b*pn$=$ogCCyXTE4xGP zBr*U%Svc72agY6T^65?t+W?K^E4$P)lD_OvQkM_aKA-W27ss-WJl5rXmEXj3N_d#5 z<(R``9oKNofeuw4`;;=&-Wry!!n*%7Mlx_Caugc>9X9-0n_APM+o4(lnHG}cxXngAg!La(*O4Ip zHs7s3T;r=zoktkJd_3u)~Hb)6gOn z-jGWY`?i-4BH8pHS5^7T&VlOGY`&GRDHlc3-#T-@=s@WV<6OtdZ%4G^Xy=m!)P3WJ zH|I@sVk%&)@}d*-Pai))@N z>v=&s1WvTw6XZybc9-k+7e-z@^=u_AVYkClMU@u%l%X5+#iu9PK`{4W$fIh}hnhFOKo z3jx@nz^G@|{I<-u(b6t;t0C60#0%CTj&NJgd_)zY3me>dk%ChYe8SV+j9RPXGWGpM zw=}Le2eC`ixfis@U+F+K2N*?2qWz2zmVpux*q@pjRTyIxQ?0bI{nL2=SFgq5+h(KI zspf_`&ex3hK!J`A1mt>9C^zE@e-(vg2f>0GTDi8$_vjm{QBt Z5xE<=rDcQtEvrAWgRP6rt-aJUe*rx1w21%! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/invalid-value.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/invalid-value.png new file mode 100644 index 0000000000000000000000000000000000000000..56ce39d6b1f54015b85272515fda3ee484e360f2 GIT binary patch literal 2093 zcmd6oc~Dd58pZ<|5(ult5JX6km?=uwQ8q6K1Z6XXML1zi5D*Y58bJ1(1Ta8>3kp%I zQ!qjiiQxbODpEoa)UpV+BrLLe@rqJ0tqZQ)L(|SU)Bij7H|IR>`##_E&AjKYQ%s{C z(8TCt5D0{(mnS6vflwlEysAjppp+`k;oUkw7m;cyUtj35Xq zt|W7kVHBpqiQq)Q&^R=hFMSF~f!WBw4=f;PWo5-?vlXL4cY(WLh#(OjiA3TbxeYM{ z4Pm}a>VbM#EcQ!B3)F&9I2aHEHyF&u=c7S1j1EWV%PziR9=;qCy z9qnMF)X(+HYv=Oqx$IM8q8D*M?(EED*UX53QRwmw854ZCQ;uV#rEWL& zK9WAjl4&hVrkrdx$IEP-auC9klXPbPR6K=3jJTH#qPFA?fA2x5e5*Ui!iurMr-umq(2bQA3)shJtdHKLz4RX z`c;`J73<@i?d%doZB4qd1G8Eem|Q^zLrx_B*5HEv^sky4D4iUc zBgu1``Od`#E$#PtY|+-u8)x!oY`d2RH5}XeFj^)dJsDkrnqkN95JkPFTtO(K{Ri8h z8zmJji`7;y?wR6&ZCHlAwOV_~`JJ~0oCm`hX{wGUyi$6=+p=qoae(Qahu!fN-Y2$( z5(SMd+(ypNMaBoK_6y22rTagB%ARR^@Nuu4GW?v}W&22CJhKOOKARnrjl>g1i#OhzxD{S{^BJ|;c9Kxi{;qO3+3%Hd zp?!?oL5+4PO4|<|y|c{Lt_XN`Rl`FzIiH>B!#y}KyVH2(T*EdYb`*#>VsIu=zOan? zHlZ{w-8(f_=;~i&6)nQ^t8NBo@z^pj5WWL*N6t)EV22fRB zr-$S{Lgs)-vO5AAVQCj;++km`ArFjQ*mlg2^}5+GVp)vlAkc^sdOT$MwXmY2(ht0&)?k(IO7*u46>;gnbky%f^yuTd~x23ajgnTC^&OfZA3|T z^V5C<;Olo0`M!gS4*Ny6yyfwDUHATI{pogbe@(^`@l6X$j+V}D9t*Ro zmGK_?QC=-KyQ{@LFCRW}yys)lHTT(cyIK5)ZyDEI%JSaf;=12AM>y3fAy8bSjQf`z zGuFK?1ogI@rmN-4JPtc>Rn&FK0L1A1ziUW}t$Y-_@&DZL&pm74b)^K{uYCb@YyZh` XoKv7R=@!)p{^=pSJg5|r8-x2lot|u5 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/mixed-nested.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/mixed-nested.png new file mode 100644 index 0000000000000000000000000000000000000000..fb84f43074f7a3109657561afacccebab5b8ca0b GIT binary patch literal 1781 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 Sd|k=Tx9DU~Cf&9LQvLuI5No{v literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/with-rotate.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/with-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..eda16b21064e19336a4a8d5de8ff855a14551028 GIT binary patch literal 2304 zcmd6oX;70{7KT3v5J}i%i4kNOB8nj`n;;@0jX_pfC4LBKf-K6?KoT@6N)UkrM3zQC z0?Hx?8nUp;j^IWz2qlmp8W6fc1%c2)54fe{I8Jp{*VO!(A9L#7dY?M)x%a;RF5TPH zSsA7c0{}qT)dlMd05X`bdjmw;@vOY)EES2j$6+U_QmNGB1t0(b2>>uaS65d`9@h?jKOXquI zcAc9hWq-1-ryqbnu4b^L7AN+0kWhQd#NB3-_*dS?mpE}rLpO5n_fvh@ z?AP;ytpoG>y%;6w7ph37R@uj=7)h}=g=O7%&Ln&Al|jysSr2u;#G%i#>l6S$16{E{ z9;S@H8#33TIw;9=dX-n9lidi4@tX%k`sI-}C1nY2eo7oeQq_Gv3xO(#bk$KM!B4-4<&)-EsMr>5SNUyi6j4 z`8ZF14%S^6)tOykSsm`Y{A5(7MDk`cSxuxRn46!I!IxrdX;1i9H%))IxT ztRq{O$Q)Qc%Bv<$oo~h6=B901_pKg{u}r?P6_csNK@J({=KOtt0M;_9)n@H{Uu%S~ zj=S28#V;z|{j!Ttio}<5$NP(IQy)$wzZGYltZ|51&4WiX_x9PM^#viVLE~q0*j|{J zniT=hh*-#Ud^*s`-E#fS>wUS);?%BHHrl3luxW zGosqw>naMp85i6ssazX5K{9G|tZ*ZS9#OZsYjc&>QIrs3QBbs%zPOacj$3UoBh6Yc zAoALLB@=^+qnZzVerRcJvL`1Dm}_L6$TrRhxT}ummUsFe!{->>3Df$`z~cmJ=Q*_M zve3{!ynd7ZNSkT9)gm8jD2zI30w8WUHQzDywRXn#+74G?!xTPkbk4J{{`Folj#6>4 zm_YDEF_)fMSvlj_j9<^C>&xx$(hLV9wz$^XRWvXq9tt6VRiPr^&2UFeMbdF!GQ{{i$gHtEI=?4i*s(CeXIW=iLNvXwyuXtsY~bTFntI-{Owa2Q=_T%TV&d9#iin$Z0DNh7;7WlK-?ER`>aG65&4Xk7I+G6W)=}3t>lHzHm|7Il>s9P$}zq}1)Uh!E7qw-kP4Jyu-n;n1UM zo6WWo2RK*e79?^}WigXtBtA8*aQXp^ayDLU%$XZ|#f_^f);vQ3w}>x#Y0h*nuCSpd zfP0F~!F?tH#{gy-2JH2#vxOBB%sb@myMBrNvS(oaem$H7Hw&8K!#9ZP@#dFEhxlm= zhPWC?1+QvC9>D|Pj1D%w_ERn(Txa?z96?}4Px;&L7&h%H)relxvX+gx821pWx&h9x z`^RxccH!hp<7^+e_4D6Wi}{1k!+Po+eQi-jHS*T7<;lS*i4-tois0{~S7}Cnp>5(H zl)2A zzlAdTmaL%XTTWRxf~gPtW{v9cO`hF2(Lb*a_W7L+ON;QhPFxo{50rlW(_NiBu`EaY Gr9S|tVC0_w literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/cbdt.png b/crates/resvg/tests-hinted/tests/text/color-font/cbdt.png new file mode 100644 index 0000000000000000000000000000000000000000..adcdfa237b234dc940ec9ed5487f3f11bb0c1324 GIT binary patch literal 10675 zcmb`tbx>SE(=WU%?z(7@;ILSNBm{R4mR%MJ?(Xgq++hjs65QQAXo3bOcnHA>&R+6- z->tfJ>)yBCKW^1IQ(e5M$zwSA6BGul@;bKu@0RRA81$k)=004>O-;06v+~egJ z=LP_QDBM z(O&QigrN^-VNPed%eDA@ynu77E^9OGNF^TB~;?4pdWJSzQ7&#MsK*W;{ zAn|@%#d3AN?2LjEq0B3G{k??7zt{Fqgz8O>3#I7F0j=ezDZQMTQR3}+p?_JA-MHbJ z4sDhg&JZn3`{+`mM=Bo|==Bn*fPlylD5HY6?SeB2Qscl^kd9EO^1qMDmiZF}gGbt(jf1ccUA9NE~3xAtNu zpb(|R$RZQe%d0WNhq`co_UT66vikB}oAYIa1kd954QJlX=l^Y?{F`s|_OVI@;rH-1 z{WqRAEIqwc-xtZ|W_NRvtKqz+qWj|ul)g~1su<-$Rsd$YxB?ne`#u{@Hs)X!2p$el z$@FX6<{!-lp61Wa{rt`MlOMIy-<;<@ofF}5xnf$qYieYsesv2r?K!C}JhXX-(MiA| z&Bl{2*$N|P3D#g_a=ZW9v5@_Kwa_mdrXT7kuyVdxhK5?|YQb}YE;ZY^F<4;{PviI4 zoH=#;Y;bCuz*X5nZqM#k0NNAw68EL|vKn@T3?xQ6tO?0*t%{9=vzqkUk_MLs70-yz zlQ{28eNOMSj$?+=+h1;;HE*6`9Q;hC!PTfD)ykyMy&uF2k7f?m<0^W88_eSEVr7Fh zzQ+~k@kC_)0ydf8Fmrhb!(l?P3;>$bx<<;=cX`8@QsEg=p?fNy#Y`W2j&F;4zdjpS ztvw;?bs^Jj{+JDX$W~k_02bEEYhV{PQGft-l~5+OB`jjF!IPTru#_GbFdwwYRN&l6 zqcD-FR$&w%;&aZ%YqS=^-TJgHSl?Rx^eph|Lk|c^UyE32Q}&Kv5+o=J8?>(8WSrnyGqWTc6db5vGUlKj7EAD zok;ixW~r^ z_sQyf>%wJcn&yYWJ@B^@*NXtw3U^Um!Y(w^DkHOyquUn zt4{ixlc(L9h&F@^(G*0E85`_!CrE}snhKe`72hqtRswGYs0h%wV~7PH~573 zl6O|AM0J(kpOlHUwU>Pq$3$mml5`Gf;DFLhPqF5>nh*Nw!=UyWDbI+adA^%oBRyt3 zYSa;A+U1ABrk$IMSp0$zxlwr5DIFZ1Jbjn5k@Vn1`8DeOvo^w7 z^hI%%V+ZimFS^PVEFkSHPPgcaSb67)B=|JCWpVL4l+6aI?1!~q0U}N@|DqvkK%zAF zOhhbyhF0sdf2l-Si=wvn$j6FSirgq`K?Mr%$O=qDA1|^@*i|09tQ*@{CdIk$cJ&a6 z5Zy<-r`e^HA%!Ql4fEX3RqZQXW%~>TSBgUzD-^-WsVJo5Sg!8)5mSwf_jV-Wn6Q*8 z&{|NzG|6|5#*K>0nR3h-UKx4~p6PxyB=*9^#3G^}A1_Pn@Bf6?!6*2!7+hj| z4dlc=JW`djBCH4^a)8bC>^La3F_nWDv1TA_X}iXdVqnCSjt?tg9$zH<(w3u3KIzPX zo3J9nEG5E@!YUQ@5HodQ?4z2c$N@sYe)YWPsf_k8`D_1}UiSpeQ;t}|QY@iHW?R{t zsTa&Gi&~7}XtOy^c9Ljo`WM<%^pQI*#6R7#i0fg7QPQ6yY&vO`z@&>BGxd>;Wz5dk zk|dC}dBu+HuT2}bJ^_Rx{}yFDJiXMut9Pg?P{lr2u}smxFfNpET#>pys)#6(OPltD zjdU7?$tVy?o?UFt$dxFM5m7uZ%U;zeMrIbDT;KNkL)377r8k+lTMh9@dG5cB*5-Tq zw0y7lq)GRI$7{ZXJx|^rrm3ynQpw|HYIe3R{ed8wAyIQK?J#af`Hor|80BL``jw3| znJAyh=Sw5~PZe+N;`|&8_Fq+NH;>0%nKXWY{e*um5HQcZ7YT^}9lyrLq771$6`T85 zUvFj#`U*5|W1TD^>XYtg4YLKkB28oh9+56eyQk^vD0tayr}fIIix&cagAn>ta9SL(YMW(42jb0*`>>d0SJ?N0?s+U9=pl(TJ)>JRJN!ew`sWCk6~)`cMObTd zXlrFQ$JtKuhZ05?lGIP??mF*t4B=f?7kv-Z0Ri|_qtBqnMcpim*qo~Q$_VO(krr=t zt4K4J$e0z&W2nn3%S%Ie5>whyn>dt4v5`rM%V9b?uEL4RCn-!K+@N4%dQS98tw(kU zLhPR?=yd*b77JQMbaL=nH39KX+b?~|&;>0|ibZ-SBI!EQiA#CNE8n0*etzBVPD!lkQ871(Y zqQv*4tU`wEVAC!-&^$x4ma2{W zRB+K8^r+s`$kuXjC;5_c{$5}SA($sKUw!N{lteVbC`%9So_)4l$1(Rs< z-#^PevkKf*JW)@s^EmrYdp9mU7R3Lw8v88Nu!oKkz~jnX18>}=fW!T%i;dcuXVC7Y ziLjO@7#Q+c)(hj1#1(64cB_TKELXL>{_s_!+{=RmU{bsxT1M!nXm zE#R&=LLaCT36OsV)COUn+|l-vdJi%+XKIV(5ro5hm&!m9Vc|>oVp4Di9wl+OAXOZ- zxjwUCR+gFhr(|5e+<}QBa#Zu?qV(^l%Bmh4x>x=UetaUc#}#Lz8$Z4;UkR0>9lF~b z90)=jy4JGi%()vsNrVnTQb9b-9q>jyDGM7Iza3RJyTSbe$%*#~wcbPf%FX;nXLPiI z5BS7)7J`k0 zCVt!1@CpC=k}V%UX{TJJwQ)73x3|(LEUDEqaIPUS?bH%xMJs!ZN&S!Cb;|5{V%vr< z2OGEJ5v~!rdasm{Sj+ih;!0k$R`+{!^A2=uG{AH0#~*j&gvuXw4dPE5z~<_x5Xw(- zMAe<;6WFP61jw_(TZ`eX-zdxlKM!}MA~kWiAnp>&7;`6etiGeQdK2` z&{3ISeqbQ`6~X;?Rg0SgIs8}re+Z1`soOh-Hy+k7#2&um&`HZiFc<}~f3O)7dt717 zed^i%P)-A|TB8(5-qq5cVeRG?NHj(TAwyeQf7P)NhW28?&q{YR(nLon>mmYC>BV11 zjhd3K>+W0rX(D3qJp(7}H8|j%m zQK?f~$=;3+7~2F95+pCd)mWBRBu1a~Vrm^WUPwt{(tledB+Mj-$aE3yr?8?yC}V;W z6H{!eIYS7cAueOxHsdj|rGs_(EnU*KocbWh!6-<*(TvLDPd8S0I1xb{l@2GqFSAWF z2OoKc_v&0=-pcCgk$?{B%UU3+!pHMyaY7{eLn+FYwmt7u00yoxw00R->$tzhKg{w1 zLq$6DIdg#NB$Fc*MyNfQ=_)l0`|Mh@c+iptH8W{3aOFx$cw6$Oz;9N0!au`#tQS7( zevK^u_BN3pnD}yR#h+o1Z>?idynzk{nit4~K;cAS?rhas7F)pMUCwR~KU5MqPXUw*3JcDqMui~=F2;N%q$2`N|=6!?nU0w>H5 zW5>ZQZ6xUZ_Kj$cv#Db5`$28Icx4|s5^=U*!(+`|zBa)!Wv~*V3wyk_a8&74o%0fl z;nIrO%fhyL{@L=#eT(}N!t}n1t!!uEes&Fc>*X7Gc&T;Fu_{6Ou+NZJnC+F#Qs3(8 z%(q%k%+Mq3;lL|-_Od2|-BXv{SsP-h$6g)@j7q~uxA?|&d@*PY9U6hvVV8B?gjK${ zfVN&2XX-oD6!a8v5^OAty!P{x0UfJqU8Hg)$z|>}Qg&9A!9Z`y3{`wk-xeF4&U)ZC zg$6oX%n*g+RSrXdrT^h3oHN#R(e5?&Brcj7fGLf*67*i$wAf!P1!7d?cxdG{2WF8( zX?Eb|KwLER-!2sR&4M4v2ha$;ElHnunl!i+Sn?~3qOxsq9%P>WhpsBNkTt8Gb6VUW zlpS1v)zw81fO@9ZU(HkM^6@L+A-Fckp z6A2@EmdZHw2Ss^&dz*v+8jb{cdr?VGB`}y3arN7HY8fJ#UA>HDvrjQ}*Yn$LH|(w< z;7j(@`{a+~HtD)guC-xS)zsy{g-hGDdVXVd0wB0H%s7|s0>GdGW+8lS>FzUdj?h*Q zdkXsOGW{#BYqFNej%mQ_qJm=Uu>B0v}60DzJF>t;`=JBSvfnKr%WD8>Y zO>DL945mA5aZ^<$`H!9`OGRa0k2%LgarNNxdlv@zdHP=G$sMhm4{<(KW)#T#xr=== zWN!KT+A3{Xj(u&}!WRYAW+7_7jm$iM>!L3;i{#!W6rmBmPcdCJh(R?GFSe-Oq5lUQ zLxTSUfGP2;gnal z=d4FWb06=cP9Ij+>_}(y;1j}TY0sKlaL$WZ+zGT_CYxr#%>z0g%9S%zH9?^NtRIO) zD*}TP3w6LHcX2%T;k&uM5G`fL6i2;1&t7G=jQ&OW)9o#%FaouUB>L06=0?WnH(hQC z_?-dB)BcLw@joEOlj0MC@h6*CHNR>C0`{{P6<#RG%42ed?nc&fFwkv^Y|gF?nYPDn z77-9;z39Z@qaPP`>@%yXwQ`9gbNIE*#Qn!4$l6c%`7Cr@P1NC$MsRcMM=PtA!h|#V z?1-R|6M)IFoi2+c_-D5b-ltqJL|j4;$=Q~55@!<$MOvc4Ax)&M^EsrEK_7<*u=qN% zUv}Vm7GTmmhY^kvTc5S9U#g7a->jK2pARC>8;LFiwuF9Th9E{N=L>bz<#K#0E0KoD zokILC?ohIUB!KBhIc?cIeIzxAn%c7l5?~{@F9rI2;IiQJ%|h(Hg3UA>Gp}-vaqyu8 zNla`_z0(Ls^gm4{LG#-V9-Yk-X8Imcx#@-O_ZX?a@p#{e&EzXQ*y0+fsO@|4sO_IM zH9on_J2^fv9m$ zVPveRu%Y$rwf%d-{Jx!dB8Ov!mi+4<(>qC+eo9J+$pp)3{cf5vC2nh(L$ zBszo14*7&K#Q|#KB;pDq7GWLkE%ORXks=a<>ZJG3Q%$pn$^oInn6NSz z+?j3)Wjrx2UVrz9!>Ynfky}pWK<)07(#a~ELy-(-a%9W#>r^48-^>5Y4ue z&^bh6%xLk7DSGe~Gp%~=w2ZvzOR|^1ys~xT=WBZP{z}r|DJm}lrj~RH2R=*3M5Ieue(*$P0K|6X0}HS)F!DCRycmwxmZ^RQE7RLT4(8jm?(t$ z1AcviDqoF2!a_WVCrkjqTvFkCSg(5eW!e`Wp8II3@A$Q2seRi>T0N$&nTT7-QJvh z0*fb)Zgd!Ibm(`t?@L)QY*!s1@fJ6(eH9_0jAN`FSH9I%_?owGQ53<}egCCrD=XIH zEOZu^NLMYROzcUa(mTFp!U)GR@~g+`veHn?9Mxg91G{mLzTekS}g*utfc*Faj-fZl-PB|Qg|aqnK@Z5^G# zLCCsYUc$k$4AsBR8-lD|y#%a12>$y|}e%(-h;@MaT^A-nv z==D*)tcq{vjsO8GB= z>9l1uJ^rY9(Ne_WswBinhj{K??$$BMvW9QjP=Fb~S@rNHBG}&^N{LLO8r8(&pDBir z7xd}BQ_5+|R=8jyBp66!7dxceF+`sffamFssZ@^Ck#`ZMIDE0osvT4^q802YnmRu{&JY$&Ak*|?4=i<0Ct z`U>oZXOJU_l4XJO6YpP6XiooNu6CObIMk)pDWsr2j#U8J`Uu%QqP{yVX^q&NPzJ0WSS zQ>9ZdDIG!2z>{Ei34fB-yhgPFpua^;ySjNhdCU^Ufvo#(>BsKbm=mU9 z3{#wmM$@YQg+%wouIfciz>~z2ujq@XO^=Pi@PI$_ohKi;w@<{*D}3)Z5Z3-HSAV=C zUQoa5^zL(Y{k-DP9S07${Bx_b!g6zC;G3|4m|Q%|H}C`XAXXeU<2SC|pYE;$lBXZ9 z#p)4Jv^)ZWQ2bTaC_=*eh~DL1v&R%M_2_U{1YI~QK(L+;B$9kuGpq6Ulxtj3jQ9}zn33wFRz5TT)WROU%%B%?yvM5;m( z`@CY9PL-sadB##3#Rrgtcu^g@9visUqL5{oCr~aksr(C>l9k@9NomNhorC^4^-$VT zDt|b^bE>SzJg}X@`*|rxD!Ae!14;bQ=S?u%Sxywl)TM)!G(B6FpKSb#HC2J&XJ`Zl zUFe7arN>RLxXZ|RvL7g z_r5PEH*-i!LmIH7#9HsK>84QpIV{H+n7OxG(;VR02+-U?5#?*|DeG##i_uo>Ru`o-DC1bFw$EF z6o1ec_h$0Q#OvP~V}+>&veo%0k#v|iY-M!V$L5*q$1$BWD-|ZG@42TbBxvS?^fO-q zgoaM9kEr*L89nDTX(#_s6a^*H8*-Wm9r1_%OM9>9$0n}I?o&`5qe`&w=GZ*T;wvF= zEkI|u<{L84K24urC($%SM)T|Tp7Tm~FkVB6G=q=)kKIIauLVDOqi@QXZYYlsi^@Dh zJ}f;)iJ5s&dP6ZQt^n)3E>yex1p<|nBuQFu|BNZ;I)=-+PPlA0S_00rPcYk~HP-#UgDeg^v-(dq=pp)eqL^~bFK z9q?J+=Adi$`5vdiyF_L)#sPqo~-yUW1q%@o&m<#$5pff(eO2;_8wHKONGd#~50 zCC2b+{JR&PJg5qNG3ncRBkAY(SXs+moaxrQ%*D=5d_w3)QPSqhU#9n;?6O)O$vhX> zd_0HaL~LnRNAH3p6o)V%PzVX;zG!v!VrNl&PPHt|%sw#_sulQdC~drG+axcFP;IAy zk_>^*(nPma1R4d0o3lK1pWqkj8Ig_3zKFi!z&7l~64&I0dlM7}1_Edly#{!>kLXoW z5qEQMo21*gD?i`;n9JQK?6RmW^hszy6HsG8!^QxLN1=z6E4}3tnTnUicN$9kO_81P z(ut-f=e{7}jqsmUd;Qz-wUnq5!A8H|QjU#v^+1hysK)9JN%tNB5`F{aJ|b`b^oEb6 zNj%Uc&;hs)+}J82j(Li_4e`C+%&c>ga0Yrs@1TCwt_7kEif0o7qyfkgfqXTkJx^U$ zPusI5FWx2PjYUZhf72el7;Vz^9D{$fJw6(t45@X-!l*?YyyWWmO}Dt_2j*2kg+MDS z#?LED-Or--{{|;fLq$#8b^-hGU4cV5P5Cbg4jH2mKgc@#JvRB}N(CuUV`E-tT>@v@ zZXcW4zE{jc)bZcOGh=;ms9L-^qW8@%JuYy0{*b4;a5^f&6eZJOYsmU-ZDESIewU`OT7GQlS)`Auc(?2EV{ve`yEP5uG>6$ZWz9z5Y-~++OQnNrC#L&~{1sv&%oQRN zB!_FiyXM2S)mAE+)U81kRiDD{iB9!q$Fq;u`=;x`7+=A}ONZU`@G+F<>Uw_h;?o(M@=tu<^4!$6SH4YH z{4&J&{P86e`MXU_jqs_TeS)Jh{ZpD)od?h3S! z`|ndz-JCj9?QfC&t=pdf{*jT=!8gs&g5(_4o{O7!KImP+V5!=4j#WF@Cps6TanC7B zCsK*K>k?v=^}}ShAYp0W0 zxNjsyGS!_iGuy4&xbJ5BD7y{Hy` z`Q9IcaZ(VFJ$E8FAvFmOGXTRs@mC=`Sf>joD3ssR- zgU@$|Q->aR7hk_E>s`}H;z=XL1Bobj^0168k7qRqkYINi;eo+e5r8ei--%OJSk%0Z z!&L`*L8g_+)PFuP4#&DL?4Q;@uqy-98Q;I^N*>KnFQ|T9;(`{LJVd8S07v7*z4jed z4@shcR_iefI-|V#4O5%#|4ysLeV19W@4kV>F6Z$D_`?`oW8!6tOL+$&#UPYHcYqy{{~QkABw%CEa2rL^y@w9?;y znwLsxZw%i#zz~I?sEJEgCrRF~c z@CyP=B7Vt=_c(L_prnl>1po=g)d_D~ueDWc(p!xAV_=iO-@*y-Je_S|WFT%$r- zQkD$ixSiw3E=qUYN`aP7UX@LN(gX}H0yDR>Oa{x?f3uscoujATYfy>CWab194$M@0+GXJgNEW=pS1ENogw1f) zRM`=-yvw`Y_=4XXw0_|OJjHH#zQSl3@>$(sonOIE#EISDt^71N>=12?$YgPXq2?dZ z9BdG%7N6w|7Ss0s_A-vG8+ze%qQmGwClCRu1U5f8aQpoV`N~)_wc@On zo~)Si-90hh@P@xr4ap1kRgE6HzNBV1;Pm<8 zEptU`ysaNgG6FmL_rHqeF!zoIt{mTGkjj$3Y*9(B$xh&QO?OMqD;B|lq0*PymhoIm zvE^ZzW>LPA$sW)eYpr9OIeUEw0w9rmFeFN>G1~6xa`-}xAprt{JqbSFt;AW(@0A#E zjut}Px?a&ah5k7nA~8{ZsfBo9)0^N&FYlh{KZJ6s7$UGZC(#SenERG7Fb$P29d??< zWUVzN`<+Vo%DGMc;iMtNMzrCVjK}1^I~N+^%bw{8m6+9YoPFzQsmElFc0zH65H>hZ z7_h`L!BxNfVbQ3i)`99wTap8mo#DF0u2I-7( zlHc=&OfznN$x}d*) zwcIgGhY@r|Km^sJiY{dEu!D@Sk>0yr9c$B9@&czqup(YXfEcGj2$gLU-by-04Zey9 zBxJPERs^%Tm0NO3Xoje2@Hv$!^?J<-@KxsLZf8sQ zCpwe`DGi>pv`e+(5xKvvCtjZj1DeZ^fgD(4^si?0LdkkDEcYS}woU9N_>-By>^08e z(rwdUG8}YyJ=)Hc{jG3`xxESF@?LPv&hUpic!%F>IN}62MMId3o zC;%D(A&PkF-AFmcWG9BV?K(1+CyLCMNXN{mu7y1;gUFbNiOlqY?Cc4rK&=COjE;dk3>z+`%QIZ~dz>l!!f$^! zk0(nzdv;w4>0c9iaYI#Vs7b)4l#`QGy{~OK0VJpCL}F0cc9Xw$>O?}60Ts}jF||@I z`9xOaQ_by~tDkPU@zg4%wlsacT}X=OL5;ruj&Ehu+j;p7c51JjQ}zFPRM+0#=!NDJ z#M-M*{OYx^_nSWZ?`Jj*tpn@BUO!V8o4xw%mtU8kz2pd#`!MNNe*4zux9{u|->&EP zdHQeqbN2(<41rod^CEU<^KEbce{Id*lFf2u(G5G58cJ)}*KEJq?p?aW?#|q`XP#$e zs%<<|^!1$mlL}sj(r)j^mB}-wF8RtYyzble->;P!ZtPrgRV2)CvdE9$IqMk?Ed6+A z%L2u@0M+t>ltL*D0=nia#rhvTL&}toMO{nXMb;omwHg^QT|D@nQt>6 zU;WunILrQ6S5WM<(p6lIadms|8OWSp5xI1U>f;$ZMGj60?keRr>)EhqOMyVLRNTeW zXGMFCb?0noTEDd5B$wLSHxEpG{_j~h|E2S>$G3g?A`+y|@-)Y6F?yYH_4uaE8%1YD zE=!&)`sTfSUu1&gQl>*%vgbZ6x*D_T%f_I`cNR3yKbC!$y~Mj(&VK3Kw`bp~3F|Co z=>3v6DfFbq<7298uIxBJW8Ipc)3+$KT1;j%_$&YU-M8;C8$QTsdGayrThbN?G-Q=* zQfY7Y|2aRjr#acoud<62X5DL<_io$H1Xg}EkC&&tZG59mAEX)CuK7|X=J&F1i#lsk zRD;{{8OMaLy?s1w&V~b~FQ;~W5?|vJ& zp)BtM+6G-ypLlL8u1q@lzyGWI?y~%51D>`-f!j_=JRS{y@)|b(kMhXN(9jVMbonmw z?^kyG@o&dIo%?X-BtgHg?rsI*1ta`>Ev2j#h19A&#rap z>6prbZQ5&=_ emw82}dgb#8?I|}|cEb)-R(iVnxvX1XHUH|~Qm5zqGvG1p?2}wqP1hj*IfV|=~Iu@_!p#v_dHw93OOnU?P zA7-V^y8#NGp|PM4iCS9Sq+CUQ03-$oxWyDxcTHpVI`j8PfE(KiXvxnA9fAi$fOGWF z03s*?%nt`x1BoC8*2`XNAcO|-pEN%l@rP$%{fCFp{KNkdEvT0>n`ClxLt_Cgo!~zb z|4#(&e||DyK)WcFWX`;Q;~b)inH69If6>mN^E)>r%Ry4`y?$M+$VdG74W zqpr$w73vpj0W)l(-Kgua2KSN$+t@V)kRoz|-C?bx>M5^hn+uGXyB1`@TQ=$#F8IL7 zqVyKn&N@1>UdS~#e|SgQV<*>ghW5mN=)Dg~CLPM-H1F4oeh}-K(1Tbrcv$aq#q=?$ zQ)e_e7o#8Cqv(Pa5Ho$dr$0NxeZ547JX81{z|hqNg&JQ^DCb>o4RCGU7YQ!uO8)Uh ztQc!lEBl?(gcM%8*F&EgPrVD=*PKO1JFSWAv6SM} z4cW&C#4Abh8}ONO6UY6!qc1@~BTl9(41qVr#TF)a(OTQ zeshg!q8FYNE-CI_c@0?_QN= ziS#Pjn|1+cAN?h$Y0a#`quUOin1x#0g-CHfXbbccm|_c(a`M$UeQSyAh9t1R_1j<7 z+dDe)k(XKUiU{|cdp5UPPf}rkJNFarc{8Hpvo zV>h*{{p4D$44Bx_!4;~ZR2Gu{c-CFdhezXrY*{QMlHIrDewFXKv=ry-e~I`Eeu3}v zsNT;$|4RDGw;QWs{PZyCxBD*PsC;mzm~5K*JeZs{EdD??XrZP# z+~?;Z@AwfZ=uHD*L-AuZw)sM!;2hB`r5!Xv-)>y-;HU;zc8`ubAw5feHzacEbF3_* zg)EKr>+NZJ)ajAIx7TAQ{4hU;h&u}hQsx5GWh@Nb&~FPZ3bb-h9#R5knngZ?2(y{Cj}vrVrwo?kI37S%S99K={HtJMB; zh|~uEROO8(qGxjZ#=yE@zPLb|_jm5F5h+$Qwxxx$ku+(LC_ya6ZGWJoBK9K{aop&x z4_YQbQ}tD&n`0uku5`vX$y4jp5_b60^nW2Yvu)E@7L?fVV-ZGMtWPBXG4 zl8JfB?}QyYW1QL5f_d)dZBeSKN?Xr20cP;lDny!4Esa=$Kaa&1lJWop+D6rb+}9Tb zGj>`;D~$8wM>uL#IrI{)gs0_OM~KPlEpj$p`m*}HJuQ-jZw}^(<3tV{tlG5G8)eez1@hWGEBHLl zl73ct^y)_ojj)doaPp8IaYdFku0w5bG+50A=IeVm-2KZ`c&=r(73#(9f98og9dn6c zFup0CAG-TC&BV-GedSp$wCyP6c+2Dhn)2+g^u3 zwYN{{LgiX1jmbp0x#9|t`=MR(T4of5kzcX{+~0adnHZaSoS5n~T&=zm$s9S>URi)5 z(cxZA^!!W+x&v3Q^`cJKFeuX|JGo)aoy9biGaDVl6ndcO`M6|X6NZ_Or!AMpOGqgx z^nfFZ8W(>#RoVlS{Z9h^p8Gtvu!8&!1Le@CP9&59brXQB@s$$W9Y2Q|@ODq;C+|Se z@7U{H77Gm+v}M_0CIa{gc_PDIii-EGiOrP_($VZDeF8#l)aG{#Nm~g8xR8k-qyqid z`T-w^Z`W(8S2BK!Bo(7_qe528LJg$`RO7Okv@~^MO3i5D_xRIf5sx9j&9-t90l5|t zWY2`>50@zl=`W!O`kgt#%Yb%!kMS=yMySPKi;xv7eUtOF-}**2bIPupvF+6?-Lw~`3SQ*cWBj(PqGjh##e>6dRb-K z$OKG>ofGmX&q;eefbAy9olfF6eb_aV8oIeVDEC#Ked=HmGZhcbs&-iXxxd1Z5f~ zIt+VWPtK2(r$TGW(<9;l35O5GAw{)L>W#O+syX2$K^w7p56P>pV_U#r%e%?$7d}~nf@u0 zoM9lNq$Zf(eL;{e`IO%yHuC2`4sg3WOIL$vr5mdGhTZi{y$D1u2OSfzxh@VA-yY{T z%6xI$D$u%jqoX ziua4$s;>*|#+PuYgSE_FQ1ec{4&yHOCphk8O1uk@9&&1P1b3~86&@oE+J=uJEY*4X ztIozQstny);K+_6BcX9@pnS6HHbksufrPBlmaA9r%U}u>s&rO!;Xj?d)y1fOpYByE zC5LQDFx1#SFlV_aU)1OMs3|FL@`aV@2?x7h%7$&*DNSl=J_S?J4$km4+S*Zg;N4iu z)0BB1r=RYNBeFj8WSM0CL#MX5$eM#`?BOtv?Z*lQ*0E7_s47G-A|0`f8zQVMd75>f z?tT`=+$a*vi#tY*nsAyWtz3F$x}UD#{pVU@mOpZ;LEkxtQY?@@VPaRseS0d6oT^TF zl>cRpfSpD|GA04Wp^jL`3RwbXh9-w1`b#_|?ll z4pu74XSM0nEL>%BVkn8$Nmfnx^h@s+5&4@*VP(1~V=ym>@4YoNtUoEtQO~I0X~*-( zkUT!#Uf{rweeop$`5RyD>%&uZw`*W;dICr!>A{hOg@r`&kjRvDb<8sS>Quu92%b=C zJS}JT-JSpnJ>#b-g4eLjz5m2g&r(Wv5l($C+k}M6^%)&;BoEC+gJIU5X|Y#j}?8F$Swme&E9c)K@1m#8s$-RK+Q#getn@szN|88hc4-H z5bkS~Q2OVIlO~~QpWKqPE;dP(E#RKC>a(&%@Gst5auJVj#6dO(whPb5xU9pyXr; zw?%VUv&XqETfzsK(J#`Qj`5@h?0Lj}WcvXcioQ0xyGQSEyG!n2|41$oN8gK$MyemP z3q#yPh!O#Yy<3m#Y-u!K{$44%L2le9wvj)|GD4Ib6e4FmFrWVj1Bt$Jw*FobWTc(s z6%m~>AMz&`HhCUwQmww=v{9iED2x7~OTS4*B_LX;$XXHv5e_`>o7FFm>Uz|3@M|T& zEbzMa2-Gyp34ds~D>wl{51bH?u7?{0b%&-bTIAc$jY$@mXYUzpHsX1vAcIU&nCfq| z-R$=@?!xpaO_A9nPboCvm5w`9am5$>NxW1iTscc8HL=Mb4h4i0IPX}?F~>=tVyJsH z%^)J%uBHX&lhni2RUkB*2vD>ZigxNKX)nS&OV<3&)?KAUD^N7Sw5KQp(uEVgFp(v^ zThb|Mm8=b$Ht57Q#oTemhVsC=67I3>_#5e}LuXC=N3_vkfdbqSd-DZED1w>Z;su=) z##&6*%zjc#UdNO5n!qJ1ov(e#&~NKl&{x`yS`!l+*7H&!3iG<{@3>@~jdgGC+xyg^Be+UHQdDdC6Cvkj zMly~U(2__9{N2@RIdZra&p?QKeZb^7{;n?7EK_uL5yuHDm9WoG!0a9$Z2bX8DV9gQ z`Znsm`i;`(KVR)ucZVt7#0p1erZx;;^NjMdTD_$kgS8!hBytnNosmvoL6%wQ=uu&s!UP(~&%)~prlug1U%QQIYvqBW=0hOqTWmszNF z#%YG4UL)Nm#!Ogy9h6_G`^)7qx-h*(=Q3qY)#2i60_}Ve>l=QMoAXEHbrhO%#|tGOBXMHruF4N`TMfq^*%GdxJEAOva!f;R~Z8odNu>ivLDmbh9>x@a%wReo%}@upDA&>D5? zC|7frY_|7(Y=x2xuRM>xZxDE~d^d#8)F9e#GYCVhVK{a>VMM=I9ZCEX2BKoOztEl1 znSUD&rFM~@Y51iqX=Cm+YEu5T;B;o5M&#^@PgM?8TC1{0*7-q4Ovu|^j04TcO;-Yk zx(U9HgMgy|3#~nH$5^xynz--E(|LY<9XTV9bzF4lCVhV*#N!$TkQ(zMH|4fh?pb3^ z<@`!N;)XSydX)F1w#1?E$&d9Pag!v?(-Fn!CFD_YLqzF`%W|}iSmDx)8cgk5esaJ^ z&ZkKh_r|d(@m`hBG`u@I;3Ovh_S%C)7LAD=HuUkG^E=+VB^lCjJNC+>lqnl_)W4*p z0KAD-ad(`}=BLkBQ$C*TuQmU@xBufnx@8TnHT-gOZU6je(O~l6Y{?3(%NG2qsi`<% zrJX>(j9C)yeQ>z;VCI=)*1Rlvswy6D+I5<-rl?}x(7UNbrp9Gme-h0X44K;DlXu_1 zWl_ODM>02N`T5$$-&d@C=5Y<5O&((DjI2LYt&UY6{KabAUDB-`@j+012x~u{7ZSQ_# zY}qsH-n75Er@Q>4XLC2kg|~d@&9$g8wU|Ef<)a@(J6v&wMFCA}?Q)!RFkn9E0UopP zm+~7rCH61u$GZ`>C93#5d#~15tn7I(6g`7qZN;tsG#}` zi>de03ni~+3gvu}kr*H~?s*@vJ4>oJ| z>Ak7-e5+HR=L96=Uci{g!YNyTTuqgHi z*U`)NJ`^M`%@o!hQ5!hGHEQ*0#Vh}S_iwl)!s4vLld&loHIJlvx2GL6(Xj-k15m`h z3_8QSncztRQYY$pJqe?9EqeRwh;@i%?o~J(KkawY<15jj`3h=*!|XTgt;?Bj#VX)B z=6&glmU7}MC+rFoClcq(%J`eW%=&rv4VASH`7RGYnZo0d!y+08Yyab>kS-&Qmc+0`xz zUM}`{>a*1$NsSvaWFM!_s|Ya5Z5(yJcIhYGiFiGh(bIcuhpmd3ACs4NNeU%#@D1dV zho^bfGgtnvB)lAtvA;thneoYINafn!*#?93=L3~trL4@_73wLEf&JS&>UlG~)Yu2N zgC`c3zkkwVHr5;J>-eoq{^-vw0MkLq06B(Al`D|I1q^M$d)ux58XR=Va|x`X zbc+Ao_4`Ask}!|~LX=R90XFoR;%ANVVLD!9F>g$?eCaQ!7acIl}z86vU$yQlXVi2LS8yT{O8T*pG z8ry`AM1+tfjO91udw#!je&>A8`F;QU%{lKm&wZZfKFjMq_qq4nCuY~Laj>0c0{{RV zh6Z{!001C@@tr(D=LCg44FCZ6d=2%qEgnoPf2rWW$+GJWCp=4Bla$rD`uIFc8c&sh z^wbNVhw#G-?*r2_6sOO^JZdwnHagTWrFR?Vn zqGO0$d?z6eq6jWNIzt3OXI!E49Ujv8tspx8-zz@*kF@^3%(-?>Spk&&oWep$tI~a0 z`tEJL*1G8#vyqM`6&OFajF#TU3E8dzIhnIDbB-j^E+s#}Rwz*;`6^y{@2J!+NPY5P zkN4nbz~B=4Pj^*yUcXw`vg?%UcId`-#b`sP+Qfo5mZF!8gT;ubPBjJ?EA2Ok?R$O` z2or3>0Fh8)UWw}s!1*e5K*`YBa}(7KC{Y54%$?Z0X_g^ng;!xl7&a$MB?r;cPkCKM zIrl20;b5$oIU_4df?M-uiWjmunHkaYv)_>lFfd7|N5mnHdNE`s^COYb3wE~B^xD*Bl)@yU&fGHjH5H`~auQ~$dE z;CD7G$&uX=t|DRU%9!^gAEnZa(eTvrA6&F~`S~waHl@Ybl@F0;!oJGwG+TmuTUCJ! zUvs>1pmfMn+g_b67PIelnMu=m3j(33Oc!sL%U}&bczje@eq<|nP@~Y>K{D3r^KREZ zC-(iXv2o!xHR^TyPT3Jso2!Zy+S8T+a*Bh{`$isv#(k#(K*qJf>5)3CG)NgIzpxke zL7>B&%gr64_l`6xrrquuBgo<}g!zv$<@SIi2+XS|N;l5MO8uI4PmCZ5naEHeNW-ud zdGXW%|4Yxj8W<4XXl)h~7kd#WWtiLKeeXSWKp`VF=Xr-0KLZUv9A(zKp9L?$iUEyO z2r=+lggcljguzmn5q}@5v|47Lc5s=lSKtdH6tvE2jA(^m*9T9r(bo+n^X(h~@&UjE zn1S0lIfrb=g-d(kOwHf+Z_`l~-|vj%tAH@{l;Z*}R$f$FKsyfXjKcoKy1ns1LDorT z)e_JHhg^GU^|o9&$u1(RemB9m1KY|%T6^M4%T_^7-8qhuhVjYYOJ3v@u#ec&o!T$b zaOK$HQLN>344t8trzF)l3ZFExkZuZ59W7nozf~SfOWXEIZ#hZ@L4++HBNuY>a$g5RwJI#cfDZVZ*IDhA-WiA&injpb^jso#Xw}OvM)~&pxwdwObQk?7mSiU;tVm0`6 zJHUUigO&j&XGjSeB{(d1hg@$>3n8P$#(9zQm050&iFr#}&;=)Q`V`p$D;Ha_v%vne zJ$KF_KmzM71E1_@as4p>&wZg(8ZqK?D{P0#>s7+9IC1MZ(sIHR`P=NbFEDp>pTyl8 z%C=R0b>cD|(Kdc7K9cx6vxgx)n!Lw4pSt7sWVhcO?sxrl%5u}0-SHs)Ao&6h>}>^c z&D%XEmZcK$W5lQ$21bO=oSHV@7`f0(FXL1d06vp+Fism6ZXo3ofvfTNtA@LTAIXGD z2C$!(YG^I+QC~CQM+-Q9oNV)Z9pgK1hNm<^iB*@rUW(QWvHWoaEy8tO%kqD+($3Rv z@nwqA>K!WsAurF_4mph)Ri`l_+A*X2qzrKn8F7NN(@SL7$+vvSz%{O8M!nex_0FoPF zN10Kg0_dGwOr>|hGuwKkwoQbh?B_B0I}hIOenA5y`7vM&hi@M>Tvy(NMr}fbc63() z&^BfP^j_iwL0Sef5zy%0@dF)KRi zo(Ce4dh)^{4Z3e)O_fWHPGTT6=e7kg=E}T0%*2 zRtvX~uyx->>=qZj2UzL|jv9r|C>UHZM`~-m|6RSB+XpM$Jm>an!cEPH2R$?higzUe zK3x^w`{4Li{^Gpk31I0DgJx)>JfJJwJi&b>p|}$qiVR77z$%NFaH$il{S`Pc+I*-K z62IQTS(h(EZ2qS5D^0)sR*j5YbOi=`kuxt_5{Lvil1uZ!7aY_#20$e*Pd5$V_|Fr_ zO^_1sA#{kp%fnh(@If^s|L&5v>%5oT7*@T(d(+w2RWsv7{ffZt)9-zPLq+KEm-UNR+V~s!_mnd3-=FB(zcU0Z@a}4Ah^E}XKVCa@KPcx!sF{DqIo?5`J_oYY zRj)6j*OPG_X%bc|%df+d!q=X>+D^Yq1@pgJBt_)yJ}b1vst-R{D~h46kQhlrazR(7 zh3m+>yTmAt?a!}S0$34LekQxdHh#_Z{$7ftJXk+lH@&7>ac2iwtDPmNB`aPmo(=LJ>^ zLdSVmF%#?AKQJz|Jwg8P<&b$NA2KmTpeYHMjE~-ehY1?@uTj&y)V`Tub(Hk3#sEt% z3!<_TAok@2_Z577$mfsF%-U*^d@VuZGLrL51T^2%j zIKWcT0p%rqhD8n>AWgr>i0PqJXnNa)wH^+)o*1*wS=4E1xF1G2TJ!%BGyvf@cRwx2 z6#Q9YXM+TDP+fbJGHQIHDZ=>8kD+fB(xLu5MUs8ChpRmhJK3@KpMM-(c*cxa+z|bX zhgPeQU=0sDtTSQBYnAc;(-2@r=e;dTx$JV?hmOw7uXXYmKkB% z;tKoc%{L+8EEv15>H)A;u@1&(ewAR3#9+5JzX#1fJ>TUxUq}ueeAwCLJu^+~c?Nh6 zJ~^1)pVghP(3>88QP=>4PQFn?AuA%cBg;~Q@kf)!^Plsr!hd$E+5Yh>+5J<){BWXJ z0Gz-1TE=lXNT+1NGSM#N3JYlxQ+GR7z)O99wG#>^uv|5H-wc9ke2o0{90&Uw@;=0% zIm$n5AG#5L@G|_z)Yugj5NiFbOJKtNs_}58_qPSdRBK0@Q*80_*T(uz()&JUMx}Ww0xT4P&TG+5e0AF*C3?2P7PlbKH77HNQBac{CuB_C;^ep^b;G$ z-o=s{5fzoW=rnqL@_S^$dN%S$T8=Gmy>j>~U|OAbA1^P9T(Cbq9dwhSU&Qhkd(hsG zoqe_Gl}c%8;{KdOtSR|by*LuVjG$Zmi^EvP&}-x&0Hr6e58P}*(ho24{SU@6k{_-6aD*~s3EKF(Yo z9D*>w)W>z=6;e15HVBWFG~8j^l!k0?YJkJp)ud-hLo$xkn#5jyg~Hi{l?-ZyH}$$` z%}VLQhrI&X?D5a=Uli4{wIhp_?;rL{t4FP9Ud(EH`~lvluh+cmU)BB0w0rFgp6g{}T4j63_+R zR_}@lIAHH$bLv~9|L?dz^Yf{pVWrKVR|2yOGrDHiRapMc z=^bs-(h^f9KbUYA_~(F?ZR4gujtW=?bHj zNvxO5K>;JQqjsC1j>Vv$bA{q@-K(s2KmXXj7!6tu}B3$qmBjiBX%}q>8gttNW_A zP0kUJhGl*E+GWm+%$wsPKC45Ee3U$~(ucLx_1i%={b#A2^M`t_LtqRYBKSLARGs(q zWCSX;WD#f}I8!+#GQ zTjE8POEs!=mPgpjK=d+WRpm{2i5YgqarHZQ zm!6sRZ2#KsbOLiTR+-SgS*pbBS+wNxA@=8CwkG#X)qT{bsOr%0l8nn+Eyr%0PnC)s zlx*lubg@&46A${9Gm7V3AoNLy@XNtOkbA~e$i{5>_Zb3;k zu2@omZv}#@IV=<`T7prZUR1K8imBBu<<#oH*ME-6ottJDIru5(zAD51digz_n0$^R z>#2V^PwDCDI-h82b<5&o4V=E60`W2XW9cuZ;4QSQCq5!7Y<%B>im4{fFO?Ws-mo_n zsCb z_tbN32}ajAC(Qb}-5Gd1&&;4?>b9XR?TrO;Ya_$MN+(8cxf8pX;LTz0M&Y^D*t=2D%2ek!8cqQet+z>KlC+|So((E*I2ca%1O`%*tQR&S zpQA111x^?FDh_jdA3HmfxfN)pOkFK%V4Ay{DN9K`;%V^oekxw`F9d#zhnAG0`?qr4 z#_HigOi?~nG?e8##eP8iGfc~EwYqgH;y@Ec^Sj*H43AN&_JPxy*2s-SiruwFCVEs0 z_LDpBD#BF-{LC!+ZCUNs-@Q9tarMb}Ie-21k811O{?xyHNB51ZP{j#Go7RX3s5k5- z9>AM~2;W}jXRfSk1v3mi)_m$u?>b@RT+)H$@@MTPp@iPoE(|<2GxcRSJXX{qs)S_?(?uv3*YQ!}>r>w31I;Pg*oVa$X+-_v{N9!%lC zGvP_~R?1&r5MVObj@THj3Lmb6i5R*!dB?QxG7|&7$S-hKJ~{y+^a@^_Wy6bSGft2M z#jIk=-PtF>P21h78@84?0RjD7If^?CM>GQZ9awW|J?x>(!c;SPte8oV{uaxOJsbh@ zXwyWc|N9lwF4i~jFdP!R;c0eBL^#n*C9uK|JFZuc&|A=4hPsmoQcsX6rTwE_A#AR;#9~j;$o~T7e~{V$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/compound-emojis.png b/crates/resvg/tests-hinted/tests/text/color-font/compound-emojis.png new file mode 100644 index 0000000000000000000000000000000000000000..6c6724eceacf0b5bf861d2cd4d1a516453e23097 GIT binary patch literal 822 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOdU6XFV_|1$^x$u5Rg2&0{$ z8OZHqXl`t5Y-nfz3PQv?8JfU~`C43>nq35&%oco(A3V*1Z4a-opO2>08WMl1ko1d0QV`g^1v=q?7uk|4ie1_1#B zdwU0mfcS)j{QQD~`u2|g1?$&uIB@>{{nxMGfB0HIY%!e(2)W@Cr`Q_zqkL<+*^vZUKeYX^DDXcd-E%*BDY>&6^@1NOtZ~vPIQGZWKy*_#R#f8&v-_F@M zul$cq_L_8A`~UNduZ791?OD0_aG`C{xn0u_asgd;HsPQV?{4{~cOQ4=d{>Hay|b$; z+Imyjqib6yf1VW@`QUx(1}31Focrrv+8S(n2jN+l9sV-Ut!Trwc$ewdHXVz4-L`d} zY1sewvpwGD+h?!&VO;aoK=j*xw{UTIM-6?|&PBS5u1d-<-(!p#o@9jp zD4a>tm~C#Xql_a;p(bq&=Hc9`y+(iHv{!-pQ?6z3sm-yDUU}~0YG4Xv@O1TaS?83{ F1OPN2Ku!Pv literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/mixed-text-rtl.png b/crates/resvg/tests-hinted/tests/text/color-font/mixed-text-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..ee64397bdd89f45ea932a4f8c58104a61a3949a1 GIT binary patch literal 758 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcth6XFV_F+pQvBT%rRp#f70 zB3@r#k5vj;aOu~4Q6OKoB*-t=fk8mQz}`PTJ|QK)pr*c|WA>Z{>o@E_aQ?#c_a8R3 zt}Hnc7R&Ft!2ne}>1;pNvzzHS~3IW-_oPqps<%m)T~ULx=R1&y5!h{TG!GCSNa~EAm6a8c0n}n>Xjorg z4-o{C%F4=Mwl9#Bm6iQ}2E_P(8bnG+NW41~Dl9DgA8ZsvijR*EYTX&%ug8M8xIq5; zaWa6NogJzd;+X&c-@JJ6=*|V8;Mc<*uXnpV+GKxYmDT1&4d)k`9-V2ha(cmvY5995 z>dfy>*xaeUsY885gVOwR*`8wiY59^<^Cg-y40_TJ zg7xb+Y}mPf|A7OC&z?Ph{=$Xp_wPS=`0&B&*YDqd_)z|Seh~u$E0d>-V@SoVHx~?f z8v;aFHYnF8DkfI3eSFW@)HHkH)C+6&9`Vxis@$Z;`t0nfFopl8CaHQ)(}_HRgL-X| zdJ-bFDTM}%uX}YO@f*DBrYZN+w5bL>&KxUu2ffN`xxd$`=wII5yQi!Fe=jiGEq{~O zxhQ7Rr=FUoGv}JUCtqGSedoigzQ=An%Zk^Foc7k@nD&HJi@q>Rzy6MR#?^OnejgHf zA3Z5Wvf(#Z%Fc!`#(f>xUSWAtLpRMbEDef$`%j@X$}Dou**TtP{FZGp*%iSwyF?@E zLvUo5%-isjzr*~syp=ztn(HJc2j zP1W|w?Ypq(IqxT@w0X(q4Lb29n@a@b?#OP4*f!Hp@S#_vEh9^}njzcCHLkDcn4~lA zJp`$0| zu0L33$FT49v}bZT0+H`$KA59z)t{Q8tNpo#oqqADEJN40~o=xnDZ<)I;_3-Lkwz_^|s%rEcxlLi_n@UO|b$yCX zh`!C7xkObhd##O^#HHgZr8Nys{gGiQD{6PHOZnNw70KMQgGc|XPUN)pDLaj}1g8sa zcxttF#o|k*KX?nzNhNNT=sa1Zox1aaVaD7R{<+}_*$$JZo?7($(A&w)vdeDRTHFk4 zPt=XvIPqAD=>^$6Wlj4zEcwgJucu!xFXvZ${^a|KEOxflr)IIgVVgWvFevZP;>W9( z2NYG8)~Mvmai!%(ni<50UQ@VmFJaS}J$trS-TdXc@vG3h6|;jvrl!_0y>W@W^rZa< z_w8l7rn!FSvrd$F_g^K{-oH}yTx4v`FQbHzsaManx@>#H6Ik zthuzy_SXIT_Pcl&NB_uwqWmH!@15ra)mE0|nxg+X500fqX2&eOeCy5|okJ7253b0L zEU~>)$5WaY(P{Qp?12BYR6ixB$*vK09shm8j?1SrUeJ25xnusy-?2A#af(iVq);QR z`GKl*%XVBp@vr{+uiiJx@!Z~5ijdhOiZou*Yf2O2ii2yE*Fm3-1EPYxb&O)WWib33(ZO>J`NkdiG>oc?GXLdc+ T&Rl6=>B`{g>gTe~DWM4f#7GL! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/sbix.png b/crates/resvg/tests-hinted/tests/text/color-font/sbix.png new file mode 100644 index 0000000000000000000000000000000000000000..f7839ac35c4e62022b0d9e4cbb01a4f59e6ef675 GIT binary patch literal 3375 zcmb_fc{G%58-E6qWlTwyP-GuW7(>DkTE?EG7`w415!oYzQKHd=NwOwNRD)#6zDAgA ziL$(rrLiQk%`o54`+nbdzCYe`zVCd`InTL&*LB_Z@43$Jy6^isPrRuK8pdp+dK$ulnW*17+uzB?=u&?#^4o^#zxo(ieHZ0rO~kKQ^G5i4)R5VhoD#zc43c z4=chM{=W|vL0 zIR^?MHtS;_e)a8KP(q?$NF>r<2!@0+M#ggsduS;Ry5$(uQ|9G4^+^c5e>P&~3pn(O zW{t;=0U;jtT3J(8De0x&Y-8MNA6)fKtxAF61NmNB_~5Br&gUsv`Jy{v7h{|5MrWhDJtcvry&04k2sI0dKu8E0^SuM zxf8F7>BgVpHxp+a2`T;ij$YT(PeyRzz%V!uvDR*1uvMh- zZIWeMf96F?0^yTmt=n*xALnj(n~#W*S2YeJ4piD>!o3e9wKv=@*@ihM9_Hc8Aq7}t zzFRS~iln1^p79e;xJ-!mhZXMIU6;v69CoxK~V2|Dm^L4P{mkiZz?AYa03G)y0 z1*ZC?A4(TgQy)58NbM4+GxRL^g4(t&wSM?IK}1f@y+fBHomSbs6O$V-VY+cj?b1ZO z#*+Z!_ky;Vs3u)3yDCl#jW5W+v?jg16D_5RbIrE zjyQP9)=UfY@LhN$5)o%}`a0rKm#(j9h=oV9IvB4)MK(qiFu)g+sW&v$pMnKlXNF!pxnG%t_aFyaw%3PweFT+Ml=6 z5@&Q}CN~wWGYBsx5wkgal-x?+XPxgZm6<;nIb}pliHKAB7zd#QUf7d(P|shMe>wE8UfDqDSwy+6;pG@fG#pNm0O+YSKZL{7d~f-2Xk5eM(n+?E$cZ&t}o zY--@v9cxyk3l1@khj^}Py{e+xgo>!c4(INv2D#*Tr8qXF4Wfk&Jzo-A#^n-Jww0J0 z_80A2BGqi)?ds5SG`$u>F4wOmlbWw_9KHBJr(8-)>|9vr1tI!{LH{Uvs1xVF2ySVp zW*D|=?yQ>^gRD{B*4Shrk&(Q9dI9pPR%JUS)YGQLka)( z(ypx>fS36kw{CJ+>J$vVv|#pAa0`-6U4f1xp4IuLa#^u&4mNbInp}wHS~w+S#SU7> zVmWIJX7B}Ni6iB%`X0RJHiuEHC$h1?C+x+tqkNHPj3g-slVMZN?!p&S;+sztX2mds zLmepEV$0mnJ8}_JQNC%W7l>lzfQXA;nw>vnVeLkt(s+nMU!@I=$S}*^zHK448PD|( zn0-+MQu?vSC!f2Dt|#$6#=XZC{LF@EFe(e+^Jhv7MM0&9W0=$Um~K#H$gO46aCv`r zUlBg-`6M9$F!g=uBqhQ~F4MB%KWnmPlmb3PW4hUe10sb->8~86%8w+Ad5^S*e2I7EB%u()yc2WqN=SzB$x0Zn%lD5UD;Pgt0 zl}0vlzK#M3Wvt36)DWEhkupSOK2eIlt27+-femA>)QR+UBBOmq1@sCZD;N zUQ;!0`tkE0D1&-=N(<7xIp)bU|BiZ6R@NLIugkcj?w>E8(pUQ&cZNGZbEz@X%HZe0R<}>4wl1Xv*oO(L6g0nh7x2u}Go2tFQLIc%saSrY27}k?UE3SQ2*I_F1_~UlCp_qF?>9`Ue>a(^Le}$K$E{3}1+aAFEyiU&x1S@yu(|*$ zX+PeR1!=5E-V87wK07dh6ed*SpY}-qY})cYC`k=(vLL=*TQ}|dO_%_w$C(?w~U(eTwK0rel*PkBe(tfk6}Xr#7b-tR=XI@+H4@o?55! z4k$`_Q>6*OO2?6YX8vmsAj8jQc47w{ z!7XpqlJTI96^i^Ffw0>d*vKX6=8e37)>JJo#VO#_blSG{*{LoK+rD_{sjkV}P_=jc zzVl|>?39q5p`N1{MXu9+M+ktztjESQ(SvvMF;DB zekKVVVF&#iO$0+ThH%l~UE%&+M22He&_9F!#O3Ao-Cg&+6BfB0EA;j|d4FbDS8p)$ YzY$fnF|{>d{0IU1XHCw$)OCvf2Ph8cIRF3v literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/svg.png b/crates/resvg/tests-hinted/tests/text/color-font/svg.png new file mode 100644 index 0000000000000000000000000000000000000000..476deb87779d712237c1be7b8c0362eeb3e01ae4 GIT binary patch literal 1843 zcmb_cdr;Ep8paZH%L^spr6ox-Z5K;Dnb)IXkr_dRH(0Gmyp)~;l-JA>FEt5NSi+_& z;h|i`ED`g#UQ#Q;98lO=G09unhO3rkV&3R?$o9W8=Z~E^GvD{V&+|RcJM+%>$5VjE z1)Hz6TMGh#%tH?BBY;3g$S>D)wc!PK`$DjRtivA)LmMcd#DA@S0{IG+V*v#oP~dWM za)53ugTXN1FSc&%O2q;4m7~A`3WF2ZSAWa^27ifOp;*8$ZZIgYGaaD@)c|xd!it0g z0AOzRz3$`m)cDBgfNFF=+5c<%3ssvzRZ7LWCkG~*_sJT|q>X}6Nnp!;PRqS({Z+m% zs(kB&45iRhBFvVRxJ!%OL_g9id9;>7q<}@PD{z)vb`~)lDj5#EY`h=?E=Y&7Q}(cv z19>!CF3l$Iq#HW{%8s|nJ8qeK%<^nB;%vlP`Vj~n2c}`c@n60H6X9`ud4W8hSsZ>E zV}298+RL2DI3l;vo3G_h@dH;H}K($v=MMefo#zdD(Ovxc@O>_ z{WqTZ8PpnDN|tHE%dM1hsH-d^;oJO|p-@UcqHphgYwDVx$VlruiSv=zWNmb2tr=$% zj$)RY-h;6I-hx0XE$kg=^ll{HMf7&qV!QcK?qIEzzCR+-_^#wh z5z(R&TH(%I^wV;fzvnyypK;!j)^n6cykI{)tB3e$T~SDCcCL4S->^t_@KI3z)bly0 zi1_}oka(opB?3C>Q~nC=G~Sk)5ilf?F=HCtcAguU4vtMtZO}&F;(LCVJ-54$rr&=S$s!_69FC0vy6u~i-7XdB4gPGpFYSB!E+A}x%#&YY3_W7c0G;EU& z99VzB*#`4D^XZj|b?=Tw-TPJ8a0m8?s0baX|3zN7EoC2kg5Ko0g5_fOF6uFialVzTBk3%fzMLGS~RFt=!~@y=N*a*6NDXA2M(Co5w6_#J#Ha z5G1ZX5i3Fbuw@g==T%Zyln3yiZ&{=X;J8Qx2;wB4pp(y&mz+eYm#@)X zPU*&;C!Zr!E0sIG`N-Ux)h;&ucwHdiU#PZ@+e*IG7WfFfZ7D#3v0*#Tmr9G15bLK7 z&k`P$bd7fsep}V1Mi;P3EGHsfQ{1hfxtcCWg4y9jBbS?OJW{^|i$qQjZ?{JMvpaT{ z(v@^->|SN(sKVGE^*B}zW!dh?e`EKLQ!%GMXamD72Z@S9dreQ>a3vvojE*K*P%w6^ zdl_ZYs1q1lR^6^MXJHf!oTbhD9QHcq^qan2{s?_#X}cZg6wFB z*wc$D5xJ;~PV`?*cf9d|>izFHak^uZ&FfUZ6tWS>Y_*X%2+YwpxbjD~v=5p(WBzhh zt%TtJbBg1%vc!Ki^|r4mnzSQlft0@(W>vMObyn>^oZ(jgCH6zmxPAA7$hrRklzV(u literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/writing-mode=tb.png b/crates/resvg/tests-hinted/tests/text/color-font/writing-mode=tb.png new file mode 100644 index 0000000000000000000000000000000000000000..98fdf53badbcc2535c88a08ec41525f0cd3f63c4 GIT binary patch literal 1473 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAcrZyC&U%V{eM0HLP8m*!Q3+e z|Ihd}Ha7l0>)X)KFuA7!$OS1o>kA||%**|M+HdcYEFcLKKe{sI+`2@dvUBSb>g((O zpYa6>UfU7}WIWmx`Tw-<^L=3;L6BnKPe+139}NO30J6Ux3;GIT`~Ls`|J#=jZ(lwH zvd)kHLb}o3d$^PaltIdlV&Mz|Ew5a~*OoNrv3sy|a-!oBXes{wBuK3NJ z>YF;$S2ifEXi%C~A27c{wx`6Qr`UdKzC=&DNKcw@b3A`j9Dikud}SC{L7+f>0DplW zYrZdQmKS>($oC8q*ZxfcQo1EUe!&a^0tyE94h{kF@d*i8`S}F}bq($P6DG}`J!j7R z1p`3u+Y-hc4$;robt&#W03SR6fF978H@y}97Z*uWsbU~tD&=I`PMf8L)L zOY{t5o2dHLEuc1SttsQ{xuNPTS2m@boTTb~ZT|@%IZY=LgIX;ORsfU&s{93&hG>F_ zLG;m1B(r)$y4bCWuN_1}X3U&9(~677*!b)J`qPsYA1p6@fALe^>O(6nL!7t0f2XP8 zSH8Thr7chLxKvcL{~FfjjA`X-enxW?Sii46RMfkbTWa?_b)Cx*%NeYeuT$4KAF+D@ zN97lRX{l=@ITGC}Z*A%}E#X$Y!^i0uUA8eyVT!0?#%aB4x-CW8EV(<6-fA$9Q`vDs zydt@1(v~+#vQ6zd3eOw^opL-rM8vD>?v8l=;Nk%%(P9S6HDVjs8_0i+SYN zRp#%s{;f)9^XZqGnKzFz^=AZE-G3FxaI>e0KXd0Xqvq^2*$Ng`%DR`ue`J__)jH_D zZ`r26|E%-2*zn7$?AnsuWwy)X|Aod)Z<2JIA8~f~Z}eFjxpd8|m@W>c^0^UiB; zt^BtrZCm>P!ooN2yG{RA-?%k1j`gUw{N?ZEdfzkO>~Ba4tvppHeqS{E+jQgYl{L&= zv$?ms3vZODtm_jIoSoO3`#$Y=%U`~Keajb`vHm&{BOm+AlC#V9;b!*;x%H8sw=eiS zDR@uD^c(3Mrxma1U6|9`?cXy$b6Vh<;03{%{Bvd+pEc@mwO!}O*LUt*AD@`}5pjvg zD>~f~-S^E|jk;0|SZ_tJ1uy7LHG(p}R&wcF1POp-rn3br{Em1AI+W z7QbKPQjHrCR!>BBBqg&N%wWo0GeL91djCeVX(vT8l3AA@2=lJ>Zu4t2yY}P%@&k+P zS^I8BSatsrSz*tayXJw&4Y%oKTw63R95VuH)k)&AkrKBuoAwi^^=I&duV1e(Kk)z7 zZf5R=g%VwhKCa|H!F0F&+$GLWBD%KuEzA$x5?I;4ZfI)$H9r}`sEX+4e-&z?t|Qvp z^(bEh(@Fvo}-_BoYA@Ja)LhiIrPSCt^dwL1Gze@F`4% z7&HxP8XLrHNr(ksKLKsI+Rl5;d>Zfe>|E)**pio;UsFDR&IOf5p00i_>zopr07zP$ AX#fBK literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/direction/rtl-with-vertical-writing-mode.png b/crates/resvg/tests-hinted/tests/text/direction/rtl-with-vertical-writing-mode.png new file mode 100644 index 0000000000000000000000000000000000000000..506f03f9fa0156b002c18c45bc3e7a52d9f8db40 GIT binary patch literal 959 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAeA5B6XFV_v4Y0NMxb~@LjzV> zpm=?KJyt2WARiweoDF9LFDRP`b!d4gsHL!Av=|rR^astT>2?vG1WRoh0-Nfn*B&}@P zz)HXZAhm;s@oW3RrqUmFvG-;6`Pa9U{sFP}`^O!&=f6gCXTDZlrUwcl93k>=!8gmr ze$Ojwn>TH6`tuo~Qu5$obWL{7@E|?=@8{uSnd`OtZ0@gK-Mdxssz~S6xP8a2#+^4d z@j7fZ%X4jo?7><3C6Bl53f7DG>U`&FHn;XwzDMuamT#ylG3toCduWx@nYY_2)?6+B z@O0_)g`rAecY8Ot^{2nIt}~RJy`4RryFfiPIrgkdReI^vS&4tw?36y{*}N@fjlpKC z*=Oe_E`2rgMe)gqa^cpv=(WeaS`%f&PaR#Q&X!-gm3MWPTGaWcNppKS+kCgmuFg`A z^4%D5_vY!X%&V dUVDGQU)eVY-y3J@PN@Rr5l>e?mvv4FO#r0dX{G=G literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/direction/rtl.png b/crates/resvg/tests-hinted/tests/text/direction/rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..f36467fd4e01c9cbf353544de17cddafb0ee5333 GIT binary patch literal 941 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOdU6XFV_8yXrK8ykTPf`E^Y z&&9=snVDHxS=rFg(8|gRSxbF=JF!Z*PPqEpZTW zxOiQ&<93Bj#npf27EX75O4@IiuDH*xerZYTQjJJ%?ZBe=Eeq<7X)R=(`k$LyOebPP z0wV>ZQGjcTQH;7I)nKwK=o8{_!KF{P~Aw zc^ig*`aa9f)`oHa^`(Wj&wu5v*?Rx-$&a`6Uw`;eRWY64?%3gT#rIYzFN(YGm7lz} z&R_lb>iBEFXFq&!IP2-%4_Dj%rQNEMWeRhNzw5L6W0K}A!LTFGo^CxJC#qk%Z{u|7 z2*J>Qn{0iTr%S)qj9YbD{Or%be}C>LFa2tBeQCu`D{j{`X;q>#T z_8mM-ei%aHnd~UQq5T&xFj_&W2I#P9&?tsR^nYiFaG15O$J?H*22(v!6TR*;M3q_V U*X>*R1e7&AUHx3vIVCg!03bPFiU0rr literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline-and-baseline-shift-on-tspans.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline-and-baseline-shift-on-tspans.png new file mode 100644 index 0000000000000000000000000000000000000000..67707dcf8fac1c12ea80c394a70f76c7535f02ca GIT binary patch literal 1792 zcmc&!dpOg39A55;k=2e%i`7}+kl?>5Fc>UZGd4DsmzP&mR3wo|SS%Ka zL_#1CX=!P7b#=+q*Vk8~#K*@=Z2kQFe%R{$T@DTolJ*Dw(Ekw=6BD_0enpa*X@on* z1LQAGc;+vfF&R0_%Pwa2o+zLCa5}Dl`=tpLQCL_I9)@LBr)6EPX1{GOiFegewLLNQ ze%}fRBs=cpVCQ+M|5JOT#7Y6gvTr@H>sky+LF?zQI+HziNHhfz`09qi|3cAUKOJ;B z=euESagrUlcO4{b_z60xw0W652-EJ{bi3mHhY^&qKNfMZ7d1LD zq8hQ!pDeojAZ4*3m5`nLz~bRBN(ElkF>&L4{kIC`J$~B5$P9V&prMl!=~wGh2Bo~3 zKWaK}cw@!4Ok-~8s%u}ogAXNPh>XqGIf>k{ox^7fgH%41F%2Hwx6HBd7#%J`A3A=w zq(-K82})JbjXMm%zNk~x@Ug`Drcz2uBcoxj=F4UcZndcHZjyr&?-(^szZ7g&sb{%S zOp5VMWXmiQWjA*z;f81TnBlzU0sa^b&_<6P0h6At(%sGVGSbU;p7Jn6b#UeFE*-!f zym+PV0~5b}ia;ByGCiJXO82#unU$RisJ<<g@V;r!d4k(L{*0G--|LKzVH@M~1#;2R7+MFO3q(#V$B9nGl1(ZX`uTGJ zA#-3MmiK;pz)@yzXWz4P(dP7|T^xl+n>Q9?A$B;IG()T7RlE?3*(my)9jWND0d!P_ z>s-N4*=2u)&Bf=pd?})9Xq%eJ#0v>`IW-|QQRcrRgM7iJM`vbT5IgP(Qd1iPpO+Ej zI+QBjJ+{nkY@`YkE^z$mxj077@?6DLXbN8Bz2R(3_7^edyWDGtBzOW>Xt+-l?ng#uQ(?0bR;5bhE$)hp7M# za@-Rr)8-i#eKwTaUyGUFk@y|9*TX->3t>1Ri;U?MeQ^!!G|Eip5bua~3&4My4imc*v^`aT&QLYQ%+U(5*K1j70(zWQ! zt{A#d5snuqvCf!80;xl?IL^n3fD3_uIluR#hJM{e3a&POryf7F%mq|L=WQ5GidyuggEBEx>orMwY@vH_~j^u0# zb8GpM7Xy4#l1u5bkt7{$eY}nHgm=mGi}`ItXO1%<4od?Eu4S&=Hy_>@Jb5i{H+a?j dNBSA!{)m+XmUDC8W7?YHbO__{hrR!Ae*p)?Aw&QG literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline=baseline-on-tspan.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/alignment-baseline=baseline-on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..4e187100d1ba5c70abbca37bdb9fcd97ec774e00 GIT binary patch literal 1452 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 O67h8Pb6Mw<&;$UK+|$Sa literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/complex.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/complex.png new file mode 100644 index 0000000000000000000000000000000000000000..617d0aef7be136806ebc3bfd394ee6fccfa89f4e GIT binary patch literal 1484 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/dummy-tspan.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/dummy-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..4e187100d1ba5c70abbca37bdb9fcd97ec774e00 GIT binary patch literal 1452 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`J%6XFV_8yg!N8XABMWZ>fB z0_P&LnVFd-BqVZja@g6~Wo2b!V`J;<>mk~Og@u7yxVX6d{r#1}0B!=1!No%;9zdwKf_4541%U!C8Ox>^5_)^wKc^RG(kn;r%0WSm_td{fn2O@Bd!b&KACn`aX;|NK&jJFs$- z^ZTAR8O3`7WsR%0&NtW9d}6Y^>|u+>4Av8eo;l7;xo~a6^sY0(-%~Xf<{oetzM`A* zlII#*hWug6W8A&5OU^7U-~aM>1b6Q3X&W;a`{pY1&7L@8iMPpIRa5T^zaFL^aV^P| zz0dA(WRmCGh2?FD+h-iOG}(Ritg{mGf6bEbeh+)5C9%GF&*vk{8qY`uZ|YsUH?k{- zdycb?-kSD@TkbmPtmW&3)BBZ8s@0<9b;BrpJ(M=cc6-V4EaY>do zQ~y+$?&UayTV)kojCr^a!PpFt~!y+3s&#Cy76)B|M%hgiwk?+AL%f==sdM5&3FER z?#{p6M)r&9_c>};+_&FSbGRL(DQs8Wi@E*btG>SqYd;ph_l;L?_WSJbHEVpo1T3AG zdHMT+$sld}eFb{19=v$_WW&tjLP5q+gI@W6|EG^tOI%(}aw|P%bH#kx?4?ZDviI5t>Rn!%{MXYzX5%Sjy5c zG{ydMSyHIP828Z9phOx&Q7H^-N1ko>kNsz#XU}ua_x+sj`=00hEv%WBF( zAP{*MXUC%u2o$w;q$R|Tdr_p5ID~k(9XlwF|GJ{0qQpL(PXC(4;c#DhJw>C@)*U1g zsjI8|&#Z=q#`;x3L17)>aQN2(8u7_mV}0sTcTdPS+e~fka2~$CMB@42NE)4y@^jve z0#MMLAGuI^`}FNE)A3m`#(5QyZAi=+Lqu%YQbNhsYE060}Ewga%w2=3Zl#xZBkz2rf9t{Dv4cVNx7^qs)kx)aoM_7{J#(9MQcrj*s_4&-NtePbExz?bf#46c#xy zrnJ+M+~c0VEFjH~zn3uY1GP81<-n$Ie3v!R;y28$Az*b=ZSQfWTKs_O%qpAVmow9R zqu2ev9eVtr_R>VXV#nOnos#Y0IKGol^6MOwNI(r)6*1xs5_pcFiNs`}>LnZ74Vj&K zXBrZNDV+irzY*ikdd5e5fbB7?H4mfnu?~hanP_bX#&@Zd*PT1- zhqBFL6b6G*DqyOAl}w^rBC$?$d0I! za+IcD(Jg|^;h3IUwjNNLEyzKk%?8a+q1!uD!@}cHTnv5g`#mytJbzh|B7thNWhV~3Et zny!|a5!{hjAwDbW2&wt0*6NIw0Zspwp45gh9g0V*oSzYkVUl@N;!THx;=)a2>b(2I zLXOVZJ~>n50sH2bS@Cb;qAw@DvD;eQHl*`>Ls36Db3?uU;;*Q#I#eOYl%P@WI2UW! zcyFN_dDER?d z*VBX`W|ux6Vr;@>mExC%dW$X*yd>sxIZ!anf45-4*XnMs!A*EQZ4O#q8p8NIYv`)D zSjSQ3=W^77GV#%?&R)=SD`(k1rp75~B<5>$+#;zWE;4;0r2r;L-|)DfYWFP^ydUI* zRmnxCUcpF#1y)AI&#u=bz97tUOR{=Fy!zyaxnLVc9eoeb3uV@bY)W>{ zgDC5!8LH*-XY{vKhCH|KQPF)uj#LUv&gb39_p=usEiUM>b!n~IZqj@Fm(GTYsFo@x zxC!PLq7sZF4rhfs0cosJd=!F70sDcR79aoYhY@HcxOs0^ zl3{|2LKpdM;eGs7?g!N7wC7b^v=;4lUNUa7Ev7NhX!v|gkiF*sEud$4(;uP{`snJw zOSlPII1PT>U(H)enLf}{n%(n|9n zX>f%*ZGC1GxW~y~X_>7F71&9O=R;IV!@Omv@5Yl^0K)&Intx6#kR1!Gk=PMaHc3qX e$%g(lC03=Ri626Xy{4Sk9G8Rcj&~f0(SHJnQ35#t literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/hanging.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/hanging.png new file mode 100644 index 0000000000000000000000000000000000000000..a6a8476ad1ce0172b389cd396c8f48eab8c6827b GIT binary patch literal 840 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAe9r~6XFV_F+pQvBT%rRp#f70 zC}?PCSYKZcky2JxhA?DhWg!e z`33b26K2nzGk?MQ^&58XKXCT^h3oepy#LVjMtC9v15<{li(^Q|tv9z=XDtp8XgJvR zW=D0*i{JMPPl`LcUEBIkS>%(6isvK*`a5y%oYsVcO|0BvIuJ4f%#PT=0u+hZkiZEh z4+??U2b)yEB&#=w&B{HE${JrUPvR6?Gx`4Iw|`H**W9;!Gl+Hb{mJwnk3qJr`|Q2D z&)yK|gqNDe#}y+s{L9ecwYxf1KKbPr%k8%N`j;-wd^SDtrHyp#{`RGhdxK2t_DJ^g zM;v|mIpa$~pqujAO?fpUv%7S!UDYy=ZM`M`Fgg8|LG8KP%Su~v=gd64sQKzEwJSfk z)-Uc4jh!xdJoFl`)9g*}_VjPP!!b2(ZU4qJ*PJSoi5XMwo-dd&^QywO*tBO_TQcX& zylhc2ac%iajn_`SXD^+;5oV*lX1jLL-B7{Te&RO|TD4!j-yUxhAKRO?O7EI)nx6A+ zxy_NLnTfi$K3B(v?|i?sA}eX?-I=YYW~Z)OE!VFU7119V-WE00-QB(Uo?Ok$QvHS7 zvyysiTH|{{^^A+fele}tby}<6DZWkgXyFU*jbHN0KY#q8_GH$R`li&hKRaW82>=r$ zBg2z?+pfP!8Md1ZxHq3Uqyt1CmceNd>x>bQMVfH8R~jQMd9v6%NbR`k7_0>n@O1Ta JS?83{1OS?4NxT36 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/ideographic.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/ideographic.png new file mode 100644 index 0000000000000000000000000000000000000000..2c76d2a76071e994e5077c650695e0f816069692 GIT binary patch literal 1111 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOUR6XFV_8yXsbBr%}Az8<2O zi;K(9&=9W0#l?l4ojo@n$Xz?|jj;uunK>&*p5UIqph z27?!i>Rn9F{NvzhQ;k|C(aq_%{un~ zeRhI={`(%g?cW;t zAMaiRrEjgDw)J$-zNl+@+BI9(#7;BadTJB@S&kWpC#z^PSe%_?&Qwy!D4A`#N$N0X zdGW1C;RBB6A{e3sBNqlmnx{zEo(kd@=z1FGx@2wWHO+u|yycY>PZiE;H#il2Yg_Nr zmAltEU7NOIWuRd0w%M<{Ki`h}DZ+dzcYev_k z>odL5gE^#EMuag$xNxy6apymmdlWW6$Knzm>MYsTfZ{f>8> zEW&lO&utcEEO=SQU~qcd!Bx{l<$KhcoemwD81`z~)=!)&3+Hug-@T@P^7<~GPpOf+ zbxIjt=y7wz&q$Z;m=POR^C2>l*?rfkRMv)VdtuHoNNnJ>HJ?;0KE3ri1GrD`(# zl8n@Lm~F?aJxw+E(^q=#@W6PZH1zD{1oTlTF7nikX>-qSenEBh^EtHu3?0!%3 z=Dn+(!)9q&B>P+`)_)x^ry={^3404&=}hg3sshdxqU0ebxU@&(%&m*Z)awF5^%e=s9r*i|G{#F|FXCC9IpGd)_3jUu-hJv zH7kDZo3k`+(VG4J+uvRZP%UxGv%xJ zl%uI{V%%ykN?OlN+?*qJ$|=%fnt6!WDJB0%4Q_VF6=0Z#`G&BS^+|Dg0MsY~zD-j)29Sz13f)*rc%TErhZMb)5!|J&Xa z*T~RV_sIS!PXz?`iJvpzohKo!R^7R#E2Z|m$F1wTc#j8Odz{KEr>lL+NFvoXDr{ZY zwfnpLCdKY8(pl~0m*Z&g+U%xllia<$ttX0B3(mVabF)tQj?1=Rrgkz*^aUhsJ)y-e z5i~zJ;!?7t$5JWZBpV$GMli{=j+|J==dy#BR~E;=qM5peix#(`pZ-i zCXLS6Rc3cP+pM>q%8Kx{@Tr_0#I@+B{2`@a-R$?`>O0b}y*P1VtKu4m&1=qxA5&1U z-dk^K>HB~!@JYmi1@Tc5IF5LV5N&jD3 zCvQp3dY$d=P21M)uv+r{)Txu|y$|>v1zGLz7n7a2BkXLzR-FaCn|En+$M>bRUY~W; z{t|O};I(OHYt|XRe117&($fjvL1OU??8hfx`I2{Op;Y9adFSU$FlGN(6tc%`s`Jip zpce=_D>_U^*xS%+u(uD&Vn9VENy zz|tG(r&d=7e%m`MZ>#?QCD1HtjS1e`{efBQV7`IR3j<%^t{c mauO)n0#iM`DOOmvi|MV*KQ3VJ4lHsQ7(8A5T-G@yGywp@<=H9# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/mathematical.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/mathematical.png new file mode 100644 index 0000000000000000000000000000000000000000..6d6bef24425964be778d6afdbc38573b101e8d19 GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=StC&U#g($vdL<+z zfO_HP;9&rD6$Zur0je-43GxeOh;R6RpuXUPeZczn4;Hjv@1OlTYvP8wuOBHGCF{aVu)<`_jV71+ySw~ zgUXCR5im%6?r=>na#PC5Nv%2qL#@%ed*PH+=40NAp^=+jEt*hjvO4|vo^8tPi40yk z*Y+;?KCegn)4%`sb+0Avaj4S&^4O z{^7cbUuz;)r=N~W;oWeeYTKF*vrpctNcXz1guf>2-L&J!Oi(<7wXxnUQ~Y&K2;#B z6V`RAAU0h$s&o76pF%cFYPQ_r4<@LpWUpQFeOHLC#A&H0g_Mh@IXW(#kjk(*H&c?q z#Vcc%0!LBRjKn93-Co+Se3&F}+%uf7>Zcf#rg6=qESfzyN`vP{z-)0gsjp$nM0!#c zr(S!IYnrIb|9Pi?XsS|rq-=(jwUEWcLcJrR8A1mm#jf7GJLj0Cu5-SOSkq=5liCyf zYmfN&YI`-RxnJ9)Q6OpEpxtPas(pF4#c8hxjC;PTUgW;FiK&9&I#*z~>$S_9+B%%N zcCVQ?t>?=MElnK}fybLRnLKpY!lM9o}?n*)B zV;_&EatBCeKZseJ^yHm<(Tp2Cfk)gG`6Cx~A6UL=+q;F&O`VtjlvWXrbh`Te^sBel z!HWvaKe0MTGFiKa&yzd%TEj`*u>5+I#NVVyuPm!VerE{}r59|U&2p9{KDs$Ci8pFi zw`Nd@#tf%T6`$A3T8V-3fW(u0+g{n$3E=eaG!0B8%~JKArUT3sw4hiaS&xB%g;BAw SGJ@+m*cqO#elF{r5}E)xPU7VF6=0Z#`G&BS^+|Dg0MsY~zD-j)29Sz13f)*rc%TErhZMb)5!|J&Xa z*T~RV_sIS!PXz?`iJvpzohKo!R^7R#E2Z|m$F1wTc#j8Odz{KEr>lL+NFvoXDr{ZY zwfnpLCdKY8(pl~0m*Z&g+U%xllia<$ttX0B3(mVabF)tQj?1=Rrgkz*^aUhsJ)y-e z5i~zJ;!?7t$5JWZBpV$GMli{=j+|J==dy#BR~E;=qM5peix#(`pZ-i zCXLS6Rc3cP+pM>q%8Kx{@Tr_0#I@+B{2`@a-R$?`>O0b}y*P1VtKu4m&1=qxA5&1U z-dk^K>HB~!@JYmi1@Tc5IF5LV5N&jD3 zCvQp3dY$d=P21M)uv+r{)Txu|y$|>v1zGLz7n7a2BkXLzR-FaCn|En+$M>bRUY~W; z{t|O};I(OHYt|XRe117&($fjvL1OU??8hfx`I2{Op;Y9adFSU$FlGN(6tc%`s`Jip zpce=_D>_U^*xS%+u(uD&Vn9VENy zz|tG(r&d=7e%m`MZ>#?QCD1HtjS1e`{efBQV7`IR3j<%^t{c mauO)n0#iM`DOOmvi|MV*KQ3VJ4lHsQ7(8A5T-G@yGywp@<=H9# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/nested.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/nested.png new file mode 100644 index 0000000000000000000000000000000000000000..bb5b791492d83b093a3ca92e4aa4fc29954396c4 GIT binary patch literal 1794 zcmcgsYdF&j9NvtuWgN5RayAXQWU8eJ32CD>w#jWeW{c7=8Lf*FCK=TkO1YQiL`m6S z>R@8I97z|Q$|$lSbq;b%bmMT&bNX~XoKO9p=l8tt@Akgme(7|ohZfWj3Ic(&$lHiJ zKp-$~DK#LA9coE}$0A&!d-{?V@qY#!4*#~PuCBhwArJ@xfq+7x`uh5KJU%KaicY5o z1qIP)wAHIuCnhE)B_*NJXfBs)Wo5-=GKoZ@si~=>qvPW3Km42Ee-eQ}u&AIn5hqw2 z+wpf$eL$`YvZR&l$Nese#S&Ao+RQ^`b3ynqe!}I#g4&4E{b`b{N@1l$L2n%A zWp?VUW3e|KCpUmVYCUA)7T?1!MmzCf5J&@3eB$@{=T0~PVv@Q2UwauBQ?r?THm6)Q zddIA;m#$IS?9~n`R#GT)%aUe#R}orsQ)VmI`@^Z#N~4X$2Dh}ZsMni#9Oi}>fAkn- zm%bCo82*M?%{%4knClt-JaZA@=PaE7Eo%*XEV0_^$P>RSA6wmtsO0xG()DOw4Xw~{ z�>IL0$_JnHT$v*zg+IlHdo}XZD_pkIpwP6`H6K#%_2q!R^fZVEr9q7wnR zDo)=Lt0i&j<)0d2AATg=d-5K5BpsJlLN`V~W1ANbblc%&1eq?UAoqMUUeB_r2e5x3 zwg^f2fzzamKo$O2)lzqHPaZ~LJ9X&hC|pbP&|oS)N8s0vJ-vHZS)Z+YTco{CnQ#t^ zGL0Q(+%*Z?cp)0Rai%VaZET8-$ zNw>2TwGD&-X58DRQ}A}|CI*@B+D4NjyhUa&)pjDi9Tl(U+cn=j-O64#Cp;RT-X|A- zRtY|~FpS}iPu{e5#vDo6HHBmer}1;Q=awJEG`>m5lUGt7SWu5>S?dsQYD`#=g?E-UMn= zcQ-P+`C)32eDf`oi7087E0rn_#z@&=0_5%TD%yIkpf$cAw`|qA+qMd=*kk5M;TN ziNo%|FeOK{if%bMgf;wadnYW*H2rL0BtWWaiJ*76A?qtL?M;`DKeWA^iMoKOX=e~K8nyS%nV2ng4d zR0iTq|Ae)*F)*ZZZK2(o($t0@e=K=F%nHP4h8kqUD&QwA4yF<+m5(GEHn#Z>L%c<& z-wws8+>uR@j4bnQBpY-$ckxy*PL7D3d)AykBoPX=*&G2WHS!k8p>1F$HL?bVYj}1e ze0nS-YupU8d3m*L;C|HW*y|`peegC?b&E-Vhg+9Zt+?^a*-q>Ek8!p@JnWOylD|=# z(nr447%hIQ9eOZ)J9euw8so1?r6n3dL@@re#8TtArdJ|n?dkH?F`9HCQYcbedYsEX q{-hmB!=~T@m!9T{?*)H*FZttC?oLC*9j*(ArHV|V5^uP%lm7x6WdSMx literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/no-change.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/no-change.png new file mode 100644 index 0000000000000000000000000000000000000000..c0dc34816d34894b642c7a5a60d211ec30e8cac4 GIT binary patch literal 1853 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#xV`yk7D=V9un;RP&3uJ3)X$1rXu(PuR+5Z0iKq*WE zi4<8sCnf->)TkuLFPI@A-XTF@!GsM38?M(MUT@#g{x$3D&dlODOKV@xuG{6GA3wi; z{e}Av0zRDI|K6bCz<+_OQ*J+DU|>`6ba4!+xb^0OAtM6=3xk13;fwo$O#73&H#|^< zxno61!9-Q>X*!XcCeV*soqp4l-_*TSg6nx))U9uO_xgBe9CNGtKmGOzg93r4vqkdl zpO}QJ+Vr6q<{)T5uw1s{ZZCDfZ@GEnW*YDKQHIsMP z31$C%x-HQoW!*bfMJ}7Sj>on7Ztb?w)A&=g;oA0wsa4IXGejS4oUK3of$m*~X=?c! zP8oljTORRKH$k#~!;2+nuQRV~ZoF3JbJTC$}< zbgk0Wt<$C*FMaX;s0c$>kpF%T_E||QOr-K%p7CDj6pz??CbGzLvC~9JHq|K6#FJ|A z(pl#Otz3ND0-pZOo^0JR$B)zcBe!~cy%&&i60Wr4dNt}HO6MgCN(hCNtdlo`l}Q%n~|+IR!z2u_m0isP3}cn z@87y`PCHn8B#kXGHOYFi+`1baHmbERAEX`J#}a1xr#aC@(Hglc$=)IxHF!ow1lc2nNkV{=+3*~&ukD) zoXrsM#V}vSz2RuUBk==WOJm#E-fX)h#aPvTl@Ypc0acH|; z=iU%Bk0Emc&pWRlan2EOOCK|3EtvVzo-a|U}u#`ro(rO_t8BXo%yT8*tn3l~%<5GcTH7*S=nNTlsvz=}))OlJi&2@5Ce;}7oWFHEpO)A_~y<3Md#a(ZkuY$E+(?{<)i&k*Um1P_Raf1)31}Y z@6|qWC`8X?=eE;2-!7^nTP1&s%lp_&$F(oQ&EAIBy%B5SxI2fHd!1%flWFkHbS0LZ zXP7N63mmcaa2I|*oq_AgCSwk*?;9(`baHe|4|P48Rx0YLl$EghVTeIva&Wio@@wbU zY5%_8bmRAw7!HZ7()8J8P5Re9Cu}s${$I`g`fPBNzu(+usguojvhsJ!ZwN7!>5H;3 zv*lT27ooo)Vr5W2`_xm+HsV_5@*%E%X{C}n^J=bDe_aw{S#L8>(A##dmCU?tp|1qx zrnE1%d}h|(r}eJ0<^YqZn;Kidj$I!mI(oE)tg!5tDN z=k}$yaEq0^SQXRS&ogCabrzlyxPI_+_6v)@4-anP0$P6X*p)R~Z?cr#$uZ~Le(d1} zU7NqU2Lm?=N__~9lF8n4&s6ql*}@CmH`N?xZ0k07ZzX;CzCdYwJL;+OtDxA1qHGx|(a#PC5Nvhm=x~7={1< literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/reset-size.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/reset-size.png new file mode 100644 index 0000000000000000000000000000000000000000..254182f031ead8a500ea1025888e5414302ab93b GIT binary patch literal 1148 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/text-after-edge.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/text-after-edge.png new file mode 100644 index 0000000000000000000000000000000000000000..2c76d2a76071e994e5077c650695e0f816069692 GIT binary patch literal 1111 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/bold-sans-serif.png b/crates/resvg/tests-hinted/tests/text/font-family/bold-sans-serif.png new file mode 100644 index 0000000000000000000000000000000000000000..8487acc42ba9ad9f3afda1dbfb4795e81236e0b4 GIT binary patch literal 1166 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`%UU)5S5Q;?|oBj+_S! zL>xA5KjgPH;J+1n@Q0U{6DM3dePPw%fYLJNH}4+#3Zh|GDofc|LY|)kDtq2Wna2={Bi?Y_ER=U(DQ}IFG#Hh0wJr)rYOG^L$`rReDEHqLn!Rf+> z=Hner9XGWD8GoMmb$}`O&M~>dO(!f4osgYp;bOOmCv1M%3AH?VMWaco8#q#*f6sGJ zcak_ciF;i|w(UBd$c}fV&I>qpo|G~)I<>^hS20h`EHdN4{55v(|FPd)v}VGpg~pTH zO^zryid^q=XKN2KGJd|iutn#HV4jGgb>udKHyPdMo%RH^yh#acU8?P?)@*RVZ(7gh z+qc`KIZrw*;kbEHC_?enB7x3-Q>H#BmR&M&zD{jK*mU<3zSAsqxMhT#L$7IiKWtNw zJf*~19_(}e^#p`;H5oIxVs2 zG)rwir#WN*@N;-0wP#^s=^*b4W+up*hM6J{?IFcptf&`rBhC;yP) zNX(2`*HQ(8-Y3l|br*cbuPzqR`XbsVfww)&y!G+RCD#OKu;{@+^2 z%*~Lbz|ru!V#h!3x}bwxENNadzNeg=qzX*wgP)2`dF!6&FSazrDYGt7@SLu-&WrV+ OQpMBN&t;ucLK6T`iPy#e literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/cursive.png b/crates/resvg/tests-hinted/tests/text/font-family/cursive.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9e4f35aafb88592f39cfd79a2a7dc1b464d877 GIT binary patch literal 1404 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`(M@)5S5Q;?|oB=8Ojn z1XwnB=Zl<~pC;8b-^Np5O5wr`A1PPQTcTX+?6sL$C#rf+(}~eyQ3*C{%ClTJ_-Pf^>ph==My)0WmVi2Ux}-hcjDGmlwf26a` zhs;>1;uo2ApmE)+|F3r>*r*;?_r6l95F4AK#ClJpXs(!XNw|QPlsv0R`>t1FuZ#8;_(Un z^Wx)~)b?cFxuyPS`qWnUY4x3%wJX=HidojTTzKUPuDJnE)8C~3KBF?BSdi!A*`P_G zbK5T5IdyZwLqpagIliQXnru&xX|~)C_qreWlpEK&c*D`D>&pFRO+oM#xeScC`2#z=m;Fva`v5*;v(~6wd_aBVuE9(Hof_`LDA#q z>Nkx0H-5db+o&gBX;W2Op1gV7vt7nfH^su{b?8hxy&=AK#*Vq#Q*#qbC-tq7vGALE zw59c!oZ7D_kF(a3CoHWCb?}jpm3#IiV9Tw$w>_0M-Oxj_Ee3`OMYbHOc zPRx|suEYK%;sihQp^y`&*gqWcoAz~r+<^nrq&DijtM3uIe~Vdo#p)H$ww}5qXE3Ai z&$=0@nf(X!TF!2J`te6%z?qQOd-;q{JvgTGnz2DqrPkn(oX1kfYtvV+V>0;Q?0aOB zh4jK=y?TYqO87qY4!yqc2Du(xA|*^Zuwu(Ks6+wwMk{aL6z-%<2*{sEt#UuG08 z6s);3|If6H)V+1T;;UPYyB-uC?G#Zcy;FScL`m*N#`}`)`zG8;($Tjl&UF}CH>4~?m2yxHJUkN)BpP2&Rb4g z`hC%X<&)X> Up+~%TtOb>!p00i_>zopr06!U9ZvX%Q literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/double-quoted.png b/crates/resvg/tests-hinted/tests/text/font-family/double-quoted.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a712cd9e656260e3ec0ff165a5fe7f4c0634d1 GIT binary patch literal 1165 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`%Uc)5S5Q;?|oB=8Ojn z7?=&pV;2hiGubWhqo2j`roLCTk+;fBW!7W!r>=FFc7Bqo_cWcz6Lh9rt{vVd`+gOt zbD_-hDZAp1tgCW8^6mS-^E;i+@z@p~nxtzeWA}fpaPfO{8I4)L9XIY`tzILkv!H+L z@mtAP+nevYthpWIG_6bZ7rWkp-0Jef(jV;W*6%nTbvCJg>#Y09Yp=iG7-oDUdF?fg zp0AJZ@H)KNr9aEk*TceZb=#(2A`^L+-`^>87=`==?T`trC@57Cnb%yyD6Hyzxzg z)0U@-8(eR8yz!Ge^4;_J+1&ePVMi{P7F!ksIe$2ob`pLqWyqv%T#-OITS zez0FJ!P^$0@%XCX&8hSDEZhCid{fBDV08iG@0B)kPK%Ahjs~m7vpJtxrg?AA66LuY z^=h(bZ+vPxk2%z)MaD06O~;we>z$`BO=X|h{vmJ5u_B4Ulb@4z)?0kGWb^h)j;&aE z;Y5?D+qq9)ebaT~J{{>Yo2nyJZ5NllhEe}yL29;(k&v{{jR)fjbDx# ztxm4=iMmvmw)Lv^vOkV9ugaaiEM(lk>z2Rf_pXTh5+Cn{e7Ae;#T_*-tS%#DZ*%{b zdA&6W4q|JsMNBjI&;Pnd`sw*?Rf|o;Y$ud{@q4h~{5Hp9PV1GYwcoMxqt(!QBQIvlkt8z}o2A*=X~JS2A3lBDy{p-FP2c{z8$%y&-nQw>_nyx) zH_I29|GCO1I~kY_92uEaktaqG!Z96w2p?BMorxk?iy%gc1`ktMKw!7mg>vQ0f2VVD>4Q5e*UzmEu~bUU zT;;XR&8~z`y<+>di{Wv{TAlbKq9x+Cx=1Fy)bKMAweSx*efRaYDXP;ZZz0Kap z>asH;r@Qao)E7{ zVV*yezRr$#w0q@Q3GU4AwbN4gVoZJ}@y6H9GkX*^|2OBnZI{Ituw75-Te^L1)q+K0 zF;lg}tl#EcWq4aNDST#u^8|9&!6cp=8BpBvP13fi`)McN><-Y zn9LgHsr3JMuBFe~qw78AGfz{W$acN^Z1~=P3Nl}_7!)g_3!XVdOi0$Ud>#EUq@25O zJ6Ft>Pl|U6H`oMCOKGlI^{uEq{RY?CBTS2goadf4+~D)^z4o%C&;AQv+F3VMZ@s+f z;QH-z^}5s^UGolH65SnqBqUhEEB3PT3+9B}UXd>i(bL~uDG}HC-zoJ({=H}7+^GFG zc3oci`s%`s9@isEw|=qJS+%hwL+9L<>rdU>zr^Zn`n+-R*$1~|qknCmvq(N|%IAC2 zzf~^0{CU-e|F;)1b2B6;a3nm}{PT}_x?cf{Mr8}wJZ7-<@c YzjLaV@wC{t8dPw3y85}Sb4q9e0ME}L;Q#;t literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/fallback-2.png b/crates/resvg/tests-hinted/tests/text/font-family/fallback-2.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a712cd9e656260e3ec0ff165a5fe7f4c0634d1 GIT binary patch literal 1165 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/noto-sans.png b/crates/resvg/tests-hinted/tests/text/font-family/noto-sans.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a712cd9e656260e3ec0ff165a5fe7f4c0634d1 GIT binary patch literal 1165 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 R5e+J{JYD@<);T3K0RR>)0_y+( literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/source-sans-pro.png b/crates/resvg/tests-hinted/tests/text/font-family/source-sans-pro.png new file mode 100644 index 0000000000000000000000000000000000000000..af2cd37206a6abf06c2012edf2c9d4dd9222fd8e GIT binary patch literal 1130 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/em-nested-and-mixed.png b/crates/resvg/tests-hinted/tests/text/font-size/em-nested-and-mixed.png new file mode 100644 index 0000000000000000000000000000000000000000..672d43509fc52042b161b256f4991728c6f7c166 GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQDh5TB4=P~Xr$Vg7>k8}=VKf8qXv_aA}}3#BqJFi-V#aSW-r_2$Ax-UbB` z)&uG-Z5tSWzhAj=v*P`Kc`e@3B3o0$C#q++HT_I`x=3MD%E?Kp-q-3kr6_t&(}|=v zRVz~xDW5G5v^ekE8Ry--0v(G^FW41!eM9Td|NqZO&OBiE^^4J+%TC>ItG@;Qw~JI! z`ag4xs5qObNkQUQ=l`GU)wyr{x$;7G)tc{;tJiGLTym;v_T1FS&z95DH)QW!8J)$I zI#0oRQ%2=9?nK|6o33_EJTO(mIP@y_g&7mS8hRzpUhN-cvy0O)`(aO2*q z8?I{U#h+jBG*s*2gg;LXs;5UxlXq273%9IdoMaxvsTeu!s?(ND%>2rImMy)Tb-YD+ zW_Z83tU7!8LhJO%Y1g|Bzn$3c-M_-|i}BjGC$_BF=JWhP|N32XoNw)lp0;)3?=RPb z3KsZATJPlcSfC+(Lvs4j{1Zjofs5*$!=_%H;v6vb>m&8c8b1X>p0Al&eJW6BZD?e` z$4>{ncb&gGZS`-Rvh5EZ2By6{5mElZcIWXq!3_KcSC;5pcjRT7zS!hS^B1oKBc}&N zTMqUcocyGga`4+955C6NKg%{1z5DnzF3b!lvL`?0V7<(pBj;Z}yCpL3RL+S*j~~|A zs*9Tb=cugB`2f^=;+Owf@7(#(m0Z>*d2Md)(qFe{o?&}uuV7@J==;-F%LLL^T%IM? zbuGoRo+0+5!D;TN1>b+#IjUE0nsT%;Qu^nX%w^HvpPj20SaIWap@`&;uk{PpoSI(t z;s6ta1P9ZN%C7tM4=-`@aj7V~fD`FSr$J5GgYp#6h1FbdPHRo{@jAo0ccbsGWt)T& PK!t;+tDnm{r-UW|Uy0lZ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/em-on-the-root-element.png b/crates/resvg/tests-hinted/tests/text/font-size/em-on-the-root-element.png new file mode 100644 index 0000000000000000000000000000000000000000..672d43509fc52042b161b256f4991728c6f7c166 GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQDh5TB4=P~Xr$Vg7>k8}=VKf8qXv_aA}}3#BqJFi-V#aSW-r_2$Ax-UbB` z)&uG-Z5tSWzhAj=v*P`Kc`e@3B3o0$C#q++HT_I`x=3MD%E?Kp-q-3kr6_t&(}|=v zRVz~xDW5G5v^ekE8Ry--0v(G^FW41!eM9Td|NqZO&OBiE^^4J+%TC>ItG@;Qw~JI! z`ag4xs5qObNkQUQ=l`GU)wyr{x$;7G)tc{;tJiGLTym;v_T1FS&z95DH)QW!8J)$I zI#0oRQ%2=9?nK|6o33_EJTO(mIP@y_g&7mS8hRzpUhN-cvy0O)`(aO2*q z8?I{U#h+jBG*s*2gg;LXs;5UxlXq273%9IdoMaxvsTeu!s?(ND%>2rImMy)Tb-YD+ zW_Z83tU7!8LhJO%Y1g|Bzn$3c-M_-|i}BjGC$_BF=JWhP|N32XoNw)lp0;)3?=RPb z3KsZATJPlcSfC+(Lvs4j{1Zjofs5*$!=_%H;v6vb>m&8c8b1X>p0Al&eJW6BZD?e` z$4>{ncb&gGZS`-Rvh5EZ2By6{5mElZcIWXq!3_KcSC;5pcjRT7zS!hS^B1oKBc}&N zTMqUcocyGga`4+955C6NKg%{1z5DnzF3b!lvL`?0V7<(pBj;Z}yCpL3RL+S*j~~|A zs*9Tb=cugB`2f^=;+Owf@7(#(m0Z>*d2Md)(qFe{o?&}uuV7@J==;-F%LLL^T%IM? zbuGoRo+0+5!D;TN1>b+#IjUE0nsT%;Qu^nX%w^HvpPj20SaIWap@`&;uk{PpoSI(t z;s6ta1P9ZN%C7tM4=-`@aj7V~fD`FSr$J5GgYp#6h1FbdPHRo{@jAo0ccbsGWt)T& PK!t;+tDnm{r-UW|Uy0lZ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/em.png b/crates/resvg/tests-hinted/tests/text/font-size/em.png new file mode 100644 index 0000000000000000000000000000000000000000..672d43509fc52042b161b256f4991728c6f7c166 GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQDh5TB4=P~Xr$Vg7>k8}=VKf8qXv_aA}}3#BqJFi-V#aSW-r_2$Ax-UbB` z)&uG-Z5tSWzhAj=v*P`Kc`e@3B3o0$C#q++HT_I`x=3MD%E?Kp-q-3kr6_t&(}|=v zRVz~xDW5G5v^ekE8Ry--0v(G^FW41!eM9Td|NqZO&OBiE^^4J+%TC>ItG@;Qw~JI! z`ag4xs5qObNkQUQ=l`GU)wyr{x$;7G)tc{;tJiGLTym;v_T1FS&z95DH)QW!8J)$I zI#0oRQ%2=9?nK|6o33_EJTO(mIP@y_g&7mS8hRzpUhN-cvy0O)`(aO2*q z8?I{U#h+jBG*s*2gg;LXs;5UxlXq273%9IdoMaxvsTeu!s?(ND%>2rImMy)Tb-YD+ zW_Z83tU7!8LhJO%Y1g|Bzn$3c-M_-|i}BjGC$_BF=JWhP|N32XoNw)lp0;)3?=RPb z3KsZATJPlcSfC+(Lvs4j{1Zjofs5*$!=_%H;v6vb>m&8c8b1X>p0Al&eJW6BZD?e` z$4>{ncb&gGZS`-Rvh5EZ2By6{5mElZcIWXq!3_KcSC;5pcjRT7zS!hS^B1oKBc}&N zTMqUcocyGga`4+955C6NKg%{1z5DnzF3b!lvL`?0V7<(pBj;Z}yCpL3RL+S*j~~|A zs*9Tb=cugB`2f^=;+Owf@7(#(m0Z>*d2Md)(qFe{o?&}uuV7@J==;-F%LLL^T%IM? zbuGoRo+0+5!D;TN1>b+#IjUE0nsT%;Qu^nX%w^HvpPj20SaIWap@`&;uk{PpoSI(t z;s6ta1P9ZN%C7tM4=-`@aj7V~fD`FSr$J5GgYp#6h1FbdPHRo{@jAo0ccbsGWt)T& PK!t;+tDnm{r-UW|Uy0lZ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/ex-nested-and-mixed.png b/crates/resvg/tests-hinted/tests/text/font-size/ex-nested-and-mixed.png new file mode 100644 index 0000000000000000000000000000000000000000..6fb0c6beb65c473bc5e4448d02d39abcd46aac16 GIT binary patch literal 1018 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDpL~V z7tG-B-~K@ThlGF)_a7|SpC9kPe*XCj2Ja^nCEaktaqI1k&aB5C zB5fBhy?2e9RHD97)Vu2c_c>%7uzX>o+w){^jphdd+qXQ-9XgcTG+o$hv;L&-2=Tt^cc2Vs0?n|NHjkZG!E6?lsS?5B$oD_ zG?G8Wls#AGv}~;L+LE_5_YYdBw4YtuuaY~H&2Y1#&W57kHlX+5N}L^X%{2R8O8>v{BEK@3QId&&})kc5`lfE#751H|pn)pS>n) z?#2CAwNkf?O@BY5#Chkz+J9>nc^{SfHq+eC*xFe%+uLpiUag<|>iw<#Tr^Ao)J}4*{n@z1)@;8j{Bmv5 i)00=GEUYx*{m)>QX{5DRNJJHsgFRjST-G@yGywo*lAnYC literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/ex-on-the-root-element.png b/crates/resvg/tests-hinted/tests/text/font-size/ex-on-the-root-element.png new file mode 100644 index 0000000000000000000000000000000000000000..5daac5671a5d2008404140770e2496f2caa27a58 GIT binary patch literal 1072 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 S*2-6)9Omij=d#Wzp$PzsS7Dj} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/named-value.png b/crates/resvg/tests-hinted/tests/text/font-size/named-value.png new file mode 100644 index 0000000000000000000000000000000000000000..c5b95b568aad81bc368dea5d27e8744fc86e18cc GIT binary patch literal 1801 zcmcgti#yY69AA`UM41kig`OHYcGSr&Nvnh8(s-!#lbBgJBc@z(Sy6_B){~mcT%t2| z^25&%VXARBs##$?L`B(Ln~pit9659H>--1jeV+Gu-}n1ozTfZX`~7_1bPv3fhT2v& z1OlPqeAK}cfmnlG>8i>K3I6USC&h5y!|k}EV*H<5{^(qhLM0~36YquCXt)P=$ll%K zB+;K55tW$4xN++?GpG1Y74-N?hv4PgcVfw`b6>bB0->_q+2Qc<*uk0MbJU)r+8v)H zALGZnvjjbMA1NUlqUWTs%hXT5I;>SQX)xaSWT}PIyNu&JcxA*I5f)psJQG_+`BNN| zdHL>ewGc11x+}nw=Rs;7D!u*Ho@-+z7ig9wAqugU=nMpx)p9IJ!&~&U`@-zQ+8Vjr zQt9&j1mz2|%x(|)4D|P~>{%iXOF}B%KrtbD;1}**4fgUQI_9e^gl+K4@^r;s{hW~lea5V6XdvzmmY6M%a)fbJ&$K6JAx<(;&bZ9t#j zR4y-=_;DX|G;=;Tc43q2a?P^_}tLq!{3p_WP}Qt-E7L(@*o|vwU0!O6OIl zedoDC)vFGh0~_jGfyM%x?21FSi4gf<{n9!tX*iFOq|qARK1d{16qAvrmYXk67g5l~ z1?@pLdK&B!X$P&&2iSe|D;gNAZp@4L$zG>C-1u|q2JW<*+m#4Wb z&7#7of{u{Z+1)h@C^WM^0d?NN>sVm3_3H3!eETB(d$KndeUop+a{Oc% z(Rw8!A<8xa52XJQH8%`JR?TYZ+!Gf-*BLBE(C5q(j}>wBN!>19e46}(S)x7_3C7T{ z*%#e%bB-j7K1*c_NzknrKy@|v7;IRS+ywG~k&m`A2H&kinszk%UnEYE5~)M{P{pkv z$A@-cI#-B~E^-FODh*zsm4;}NC2uUrarDg#T(h^p7>vOQoUlIPf$`^_12;rq`2AzL zg>THL24#}miCJob*|&_l#40%sdp@sZOIpY3Idad?-K*?&`d*<*zt>2>;JAZ7A-FWB zc5vZpQ$@Nf<*xRc){PE4^cSPbRG;^X{Y`YAjp%B9Rdd(VE_#Kk`l&H(E>qAVE5`iv zxu3$KN=bg1Drf2w_E2e-8tlBibL5`5zA-q%QB1S_+&jeR{}S$YdmlZpOBY2rmCcW9 z@6aYNgg~&nmfbH}Su$kCdEN9+MqN~iBYvr{KZ(AtWGUaD{r;|~$o$nneD64%nkx0#1ev8LhZTrGC zgmZyD-$N>a&AXX*sr_RDi9LMg1ERW%vw{4PJ=>#tBAXuC7;x$8C8uz2C|7t21o?o8~6+I2vNoCfoAxG|L z5)XM0^kq?z=&F@)Cv%5|H8 z11Ar<0HI2f%tBGpXRXk)wXd!iud;yFAlf8KknjtPVJ6r;_BI6Ft5?Yo%X3)_G~>x- zkxXbh4STkGqo(`Q_k1rFiiCJQ9zn3%ITEYyQ_YM{(T0r-Qyd$ z-tjeb3`iU=&7L^$jj?PPB~O?+CU7io!H~kfU{?z(iuu(`#X;nhPXIU0x3|pi@raOB eX*J(po`@LH?tIdjquR3ap*cI^9V&nJzw!?ZVlOrT literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/negative-size.png b/crates/resvg/tests-hinted/tests/text/font-size/negative-size.png new file mode 100644 index 0000000000000000000000000000000000000000..0c96ac6a10b9f3b401925f63e9fdbbbda2035352 GIT binary patch literal 642 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 BI;8*r literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-style/italic.png b/crates/resvg/tests-hinted/tests/text/font-style/italic.png new file mode 100644 index 0000000000000000000000000000000000000000..692da732dc317b22c8be143228496f06fdbec1ec GIT binary patch literal 1346 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQDh5TB4=P~Xr$Vg7>k8}=VKf8qXv_aA}}3#BqJurztPIEGZ*dUK(XmDxaq z^}zLjj)pABtu&%^V~Xszc5CB1xgu;$8JP9-*JJpNBU) zXw6S6Kh7QZBK?2k>epV9Ydnrh?tb<|_4npHjxSlu7arI9eJ=0Ds@78WhOgiBbQ!d^ zZct;8xc4e}??RE?x5}lowOWrJNxhf3W_MJC?!5?$GDe2=Vqx_x?3H)xdXyUq|D^gK zd--qG$>h-Ot84$w-0=FM?bDKjN%ikpSDk0kDm7cZY06y-#`8a)%W0%+J-BIymdxaW zYbA@XeR{_}KR+-lG`x*%!od~J3#-eP$(-&J*W(Xpwu)ffy>4Biw3DzBpQTixa`d7! zL46I;D+i^X_#K;nZ|eS8I`6-`O#k#UA(bbPHCyoDibLzJe)v9T=MhGSP0Jr{xFvn{ z!ZNGGop;Pt8rJR#{4SIJU-XCk9^=*bBQ)$PRl(aN{oI#PV#R?M~i7M4E~m1W;#FXo;Wq1k;oaaKXc zhPw34!F6-xB;JTCtY{Y1Z=UGBaz^d)GpRlN?lgx%uLma;xA@2fAu=o9(%0ryQQ#G#+;_i72fr?7BX`)Bq(qsJlCxI z-|DTtgK0vKK;$M+w&WiC)cwe6t~aN(Ci-}tVQuz_ecZ2}T@5M;Jzf1=);T3K0RYR{ BI;8*r literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-style/oblique.png b/crates/resvg/tests-hinted/tests/text/font-style/oblique.png new file mode 100644 index 0000000000000000000000000000000000000000..692da732dc317b22c8be143228496f06fdbec1ec GIT binary patch literal 1346 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQDh5TB4=P~Xr$Vg7>k8}=VKf8qXv_aA}}3#BqJurztPIEGZ*dUK(XmDxaq z^}zLjj)pABtu&%^V~Xszc5CB1xgu;$8JP9-*JJpNBU) zXw6S6Kh7QZBK?2k>epV9Ydnrh?tb<|_4npHjxSlu7arI9eJ=0Ds@78WhOgiBbQ!d^ zZct;8xc4e}??RE?x5}lowOWrJNxhf3W_MJC?!5?$GDe2=Vqx_x?3H)xdXyUq|D^gK zd--qG$>h-Ot84$w-0=FM?bDKjN%ikpSDk0kDm7cZY06y-#`8a)%W0%+J-BIymdxaW zYbA@XeR{_}KR+-lG`x*%!od~J3#-eP$(-&J*W(Xpwu)ffy>4Biw3DzBpQTixa`d7! zL46I;D+i^X_#K;nZ|eS8I`6-`O#k#UA(bbPHCyoDibLzJe)v9T=MhGSP0Jr{xFvn{ z!ZNGGop;Pt8rJR#{4SIJU-XCk9^=*bBQ)$PRl(aN{oI#PV#R?M~i7M4E~m1W;#FXo;Wq1k;oaaKXc zhPw34!F6-xB;JTCtY{Y1Z=UGBaz^d)GpRlN?lgx%uLma;xA@2fAu=o9(%0ryQQ#G#+;_i72fr?7BX`)Bq(qsJlCxI z-|DTtgK0vKK;$M+w&WiC)cwe6t~aN(Ci-}tVQuz_ecZ2}T@5M;Jzf1=);T3K0RYR{ BI;8*r literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variant/inherit.png b/crates/resvg/tests-hinted/tests/text/font-variant/inherit.png new file mode 100644 index 0000000000000000000000000000000000000000..447ba5874fb2cd8c42ddc5ca5a43b2a8ddaca50a GIT binary patch literal 1070 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAmtI@6XFV_sRCBFteFioNTMXj zFPOpMzy1CX2Lc`#+`n)>fBk}l4HEltKTKO zMxGmDX6W{r_ulJmpJ^vE<=bkjHPKOg5KEd$BlPC|x)Hl~Tjs*wg{Pj+w|KStZ%4$( zulK#)m!8>u+-v%~Hm$SYF5SJa67l_d)v48|*9LoSxb*v0_txw0?ulK~f0|t3vx=R+ zed@WpzNKAm<+jUf6QLZ`bu7UK@7JdbjcY z%5a&DaYk!iRDL`7^~~B0kIcUW{n>laEBX-QqLTBe+GwY+KK=MQnVf$#I~o_Q@xpdYPQ5=F$mA=kH7U zpQsw~RdLnjs1386_ovlI_?m_%a&$MpSg^&8XLaIK^US`bjxAH)J4eKFHFLbyjr+RC zu4BWwzp4+@d6d>%RqT=d`O~rGtJ$6DKO^K^BA$Po^kIuh$A(Xrf4o1RTPQI1^#{wl z6W1r|&U<5bcVd2mZ@WRvwEy2(*Q`Hy@?CZ_hj!bB*c(9cQd`}bA%-0r+%A9HV>AD& z--bB(wCuSXU%+ph{IiqJ^nj@R>gU#H<}oB zR3FberQSFvN#J|$)wt8@ySKNmOS>QOb=qWyJj0Iv_C%y1vJ)SbHD0S12Ihh|`7H~t j-`}uhqt;U|>C^ViKf8Ro6+H_5K)K%2)z4*}Q$iB}HU7oa literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variant/small-caps.png b/crates/resvg/tests-hinted/tests/text/font-variant/small-caps.png new file mode 100644 index 0000000000000000000000000000000000000000..447ba5874fb2cd8c42ddc5ca5a43b2a8ddaca50a GIT binary patch literal 1070 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAmtI@6XFV_sRCBFteFioNTMXj zFPOpMzy1CX2Lc`#+`n)>fBk}l4HEltKTKO zMxGmDX6W{r_ulJmpJ^vE<=bkjHPKOg5KEd$BlPC|x)Hl~Tjs*wg{Pj+w|KStZ%4$( zulK#)m!8>u+-v%~Hm$SYF5SJa67l_d)v48|*9LoSxb*v0_txw0?ulK~f0|t3vx=R+ zed@WpzNKAm<+jUf6QLZ`bu7UK@7JdbjcY z%5a&DaYk!iRDL`7^~~B0kIcUW{n>laEBX-QqLTBe+GwY+KK=MQnVf$#I~o_Q@xpdYPQ5=F$mA=kH7U zpQsw~RdLnjs1386_ovlI_?m_%a&$MpSg^&8XLaIK^US`bjxAH)J4eKFHFLbyjr+RC zu4BWwzp4+@d6d>%RqT=d`O~rGtJ$6DKO^K^BA$Po^kIuh$A(Xrf4o1RTPQI1^#{wl z6W1r|&U<5bcVd2mZ@WRvwEy2(*Q`Hy@?CZ_hj!bB*c(9cQd`}bA%-0r+%A9HV>AD& z--bB(wCuSXU%+ph{IiqJ^nj@R>gU#H<}oB zR3FberQSFvN#J|$)wt8@ySKNmOS>QOb=qWyJj0Iv_C%y1vJ)SbHD0S12Ihh|`7H~t j-`}uhqt;U|>C^ViKf8Ro6+H_5K)K%2)z4*}Q$iB}HU7oa literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/all-axes-combined.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/all-axes-combined.png new file mode 100644 index 0000000000000000000000000000000000000000..3d0f560c2344567f5595479f84c29de73f92398b GIT binary patch literal 1267 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`&yK>EaktaqG_>$iw%f!0-%A2KfE4*TYY{S)k|3}LGfAT*+ zV%J=O*Q=RdFAw3qr^2@;$0{MTHsR@7vzyG>=9Y=-r3r7ZCa!;X;Ff3NN$baX5tG=j zZBw&c>D@oWa>KUP5)UTB@`T)=*E3t*2=ME4&-lgZJzrz~l|QYwjt6Cxx2kp@D(VR2 zTm6c8->yHZn#;}^I_~0SSk|>q$hM(CFk9y?^NcEI9YOJk$IG?YR{v%_?NcFgZj0T< z$Rlo^n_S<_Ns2rY6?I9x=K3k84S%FgAD8;I%Jq`#vIu3luSen{>RvFc*_y+k|H5cv z#hET&g}$S&Z+=txxzPNyMsuj+^#0V1D<4Mue8qFk<$K71U7lk7rirtEg-7T$v(Ao8 z*m-HA&a}2Xw>91y(vExV*==hkyhiV5~ScPfc_9e*Vt>{4`bmc=!ln}Td*oz|b6 zujhPsNcj<7<=`XUCpwLD!Wu=>i4P8!_DosVvC;Ydq`NnlDXE2v_Z?lv6L{9=2b0m! zPu3Che(Wy!rLCH@&Sj1F8bz;TiuVp1b#VTZ`zNmXo6D~GY1|>9{fR%BHr#3a`mbL0 zQ^d3LM=zaGXun!`wcP)MrA|15*x8qy*EaC?r)<$r?p?k9_koQrff2DrTc5PDg5F2mOzY-U9cg>MaT)*JO_8evxUatKQPpDX zuKBia;UT|goNLs>Zp2DPWF6ZUnfh*jRTX#kw4CyJTFl)(Y5xRHYKNWuWxGbLSoltm zVnoWbJL%!ur%qkCeM6e-?kHK&X4hNI<(Idp*hYl=>L*m5f0lYiwPo8H_5Wu+=q7cl z|2cd?Xm5+^>>UeVPJH#O_0-8v^E5@b?p9Y>JNek%&0TT+QP1ZrGkN&#>aU8ZpA}nv zzb|_+gM~qYgXzY{3s3)Y>xCRF^;dD3rjv4V5-5ue66%*4IJ>93)!d-J+QmrIP`p0- VwRG^}(sQ7q%hT1*Wt~$(69CLN8At#C literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-stretch-condensed.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-stretch-condensed.png new file mode 100644 index 0000000000000000000000000000000000000000..0619002a514fa7f5f96c355e87c52fc59ceb3d40 GIT binary patch literal 1529 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/explicit-overrides-auto.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/explicit-overrides-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..4a26241cc7617a872b458acdc6067cfba470cc4a GIT binary patch literal 808 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-25.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-25.png new file mode 100644 index 0000000000000000000000000000000000000000..4595317b379b17836ddb3b045ebff7c4d5f396e7 GIT binary patch literal 1439 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`%0b)5S5Q;?|oBTN_;& zc@Au-Nn6H#v;J)IF&>5TJki6QUA)RcN0pSq7dow0Un8+1;6M{Ax0p`E{3g|i4G9OE zSiQj{_cRb2C;=fOAc{7yfRt`X-~^Kgg+T0sRMnVWQ}^ca+l0SiPm(`A)Z6gy*sUuY z6JlRQY}nMts=c_6H9PotQ>kXs!Cfh7qTJVXjk_W?@XcJUB(}!&*~$*q>?t=zHzx4j zI`h$d&BdZ>yYg1mDzYbKpEoF@m(EXS)Tc-KYA^S$t6PI&zcM9`m#FX)VDPQ7I zo6mGjFN#b1(VCvO98A3C-G`MY|{NJ;dZ4xZO?lRHErMlcNh}1|%|x0Zk4y5Sb>y<$d+ns>VHE7and^ zoRE_7O)VjC%aP#2&;1h&*KmFPw2)D}&1mb}J}%`A>nylWX*`?rTK}bKUpm02eSk54_XRQA?M9kdXJNMKWT?U3XV=U4!+O+uIZ77M5D9aoENpW0cM= z_AR`dJ#zl)!%Y46qyuJck8XDkGGXCfq#Aep_@c!d5*%*HMsNDD*&Hb3>dz?C+In)8 z0RL^S?=6+i8x*2C;~spqSW_6A^K7E*hqeq(F&FL2#rqqt?r&k$IFlD&b8yGv)w&0r zR?9SAT~%@Y=$Y!74Ua#!t46%o+ZlJ|=I`wr&Pg#Wa`_}-nweDLyy1rbmoJwqzw54X zvp>#%q4fN{$$zxZ+>=M(3@bP0l+XkKzZhRn literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-100.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-100.png new file mode 100644 index 0000000000000000000000000000000000000000..4a26241cc7617a872b458acdc6067cfba470cc4a GIT binary patch literal 808 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`&H^>EaktaqI21&|S9; zL>e4#2F;MH`L_S;qtvB8Pd)iLzg2icu=S5qSC)yy&kXW1^#0YAHh)9VXHiYtL{2fC zhz$t`g}`K!Du~_0>J28jr-9hqVmc5q0?dxszycHjDxBxd+55^)9)_}?#WA<`Z@g~`?_GCs*ccgo1dkso-+-z)hWNetvurRtM4Y=fxV?x z`(({JJ>PFg3ha-*8nJOzdu~;GY1S&gcB$7zzi&QR`lVpa#yp=EKIXOwyd)k_(U`i+Q1c*m}$^~fW zrWD&ZH(SeI8}KwdJW-Y>7Ik>V_xiINZ)t>m-1O}Kg#&hL_Y0p}f39>&v++_BrN8+b z7ddH|eXsY`YBHW`vgl9#MlX@sT--&B-m450#5c6CIcg{TWm?xgX<9~M75x#H-iM`@o-6jyiZCC^N^F;$J)XqBkHg}Ey98Pl|zz8;}TuI{U^ zGEUXgFxjy=BJU$x_MumHQXi%;YdP*bI_I!dfCuxm7N$wO!sH4<3=8`=j@tyaAsfW-}?FB@r_k)Bi@`!U}&&RxZBqHd|KXN z!|qoTch#Alsa^9eI#Ks__o?PD=S)+rtk+EXyG%ygeO0=^)`I-KP5r88H+XG)b4Yxf zQtDsc)uJ1EKKQH&?o8d3y8Rk+(B$TRqZA97ZrLr<&Py(H3XQm%&Ykz_<+`5{Q;*tr z_4Pl9_!Ay;FYU;A?yN(Tir+}6ZHW@(cAFC1Gj-Ezy_GB}I?Ls~w@uob(bB`Zay##~ zSsT;7E!=5xsIf;iQ*~+F8cXv7MY^A^H8*lcOjr{Wr+)3$_NC1B)e;{g&Kt7o7(Dd} zS<1*7QJ%JFPmOl(gKaUN?4l<9za6pu?S)2G1_J?>4WC8o{x^E7TQp4S5rE_Zoxw%@ m(g$WtTaj<6fnI7;o-xHw`nl?A8NU>$eDQSkb6Mw<&;$TE5azuA literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/xtra-extreme.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/xtra-extreme.png new file mode 100644 index 0000000000000000000000000000000000000000..96244e875bbb038835fee7896d12fc5c3d76e4d4 GIT binary patch literal 1624 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`#1i)5S5Q;?|oBj+_S! zL>xA5KjgPH;J+1n@Q0U{6DM4=KCy7D_}+%=^?;8FIVV<%*p|k9%XQMbE7#BDWtdYKUjtV#T3TJasMO=a8$)Ht&6_{Qc# zS*`2RcI`gP`EtMGJ9`bCBZ&w3ZEr2?3s3mCVgt|mWkLccU*6v<*!s;sw*Kq#UF%MZ zZ#Z>(#`}M(*Ztp7d*IcDt0y$)Oiv6IYjs-x_7(TqE7$!RpT3$HHp{P$eM5vPtJAmZ zWp|BlxwSv_J5o|4GtHtv$Be%_G}z;z*DrRt^@q5GJ%1%_u$$Ug_IN|Wv_QXyYk0U< z959JcZ#t)WVC6QAN0pq%rX1X)>=>)V^Q0>+;!LVJ-|ADFcbq=s94X1RT$ML0hT}>3 z^GiP6ZF8>Pxv{*lEwWoUV-Io=`C%yOZ z9(Gz6A-SY#-~TV%>p~MuD+3oEKDBAbm1@!3ZLA9O);4dl?d4NQjd11*YJK`*su>@* z!==M1&6}1d7Eh1~`^>hcDNZv_CafyuBlqsxA7(f>bbj1_I18xExZsr4iyn(T&;Pwz ze<16hZ#2I%L+2^04DN>Sck=&p>Fj>~eKSMK4)Gw*S58_x_!LSb?n-aaS$9)j2bjE< zB%Qo;NHO)LkCyB*^Mr#(GOuqiXyt0Xa^@Vb0_Sy0(P`Ir%f?NK`^L*1y?lm;c6r%U zXOUGK8g`p+dh_GTyCboOR|&XovKE+=d(_w>e~Bo^<6RT?30-_*x~96J^+-$mx-Wgs z%_YkY8->43)xDkWZNmC;i{Iq?j5;m~-wtfKS13?rzwd|p*2b3BpNgwpm-#1_DHr6+ zi9HIa?mc+9$Y|w;1zbMI`p<;Q+X|kQO-S9c;=jSne>!Y$${0>xQd0lkH{p7s}R}Wm8al8NgJh83T9L_3g|NiUEzLOJo!04z?Q`G5ghYtBH zTGx7$b&W>p#z?EI_(Mi!hFo(emo3TN#kE2!`5WWurxTB@33C7}Aj)78&qol`;+09x$S7ytkO literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/650.png b/crates/resvg/tests-hinted/tests/text/font-weight/650.png new file mode 100644 index 0000000000000000000000000000000000000000..29d739899c139009921b0a5ab24aac518ae61dc1 GIT binary patch literal 1216 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD_aue z7tG-B-+sTrhk*AA=PxXn|DfMLetrIig!=mv3IrMsG-?~pWME+a?djqeQgQ3eg@u9* z20RQ0mK-#2+Wmh)fkuq7_CNO@5m%3N$@o5*ZMwPfXKLz&3GAsSC#iBrZc3p$waYB! zZ%=P=cFM_JtL46(ZFTn(;96V}CNS51w>7`yhyVZ2ZEM>p*|Bli%V&nyCof+!<7*4I z{EUtHirH018Fwr?`G>vFVDJ4bi-YBRrr%G^J+|reEuUMdx#>4jbJc+CGrkMg%wJx{ za(~)1NWVhQVXm0%nCjfu)O{y-mG2ktzSQ z-i1=^v&7U)z$V6E+H;mT)Zgi|h>vt(1Orc-L|p!<&+GH}!4W z!ntkE(yJi zuSeX{Q|m5kW=|3c-Mw&S?+?dcucw%9YB?dqmlAVDySsN&75gNqvdHXBDRRmZdpA8w zi{zYnx3qta`(_uN{}+3%>S@p1FX(QRd`0{92H$Jq43@KBor?_L+%+fBbW>)?oCkX& zkN>)3$WXC5blTJpTMkXQoMCrcYEe++GoA~xOqrCfY^rfFelcO{ipRme$8SB1&%3C& zx_ou3M*O}PT9|csYw}t_j=p;?wqxagU}mMXDJX$8DPM@39?2=*(-O zk+xGm7VrD<;(m14oQg-c8`U>OU90W8dhVlJT8^zrzLvL#j>7FZzj(CgG1ln3NfkL^ z^v$Pn$*;?k7`#Qz`>awp%`8~TYmZFl;y$fxD7nybf@QSq{<|B`>i&Ip@z3es$MpVY z-QUN_z>>hgaY=B3?!VegA}I^+d++$W{n^DAC9ZDj)?7LfZt9CCUp)DO<@Ae`5+f_g zxjlYR5ggnNPz5i`bif*MD05Rk*u=^$rV{}nH?V-%8xlCdxA5KjgPH;J+1n@Q0U{6DM3dePPw%fYLJNH}4+#3Zh|GDofc|LY|)kDtq2Wna2={Bi?Y_ER=U(DQ}IFG#Hh0wJr)rYOG^L$`rReDEHqLn!Rf+> z=Hner9XGWD8GoMmb$}`O&M~>dO(!f4osgYp;bOOmCv1M%3AH?VMWaco8#q#*f6sGJ zcak_ciF;i|w(UBd$c}fV&I>qpo|G~)I<>^hS20h`EHdN4{55v(|FPd)v}VGpg~pTH zO^zryid^q=XKN2KGJd|iutn#HV4jGgb>udKHyPdMo%RH^yh#acU8?P?)@*RVZ(7gh z+qc`KIZrw*;kbEHC_?enB7x3-Q>H#BmR&M&zD{jK*mU<3zSAsqxMhT#L$7IiKWtNw zJf*~19_(}e^#p`;H5oIxVs2 zG)rwir#WN*@N;-0wP#^s=^*b4W+up*hM6J{?IFcptf&`rBhC;yP) zNX(2`*HQ(8-Y3l|br*cbuPzqR`XbsVfww)&y!G+RCD#OKu;{@+^2 z%*~Lbz|ru!V#h!3x}bwxENNadzNeg=qzX*wgP)2`dF!6&FSazrDYGt7@SLu-&WrV+ OQpMBN&t;ucLK6T`iPy#e literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/bold.png b/crates/resvg/tests-hinted/tests/text/font-weight/bold.png new file mode 100644 index 0000000000000000000000000000000000000000..03f5926ed495515daf4abde21559a5480faac1de GIT binary patch literal 1211 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`*?7)5S5Q;?|oBjBHJg zB5ViNtDZdNBzW)d`I$`(Us=A)wmg(FCsWGv;*=$6QZweSnIm;#edMMIs@~Id=uYuo z|9x-L*V5H{+ktlTP1*WNcazn;O}F&Eevho&m@IedT$6)DspmtZxIC4n)|&VKXVo7M zP54t?T)Zsp^7(=d5p0~tjh**%eYZcY<+y0!eTSM;ztT*OoV1$zlKrLY$z5e~^JnZ5 zKl=EaX`#}yJw9K{5*K>=o3u||dQWXl$K9l33J)_KKdwGMU+#WjLciAP&J!JN`vfLj zn6e>S)yk=FO?b$QOJ?6ZCVMUw6jH7|z+99P`R3p4Z8Lu4wg{-Kb`(9QmveW*$rg@D zOVxB(p5NeErsVSfCGSM#DQd6Vj`*gAO7Rt%7T$DP{GsvabBTQkeHz-&vVP3b43J9- zxe{{Suc2XbklE$w>5msE9g*ghS!fZt&dBDYSbR&xbB?1YA8}=`-_pu+Y?4K!*4ehx zU5%|GibXAtQcQ0so_r)Q^K)>Rn?}h7x5iCp%uid13U*CS-5)7dY4A4q+B%(H(Ll~A zN4eah4_;{MiYQh;DP6Om_T7ynmQz;xi5K;xBtNS7i}Cw!VRk>UJ)7l}RHgW@X&mxW zoniCVh;jba70lXo)#*uQbxI^x=MSgsS$b0h*_1+gFMeXO-Jnwx@nQOwxAD6i%jp*>B}P_~b9?;U)E7?%is0aG zKvGb}1=5N`A;_47gH5d5Vmc5q0?dxszycJB*pR>pCJzdM*aw?b!6d6Uhz)cRnHpdJ nf?D-8-+5K~nqJMy^yDi3L(O}>_)4=hfr=ncS3j3^P6?)5S5Q;?|oBjjRU@ zL>vxY511gj>HnOi!ZjQP=7+Y%wS~=9T(wy`;eVtpv&jjkX*!XcQclvDx~uj&`FvlQ z4C_LJzT$>;$+E|C-Pa!a{_p(G&fQNg$h?~ICbaQ>X!DWo`UOF^lX@?2+;}v}xbN)y zi_4E@ZM=5*d+tW7EfLFWw?{0O1kyXjUhnz3HaSw1H=(&p$9D6yf6ndO`;LmtP&yg2 zoYlJizt5zX=Z{QXzWlK4+b>NSz0wwh9{yXeNMl#g5TH-vtBUE%j}Z{cT$o)Wvl>hKrn5{5peK$gFr<=@Q!;4x&e+4$e_i`aQw> zbW`Qq18J+2rk#0kBr@^r+Wq%W9^z`d(R0ZEgSp&Yqkebc<7O$At2C!gukI^JTjq4G zc~uwdx6;lX4;(Ib@I-s-7*_2$Thd?4wsh6vwue-vX>IH8NTT$8MA>nj!h`$wbpV z9b3gDSF?Za68d)9x=U??<%#JlA1S1H^(8hWYa-PC$h_v;cC=N^JSn_J=T%>F>i-|JK1&;l$alBN zC%p{)qY&~_{n6S#5hnZkRQ00IDVZnvyoY+ot$YB6L~TVvpsU_dfe*xYL0Dng8#y0wx6>SH};MQxg>aZr5Jc z#DDKl4rlTG-1~F2XRe<2*gbuIynm11(jLDuk%$dFes1cEg>@EBzIgIQN{Nw` krcnG+M8wf4TSS7Z84diDHvUMzopr00VgoCIA2c literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/bolder-without-parent.png b/crates/resvg/tests-hinted/tests/text/font-weight/bolder-without-parent.png new file mode 100644 index 0000000000000000000000000000000000000000..03f5926ed495515daf4abde21559a5480faac1de GIT binary patch literal 1211 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%0Ai43=D@D1ahpx7+2OWR7qHn z!}DDz@Ba@DZ@1;`J$`QL5%**xmN7}saL>?3ZlTE5%D_Ffj7O`?q1CwGpAU04LgxtUaVw0uuH5)|hRjDOb5r?l#wDsA^ Y$Q8Ex++LTsL!e^A)78&qol`;+09Rhg1ONa4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/lighter-without-parent.png b/crates/resvg/tests-hinted/tests/text/font-weight/lighter-without-parent.png new file mode 100644 index 0000000000000000000000000000000000000000..8b375d903c0805959c6893d3d901c019026d0189 GIT binary patch literal 1135 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc$k6XFV_sS9FOiaG&Jlr9PK z3ub5#IIurqLj8mL`5Wf@uU`;wzTm?94+aYM{~efK)ZSxYVBX~E;uunK>&*p6Muz|i zHiHERtUrEz&nfiBe1mI*xsEGO>@}sLl&t|5)~zXFb(y9Uxhdu3FIx~fNtK&kRQHLh zh--T`=ZoK3%M>Wm_FcxNt*7+!zxR>(GkqdVu0Q>tyVB)nq4xF=kGC7UrYzMBs$Roe zpR?|MvMAgB19I8@M{Tdkc{}R#Zu}NetrIBa&A0s0#N?YEpUywq@a@VnrVBRK8*}VJ zvXVR>-?(;c#;r?pr^U1h=fy}c7zAf@iq0_?%wP0y$CXWb3dR>R;?h{tlYcFb&vLbY z6jdVDmCSlQ{r?A5JD$q^i|%JP?qZUhY_oEIU1K8a(TzRgDM!jrzu)F9$8Y0Qs8h&h zUe&hbd}d|QbJyH8C5OC@mP}53)KG4kp3!IeE#jhBgvh(S&ksn=N_ORo2o&J{`1H3- z_Cl*L*MnWk>*GxxMxIxtWP z{8iLuy=Rl9*faW%GL`RqvvCsds$Ajf*DSx8{_$Om6BO%2bp8Z}>qtoDNYpwcJm#>r z%F(8XX@Z=VCGYo_ti7{M_Ht=vfEf3s$xk0L>OVTXP$hTM)eT##WM0I@t3RJSEyBTM z-uxU{yG;@)pC(@^K5ZU%b+2`y+?mZ;Vl|UL{95(l%0Ai43=D@D1ahpx7+2OWR7qHn z!}DDz@Ba@DZ@1;`J$`QL5%**xmN7}saL>?3ZlTE5%D_Ffj7O`?q1CwGpAU04LgxtUaVw0uuH5)|hRjDOb5r?l#wDsA^ Y$Q8Ex++LTsL!e^A)78&qol`;+09Rhg1ONa4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/lighter.png b/crates/resvg/tests-hinted/tests/text/font-weight/lighter.png new file mode 100644 index 0000000000000000000000000000000000000000..03f5926ed495515daf4abde21559a5480faac1de GIT binary patch literal 1211 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 ZKSNZvYU-A!E7pKAf~TvW%Q~loCIB$>R!IN= literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/glyph-orientation-horizontal/simple-case.png b/crates/resvg/tests-hinted/tests/text/glyph-orientation-horizontal/simple-case.png new file mode 100644 index 0000000000000000000000000000000000000000..f86448cc39c0ab39db38ec9dfb61bb744dd3996a GIT binary patch literal 1205 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOLO6XFV_F+pQvBT%rRp#ezd z=H@~a#Ky)31O!0XR#sL(22eqLeLX}(OG`^xSsB8Xm6e4sgoTA63_d`wyHwf8qN5 z2e03M_*xKgMU8=hd9SC7V@SoVx3^lWR(pvw1S+iDz5QfsM(Y0m-1iLBw@j8PPy9Qd zFDO!ec1Gaan#5IIN?%$qgp2^QBQ~&b zi>=wq3|7Iqx*S3S715gUdc(g6=ZM>}M~-VH{LNYO>d&4Z<;OQvzO_`EmVY{5`tae7 zZo4}VW_$d9@!hoT>r>lDm|Uhw0K|QUAJqO^M0;dU3T^2)X;1bZ~vQBy`k>6H|@+; z+Inr(G(kgM<6Y0Et=q9d z+U?)R?>If zo`{c? z?zM+YoL5Wl$gC3_S@{mnN#O)_c^dyIB&V_VXy09ahpFr%c#3xusHhq{{BO06SvyDoM&po|B2h6 z{@;e*f7U0wtzA{=V)G`q{FlM}{Vqppit4vrFT3e<=Y8tjqpSY!x_Ys;`p;t<>nFd` z-hclR8^OMR`Rm!u_b0!f@{382=82E&^o@~qKu+ZZ=9c}MkPP#>;yL%F!b86fg@}ZH cY+dmdKI;Vst031dB^8f$< literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/glyph-orientation-vertical/simple-case.png b/crates/resvg/tests-hinted/tests/text/glyph-orientation-vertical/simple-case.png new file mode 100644 index 0000000000000000000000000000000000000000..8389c2b4596a42d5da8fd99a71e63c97f8a56bf1 GIT binary patch literal 1267 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`A!6XFV_i3EInd=QmfTwKh| z%O0tNxuKK1C{EO1o;Is zIQ+M7*l+N@;QWRB`xCDB&wu#!b!~A;-Oi3Vv*S0cU%#O~VZnnB2LcoX65^*j-f?DN zVE*Lk;uunK>+PM^Nslc=+#as3PvS7uTe1pJxlxamU| z7x%Le3CrTFSjQ`J8|H|*@ab$gz{IVyp>7?RI>6M8g(K80t4=|oXY2PK;5xUH;acdwg%@|mKQohxs9pS8i~pL(+DWsd*5qvEJ8S1VZIapC zq;7_=Wg8|eIXAzr_V@QmA&pZrbu+Kep1X10>$xiYVYfmq9a*&xuR@HvIa$|9WF8=d~NAiV>SdR?Aw-G+kX1;q4hFGCMJ2$y!m? zFx8c;+AkSOdcRslX*Nt1QQ0aU!GCpe(%QzUW|MarU)$)rZ~w;o*aM#p2UZ=H2xG{;krJ4`(dp>{uMJB=*;ePXgzhn zn}>onX67!GS`(JAbmw{PaAi+_ps2ox-OC$y-?Lro{WX_wYmD^0bKzaS*&Fh<<$c-7 zpRhOP$BG+18;?t^nVtXO-L>P3A91aTUOm-bUUa!>#Lbw+H=gX6X6qSb%&x6_M|<1a zw>R?3yFwY){7LY=z0SlDem?VKZJW zJ+LcBd4m^sSLx~3mj4$$NE2etws5)iw6E=)QDOHo^9@}adDbMYk&Jj6!M%a&^-Z4B zpC@GjljrPubP0l+XkKupIB2 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/kerning/0.png b/crates/resvg/tests-hinted/tests/text/kerning/0.png new file mode 100644 index 0000000000000000000000000000000000000000..60dc13a6743f31b86002be7934e2c9e174e2f1c9 GIT binary patch literal 2358 zcmd5;dpwhU8~=skJgZ{L-aMkRT~3 z3F?Q2hJvuLbpezE;FplFJ{}kdTwK<2vz{JEpO}~k$mDhQ#EJDO=zumKKfYF~K~oTT zJYZr1qT4TM6_(*v5CKw~2)F9$_MATtv{zec43KR@8=3heBFtt~J$m6+7j1R5GZQE`KU z0$6(hXx<)O2|2kK>5liXgE$RMO;b~ATRS&5Pd|Tu{~#*$+_`fRNlB@xOy$ z<>eI>jg5^>FPd6f+Pk`Xx_f$i``*463WrCAKaNj)5`CS9Ff%hdJ3Bu=|6^fsaq*{E zyaYk~YxTciWyM@?RT}`ARVNIZaPi$=y(LPA(TaAJ?FB8SPeP*VIVs2Uin5vAadeLs zcgxz1Q-r>dOQ!_ab)9p|&aj|pm|HurRaSmsmt+DB{hXYA6< z%*%1{=g&ziv-zp1H})1S#zg*8cR-ZNF2b_U+R*#$wNT&YV9}gvWKhp`oFP(qZ z{p>!I@Yf;sg0$8ww#blp*Yx^l=;S-V$zvhRE#i*cVn^=_iXI-tQ z*KhCx0cm+>;;L5OBShJGkxFKqZ|#jyQvANaR;&@~i0_&q*_&vd{lQJ<#4GiHi`dyEeS~;XU=@ocUcia#1RrbpN&~gsf+1scCzcb^kwhdnAdF3j@!aaW6GFZ-V|J0T7 zWfO8jm!Kn9MD7~)?Kr#W{7bql^*nFxOpRLX0yih|Ds{gx(Tav`4#aJq+lNy5qq%s-GkP@l>xYbIDz9-9_1gB!kuWX7PDIKh% z*U}0_as}{ua>?EO9btuOgg!%&g>cClF?mp%g)D5z>d$T6&ge=@h1cFeGax02qu6_&#Cbj$(C;@o@jGg+bV%CB z{qEpx+)?YoDgz=c-w2H)>UJ^x4_%PnH_0xce6>LuUj-555?_U23Nt!?Z*~l6I70hW zJwEi&aJy`$k4v9S>ya!eLpB+;xwP7ntMcG>)+2qQZT$6J^JleFbSf|i#8`Ll_IO0A zRf%i(ZSSQ1QTTj5tL?(e0#XGoDy`V5Fcs0Py$s7S_&pr`SGr|oET5#)bn?N4r9l1IZBu&2uj9!6 zbC12%2l(%V`V!qQ$H{DNDGWDvlFj7_FiB>^duUcyHXwCF^;X0)cM-s!J4w*P5gWhuIDf3x zgUDA#ls0dAs9`VwO)Zc{I!9HapqVp)Qqxo$k)8D9OG!c(O{1=utKPh7&aZ zLurd{)Dv7-;H={5v$XkT&P}7`+5F}>PVjg>Yp|CyS+4S6G~ly1GtWL$<6kp2Kj7ZF zT!Giu&eEawcM92kb3fkFk4ITVMtKfxt}S}L+IZ{G-3>tIvgSoW_4ftpBPZ3JNOq2? z)BqPCj7Sy!FD`F{|Gy=<>#o+ltvi%n^BFG>*^MLAC^(-MU`|JD2$U+$=D9lsNNxsB M4tUJN!~U252EVN(kN^Mx literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/kerning/10percent.png b/crates/resvg/tests-hinted/tests/text/kerning/10percent.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb6f2dac265f75a642368b20cab65b7408ad7bb GIT binary patch literal 1454 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 AL;wH) literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/path-with-ClosePath.png b/crates/resvg/tests-hinted/tests/text/textPath/path-with-ClosePath.png new file mode 100644 index 0000000000000000000000000000000000000000..0af37467ad37fa2e2f097ce5e6eedf82afae2de1 GIT binary patch literal 4848 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 NF}h&}FNI;E{tKk%&M^Q0 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths-and-startOffset.png b/crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths-and-startOffset.png new file mode 100644 index 0000000000000000000000000000000000000000..f79188722a087335acec4ea268b2fecb86f00224 GIT binary patch literal 1676 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhkEZC&U#3)8G%*@PgZf<&ddc3^6;^N}$?Ce055fKpq0RavU4i**`1_lN|#erwf zEdx>(B|(0{4h#Yc3I+!DUI78|2?_ZH^$qR)6DG`Guyp-~%{%uWIDh`ah0FIJJbwQ2 z)%*7!fZ)^DFW-Lt{PU;2p{yFaIlG$TWpOn8@HHF#0C~HnZOBR zCma+4lTE51b`z^NnB<-Y(V+v@rxO9vO@zi>&-#-#9NTrgKWM|Z>&Ep{n!Z-N|G8LT z%}%#}8Z6msX4-Qd{Ix0gJ_`dggFwrl-RFL=>B(~Q>`_{i$hrE6(6tRMp-G(C5r?!k zwwUT9PK`JuHEn~JP9m>&gzB^nZK`X8ydw?^g>|aZQ290G4WHck%FeA=K3A!0vGwJj z{=TJ|;g`ZLm`UH@N^90$B^6S4|9|pJ-f3|;H8#F^k7^Zd=00nwHacu}dmGP-Pn&-9 zg=8LXPKc~=zczbLklYego-K#*_$c+D?8|AIQ>}l7 z#)vQ-Io)JkR2;K!Yy8o~KbIUPrZUP#&f|NRCu;ptotbqSYsnIizc0n3UDswsdhWM9 zn{=9~X{!3l9o38aJ|``>u&JT>eAp)2FRL>?w>KU-`Dp+7m3BK%-uC?U?WV)VR7Ljr zhi`7(u#%%=`qBGWtTN9wS4389$mufqpb#e}rBmO#&Zc9!E8FTiyZPte?z!icEp+7c zq2{UVd(YnRmMSyTo}JGl5+zokdZqr%>PDv1Ojbd=*4_SZTmI|%pQ`zbPCHp&IyLXj zlVzE=-aTxOEQx$`P~AW1889UNJb3)B9b~jj&8eEWJ8vUjDFVZSFKqMVCI7T!(k6rtrzoO&b};H#?UdnmHl*#?{81D)!%JpWHeUjEKpv%%l3$H^M+x3^83YkPlr$EJn^OJg8M>J$Aho3};BF2bxgXIag!uj0%{Cmm%!T|YnZ zW!RUa4vr}w55DsLwAnOzcb0UOsaL&}Mh8&wr5zsW_0dx0*1tb)ZfpV?ZaQ<)>nF=C zUs&9i*60B$m|L=~>+bAzhp)47sdU>XnqK~?wQSd$TUiStHvJF|yElLRBKFovN9S+2 zqs62UBPPG*k$=STP!)$AK&@&gY8m!-$%zDs-51>7r2&lI@+0e&xE}!%1qG_ zy`duVBNQo5&u!R=^wwC!fWn*%5oynVZWy6namGLiLBr1eB6Yg!9n1F z-u?}H>vyVXSbPg}nyBhMO($~G1lm#iPEOj|erTVL*U6SkF(Plwr5ZMStppYIp00i_ I>zopr09!}YkN^Mx literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths.png b/crates/resvg/tests-hinted/tests/text/textPath/path-with-subpaths.png new file mode 100644 index 0000000000000000000000000000000000000000..89480805c5d61fad6c9533863ab1d5e518854d58 GIT binary patch literal 3349 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 JvIF$EzXMmc@819b literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/side=right.png b/crates/resvg/tests-hinted/tests/text/textPath/side=right.png new file mode 100644 index 0000000000000000000000000000000000000000..d84bbeb00e1ff6160d25ffc78b02f37217e3d869 GIT binary patch literal 3475 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/startOffset=5mm.png b/crates/resvg/tests-hinted/tests/text/textPath/startOffset=5mm.png new file mode 100644 index 0000000000000000000000000000000000000000..81fe398f3294facc6c1fa8c5373952b7fa943dc2 GIT binary patch literal 3395 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/startOffset=9999.png b/crates/resvg/tests-hinted/tests/text/textPath/startOffset=9999.png new file mode 100644 index 0000000000000000000000000000000000000000..746d45cd7241a6e950316859716452a033cc8d6d GIT binary patch literal 1796 zcmc(gZ8Xz+9Kc6hvNMWE9&Zw9a2t6}B z7z~C8*tH`R2Gej{e7af-qzmsq4}*Ot2-x8pp7BoBFT)H)nV$Xq+GWEHjruopZ!MF- zJpP~{K%I9Q__LOvPKO4b7qj(;whTFhioN=ik1}okIX=&}uh38PdIE9FmWw6mvV=lu zyeW$MdX31d)YLyHZXPbOEgVhOr11;^O}JzBdX|<6pcx1*cVuZTvIQCl1}uED*Dua! z{{#F>Wl4gy=otw1nlCvnYO!n=O*<{gbHr%Jf}M3Q?I?cq)8_ethywyS(F(0kn}6eg zWzX79t&}I#HOuRxxib@LQY}!_%gsmxY{%uWgFhr z6D9iOYi zSZ40WiO|q0c_m5gtJWRt3gtdW>tba(vbFut1<|&)T`J>JkM%hiPo|%A|8b+~EGoe| zKhFvYJgJ^ZlskOhMs=f7^AfXB(O62S=8;#>ChBYt%!!rP%5aGSg)c{YDC=h_iP`5c z>mKtMr*=*Dr2itcuf*Z((^wm=FHa8acUH#iNv`88$MSPsaKn_5-3_*iI_NuSw~mc- zIb4}ce#49+(DfS`c+)MZDecV4~Z_3KT zdQa22v5liXPEeHISRvNl*&7rd0-l@!Hex}-4HK;8S)q3nNu4MgXsYRWNBGbV1s%%A zpuw2=jROyW$E4s@WOstt8IeP{S5%=gI2QG_BE?NSyRP3@x(brc4HZsK`XS}Dd{?KQ zELBdqFK>56Gu55{hyc-23k>AP#vLK41Tl)s(m!

#A4eofeMWS=wXps$TD>YNH|oW)Mt}2(HLe3t}cR!osO+a#)>8 z<$XCfU!mO%se9M?^EDaSyfzf8}lk&}{C_IXUy9r-ZdlIPo0bMyMk zz67NQe-oB3CC>GildM)(19yww5^0%fqsztyd3Gz=dpGw4$CtX&_(R?2#bRb{yS%T( zA| zZPyhmM2_a>3)e*nryYFjX%|U5Y}9n0_~9E&BhPgwyt=Y{;kv;BcJAF#wH?g)6RvMh AL;wH) literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/tspan-with-absolute-position.png b/crates/resvg/tests-hinted/tests/text/textPath/tspan-with-absolute-position.png new file mode 100644 index 0000000000000000000000000000000000000000..4c372caf07f1eb25a0f97c3e94e2397882a52937 GIT binary patch literal 4408 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/tspan-with-relative-position.png b/crates/resvg/tests-hinted/tests/text/textPath/tspan-with-relative-position.png new file mode 100644 index 0000000000000000000000000000000000000000..f0fa1c5072d0b7084a7c09a4ded928f9dbc4c19b GIT binary patch literal 3795 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/two-paths.png b/crates/resvg/tests-hinted/tests/text/textPath/two-paths.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff22ea102eb39afa3ef60d90fbd203157ce98f1 GIT binary patch literal 3598 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 Pp9yPod$Vd2pPT;xw$77P literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/very-long-text.png b/crates/resvg/tests-hinted/tests/text/textPath/very-long-text.png new file mode 100644 index 0000000000000000000000000000000000000000..09a576cf409fcf30dd7ec7481844782e50acc99e GIT binary patch literal 2806 zcmc&$dpy%^8{f>KWD;3Yp^+R$E9Q{XXwIiGqfPb<8&cSwFp?}!c|->}jHF1V2xCl7 zax7}jr!0~~A(7gO5z^jOpU?a8dH;F;d*ADG|E~M`ey{I+U%%_0`@S!t-R!~A%F+M; z0PN_1@&o{Yu%F*1kce@+bJku2($Ownwj%i7jSisyvY$%&FZUa7@aN8*+kpNvL?V%D zYHAxbF)=YBh(@D*e0<<=xW2x=XpM*=5D21_yu7@IhK9Pjx`=deZ~y{7KD7kNQICu6n>$8 zonCtOWnktZ&v(5--)e1AxSZTE{%)oJ=*+7#LZ{B`CF;_GySo+hYR?3vH==;ZuTbNm zua5tb&DCktDFz7GUY^}zRPTYr7blYh}my>rV+$=RjM$%`yfvU`FROpo0s5OUwwPP-l z>i+1+US&FpY94v5Kv+|%t8qz-w3U)o_e$b*VQISJA*o(&cLgTZz-bha{UuIM(H`3a zeIb!6Zv-&bv1}{wFJ-1@DTQVf;45#K_F_?>Se{QCYt1_rrw_k0Y1EtcKytoMk8VWHE5vmUj(NWUmB8CEPAmypoel>$9pC5&snkI$a9iNui*<5px zGm;tl{Z&R|d?Ei;e4*`jX8(yN$!dViSmZkYf-eFG}^M+ z2w@4dOD#3+$JfSSH=C!9S0BOB8zOXNc^JXHZpV6x9jo>SD0u{|{QwwpSUa%O6uq0U zH|IlhR`^ciBpDST2FE~7?+7@o=o19$)HtYW2H=08w`+C8?a4tWNy_Di1HslY zoa_GY6quQ;kc$25dF7=zam>sS?}5B!X1vpM=Cq#_-jhKs0d;UnFU}pmKa=Ictn`dkbxA#ro^1$oMgMmlU`f;z7P3Ny>(+F7n*dKu!xVAa^S&}R$@er@?7>mDqrs@2$Wrr z3LVB#gkr0)H(#A#sc)Vvr}?`Ba}a$Mruwc0z(@ysIvXC-Lo4oNg;16)?z#jfQ_+*L zk;itciBsU)CaXZlo;XZ1Y(K86=4n2ib+LV{``q$uW2UPV27X0LZp`mKtK;kGk=T7; zXG@iCN1GGemUrkIE*vw$EV-|w(auGDsCDb^mu71(Wc8f)*Cegfl4x1&2U5A;??q}@ z_lbee8zF^?QE>h94C@jgpgE>x_`@$S5B~_L&x2%){&+ip_!k`}ZizELG z&dF3giA1SpvbwSR>!&yvmGFE&tSw|@b?zY4^_@e6CN{NQ!7NvTb+IZ% zXh_oB1^%n9#opOYvVIurVS5{NIdxY~Ah*ByZtK&{Rjon~Mo?j^&i#ObvT8hj>Cv&0 zLfBXDTXmN;QoZI{V2j(Pv=nw|N9;~5R%%5e$H)n-cXZkV!Ue01Er*u_F-hhhiCyI4 zXKx=2r1Wn|9}+Lz%y(;~r9NP>IHUXn9_^@aeJqM0KllM%y4ig6gJ%|*imM;(8i54_ zA+*%bYgAvx=Z$+vkNT;X`~$;(TFI`{VCAwDOzz15jC^yI6A~EXaVL1w*pdd=T=}Hb1w!w8Yu#I4=F3YU(w@G3}Sr z+(&ng4K2RPPVT-2W8HeY)-^JE$5*S09a=V2(Zi0;zEG0Vk^X_ljZauh%wD~CDs>jm z)~*GIZr?WPH?*`az!sj`pE^r;!(YGoaNgdIkx}Mi|2OKi$(8i##@flXT|1tjW-yS+ z@~{;v5HmKCREGa+V%Xg*KH)^yzV~n11H664Vpdzm-#lKo_Ae_r(z(L#^GgW4aDV(1 zuCssQEkh`EV_fWj{{CaN--la_*~)I|5ZChaiiOh&;(Lz=e@IUf1zPT%YNKb^+Zf7cVp_8RN9l;+As Z0fPM(uNkTJxWu8RB3H$wFIR# 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 H4l?#XPR>ZT literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift.png b/crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift.png new file mode 100644 index 0000000000000000000000000000000000000000..b962afde2e6ac7907a7d0e63bbd1a921d01e3f23 GIT binary patch literal 4376 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 N^t27M$~EjG{snL%8@B)e literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-big-letter-spacing.png b/crates/resvg/tests-hinted/tests/text/textPath/with-big-letter-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..9a11738000203ffa4254c3dda9c7259228897532 GIT binary patch literal 2097 zcmcgtc{JPU8cqg(%&qx=?p#n{;RtD>l=$WQF-?66qu;W`2W z0%~e%LPA2iy1EbuL|Iu`SXh{UATlzNOeO~f1rdovJRWahVZpzyJ+vLc2i!F$2WJbA zv@{Z_r)O?%;pm9R172Q4;-%0~GMPf5Qj?QYQu6Z)3Ye9ZELKBXTN|4_FfcGU_)NJw9(_UlbU@h1O{wi)Q}0MqLMir46Ozh!wMFkad?UACac9XODVcs$fl zw7s2EZa>AfpBgP%n9eicyfrPf4^T?v7))}Xzl&Nj&fB~tQa+8Eak*y%zdhz(d3{X- zRD+nh0gZ2pPoIXW)frNcS77(uBU<4$bDB<@7qt`T=DSz^ctkna`YSPn2YRg3Q3@VA zJtZ#y>})QLv=57hXKS3Z@Iv2BYxc`KWroKdW4$@X?B1U!^8_zaV7A7gPv)qtRmfHd zDY!;50?ZRw`;h!%OEfxncO@+<=eFuYE$gB_3fQ#iPMsNyW4K%Vvu?NyY4^!BkLJjY z&%{8MQ$baWLiC&_p&XUDLXDvpc&=A7ZV2*(j_eMsl?*Ii%fy(|^FL??et55hfmX4b zPI9kCI;LORMJ@G_aouzUBhN>n%as-N1b_G8@n@EudSY3e9=b1*KB*TK4%P8V^of2J$L z(+b>NE4k;s&U&7knr`qxtkcOe>~S*q zQ$1@W3@d5mroCG%*HCWe4k(bq^!7huXQ2&*62}adibGE?jCR^Gp|uM-of}VMB#LI| zT`s8@19nDPFj~(L&7}3I+uNcGKRY4o5*V2n%w$l>3}lfQ_I79I3e(&xmB=;jt(4?tNoK3XmPA(q&O9h?ia;)cC-nSeY{iT zH;CDU9mT9vaUf@MK60EyysW^LFr_{90*U{?k_()_J>C|3#|0g(cQQX_=Q#819>C2N zdiZ67$Hj&*vPYs_HZ>Az-^ot^tP~ce=nS4YyDcYYb81RU?nVGwZ8PaMTL3 z>LBQ=ndl8lU6NsTT2_&46OiZ&bMAPlJt`xjR&+O+=~HJ5BaGK48usGwJB49Pxg`90 zSG!zIsj|3X?^uL0+seiFK6w0JwIzLMpZ;)|%jrr4DONvP-NBk5>Uuw6z{gTCwOECw z&3T{HmX@Q`>c*6|)`=`#d4a0~lvzh49Ub$RSNAq!qRw<^uLoDrygPzTPMMoc%}6a3 z4c(15M7SiS&kcJ*^ILG%fT%0&HSXlQkBFmNM(W;OOzp1cdJ#?oq{2&-Q%#&iYe2@z z#V2}Kz-y!V#QwWSR?K8pMcc=0`ILp541f)MHsrqORn1TZTHlB_L(q=W8T%UCjbOht z%t}@w(|{=!AhNgdN;Lz*+muYz!64x{(2X@`XfvfGLA&vp8cgN;bNhQU{r~In jxJ)z1wtu>{I%+|nRBZ?}t4H$Ue}W*Kr31F&EHUms^R%w4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-text.png b/crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-text.png new file mode 100644 index 0000000000000000000000000000000000000000..d9e1cac8f162e10517ffc0ce676927ef72ce7b1f GIT binary patch literal 3348 zcmcguXIPV45>9B+B9Sg!imMbMQ9znK0|Ej7 zM@vh~!ouP&1lSD>3|w4XLPJ9VUtC-qi9`ws3H^niKYt#J#d>*pX=-YUii!#f3Ia-P zZEXky5)>4qr>7?%ARr+j;q2_p%gf8h$0sHx253+yl#`Q_xw-kNQ>Wl?xVN`A3kwU7 z2PnbH$|@@>Yi4E!_)sWRO-&7;goTBH&l)z{Z& zW@ZM`0zCkAfy@X5LP0?RXwuZw6u1Q>1e8D$0}i$a61NL#7Z?i+#sDUt!C)jD z3?9`Sew#En`nh`;-C0z%eMl$GZU>ET(pL=+w&@#t4C(>>U}v>2y7vd;h`zhcINYbx z_S!3Gos1*w&IEmP;T?lcFEnS+G0y3=QFQ?irZ;9>-r+PET2(D)86XhnOT%m0*F(p@ z4=D=hfVo-fLS|j}UVglg7C&Lf%aM14|J-NUKlj)o^js#%A_;~hc=YXy{@Qi$e+K{K zqpCe~G^}qW(t|cdKpnXEPKCI$K2t~|xsGt0Z{zd3%(c1LgH@vNqwclqeM0bgE3M{W z!1c_n{lXWf>||7Aw+U(#L!^~m>jh#&<5yyeQ5cVA{xUzPe1W)c`L<3Dhh{6UNtU{_ zqhG}tP$WCYelMqcMf~w`)>ZXkT5NKC-WP>=o|Ic%Gq&%RE00XDb6ve81{b<-`&y=AQPen?bLP}fqMW!( z=jez=dm??8OV?6aG&D4OV;Q8gOXfcPinyHzXu7Z`lafuw+yo zb-b)J2gaOq2j2|85n-UZW7pO!9d0`2FN=(4_MT74g4;j$NY1jl_8Ps=DB?G^^@XIA zO(D{tKIqJi?59(rCExf^gjrrA%R>P+2MyHWqY#bVBwqv&p6)R%JL>)w%PEYt#u9lXR z!aPZm1C@*i;=U)M$L)p=x-;KgCA+2Eu9|TTv^OJRy%V&Q3x&6M0}kDj6PKj@ zj%L$QGO1(x-HP%UPA0qG-_;^O_I$>GXoxv`p=?KbV< ztN4pvF@aMNBhPu4NPdMLXKiO2*m~v>ZcU@bR!grOB0Uf|1{buGtFCK!BxfomrT*=l)R5CcX()&OkHU%uZ?R)KJ^5i>x@4 zuiD_sa~sayAs9;yXFnDvWaZ1pDNNcV8kLd*Z$Bvg0{gPJH6m?wx558KRdrUIVX}44 zpuL}5UI?kZnn0|&{)E3qn0>~Vpe;pyFa^(+GO?*hg_ffn&b+CJK>)XW2=|g`(E=c0 z&JYf&7Hj39_oNl_jC2)GK^?<_TyWZV2;Bt)& zDf2#|Q%Wy)vrm8iSgO~zFoH1}q~mGp0iieAzXXV>I+~(CRwURIXh(JZeKpx!TO4rEJz~9Wp;Z&aT0g!-;Ps*!SjEl-hie4cE>=MbFeja9Mwqh8hd|1yPzs5YUaTJVb|U&)tWySUQb!`E0u>Q ztZGb8o^D55dikjNUqGJG`Rw~U_T-phT#qq!py`ciD=9EvgM?;<@&8Dr7w>5dxWj&r zeMJs_m7_aBczf8FkxP-DiQTn;I}Hsv3(|5%c}_r+Xp9dL?Vg*a!(T@wj?gXbQlGvN zKb>UcfwD=K{3@}#tp39&$_gotT*>wElBTB2@h){P5VsY<%e8`Ef9D0MIE;kyBXN!i zMv7=Dsyix9Kn-4cB!klhu%)kH{+0DN(`y%b5DO!$=p^hhZG})<5A0}>56im-aDHz} z+prU5CAFeB;*^{%`HbNdpIZTsbr0?XM!naavl)U}A}Z zua8M(wIDWxq&IJd}u$fZf`?cmHK1lgf4f)rfB~tvF{(fIgF^=RcyF8 z6Ev(B$CS~0=-L_MZM(}daSG=?{me8=*Z*J!lFjWe4d;d?GM%Ww5Orlb>WGm&6rtS<#P$VZ8|lWaCede z>F{Y&4__!ZQO{e%UJg5|yAKWRzwY-MMhwyKFFdFbs8F(gFZUDWI=JXN9LX9wG$!2| zMBu;Q{x~ZUlK`@))oI~1PLWULPv@EUednCCUIvRN@66ZUy?@f$QnrSm@}g|Nv1FRz zWfYu6#A^l7?=n!VKTU<3=Eyt0b=aQKiest_$b7 zy}_AllrUiKdnm>AYyA8F9k0^=95f$}s%bH*pg}iuMwn@ut1XB~g*U%OZ9`qNYc)D9 GG5-W!YBGBO literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-textPath.png b/crates/resvg/tests-hinted/tests/text/textPath/with-coordinates-on-textPath.png new file mode 100644 index 0000000000000000000000000000000000000000..fefb64c889a79a22a3522668277117f9f4e0bedf GIT binary patch literal 3435 zcmcguXHZky7EUArf|N@QNR<*w=tTiFp@bHilwd$0Afd{o-ylt*BFzf|AzZ3}6hWF1 z8=~ZfqJo0bi%1itO1T1(kmQ~FoOv_v&;9q_nmK!|_3dxI^_@L)&g={)2P-}vNgfag z#Ajn|;S2(S;eS8e901~QH`xkk3Y_d*Q9%0-K_n7y+_;hQ-vNL>fuF_C_3G8D|6%<^ za5x+iiHwVj1MmwME(8Sy0R;>O16Bfo0C3KoI~N!j=;Y)CaDcG3w&v#M78Dc|6BCPw zh>(+$)6vmUQ&ZE{)&^QGE-o1v88b7p=;&x^X=wmaS62s^z!W__JwW#K>C*xN0zN)I z-rnAT8c^Wzcq=O_fZ*up2!%oo4Gn?0z(hbWJUrag)Kp7L3y{^+)a2vi1005hg<-K+ zfX~Uvi9jF}6chm2Q>RV=BI4rW7z_q*c;v_tz%YP-!C=5G@KS&>utSmM>q} zY<3BoeUsTd6TZL0X6&)qtRXh*-8!4~jNx0g$JnMHZqivy)?Zsc<_})fu*3FPr_GAOhK@bHZc*~ zAP^7B#=_J!ZfgB~~li^s3 zzn9~`(;Kt@K{`qCXU0!z-BrYzLNg`Lx9yv_4L4NvNsTjC4e+3uKehMK$9(F3)y$Ax zLtH5OEfB`kK_DLZ@w0GCx=88m*5ICNswc>aj${0)5CI1fM=kNEV0x7vTKQUI_d|)p z)TS`n{E-wb3C!YCeM=8@sV`Rzf?rF3J~HmRURc0=s}>TNh+J97Urp*CuQ>WHPN{y-*Jq%8@lWu2V4m4a-Pz6DinF0p zCApT%eZmg9$nOLc{9A5{W;pp8#QEV{I9kOqIEInXXMy|2~y z$nu2r@6>IXn@_HT-q7IVyL-A4TRCM9=dwjYX%X`?ufu|J0u!0hz}L7R?qylkg!E3{ z=NBJRb!btl4CMcQ&Z<{wu>Pe8YTIK?F*MRv73InM>7a9Z^>B_cJN;ZqW|3fAHijU& zlMa6vyNy|kscU2#TlQ@xC%ABbNV#lQ$*r@zP}wK z5E48Kn}x&g!;CkI-`G}7a;4wuBD`cKhFiP)sl<-jU?5Ugkx6Y9ttj^ZbwQ05OUejM z?+f0o*?gQDS<~G9y2>a;rE(uP$6LSZaXM*UU{xNCFto3h8WJk0T04I%&g%h|1KXz~ zCZ*y^{Un&Amhp0;Rb8teavVKAVg#~_^*he2u&>eKKJ=}@ZyU%@I-%6c7T43W&6O5n zEc)vyaHVUNA~K@cDqY`>725WSo_$WE_~E=S%SSZWxF-+R4n0VC>E(r$=V42Xf&||= zyL+W!QigXo0B2BD*wXWb$7*o2#y|@W^y6(7e-pRK)<$MuF^5Y{kfXO~r*&Jrr)d78 zGyVd(hb!_aA6CQM?8$JAd#RX(Q^{N5pfLb&AP0a>fBu#%Juw2QZL{?};UJ37EuYdg z$Wx?#wO}N&<6_%TogtJznwBkKRpy}Q%*35vKk%$%nWC)pFIC&wgW@KZnB%LwgpIpYOMOi8# z7itJjA}3Tv$ztH%GrtD32V~JGOYO%AkLW{c=gC6gn*}*b zu4);|?@2>ntab7mTRkW!uSe>Z{e(UeUIT*_eulyDOf4ALHusB`9~N1f*THVUKI-BP zh`l|6(PlLjJ5wKMcH^^5F&mMU?TkXqF$#^>Jo7vzxF?0ib}VWxkvSXbA6%fS9>6HW z*ig&>e|Mf*ITFd6URGqQYEgd!Rha61w^Dfz`qiY^L4|mFO{@{NdCOrU&7XD@T(PES z?A-gF%o^TbuAlp0;D2Rd4c93XZOVt#s*(MjjG=oH-FvK6_LY)H)jP5b(Y8jdinWx( z;Ctopue^z@rb3fhym)62Mg?A%M|qt@Ws)@3*0+}7Z&L_H8miohZ7Bp_m4l~Kd227l7~45E~aW;G52)C4*2-@=2@WB9At?} z5t^p2v-ESr2VX^3m)d=p)iWb;0%s>u1^;kNxGxsP zo*>k>Q%XNc%NaYjb#Wu%UcZla^9;*+9h5}~rytyiN zuef2wLOSkIFKfKR>Qp{cs!f8T2yNzWg-ehV;wzwsW~jF-&fNz!v88>!w;py96e85L zvN#XQZ6NwtsZk-)Qrorz2W^54ZS1A*^m2W36*%3Ll&-$9S$$~n0 zE1WP;t*1T*L@#0N5av8)mH)3Z(oL#`@5y1Rfv~i|zNo+kD6;x5uDniCbBH{8ihgB2 zaU6U@J|!Y@S{D|tulw%0Lf?A+aqdr82 z)Ez$FhDvm#rx#B?W>|QPq+9C|$2X^4WwAqJvnei1G|@(h&<>$$XywIJs)|XuBu2Lc zxBV(EFhqU{S$pdxz1V&?54FcUl@e@bk@-=m_&o$FzF_**w&8A3X2_Zx3g;=T`;`amgBXL|-nq&WCuDN7x3JvJY;$9u;r zyE34s`mb8#^B>6&sBL7oM~5hB*=C2lJn3qM{oM9jC*+ElYLW2u91$~b{CZl9T4;t9 zsw8zhJX8g(d;AaqqthH8LKVvO`thoPRxqxB?spFcT$K$V=2cUDCmAP2eftiV4|{cb zb-RN=%IJ`LE%2hu+fBvWA|6=+2=fS9K%??hRCX;aUou29i<3AJlL;Oi`7A&O>${-y zpZ*}-nLeDY<>quv!0IAj5z5S{(U7+n=AmZ}<0Savb}{{x#r=NmES`IB1>&YBs|7xm z#dba<3@S7{f;%vtE#!Kyi@+b#A9wSK(I3fBg7yrP$DXfgv^WL4Xz-Al&}xg4EBlfN0{X;pkVQJa+AP7zlIKx2j(pRzdZsn$^Q?xhnZ*t@Fb~z~iZ}OCQf$QY|J<+|# iO5tzIdYl`&oPCrubak#>o-+9R`fh`AuxK{JUHcaUUqd1Q literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-filter.png b/crates/resvg/tests-hinted/tests/text/textPath/with-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff22ea102eb39afa3ef60d90fbd203157ce98f1 GIT binary patch literal 3598 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 Pp9yPod$Vd2pPT;xw$77P literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-invalid-path-and-xlink-href.png b/crates/resvg/tests-hinted/tests/text/textPath/with-invalid-path-and-xlink-href.png new file mode 100644 index 0000000000000000000000000000000000000000..8052da3aedea50e3157f4f75119f842204be91c9 GIT binary patch literal 1602 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!uv<+MYX>2d~C7$e|sqF%Sf%mr&1z}bR?(InOyT;{qUs3lN(fMM0Wo8 zd2P*X(|DQpmnYR3y?va$zpiHfdGkeye>IDf&YP;2JS>^7YrnO&=B;Y|e(m4#os!qi zuc&<9{aJaEG<#UcL;XcbM;oPI+NJNCRere0duq;(NiQrIL=FEqyJ$UdaDQ~F?UU+Z zA=k|{GGF+vJnURyS#Uq@?4(DnhlEUzAJ1OFYWSt$#G{W=Z#@1oC3e1&yV@K2|8`50 z==SQEsfl}?Lb^ZnMm*W^OnjQg52cG6xtJ4N-5+%)^(9J*9x)J50?G(XTaoF>>^4>K z=A?|3>hjZWOxO|7lTjV#k)tLvO~Z2Xjkbx2-j94NPi{EUG_5adN&EA@X-AJ75}Ih+ zDO`AD|6$=y{YNQ>gjBh3RmpM+a(L2H^yG7qp_ps6G zjmuIa(xwJpdb)+@^cpsg>du8vL8_}$Msfg3~Q0uge2p)rxSZPF3F zGXm^FOA~pUPE3_9TvoqLI($(gFM~%&;<6PU2@!|)NZYhZK6ddoS(DH9Gql6{^oDu6 z)|VwdyKzy7_x0}Yp@M0BO)PCs_eoWyOHTW}s(o&1g#VAz_gdeumW3GxM2I|W-EjK% zskvYM4}CiDVBe|i$I^#BUAPd)@>PDCe%kM(h>3l7Prq3$@hdf=F5w5zpmRz8&;CBO z!AA48_~EV+nZrGWG70gL)5Q0EJ+k4`(>0ro&!nDcn;JOjM!RH^{R3@}!?V7=4Onf! zaQKwP#dB}j&Kbts%>x=*JVWrDa)o(Dgq_M_^|q(UwZ9T0ep>F?Tv1xenVcA5Yg1Oh zz-;sH;s!Ra(`$INmxs={8Z3FuUv64fSevOsR9b4pXa8)W{%dAy=3JX<a(~pp-{>x6oiu~x@TrIk7lYab7cE zidkX`D1o$O8m*~m`sE|&*3|TQioc0;n47PAk~0sp@+QTLf$f~eYkHbwJGVs&w|B3K zyv+Bt=|jJKA|<>(3w8R@m*BWD(eUP%`X)p|0ky`;*SzTJcOi z%&oRxyD-nL!*=hYUk`kCxresj1Q{qQF4S53S#I8n%5;CF!bDfWFHVW6Q*w4r%(!X( z`n-A4kM@rF`DbU@>UK&;pIRW!tGzhw`;E9x?cZrXe~SHE^#9qGl=D-++z7IMrEvI{ zrq+W4y;GE}@10hZ?`tN&wXY%_7~-pJno QtQ#0SUHx3vIVCg!0F$x1@&Et; literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-letter-spacing.png b/crates/resvg/tests-hinted/tests/text/textPath/with-letter-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..5c27cf97a8cc74ca51378f12551a1e84ff76bb9d GIT binary patch literal 3031 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 QtQ#0SUHx3vIVCg!0F$x1@&Et; literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-path.png b/crates/resvg/tests-hinted/tests/text/textPath/with-path.png new file mode 100644 index 0000000000000000000000000000000000000000..8052da3aedea50e3157f4f75119f842204be91c9 GIT binary patch literal 1602 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!uv<+MYX>2d~C7$e|sqF%Sf%mr&1z}bR?(InOyT;{qUs3lN(fMM0Wo8 zd2P*X(|DQpmnYR3y?va$zpiHfdGkeye>IDf&YP;2JS>^7YrnO&=B;Y|e(m4#os!qi zuc&<9{aJaEG<#UcL;XcbM;oPI+NJNCRere0duq;(NiQrIL=FEqyJ$UdaDQ~F?UU+Z zA=k|{GGF+vJnURyS#Uq@?4(DnhlEUzAJ1OFYWSt$#G{W=Z#@1oC3e1&yV@K2|8`50 z==SQEsfl}?Lb^ZnMm*W^OnjQg52cG6xtJ4N-5+%)^(9J*9x)J50?G(XTaoF>>^4>K z=A?|3>hjZWOxO|7lTjV#k)tLvO~Z2Xjkbx2-j94NPi{EUG_5adN&EA@X-AJ75}Ih+ zDO`AD|6$=y{YNQ>gjBh3RmpM+a(L2H^yG7qp_ps6G zjmuIa(xwJpdb)+@^cpsg>du8vL8_}$Msfg3~Q0uge2p)rxSZPF3F zGXm^FOA~pUPE3_9TvoqLI($(gFM~%&;<6PU2@!|)NZYhZK6ddoS(DH9Gql6{^oDu6 z)|VwdyKzy7_x0}Yp@M0BO)PCs_eoWyOHTW}s(o&1g#VAz_gdeumW3GxM2I|W-EjK% zskvYM4}CiDVBe|i$I^#BUAPd)@>PDCe%kM(h>3l7Prq3$@hdf=F5w5zpmRz8&;CBO z!AA48_~EV+nZrGWG70gL)5Q0EJ+k4`(>0ro&!nDcn;JOjM!RH^{R3@}!?V7=4Onf! zaQKwP#dB}j&Kbts%>x=*JVWrDa)o(Dgq_M_^|q(UwZ9T0ep>F?Tv1xenVcA5Yg1Oh zz-;sH;s!Ra(`$INmxs={8Z3FuUv64fSevOsR9b4pXa8)W{%dAy=3JX<a(~pp-{>x6oiu~x@TrIk7lYab7cE zidkX`D1o$O8m*~m`sE|&*3|TQioc0;n47PAk~0sp@+QTLf$f~eYkHbwJGVs&w|B3K zyv+Bt=|jJKA|<>(3w8R@m*BWD(eUP%`X)p|0ky`;*SzTJcOi z%&oRxyD-nL!*=hYUk`kCxresj1Q{qQF4S53S#I8n%5;CF!bDfWFHVW6Q*w4r%(!X( z`n-A4kM@rF`DbU@>UK&;pIRW!tGzhw`;E9x?cZrXe~SHE^#9qGl=D-++z7IMrEvI{ zrq+W4y;GE}@10hZ?`tN&wXY%_7~-pJno QtQ#0SUHx3vIVCg!0F$x1@&Et; literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-rotate.png b/crates/resvg/tests-hinted/tests/text/textPath/with-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..7360da828154bde098bc58e97ae5fa476136b070 GIT binary patch literal 3114 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-transform-on-a-referenced-path.png b/crates/resvg/tests-hinted/tests/text/textPath/with-transform-on-a-referenced-path.png new file mode 100644 index 0000000000000000000000000000000000000000..215041c5e8146f7abe47c3287fb8645a091a12b2 GIT binary patch literal 3313 zcmcguX*ASr8~@LYT~oH16nU~l7@9(svW2WMXqYjUd6)??;m8ujP%2v}yF?gShS9vX zvW&8&%~r@%vQNf@>{9bi&-3N|@;>LhU*7AS`*;7Y<#*lJxzGLKPDI&TLPZXW0002B zwla4D01)E$5`yp|_N6hFJSP`rciw{M{_p-=+@12r`@b#--~(8I$+Nl8gsTH40OCMYP# z+uPg7$cR_NLtc<)!otFeii%=lVtRUdFc@tA{`~?10*4MA!r^cd5)v*hE*K0(L_~yl zTwq`zuPqjf<@J=3k`fdYG&3_36%`c{65`28BvN>II2;a_lau2Sb8~ZLWn}_^z$@TY zLLiXP&`{p+U@(}+!@|ON-FTDpw7$N+yaL{#c6N40j~=zMvO=LyyvgI^<4sIV{`q?U zTUOqn*OQmKec8$08NiDn$;-h5jG_rK6K=<0G9HX_?90*xfOtOmuSln=exOL+zM83@+Dy>T=BR z?b~DPIqT)+t7{Ft%fG(wjoyo|YN4qicZv9$Cr{ix!@9ZSYs6B#|7Yyc1;TbrAn zj~rhdI1cSVit*LC-dqHIlI7S~1V@vE9;~C>?%@>fwV3@Gi_HUXJ7y!WbVA>m|L<0) zSiM0H%AV-cIwxJUcvp-t`1Hp#t%YYyj++@+T=N%ab8j^32C&c2FmqX+;qX3lH@C1Y zyg0h0l8P%e3SbIYu;v11a5>s>=i$J!q9nMse#Xm#(_+hsU-4GzSvozohdYZJK)IaS z_rSn8V)xPemNk(8{rb8usPMc?%9OqWV-cLL-6427-(Jm@k8GR2$7rpj5|J#LyhFAq zEu(v$C4`X?kEwf7@4htPLu^14vvdmM!GS|#WYycz*%>dB9>ySF?-c-YZfXw+7{6WE z1i42m<(p`00AiI?Y0BMXnMkfy^Qfg2F;ND0X@*|wPoYn}gJn!YOd8c`1#jlw1fMOV zPo0-ac+vivUs}wr4P)TqGW$&2KyXeWODC_yO_(NexNF5@0`#Svu3Wlc?g1dRoO&H4 z(<`ZonJ4>1&!FSA9~u-$l&a)lM)K8~$*PGfl8743-6Pp(XJh_X*1KXH%?5S z>!C9~wjjA9ZkKd6)PUgT74#%Qt@Or5PP8GGV*Zj zAY>r*>Z77ugc?bz$K5gflDNX>7DGwa+ss)A={w>Nv)0*kv~$?SUiU=(#;wSua8PtP z71-&MxETN@TfdS|R$HJgCN&)^9bNU?+x4nmw4>mNy396pB76V?$0qoOxO$lQ^ix6_ z;@yr%3H@ z=&kO-@^H=MnFz+J{YP{uEeOA3syG@L@ zH*Tvd()A8%=lMIjgM&|;g&@Y08!I*MPp-_aR~I&ojOu2dEo|2_j$OfDn;#}B_=8QI z?J~nMEN`nz?##cgs_JzQY01+}R?ZNlKCHLD9MPu#0|V`-IaE`f?o{bn3D*h8vZ0)J zvLR8IuFhTqOslVaU?1p;)YubzLg5LQ@Cp6i(bZj2?#gK6r`Fa4>ZPKTf(hMbw6J6p zP3&BUR4kvIY6IF!)xkdIeUx?ObWjT8eQi-^{klr`6k#x~Dz!yH6lo{}iLb`e1NrE0 zHb>^N)Xo7{m;z*nz^Vyw?4+iC_t;2ZQ#+Il;i3g0vex2VSwc-`FLzB5V2vj)`qZ`p zF9fBB5)*b`_!>TR#SKh$rUdIzqp^N(KcguP6CW3}(Vk2Lqut5=7*&D&egZ;+kG=~T z#k=2O2g%bbT6dam9d|9c4l0+odiwEta{*LxAG!EzLU;*@A(JRqLIQ97*j~Am_hRbQ z1K#T;ElREJ3@>d>dd-#)T}AI&H1s+sx4c|n=GeEchgJmC{=aAwrnBjMV^Pf+pAh);8}y3++fz9xCYZzwS10?~ow zdL?2lF|UUGiN?;Az1KYt4H%?XY}`tns;E8-%+PvDV6P+!C$+w915f9yeku82{AZic z{s|Famnd70Uav9vY@Im~BwRVUrM2p;#}jxlbC87~6Q7V3n~UbdJn>gGmi&CeQne$b zaqNY0YBwQdewp&g-GYehb; z@MHipbAsUFlE$EVIBu2;lm+zI%bA?iv;|nhFU}xZ!*=qfSaySf?4{3-n*nnz$SE6h zIILZyBbA|~j1Xj561RPVF3Bn#KajYu+Yo)soWW^!4~tN*-OuG~IRUl7!27sUZH2;S zw_*ys>05#d!(aB)qtzCxYZQ(@&`r}|%@pV|6IE41uu9yJ;)sQ>(WhS}Ne8c=oM*+m ze?Yn^nAF1PuB z8+D1T>|Rg&+~E;{C8G*YV>`}AL_%`oN(8Apb8;aD*O7XiZuRQ=4^u6 zkIsnY3;b>4&deyWP)4KC-kEF*IJ@fC_Ux((S+$1{qP;k?c$$2RF)@L{q1^!WKl_@x zB>JYdzx7S-PxI_0u2eX!_Bl61p~|}J!gn%eLPyrNYn=*y==NaXiLadj#wlY}^u>C; za0jED$hZ050w_*y(9{~*(&FM(sjZcOpK6sNAF5~r@v5YE*=V?oOzYmL$e3THs39)% zNr0AqJRov?vxeFH8n4#9&i`k!LZo-|j#w*)gACJUlCxaKb$W)@QBH`| zlRk)bTnc48yRO|IdzyL`do_tdZ|lKCee_0f#;qP}kDurn+7|cu8g=_|ePFeeErsKa zD2z&>ge5<&4>;28L|PxkKl`qi^7!3_6bi?n$7zWH7R?^f=o#7_#?;}z4svY~4raeu z<1ZNImx13%P_G1n=Rb=-@)z>k{^tCm*?%D%@teaDn7^@(?>Dc*3;%`B{y{iW-5J&H lJg};s{oJS(VRSTbML6`iT@vdZyZ-mz+1kS1y!H$}{@)`v{ptV! literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-transform-outside-a-referenced-path.png b/crates/resvg/tests-hinted/tests/text/textPath/with-transform-outside-a-referenced-path.png new file mode 100644 index 0000000000000000000000000000000000000000..76be77e91565b5d70d6b4831ea530df41bfaa971 GIT binary patch literal 3297 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 S)(3w7@(uOObjvSd!v6z^Z3&tH literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-underline.png b/crates/resvg/tests-hinted/tests/text/textPath/with-underline.png new file mode 100644 index 0000000000000000000000000000000000000000..d3aed712dc7c59ca0057c2f0ec542e814ede33e1 GIT binary patch literal 3988 zcmcgvcR1T$+qbDbQ>(RisI5k8mc*)35mb#P_9{iHwHsPmBZ%3dMu|;mRSBhLYyLu2 z6}1JiRgAp(J->gRKi)sy_mAiKT-UkJx$krCd0ppxzxOj6Ycn=xL1ro{DmF04#FmPR z8u<5MqNPZzi=)jbOtX#U?Hd&K|AN@qSjsU9{r@5^F7Dq|+}zv@3=9wm1Vs*oLMfC2 zNl8g>Z|~61(D?XxGcz+SEiD@xoAB^(5D3J?#Kg+V%Erc~prAlUM<*d6VQOj`7#J87 z6y)(Qu(Pvsb8}PV002N!Q&Uz}*5BV>P*6}*RP^%Y%M>Gyj*bir3_u{z-rnBG$jI5* z`R?7j%F4==Es9D&K!B2x5oRs z9XAj*xA)EucXRf(SB}Xy(`sFnV}@VPj^N%Xi@I_8(>hXuV?6h!OVRH8-MlNdbUDt+=o<-{`4ZJBuRS=H$M&wFnD%ySvvi+`X|&xEPyx7MnN-cbE-OB- zF3Nab_o;1J-r^#EBwsa^j44a>$vQ`^qR>HZT-Eo%OF`LLvFBqu$geT&f*jsawEJWn z5cy%I&{ZQ6;jDCt__4a~xgZLpQlpXp(?D>^-3e$O^U38i`0(Hp-^5OWXJdSj81I%| zsr^Y?d-N0|;m@}cmCy21eHb@t?-V;0dv5(-(wa^xS&!1CSNAgT_b{ndiYzfcmDXQ^ zkL>N~j5HfO*hX9$n@9C9zvYl@oL@l7Ak7BpXuF?{nt!hMy`)(+4bDL(44X}ilmNGx+w?3MFL(`Ik}yUh@DW^Dk)#IZmv;=X^B%rOIJ2x+&{!fPnr~3k$J3`#f#o^|3ln0u}Z8udvqh@!lB<4%U6|d+dqmBVq4~ z?o0>%2sJv2njy9iz3)rlmBPRGE@!@w#v!>D%Br^H3A`)BRdb0jPAwrYmuz)nY z?7Jo6e>o%IEH(3M3bNF)A)&Y%M7_GX^`|<)biC`9MN_JzTtczVS@A~;GdaY!9z()F z0BZir=XgU^sFNVd^lT!PC{ks`mP4Wj=c6^2{fnKR7f-O)xEv4U5H7N?2rkgiy8haZ z{c|f4w2%mX0+dQMe_q@}n&$o0(?ATWRlJP;tP3c0B1gePajE6H!WoMnJbHVwgGlFd=8-5t`I%%K zUf~+VAm5r-Mhu)PzWBrYeLkl|!`tos>ZTt;@Sd@i!boE&9=)N~joL?bQk5#q{mw^M z9>RNUQDsKxuAjHOgL;Fgl3?+legEjTao-bwU2R3qiN11b(t2b=J;OvlG3|dekOI%3 z>6MZO``oNTUo%0Wjfx%)I#upNm9JLl*JJSeovxiuQa$F@g|2y$`bQ03>18i|6PmD) zsXC*O63>ITD*a?0^&6~(84$VpWsWJuWPLr+V-DukvTsy2hLuM5xO%J~hOH z@?)eg6}l^&JAu=@?^p}cOCGxk_;#2OaYLA;W(RX%hf3aoM`bFzaiKP(w#mg7SUw`v zzcYKrc2!tH+@&x;D7yFoR7c7mzvsX;`kX8M!q5j=Tm%3*S{(Q!J|)R8SXMdnedC%O zSjc$nv*Sv@76N(i1~oYKqijR_;wi3aUW;p_BVAph@Szp%mOA8fl~}TZ`w!Nf$-7C0 zEJ>0)g~o({S|~6{(#7viIRpq+Q^&~VR5Mn3ji2^|oL_c%^Cg!``shs6--(aMpzv}| zec(6{qn`%)G^3(=s2$(zAc-y(f%BEzmMwwCJXamYZ<96OBp~!sgRSvrrWsKCkmu?N zRlLm}QoSLNfrH9JdG2uPY@Jt=-h5BtmssQ)%STl~$OV&uuwwQEu_3u@PG39(`Y`F% zhEPCA=^gTcaF+VL!l24c(zqKw4#7~F47~LhWVEdNS+`7$HNzm)Pz=^O4Zlr@lGm$2 zF^WHX7xdj;X`zL@w&o^R*b1;tDdk;1@69_Qm|pg_G(~QhE&Y@@t5m!Om1^OZM=^{b zZq%;H=%;w5ctDQ8aXQENH;k3S&;b}L(Rgw7d+q9;%h_+4&AiTCo1!>wcQJP=^~=jq z$vsY(upHGI(IF0qrCl~N3xEfqFOi^!j(cmHgp!2MTDK$$OfI35(k~1k`Rp)xqqdTn z`#&&ULur&AHJW zR$SRh4Pafw!gS!$B8Q@@Z=XZ!wH+5~&-BOT<6C%ko(R9(O=xA1^W@Ua-CwK3G1B}f z?KU38G`d*FNXPv?yCOE6=LJWMLez?cIfP|rC= z1vya_tmxQ9z5;*w%kBUsilBd+JRsRy$h)qWuh*u%x{X&Z-FVp z%hXcr*P3#u_ZR4vzQlJ~A1W6a3ifG;_b!$XV-4Ddd4SYV$>O}Yldx7iZ6emj6Zrhw zRlH6dJe{?1dK4oK)~+o@lbWP7aBB9_a!qK|VnGESnk}S|tTTF>aH2+dWHQzOav}v- zFzE?07`{uvmUsCi`EE6f>&7JG#YDU-L+*(c@$ys?+wuz%K`2klvD>}6Lx}X4X+&Rd zKhsBfZCe94hM)E+?QYIdq)lA2yb6F@HP8F3P`Lb_f=+ngf>bW<}%+ZmXG9=`8#qK7WE3oZS!`gOv7+A+xwX;T2xb zKTx!-ct*Ko*j+pHY$to}dmAMI(Qng-4wP3}3~+&k0Z!wO{ek1mIII}DEAa~M1@*0% zCenqNS`#hD3k02na-sHhP$;NRa74GA&pm7J83=Q4@;Kekl7Uo~_{={3MwbyRB==Xc zP0XhYPcxPlIrJ5m8!@KhzmFfO6EX_~vG}*{VwcryI-CY)53KKO-+^ygJcDJI*sJ)* zO<|YQBF-lAe|0O00WoUv&Qj!8DB_ZHWuoj?-_evwyvS?iv5eoNL%K}j7ZEL8o!EL z?oA_g8K?&M3nV^GKV#JIS)xVgCn1Oz|~whIah!eB5k^z-wxv$KTLr;N#_StJq(k|iW0OiWBbK9~fzC@U))7#JuhD8S)xa3eoI zzlw?q8ylO5hzL77dw6&_I1`OVgEK(@w(#)qfO*gh2?>E7)T5}V7!(xb<>e(WFR!hw z4Td1W!NCC(sjjZh$;k=IK6UDpoSdAfs3<5yLqh}90L}+{!IHGJw33n%INZw03V}e7 zNF-1ac;0{Q0*?8Yx!YH4YK_`iRY|5(-QXJ&$h;!uM9IY1a0uT?pB z1wZ~uOW1vN4S5)E_V`scV;oQZYc4LUqSBOp<=*_(;o;`toAut#(bkV=_vRK{D(0VU zWu$HF2St4THFbaKS7kqQVQ%T?8guI7!(Yrg@723oO+Vistfr=|XXllcEs$(+f9})A ze{}8~I{!ZSp|NwgaCkVsNi*L2X?(c;_;C5`y{w?PipSZ1G3cvnWYa^lg~I1g0DvE1 zjWKtOc>DcTs|W+h&#qN^<3M^lIHV|d1Zst9*wvaW7{#kxqr@Lj?s7gaO;K~Y?>(IR ze|asbIiU_(uOR|6P%dJRiPrIE*`dsp`@6F&&|Ifk%>rpZhb#6*u1KAdGxwG^Ak>f7%7PZ!*wYYP{?30^HM z5-eT$8F<-*oKxhP%i-S}MvP9Czh#WKkpvMT1qA&DZ;h|;P*4l->l4@L<55zUN=+SxB(2z0ICL&&j(#$egw@>j)L$K~T ztFEjVpS!{HO1Ay{<%9WOJ`JCo0&`eZ-BZ+VH>P~yeVfPu=X*V6RRmYA;_8yLY3zg6 z$Sej-1f3&Pl7+Ik`(^V!bmb~h>C)h7|CRC@ecFdw*T#;6c=TY<34&veLOLd_`uB8h zw<}W~;W8@cJM||u(p*QzBNNAuWlvghYj4Kd#gWRKbFCC5o8YNdlQy}8;aliI9lH|D z7%y`|wvcBtElT;$%}ls8gV2EIZ%@DUO=#4J$6k`@dTI7(wl274wbULb%-Ke*s{8L$%hisSrOLABOGympS2xIB- zx3^zazn8m}xlh=Q%)AZXOgwfSX++5*YFD?I8`S$;vz8~J1#W~-n8wIm-@$eUNEpv8 zpt{VP^<^%T!w#|5}@ipww34B1dirAcB)Zo4sO)kd;mL} zkd6W(a$3AG@s}rTC$AROu{Y(u@I6tIDAKo4%pU>Ki}tq@Tw<##V~yaG0paN&rxp`` zFlAH5M(1EXQsJ-TGRg}_9^D!&EKP5BJ`|#DCfT`M-g{4v&}xJ1|A7JiLVFk99LS{U z8`6$FJmbg%QB9BEcya#5_DUsS1Mj$KRGL}Q#xJ>L;))y;gKAwu@B%Sel9D1I*tu|TwxFI*8ut;I8%v5rr9&h@jrg8P3tKw68&2c2eI&3gd z`BR>tPRiD7VxhQM6hp`6(nUk6@pY7f=2+!GiCV}%ZY>4sp!qgo*{ZBi( zQN6r5PT$U$<*(*H2g*6ePC*R&L5NUkbKlJEijCR}C8ShwP2vtGTf}tE}Et}&@&rQ5OEv2r@u9lM$ zV{PlN`>eXm?+^V60YpKFTIZ~`1`I7*4a?V5$gVi2yOFCm7tK{6nwVhpU(87C$i-Y0)mOCw`(yu`D2()jv z^s6ZBkPWZT=hoJiG^h|)vV@J_{gy4zlP^)cQs@2R8+C4#n36_8n@WU-5dii4@G-F3}~(1 zRELaD7)i+dXpGV4?dU7eG;a?uusTPQ+3>yeC!2J|)oXXm;Uk%1iOI^^To^TihuoE? zA$jJ~I4N9&kT!~zErHuM4ea(G^@H;FZ@?y`5nK44I>!MB z;o!r9QfEvPHF@=-o7>xOt3?X@w|4rRTH8?O(Iv|HQ@95YpkkL<%zj}0XUN&-f;QB@(;)NCJQJv~k_#$)%Tv0Zs{ zKtB{6g3mJD{#`@mHJp#W;Q>rfts>SwJ+WkLM3-It!EVF$S%RK2qG=?!pFrwNHr-ZR zqwOKrZ1kmGh^v+76ech)zJL7l%Y%2z;nCM93vVL4C=UrK0|kU zfMZBjh+|Lr?(UoEl9oN0@{m&hIfkx{&FC!-_h4Lo>yXhC!V+5E&s8m6g+QE?al6VI z#OA&<*Wmyqgi*Yc@v|j4b-y$Irgd39*TcmKi%ocKajAvexMIuk^^0%q5qou|5gw5+ z58;C1ygM*G$=ch}Br0#Q$cP`-IX?^e(Gg^7M?; za31^-W|GW<&I}o)Tj9YokiW+H)I@$^?Dyu}loteE-rhqMC&DT1i#DP~V!8G(yXVo(hsqLVIqpdF;HEEY>(T!?RTAI>UTw8a~J?H)dd!O?1;C|QUUf`C_poIZuOv)#k zw-GaSukN*drLCH6nJh_D$|bdRgS-^u#kF^}ywdhNga_J11$o2AV&AS20Q71o{=VT^ z>iJ<`v;6G_hzo@RD(u*XW|Hc=NOfw~_>Hz*-!c7j6o+|Q8m@Z^9W22?vcrF|@_qR~ zsQ9;q?|ZDjAvq%>X$Jf+r`nV^!G8+qw)82;^~I$2u5B!G6Q33e$1w5x+`H};Q6)n+ zUmIG8!dgY0{$$jIGj?3<&6|3__DGnCw>Fq?;w~kL6WrEfRB(DC;?@kFzIqHQ&?FhQ z-?Gj>yl59lu5JHf2F2=q!a^Jpd0-S10a|@X+xh9^6Ec0LWt)py6bn%=nm!~(eDk^A z`7L-Y2X4^!2y=yCDJKfviYEg1oyBvvP&&<1)`qM_QL#O%>)Y9p0$Is?L*J#ayNQjS zZ(Xn~&u5)r&fX)~gyIjmr^SAnjl0w*XvALD|z4~j0gRp)z`QmHOBG@M<=d)YHYV~X*{I)g9tz)*JbMh$H zP@L{E`9ND$Mo;6mJ{mJAZYL z=j+z#rhZ#ojio#-VPi=ug|CM3-8fmNSzS%;_7n13n9EP(vsErx*HmP5fLbHfKl+J` z^BMNsiAJBh;{zsGDDJ-N1R#w^hnLmRIVVZytaGR8rj!5G-aacTqD;w6bSEq-;t~RG z=QAR_FN!=G7jdR?QI+!55$EJLf&acL_UIl)jUZKHP3vZmHNl>nqh3Ud7~|6)gggvU zn}is-!uywS1Ev=O)f$<3Mq|0rhs{{%K>fWHJtD5}>1eR5_%tCZ`q^$!F~#2?@ha$A z^%aiy!iU$U$gBXbP&?uNDJra>73DbomDDQGV@PewXk-l)RI`s~!-rt)FCLMKOP9>% zUnt|fhS{8oWqgisETXpKjoUyfb8MtXg@R7%QuSe9_N*`-mV_Wm@#t#y)4-7-z6L~Ci=90c_UG7{6Fg{T8t zcAfpUB$5;=X*)h&9Sd7-l)}FW-mUkNBH5M|FDwj}bOgNk-FhtX$SY?S;aDRQ~zeh8f`Zt=>d7EL>0eRc@qDrAzQ zy*`y!x*-XJ=HuRkNA5D=3vhD|MBBZ@L9zpvA>u;I6iMo8^Ir5^iqNEUBXJ6M{(F3P zf*?GB%P;EhzG06Y7nV4kzlo$-=%G_x2X-#S9?kXsiO0d4UbV`AKK4g=9m*^hwD2fe z)#6N=ke#{g2F^UJuU;qEDIX*+dO`ZzJ2LxnjV~r=o}!V_ShI#cRZ~&vs@rAN8$AWc zdzTQ3EiT08Kr)5rFWTl4>4byLy-0LNN0RnljZCrCuKZlt_QW#F=o3>Ms3|5Z>9C*Q z$|;-(^VlAnKa5E$jbS&OX8&47w?JXpTLiKlk#vt&{$uDEc`cM?2E7|JLbuNzR`5D7IQ^{zi& z9ofZ~-%+lvJekDL%?~F1ph%XFFMoFZdWYk|AN@Y?0L4DW$|YZV3SPT#s)0#*%SER< z{CT@se-r*G4AAazIm05#{t literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/link-to-a-non-SVG-element.png b/crates/resvg/tests-hinted/tests/text/tref/link-to-a-non-SVG-element.png new file mode 100644 index 0000000000000000000000000000000000000000..f192fbb98e360805e2ab6edb44ea2769cc40b33e GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!uEe%EG~&sHh_#cE~A0L8qm4gF^&Rpm76GfC(tx!U`1U;0B5dhylg_ zuFHLU`fDCLrVPC)5fBOXI+MbRPe=i2|I|)ue3pEmS5*ZJqnurvG(@!5}Ly1!YX8oy)xGKOCyg%{o jnu8Ily6VOT5!K9QPBL#-gv?0-CQ1fRS3j3^P6dNQN~~2f;)^ zP(}?j5-|YlH}`%|x4@t1rG_v> z007i{yxju;fT6#Zs*++tyh-s=2*cm^u!lnbIlBOe17HgPM*&C!;1mF!0E7b&s;-Vv zQZjrZEUi#vJ_;d zmzUzgcmPf)o(2F1fDr&z03-u&4geaBroaLL;6fe!3fe9;fOrVFY#f+Pl;7Q#C#~pT zS{v4oC)`V6N~)(S-pi9G*jE#C>JqMYjeU^?n}m^`l}9@l0ifdRe z2H@Gkj|*qt5B=aLm^Rnasx=6`DE9a4Bf@2unF5#g5(@&0ON}%ou+Sm(5&shIhf50J z>#FT5`JYUmY~#uBU6vY+NJ%>+NkMBemJVz zLDZMeCy6xL>&mmFr6^-)ov&28S9>#e20hQ4kL$S}^5?nLtI&Q#OS?e0%x$U{gf8M} z2Y#WLe+bk3bn76ttzYD5=)}h|n0(1x>F?)I@=pB}53VrPDl#Bf-E_Tle02q5m!Ro_ zV)37gP9{rUwjKzH_=5zp$&$q4X7Rj?r=h*-dJsA#u5p4+JKMOUg||k?2W_|BUd=yZ zHmw=X(M8TxsW$j>V}~#9nSN({BASPfK<Fnk z%lEN9)7^DGa|}+{@x`jl4Buh{W%u@WV8VNnZ(i@hZx3R#`^+2Nko@|$25#xM1KUJG znl7PrIG;V(sDVR~H5r%`rdw{18H7(ze|7Jgm~3%ocQK*a5)zkeGrkj*1YKJ!z8>jJ zXIIM*qtUpImU5qupDJJJ5OT&KzwwcI9%b((HuOw zqr6=#v~&`)9U(tyw#Svx@UyX*7nn_u4Xof$GM|SzZMP>6yBC5oAqkytw77}Cq7B&_ z)Vfk9e_(}{nN<0}QN)q5@o}0sxPC_~q*Uwve1yVHlHf-%Jl9OahCB@BT45?zuFJV_ zwr^2uf%`EEGJG>&reByaEp&}}+#Vx<1jL z@b;rO>iyO}@bNsnLt1&G*J~)Jq+eu)^JSY9#t&7~S4nyUO#bG5S{eKaSzM8H0O_>K<>9cX$qaLPpptP2~n~}y=)SvUPg|TQ}S|NbeSx^<~!t$_?21=mj6$ z+H4C-2T`dcY6*eV@Dd((K*+~zjqoiY>+hTb`h9b5{4$dBNbotl{Y?2(A*We+ XPFcq~aXxHT@goBt52AaWD~bLWT;J4} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/link-to-an-external-file-element.png b/crates/resvg/tests-hinted/tests/text/tref/link-to-an-external-file-element.png new file mode 100644 index 0000000000000000000000000000000000000000..0e0b36898915703112e931109c260ccec46d8359 GIT binary patch literal 1701 zcmd5+dpOf;9N#S0Wi4!#(@sY5EXySo)f|_Hd*5&@B4l}@B4hd-_PfH|9G#t;T_b~wADZ$ zkhG7IYB{Fn>SCOP#ib6Ry#Wp22jxRJS(K0=3(+gf!jp>9#GV^j4ZI zIKgmQx0>-FC)vD4Nma^Ev9*1iy~CM_^`u1P;=M)=flu&PpCAkK`*luL} zZcL^x`8=y?&ysWYDullsTHWVg9koyh5LV3rm;N-yw=ebqjTBzx2&Z&Hnt`}Q>P>NN zqVNpFoYG?-P=*J}a9HX}K8-&e^SMovzqgYeRQR!}*?UD(luvWzN9R1{%vYX~-qcqo zH(m30U&;NJ0x(DF7`#bKJ+T=tXd~YYau=IRI+QiTlU)E;EYNq3|nucV1j5>Ss z!csk$sa*o+s6Y)g`NuXg4YNFwD_|yDNEt9EeZu7mWWpGJUw56N7J0y<(vLjY{ozu# zK-Jk_kodkz<&hf;Y?xGV5<#qokNM65+t5?oLA7*C-xa@e;eFUwRm zI2j=?aWF=Gy2yIQ@dSbq^HiWBd^xQGrk#yx28Kq;y|iP)jET((5~^y?pOF_;QYE)T zvpE{5Vn0>qsD7nAzxS3V;+9uhDW-|Q0xA&2H@`uSW<{|IY2|YgNDbbn2TNkaPcHn% z?iYCP4-d`q=B7pw79#*mk(Am2ywFZp6xDkatM!Cir6%?Y^k`e1#-j3R3j7n9+?Dvz zx8y-imn$(nq+%Cq+jjCG{Rj^E)yu*nE;q&gNfZuQ38XPs6Iwek~+yYP7=ydsG;e9q`UGVedIj=pkS+2HVO_FYE{7T7`{i{_{8Y z{R+JoLP751lg|Uiiv6#5k;g9(p7|KdIv(()hkLI&%U(lkbOMLDfk*l> zH_4{KlZ`L6k?B`9kj90m3F=Hd-q>H`tN19$(0f}YNnosm2JT|XoVpY87g-kg>{{o% zXawVT3NQTuKc!gEm|<^<8%BRIBS@Ei5zO^2dVV%$|JMCi#6cO6XbPv3OkOCwc^jk^ z`o68stoX^I8sGw6J+iRVwTG}RucS@a%8}c`RqStf(ihg_|~6yUZ=Yj?9=8VV@PAcOrFMR)iw40Gs%KBdTkuG}f~1SWD=< wmXk^BIH@U`o>({a6%yDvzx9=sYyONcc&ykTW%;h9{`-gSXpgt6wIyEu2R*|3mjD0& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/link-to-text.png b/crates/resvg/tests-hinted/tests/text/tref/link-to-text.png new file mode 100644 index 0000000000000000000000000000000000000000..c77ef22f7611c0ad0b367138aa1422ff1452695f GIT binary patch literal 1621 zcmd6nSy0ng6vl4~M4AY)hD9g^LAD5phB#=HvXejtQQ!|QBnTq1FBL>dNQN~~2f;)^ zP(}?j5-|YlH}`%|x4@t1rG_v> z007i{yxju;fT6#Zs*++tyh-s=2*cm^u!lnbIlBOe17HgPM*&C!;1mF!0E7b&s;-Vv zQZjrZEUi#vJ_;d zmzUzgcmPf)o(2F1fDr&z03-u&4geaBroaLL;6fe!3fe9;fOrVFY#f+Pl;7Q#C#~pT zS{v4oC)`V6N~)(S-pi9G*jE#C>JqMYjeU^?n}m^`l}9@l0ifdRe z2H@Gkj|*qt5B=aLm^Rnasx=6`DE9a4Bf@2unF5#g5(@&0ON}%ou+Sm(5&shIhf50J z>#FT5`JYUmY~#uBU6vY+NJ%>+NkMBemJVz zLDZMeCy6xL>&mmFr6^-)ov&28S9>#e20hQ4kL$S}^5?nLtI&Q#OS?e0%x$U{gf8M} z2Y#WLe+bk3bn76ttzYD5=)}h|n0(1x>F?)I@=pB}53VrPDl#Bf-E_Tle02q5m!Ro_ zV)37gP9{rUwjKzH_=5zp$&$q4X7Rj?r=h*-dJsA#u5p4+JKMOUg||k?2W_|BUd=yZ zHmw=X(M8TxsW$j>V}~#9nSN({BASPfK<Fnk z%lEN9)7^DGa|}+{@x`jl4Buh{W%u@WV8VNnZ(i@hZx3R#`^+2Nko@|$25#xM1KUJG znl7PrIG;V(sDVR~H5r%`rdw{18H7(ze|7Jgm~3%ocQK*a5)zkeGrkj*1YKJ!z8>jJ zXIIM*qtUpImU5qupDJJJ5OT&KzwwcI9%b((HuOw zqr6=#v~&`)9U(tyw#Svx@UyX*7nn_u4Xof$GM|SzZMP>6yBC5oAqkytw77}Cq7B&_ z)Vfk9e_(}{nN<0}QN)q5@o}0sxPC_~q*Uwve1yVHlHf-%Jl9OahCB@BT45?zuFJV_ zwr^2uf%`EEGJG>&reByaEp&}}+#Vx<1jL z@b;rO>iyO}@bNsnLt1&G*J~)Jq+eu)^JSY9#t&7~S4nyUO#bG5S{eKaSzM8H0O_>K<>9cX$qaLPpptP2~n~}y=)SvUPg|TQ}S|NbeSx^<~!t$_?21=mj6$ z+H4C-2T`dcY6*eV@Dd((K*+~zjqoiY>+hTb`h9b5{4$dBNbotl{Y?2(A*We+ XPFcq~aXxHT@goBt52AaWD~bLWT;J4} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/nested.png b/crates/resvg/tests-hinted/tests/text/tref/nested.png new file mode 100644 index 0000000000000000000000000000000000000000..f192fbb98e360805e2ab6edb44ea2769cc40b33e GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!uEe%EG~&sHh_#cE~A0L8qm4gF^&Rpm76GfC(tx!U`1U;0B5dhylg_ zuFHLU`fDCLrVPC)5fBOXI+MbRPe=i2|I|)ue3pEmS5*ZJqnurvG(@!5}Ly1!YX8oy)xGKOCyg%{o jnu8Ily6VOT5!K9QPBL#-gv?0-CQ1fRS3j3^P6dNQN~~2f;)^ zP(}?j5-|YlH}`%|x4@t1rG_v> z007i{yxju;fT6#Zs*++tyh-s=2*cm^u!lnbIlBOe17HgPM*&C!;1mF!0E7b&s;-Vv zQZjrZEUi#vJ_;d zmzUzgcmPf)o(2F1fDr&z03-u&4geaBroaLL;6fe!3fe9;fOrVFY#f+Pl;7Q#C#~pT zS{v4oC)`V6N~)(S-pi9G*jE#C>JqMYjeU^?n}m^`l}9@l0ifdRe z2H@Gkj|*qt5B=aLm^Rnasx=6`DE9a4Bf@2unF5#g5(@&0ON}%ou+Sm(5&shIhf50J z>#FT5`JYUmY~#uBU6vY+NJ%>+NkMBemJVz zLDZMeCy6xL>&mmFr6^-)ov&28S9>#e20hQ4kL$S}^5?nLtI&Q#OS?e0%x$U{gf8M} z2Y#WLe+bk3bn76ttzYD5=)}h|n0(1x>F?)I@=pB}53VrPDl#Bf-E_Tle02q5m!Ro_ zV)37gP9{rUwjKzH_=5zp$&$q4X7Rj?r=h*-dJsA#u5p4+JKMOUg||k?2W_|BUd=yZ zHmw=X(M8TxsW$j>V}~#9nSN({BASPfK<Fnk z%lEN9)7^DGa|}+{@x`jl4Buh{W%u@WV8VNnZ(i@hZx3R#`^+2Nko@|$25#xM1KUJG znl7PrIG;V(sDVR~H5r%`rdw{18H7(ze|7Jgm~3%ocQK*a5)zkeGrkj*1YKJ!z8>jJ zXIIM*qtUpImU5qupDJJJ5OT&KzwwcI9%b((HuOw zqr6=#v~&`)9U(tyw#Svx@UyX*7nn_u4Xof$GM|SzZMP>6yBC5oAqkytw77}Cq7B&_ z)Vfk9e_(}{nN<0}QN)q5@o}0sxPC_~q*Uwve1yVHlHf-%Jl9OahCB@BT45?zuFJV_ zwr^2uf%`EEGJG>&reByaEp&}}+#Vx<1jL z@b;rO>iyO}@bNsnLt1&G*J~)Jq+eu)^JSY9#t&7~S4nyUO#bG5S{eKaSzM8H0O_>K<>9cX$qaLPpptP2~n~}y=)SvUPg|TQ}S|NbeSx^<~!t$_?21=mj6$ z+H4C-2T`dcY6*eV@Dd((K*+~zjqoiY>+hTb`h9b5{4$dBNbotl{Y?2(A*We+ XPFcq~aXxHT@goBt52AaWD~bLWT;J4} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/style-attributes.png b/crates/resvg/tests-hinted/tests/text/tref/style-attributes.png new file mode 100644 index 0000000000000000000000000000000000000000..c77ef22f7611c0ad0b367138aa1422ff1452695f GIT binary patch literal 1621 zcmd6nSy0ng6vl4~M4AY)hD9g^LAD5phB#=HvXejtQQ!|QBnTq1FBL>dNQN~~2f;)^ zP(}?j5-|YlH}`%|x4@t1rG_v> z007i{yxju;fT6#Zs*++tyh-s=2*cm^u!lnbIlBOe17HgPM*&C!;1mF!0E7b&s;-Vv zQZjrZEUi#vJ_;d zmzUzgcmPf)o(2F1fDr&z03-u&4geaBroaLL;6fe!3fe9;fOrVFY#f+Pl;7Q#C#~pT zS{v4oC)`V6N~)(S-pi9G*jE#C>JqMYjeU^?n}m^`l}9@l0ifdRe z2H@Gkj|*qt5B=aLm^Rnasx=6`DE9a4Bf@2unF5#g5(@&0ON}%ou+Sm(5&shIhf50J z>#FT5`JYUmY~#uBU6vY+NJ%>+NkMBemJVz zLDZMeCy6xL>&mmFr6^-)ov&28S9>#e20hQ4kL$S}^5?nLtI&Q#OS?e0%x$U{gf8M} z2Y#WLe+bk3bn76ttzYD5=)}h|n0(1x>F?)I@=pB}53VrPDl#Bf-E_Tle02q5m!Ro_ zV)37gP9{rUwjKzH_=5zp$&$q4X7Rj?r=h*-dJsA#u5p4+JKMOUg||k?2W_|BUd=yZ zHmw=X(M8TxsW$j>V}~#9nSN({BASPfK<Fnk z%lEN9)7^DGa|}+{@x`jl4Buh{W%u@WV8VNnZ(i@hZx3R#`^+2Nko@|$25#xM1KUJG znl7PrIG;V(sDVR~H5r%`rdw{18H7(ze|7Jgm~3%ocQK*a5)zkeGrkj*1YKJ!z8>jJ zXIIM*qtUpImU5qupDJJJ5OT&KzwwcI9%b((HuOw zqr6=#v~&`)9U(tyw#Svx@UyX*7nn_u4Xof$GM|SzZMP>6yBC5oAqkytw77}Cq7B&_ z)Vfk9e_(}{nN<0}QN)q5@o}0sxPC_~q*Uwve1yVHlHf-%Jl9OahCB@BT45?zuFJV_ zwr^2uf%`EEGJG>&reByaEp&}}+#Vx<1jL z@b;rO>iyO}@bNsnLt1&G*J~)Jq+eu)^JSY9#t&7~S4nyUO#bG5S{eKaSzM8H0O_>K<>9cX$qaLPpptP2~n~}y=)SvUPg|TQ}S|NbeSx^<~!t$_?21=mj6$ z+H4C-2T`dcY6*eV@Dd((K*+~zjqoiY>+hTb`h9b5{4$dBNbotl{Y?2(A*We+ XPFcq~aXxHT@goBt52AaWD~bLWT;J4} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/with-a-title-child.png b/crates/resvg/tests-hinted/tests/text/tref/with-a-title-child.png new file mode 100644 index 0000000000000000000000000000000000000000..3383b4211a8310b1893e3005e9b733627dc195dc GIT binary patch literal 1993 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#c93g`DPxL+SIzkhvxeEZ>tXJ^;? zPn@0AF=xf34JAu6cNV{1|MmKY2@eVqE_^U}f1ttsze7{}@n!}FwgsLpjv*Dd-du2G zbYKu*FmRAyi20wPaPV)gVAvIRp;AG0&yOj*j)y*^x;i?Yn561GO(*id5{TTCqKHnd zSv3W$U{lJ;Nvf|AOo%$57>yaz*6qG&%Kz1^RIh7N$Fpho{>_pz@4BFK@BdXjW~=!o zYS-t**xap_x;cq2n%jH+43*!S3AIwS*L;5%A6|9v56cEWldzY4>E#Wkj1i%h2YyX& zTKY4fwWUf!huQU7T<`SOUsDsN*6@T`$xJ(z|8Hu7u07l86oWMaVF%Z9YX6m3^Ryts zH01q_<(DIb{k_)D<~o$g^3jBcsoIkBE=Q?Q_NAMd7s4&NOfNn!OklaT-@VYwWcN>{ zp7)+NBfYFvnkTNDc+5-bxTcj|VD9TvZ}+Q;Xj$}bFk+sjm~nM>Y|m8}PuW*zj$KYw zm~J&$G5Mri>t3EHtLb{LgfH!%QkQk>yVuOeCCt+tU9KB0oxDz0F}K;pfG_I?`x+*- z_h<698Z6UN2x7|Snri6D_)_B2(#Ul&i+E1>CV#!z|FY`2f#V{#0F$d?+83tvysEC7 z6mjg9STe)q6{X&H@7;gmkePVQsZ@|FX^3d51*=T6))TgJt~8um=g;gOlmO2c~+AN@>~h51bXoSrpxZW>4Htq)nx zr$#5HZYW7UF1DUex~nO}LZ?!qVV>6ivc4xl37VQO3mUdP?>{8H@!M+m36(E;mzLG3 za4K$!Q%XK|&D%!*K3g{9!r8t`;)MwFLj-8{EGoH2`7@bsU$$0e?18-ji}sRl*z2}Dcme9RG*(D{68xWeyw z%a5$*(XKx#ZT%)H;iQUE{m*A}r#A^@?_~|^RG%GEcHQWPvQA(uqxbx7m0LDKyUH3< zeLs7;PV7DUO1otXyLP*=eAtbm zvL(5B{ey2O-W$|3i?8zYa@Ornc)#I^q`t!E?N9D*XnOR%`AJ-G*6KBT7ax`=dae5J z=9#;(lX4oTdM{osaqU~erL2wN5vn3)tL`{B3g)$|8h18-PhE2Ic7bTY`)5;be)ZZ> zXtw(9C$5(tKZs>st3Mr8Za96z6oobHhot6fC5n39l}TH*^~vH5++h(8Ioz$054=SU z3iYqJHSM38`@)B;f1TtCaAN zPvd2dNtfx9EOi~r%$GYfjXRfwPPuq5Nh)~9%crs5BemAgk&e^+s5p0vr&z+T*4a}o z2i=o>ocTGF<K18y=IG>_-3hE;xh8JuI@Y>2UMl>l%u87> z`>9{{2A$GlmV6y@an-aFi}Ip`k~xhVt-tKg$eaI6|3J;Z4;61psw)qk{`1vmpIvkK z&bFN~=N?9sT;*x({;VB-{MFCWf8UCJ{;K)&YSo>;-!sqM{`2zG`-<9opXKEB;%6=L zov^c~bl0wi?WfbFH%jt|Pv<}Ht5{JzjZ6PRsLk%0<}4eAYZuF}{C`;g?bADZcYC+} zXUdm|2gvWM{Xf-9(c-`_E6E7igxt^)p&StMag`j%R)78&qol`;+0C^;7MF0Q* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/with-text.png b/crates/resvg/tests-hinted/tests/text/tref/with-text.png new file mode 100644 index 0000000000000000000000000000000000000000..3383b4211a8310b1893e3005e9b733627dc195dc GIT binary patch literal 1993 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#c93g`DPxL+SIzkhvxeEZ>tXJ^;? zPn@0AF=xf34JAu6cNV{1|MmKY2@eVqE_^U}f1ttsze7{}@n!}FwgsLpjv*Dd-du2G zbYKu*FmRAyi20wPaPV)gVAvIRp;AG0&yOj*j)y*^x;i?Yn561GO(*id5{TTCqKHnd zSv3W$U{lJ;Nvf|AOo%$57>yaz*6qG&%Kz1^RIh7N$Fpho{>_pz@4BFK@BdXjW~=!o zYS-t**xap_x;cq2n%jH+43*!S3AIwS*L;5%A6|9v56cEWldzY4>E#Wkj1i%h2YyX& zTKY4fwWUf!huQU7T<`SOUsDsN*6@T`$xJ(z|8Hu7u07l86oWMaVF%Z9YX6m3^Ryts zH01q_<(DIb{k_)D<~o$g^3jBcsoIkBE=Q?Q_NAMd7s4&NOfNn!OklaT-@VYwWcN>{ zp7)+NBfYFvnkTNDc+5-bxTcj|VD9TvZ}+Q;Xj$}bFk+sjm~nM>Y|m8}PuW*zj$KYw zm~J&$G5Mri>t3EHtLb{LgfH!%QkQk>yVuOeCCt+tU9KB0oxDz0F}K;pfG_I?`x+*- z_h<698Z6UN2x7|Snri6D_)_B2(#Ul&i+E1>CV#!z|FY`2f#V{#0F$d?+83tvysEC7 z6mjg9STe)q6{X&H@7;gmkePVQsZ@|FX^3d51*=T6))TgJt~8um=g;gOlmO2c~+AN@>~h51bXoSrpxZW>4Htq)nx zr$#5HZYW7UF1DUex~nO}LZ?!qVV>6ivc4xl37VQO3mUdP?>{8H@!M+m36(E;mzLG3 za4K$!Q%XK|&D%!*K3g{9!r8t`;)MwFLj-8{EGoH2`7@bsU$$0e?18-ji}sRl*z2}Dcme9RG*(D{68xWeyw z%a5$*(XKx#ZT%)H;iQUE{m*A}r#A^@?_~|^RG%GEcHQWPvQA(uqxbx7m0LDKyUH3< zeLs7;PV7DUO1otXyLP*=eAtbm zvL(5B{ey2O-W$|3i?8zYa@Ornc)#I^q`t!E?N9D*XnOR%`AJ-G*6KBT7ax`=dae5J z=9#;(lX4oTdM{osaqU~erL2wN5vn3)tL`{B3g)$|8h18-PhE2Ic7bTY`)5;be)ZZ> zXtw(9C$5(tKZs>st3Mr8Za96z6oobHhot6fC5n39l}TH*^~vH5++h(8Ioz$054=SU z3iYqJHSM38`@)B;f1TtCaAN zPvd2dNtfx9EOi~r%$GYfjXRfwPPuq5Nh)~9%crs5BemAgk&e^+s5p0vr&z+T*4a}o z2i=o>ocTGF<K18y=IG>_-3hE;xh8JuI@Y>2UMl>l%u87> z`>9{{2A$GlmV6y@an-aFi}Ip`k~xhVt-tKg$eaI6|3J;Z4;61psw)qk{`1vmpIvkK z&bFN~=N?9sT;*x({;VB-{MFCWf8UCJ{;K)&YSo>;-!sqM{`2zG`-<9opXKEB;%6=L zov^c~bl0wi?WfbFH%jt|Pv<}Ht5{JzjZ6PRsLk%0<}4eAYZuF}{C`;g?bADZcYC+} zXUdm|2gvWM{Xf-9(c-`_E6E7igxt^)p&StMag`j%R)78&qol`;+0C^;7MF0Q* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/xml-space.png b/crates/resvg/tests-hinted/tests/text/tref/xml-space.png new file mode 100644 index 0000000000000000000000000000000000000000..acd613b5579051da82688601bed1b2e4a941a54a GIT binary patch literal 1496 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`J%6XFV_A)uOpp&ZOAVqj=& zY;0&~$OCh8!DK^1Lan=dCIdqT14EU$IZ!s4fuX*>K8b;$L`y4%fdPo}6%|7n7?MOp z{1_Ob`1sry7=pODZ5bH6I5-?wS?yU_jTsnBnVB^h7&MufWEdD^85w058To+-Y(-1^ z{Z=4DwmPBUAKPo{xj#U-+u7y#ryZ~zkd7q z`_G?$|9-J{0lmX=!PCVtq~g|_3$Ba@90XW4XfB@mS%3YKg#W%ODt|*<=5JA&w8fZp zPJGxdCMEA_I+2@F{&s`NlapF8sA-{K1t%w|LR8Y1QMx&qUFOp30Ey$Si((Gyu1=E? zbaa{U|NH-{@(@4uwDq~^hMzv!ZMa!->y-ZN%_si^Mx6GQ`x*5wY3{M`s;D2`UyIEe zrWrf@;Rri2+kBJK=7dUzH~S=5go4$s=d};nWLVokrDezG7o{;~Ddoewp{I{>Y~T9jW|1w}UeZPM>L+y5NTRYA)UGC0uL0 zowBAVEM&@F>^70noFIO>Lhg`Xw+fd%43a;b-crBX^zGGPnL@ z`giStWf31EJiJn*Ul<>noV2&+>4GoIUT|}**_||F?Sa=zm@e9;Tk}lv+*s0b;G4|$ z*V#9F%VUo2I&9{1@m|D&NdBYeI#S<+UEI2~`69#d^Yeb~k*gNIWp8VKV){m-nwPx? z6lZAZq?zfQoyD-~t;97Rqto1Bb#da~3ZswhX$(#1v9?>_FgY1iZR1EV!cj3;Rh$^3ym^R)sn$v>g&wfo^aaM8L zMFsypRfYT9HP*+2?r+~{l=Hv*@4N?g=3xz?}54Q$B63e)e_FX_^7k^XjY* zO8uY1WHR-4(c^=fjusBnEjQR)QR!Fd^WCg_*zs2Ep(5TBjw&J+2a6moPA+8h5}A1C zn|tTJ6WbD%q68*NZZJ9Ac-*aOlIipfJ*P9yZ8*breA{KVW4YHp#hhQAH);B}jq5Z1 zDd(&a)M!aGuqms2*W|qS{@?!g+bofj{%Dmwlk(=xm^trShTcb`zvmcEyqsb%*Kp6W z-&dm!O#N^7{M(HeHB;rDys%k%sd@Ux(2m8eJ2$r^1w7#^xzjOM!yz!CkcUS=NK&EO zJ$;G$^7o8yFEp|;7yvW;XOX)9jo#`O3nugkfb;c$WL`p+o`94oIH<3h+5U~Sk*bqC aJ9k!p`S{##!uGkK($Uk^&t;ucLK6Vy2A8`4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/bidi-reordering.png b/crates/resvg/tests-hinted/tests/text/tspan/bidi-reordering.png new file mode 100644 index 0000000000000000000000000000000000000000..0dd91d52f224ac5b21f20ac9eb9b85e6d0f1aa1a GIT binary patch literal 3792 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/mixed-font-size.png b/crates/resvg/tests-hinted/tests/text/tspan/mixed-font-size.png new file mode 100644 index 0000000000000000000000000000000000000000..b3ebfc4ffac2b1295b519f58928e716fdd374bea GIT binary patch literal 1826 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 UbNL~NGasKwfDhHXiNyTsPxIG3wg3PC literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-2.png b/crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-2.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a0de16f033edbe8d50776ca7c8a1f32bcb9b0a GIT binary patch literal 1839 zcmd5-dpHwn9R5aXEL$#<%cO?FR4UgZm*oEJFw!=qZJMRbn9D|T3!}5*R45#s6qQyk zajJ!lN{7hdK|&IdlqQ;5Y|cE+`SbjHp7TA=_r34)zQ5=Dy}!SH*}hnJRTW(o0D!8e zhbs;Mi23q`D#{h?wIp{ry!G`7*e}PFl$6xeR5}1B0bl~)0D#G|3h18TzyYu;6qtkq zrWVa3kqdy+Ju9_~s}XK-W!k>ipR9A*3w0HqpFSLXosz^6ZVAX6+fS5+a- z@cSUe$<8yrk$bY!+Z#=$TMwfdeO{?zDplp(5kk$;*7L@&e}i8+<|~$W{(nszK3&c@ zf6r@O#tqp<4c5{){}Co1^oo{T?q3!v2UG`LfIm#?Yr)wqbUA!T4N@_@dQD^3OcL<3-UUj|20D)nzK1x*UKZQB(5eFMU<1tTxAaPwWyYc83zsSq9$qZze{ zr?inx2hO&a_hPNgMo;*H!*KlIAgNBzF-WK2@y;ks+un?}+^j5Wf9>#yn)}InO(HeF zYwCk-Mpu8)ikOKVqiKKZXIp)%jj}WEe1h4=sTh^8=G^SJq}N$w2MTfC8t%L=)TW;H z*DwsfaG@c>{`8j@WV@lbX!%C+wdk}u%A-Vx4HzS)xP=WCGrqA z(_(llFZT}y+qr%`i>hqCx`sz04;hW}bByZO^hv_T;9S;PjNvRcFR|2VQ%T5^8qk+Z z?jStUU!u4wt}1p@S0OjC;bV5Z=I@52@t%OBhR7_c4zGN*IDvBgGY6T?Wg%c1G~>*& zD=B56c%yV`hB? zzgG0{`%rak#a-~`(70=?a_tZ?ffvhNorBa9Ox~SkT27Pb4;tvr&60TTT+Ui8m99zC zv8WKnbADPGI;PNba)fk7+M}*D8~J;fuvtP-jV!gkf!5&(2Ohjcnnxo|qPIDt*jZGR zPxX3VHjMX$n_XWo{6TtU>p14xL7c5bmjejC~A--gw z88>)2wBZzLr;dZGdd*aJ|H}e*mmi_{>6W>|s9MsYwJ@*5G!+ks*~pJOcV;GvlE*SK zH`f`3ZypWSQzn^iVd!=qH+Vx^%%L@P2-aJvb+N>~Sc-6(tebXPY~G$lnKp53oaicOSe?m061sp$Ab!$D$lOxWkW6IP-P!TnjU6NfEi z8r*13R->>-ydhfs>Cm}|RI&S`IGlBs=R8+Fz!PA^-pY literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-3.png b/crates/resvg/tests-hinted/tests/text/tspan/mixed-xml-space-3.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4394f0d565ec3363484a30dae1ada2c7b0ef88 GIT binary patch literal 1364 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAoVT4C&U#oFJKTb;lO?c`-1ly7W6+5_;7xGLVm%-3lFc)uFapn{(k1`onOzk z_s^OAdVMXBvGd`E%=roHFEl*ZfBwC_!iW0{0t^ZS>JK>lk55ST3*%;BVBYQN;uunK z>+Ox!vfCaK4HrLN6MnYDr#m$*@9dkx`~OqJ7V9Km{<8tmLK-h+S2yYm1A+*a#^;+ zU#hI;o|Alie8=WZn}n}Bb4>rVal2^wp`cpxysNLJ*_l`0mYkY${*-XN{T{EsMf3h! zu8zAQ^7hzNfocBnk+*Kx&Fnwf+FX22YDt`B=_iv{Ch^a9O0BuOW6t!cp9Jo7t$rQ( z(jk#I_}o`0m`=dY`)uRr=;xldyM+5P&* zf82f3{99+u_p2q}&;8E&^y&QUAYft~faFGurIWd`ujj-nWw9t%Q~loCIETJJUsva literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/mixed.png b/crates/resvg/tests-hinted/tests/text/tspan/mixed.png new file mode 100644 index 0000000000000000000000000000000000000000..a307cb9c2539b8efa98db2621f39044b9c4305d5 GIT binary patch literal 1906 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAcrHsC&U%VMSund2I5g84#f-% zTn$`6bNCwgASMep2)i`6NHj>WH?Ze6=2|sa1vCaQG&0CG$O1_qVs2oLZH#4S{~;{= zj)CF7i_2aj7UmF@4>g($R0yZiu-_6aP5*xcjOY1sN0T3}W{{fPGe4ij(O322> zMxaGpCiPN4=SGwS`2{mL{I~zV-{F8j!+V7f1px*V*59vBxbR@X`3?O759eRcFF4zN z_;u#QTK}E-@n4HypY3nI{&4o3+Vz>mOY{A|&cB|p;KGLb^Y_<32q<_zLEwXff<%oh@gqG}oSV)Xcxe z*ZMa#Rl{YPPUNPPlfT44STMDd>WgsZ!zulZ^{!F2EBH5%2wH_23~M|MuybjJRfRPqOH&CJicboaX? zN5ouJpKY{d&co78i=KWr@ijl)F{NV9H_xNameXo|jgMKK4RoDmxjoY{zK2CQ?53LF zmx#BsK7=3J_yqyynx!LZm@k*~PlWmSx$~lJnG<1kd zYqreW#9iZm&0*J+i<%~3jxBnZJ%uCfu7A*2rMo(8)3J2HL+XoGt>L@G(BzW6^|XQ$ zhwdehY2j;JH!awqA@-)~`EmA2R^FN#`8>sPim}T7)jEc~d9_zlce=@*^zAO%)tj2Tv#VA%XkydefS>1- zjyG^}XY6-NuY6*0A!5VZz?#N#Kl#r)4RTGVv#PS`M*@Xnr}_0UYL@=U?7bEsHc#Z$ z5AAXef36vLjA$Ez2|Jhkpk z`N{ZZv0+7n{<5_qr=v7fxL@g6o=~5$;Z$aJ*YVDCrJGJX{usUX-?}M6#Y;Kmev3|G zJ%0R4`JKQQ7Z|_n@X$Py6n?6SHB(gCQziYdGY6|xnZQ)5O$V5-&e`j%wRv>yH(8FPL-d@o9Oz;RZXzsP(noY<8@QS|Eu%gVhfXq zTfp*3aoL7hi{|hIIJx=-`-Dq}fov-$1c$YA&X}=iRtEo<1-5Or z)55-e+vXsdTwUzEp+QnZ;Y{F^h9|uVHr(2^dnX7)S8H>}*e%l7aEP64#tgm*M;prC z&R}DZU`t9^eCUM0KOJq+gZYu?1oE~mztX_XEv6H(A>m*X>tJJeLtHft>Ncngq3+z$ n!peOuhV|_6poqD8tzVg^8}4?fy#978sDATw^>bP0l+XkK)tey} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/multiple-coordinates.png b/crates/resvg/tests-hinted/tests/text/tspan/multiple-coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..95e556a6d4401e1886d1ade37a821372d04bf7f9 GIT binary patch literal 1633 zcma)+doInVi==Y7t3&UsSFo-QaA zT@?fZfg-vRC|R85t=lDal_lnQUTW!eB5+ zB$A$<9tMLU5D4;8EEenH#fz))S}G?bB*=N!{;jie+ANCV>4k7uvA_7T*5C{IUPQ@n ztghm*k_&k!;wxL(q&wLu0oPCS`it9c1h!9Fq5}e#Fw;cMyKr6xwNUiK>ulc055CNUgLD-SzF&`c(r<{MH9%p1`$9NEc@>5tu&8&|MnM8$MI9^cr;IY%`*9J!etpaJ41 zlXq4g(=&m?46XOHIRNl0!$f^{f4VFwiP`gU*~z)p6HA@5l1{;&2L^ zVrA&;>zYO!2z&J(g&RSKYNabE(D4!CZb_hkkKG^!9L+A%1qP^NSkorQMvkV$(UJ-% zbXZewB(t%mg2Z-?X0SmRta8?v&;U3pUgAPdw4^%6*ri&)!ukb1);w>%lqCX+r-fTg zq65MZoIUI_`OBrf#C++LIHKnUq*!!GAM|*B2Pz80j;TBY1*X3)(?Z0#QEnr~<_|;C zBNBNb9^1fnVSdSbX@xFmr3Efwp5ka#-=+cP-l#&e1?+ose{!5n9E**Ee?%WAphXLq)@{*1Z94J2AVlO3_ga-(c$d+ zKah-w#F)-Sr`_nhAc1&DQq}D|iXG!*`mtr>voP?aN)0?<;Y%0n$T26V9>&92p#`c? za{Co1|J9V!ZdDTZIBuUWn`qz1q6@4p)S!*zvlY95);{Z(?cuZ15;Q~q{3{e_d^L6V zyta@DjA0t34ZQxrl$6*Q>|a)kNITl#Mj>yxosZ6+ zsEf3B(~)jAaT&&Sz&1U_3SYgee$-Y#4AHJns)1(k{ttKPf+PU>)2!#bCHJ#cH04K* z&q428?G-C-!YHjQ&Tun$g8kN{`UiVUZZD4)e~LS-1Xrf8MZdhD3sk#<=en6AO0XM~ z-4c1T2O~aZNnL-~e}baz4$aI4X`*jsvI89#AxQddIT3#!qcwFgYm4U?7R_Om11a#=d4N zYn)I|ulWpo9{7Dkt!BP1@HIo^wlD-9sfdYZmuvHrcXi^9%nvJdG0eEicjF~}=)F=Z zu4-T=axh1qR*?q`+FIDXuV2cpY;X;k_mm)se(?EC8SpgnSzPaAdGzS*4G6U2cUU`4 zR1quTeQtlbdFth+n>*dPxTB@P&Ho#i8mxs{BlGRA|5%yBYA2tz++$JM`@IZ@*TJ2C UAhPtI3cjv$qO&KV$SE-KZwZsp00000 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/nested-rotate.png b/crates/resvg/tests-hinted/tests/text/tspan/nested-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..607313a8b345e4eb9b4a2be3edb5029b715348be GIT binary patch literal 4024 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/nested.png b/crates/resvg/tests-hinted/tests/text/tspan/nested.png new file mode 100644 index 0000000000000000000000000000000000000000..c44914518a860a7d884970f9be56b60308637b54 GIT binary patch literal 1675 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT>Y0C&U#*0E_(wzR|A)9gRF3aa6n@Ka|3g1V=O}xgI0qUP$kgh`ucjH z70M0DKrRrtG`N7M1{eYg!r90Spc*iU$lI3=WSEu&`2{m1#Q#6Azu~>Yhk$|w4-&5D zAD%xk^Yz1>XKTL}+b{K>Jtu#Cd_lWF|AzJT7w(^*U?AXN|KCBmME?T=18bV6i(^Q| ztv43}1se=_ST{6Hi)B6Vc|9*5>(lDamXLVolBaS?`PWV{ygu#4J7Mppl#`QGy~S`* zR{W6=scAa&VA!9W^fe$o&zozp1H;m7iVk_HKlg0a501{tJMjPi9koq&r>3dB%ZNGp z`B6gNTw{|9E6je%L}qorJh>@h^7)CZ(I@;Tr0$yeVdJJ#>#7&7kxJ{DesYpaeW;7g zj5g*2+^H|cPbIaa_sH|bX|8VRpB9>XN~!C4Z|B$a(^B!8rw_ZIHu|tbr#y(uVfEwb z?vi5bG7f*@(>LR~cH;Z#Px0!em;b6xD9W7vI{1puMwj|428)&6#%?+#$Wi-g#+8Xu z^G%Lyi+xkdP7>TH2~YbENX*%xq$ud4w^Np5S zHoE4KGh}kB?sQ(&j#=lKan~=B`I}11e1U}CuQyK~dSZ}SD0t(c(_@#d?qV(?3x9H& zDy%TkkGv6*U9pCB{>Ja8y(YfCC}i2Kle+bTu&dOnuhprow>SN`bm+O}>L2=%Y+_L# z|DQH$=uwJ~3|qE9dR5W#gO86(;d7~ajdD<2WH>CT_bk* zzHWDPdPUsX=i1sGBGZ;GV`tbJ9(Gu4p=N|#bjhs6I{EoWA3h3e*nIl9Uu0>}y8^F{ z5Fueh=g39RCJJsz)hwJ+etspdyE4aR%YBx&F3+)8y6F{93agytV~=dPlWHZ+@7_&p zoof8T`O4Sli7Xsz3Swqus`|#utUJa3esb&k1I{0EE+-z0SSE7$(YwDoDKaxAF-)uq z4dS0Crr#mO_@H*v1!j%r+;SI(#oL>+GUn(9Tz#L~S>-GiwdO-$jh02aiuVpS3&oe-_v`mh;QzZzS?l*? z9rlTKFTIq{-jF;gv@h-99Nv8gr<5JwT5n;m;w|xS$+DxZ`tp}1S6g$o)UI1&pZCf9 z%%98aY?TcJSQtcjf88jPzwqO^@+t1OI>_2~BW%bjy`ioC~RiF9hQ()oi3&!6sI2F`bA($6$fDiWA~CA&3iAA@20vkWkC9+H!}I>GO!| hOEtstOHyC?GI$4Q1}S{vItwbhJzf1=);T3K0RR@$(5nCd literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/only-with-y.png b/crates/resvg/tests-hinted/tests/text/tspan/only-with-y.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/outside-the-text.png b/crates/resvg/tests-hinted/tests/text/tspan/outside-the-text.png new file mode 100644 index 0000000000000000000000000000000000000000..f192fbb98e360805e2ab6edb44ea2769cc40b33e GIT binary patch literal 699 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!uEe%EG~&sHh_#cE~A0L8qm4gF^&Rpm76GfC(tx!U`1U;0B5dhylg_ zuFHLU`fDCLrVPC)5fBOXI+MbRPe=i2|I|)ue3pEmS5*ZJqnurvG(@!5}Ly1!YX8oy)xGKOCyg%{o jnu8Ily6VOT5!K9QPBL#-gv?0-CQ1fRS3j3^P6ERyYg>V?y=w4#r?s5SE|c>jMw1i0=!On7)@m0U9i!P?(aE^3nb^X=`g6 z7#N7fV!c1C=;&w?iG;)9@OZpHAOHxarlxLgZommLe+}gS_%|1)kAbk`iD24(jPUTG zRZeeScVx$8^#|VJk7b~P)s`rS*Og=_z4guxh| zr+V*UaJA#Qxwt_Zq?&ZN$231O_2+|oSK*>*bxUKnYR+I=D>`q52Trn2cr0nR@Qe_i za-HM>HO)+w3r|OR#%EfbF&?a7ks$Vm{flOseS8P zuJ*yR36@H4&OE^DyU~5wS5)EpbLOR^hNuq0xv(?;uz9ui0jzEcc@^0VS2aEELyk&L zhVY_?(@>wb7zUyXASBRf?TrJJ?3^ zZRQw*H+9Bp9HLjpSZlY%v7_ky3e?|SZ_Q8d-co|!<4&o(_VTiKZ-BfbG6E*v*a{2U zMNb!+r-C=CT9b*v_Peja_lP}zYcIcQ_*J z?b$B=EO(fGw?!FTnRB-+qvZPcX?Zm}7UJYPZ@`r^)r?faN!=X%aT<$=Jx7aoHS#;y zVxaZUyC>h4LT01OCVTlTE zSd0>*Z$}R|!;;7(y7sIk+k#aOTQaiEB$0w|v(O%og;^NKuAIFBv0X3Oj71+5i$yMW^KOprW(NX9O(6teTQj z@KD>b?Y3c$c)x+DD6+5k6Cd@w2$B zoeULfswwOhE~C)CtO31PL=7QKvSIvZoG$pnPHjA*UhmmfLt$s{G2nDb;?oasIbAbL zPI1Vw{EQOdU$pb?huW%5kGB)^Vwv)ECV41aeq#vAthD%C5#^KU30hbV8_A_i@<^!5 zXoyFd1-s@^r%j4gfKHf&yAU(ufA3wu}lOG&+#Nj0ds5GeM;9LjgFg z0>q$_f1bdvs-{dIKS#1uL>-Kj!XVNNA|@>N@cz8+*SyrXv)oxr-=(D58IzZ!f##07 zfy_ICrTL-Bybk>I{AA{m!;_}y_tQ2jzvRs?7A{#YynEN=JH%+POj!3HLKb6`#5}WC z-Ll5g%u z37jsje4Qf7_!#{hlWgNQUQf)kVEhQRVfo+ZGs)MS`6tdZ$^0NsmlvTr*(A0yF+61F zVe6o-u5d}>GyJ5*o|j+4UqB)uISsc4ad$Ycula{kNKuQQJKiYEsw;B$1 rMjvthr}`QJUEZ4iR7i=UnOsZaKbN^D2ns%3{_RmIH1FG9hfn_tf?0ms literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/rotate-and-display-none.png b/crates/resvg/tests-hinted/tests/text/tspan/rotate-and-display-none.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c7979628e8488c0604760cdea701055ee3d7cc GIT binary patch literal 1399 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXO3I6XFV_v4Y0NMxb~@Lj#(u z3m5p-Nur;*RN z`({pV|7GE>^{5if=TO#vVZ^W*Mv!x&Y5ydYWpRxp84mWonAb{vbg1w zcicr@n%#2>k3PM^@ouSEq7A!2VtOQEOZ~0iAxoJ&< zSoy}tYtz;UO0W4jck9eoZ;$V_Ilm+6#3rX@x9?9_*;IKmEmHCJe#Putc?1Z!t3ViBnbxN@12hP@X|I&It#1nrAJ4k_YNDy8zMDDHIqVB=KQ)~y2ZPtVpfZ?sC?^yKV(*7>0zTdpdkt@Z`#oBgAGsSl7YR(P=G8I~8kzpd? z{EN?S`t<+c|BQA%9fpoZ1%`Ex8(;6gr!LUI%4DqCLuB^TqddC;%LClGy%pjPT$KOj iZ;LmmcLy0QG_n6|qHx&rV_g)ec=L4ib6Mw<&;$V6%5hBq literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/rotate-on-child.png b/crates/resvg/tests-hinted/tests/text/tspan/rotate-on-child.png new file mode 100644 index 0000000000000000000000000000000000000000..f6fb88e66685c421f0b2f63b637248c54cf61fa4 GIT binary patch literal 2067 zcmcgtdobIH7XBp>kswvJ9?|yJquWS+HfU{&UhhY}RfGhUpI%ze&C*cSB9Ur5mQs%@ zO6#$d+)7!CxJcNwo~QZ8BYb&jhk&)8+--FF& zOSPED&QCI9rl%Vju-vm?3ExWYLBrD?{Ic=-_r;4dRhJU@-?k2wFa;&W?qS_Gxs1>x zdT0ID*-ussjwsQgkLusk06_MQqpg)!-1DVjs{QRf0M=nvrizZ(8CqW!f*v486q<9$1)0(G%m1_i3S>iBj7 zrnkQPBsSm&qZ#eTcVqf39_gc%y16GRe%@zi+jl=ORC@~nwc34v2OiCs)qsKps?hq} z>fsBK!-m&ya+=1hY@nL(Nt9UTeTlhz<=!^_rpT%AbN89XTih*~0A0{sL5!gu<#LP@ z@9-P&AO)Bmun{?Jb17I^PS0jbar$i-c7o4n`Zx81@WPZ%3$Tp5fd@|_Suv9WnBjz``qZFk zf2J3S@6;VYoCb}0T;;C2hNKH`osow+1lwIj$>~|VZ|upmpe59M(>&w9cjFKXUanv^ z%Gbu={;Uft7hff+z1#4{?jTu>o8Q9&QDpoz1+glA&HGik#>)Xfi@ z`-)vfJP=P=GVMI=do4P$Xy`NLR`hjBk?>ZicYoD(dNYNTR``s>Q^+o~h=|(=(|(BH z_yq<(t@4Q_h$t?|^Wl{*2UU5W-S`z>`3{ro(iISxMvK0vPr4l%$C?P7lUt3}6^-@j z8F}MOEbHJ$!n<)+xTeeU_EXR_pLwyzf-PBLaPxr&psi%B7DHCQADm)mq&P%a=>tC` z*{eqOWws-uDoCgT60rCd9*!KPmcT}@%}Y)qXFJXF=;Mj~#R*(mtQpTYIQ0mZ9o!Z; zCnOvm7NEp9kC+pneDCaQ1E)?+)@bwXj!5bkSm%HqHuMS)OIv!4<$K=Cb9h`FQ;>Yt zOp$bn71%&8iqU<_RPKeH!O9LWv1;;p&0W#G?9;QO#ypwqU4vbsWzO=eoS5z+=9>?` z>W6wn40cGepT0addm2N`{|Q8!ny(rIY(;g}KN;GknT(%%mF;zR80TOk93gH1UY`?G zn;$jF4}#F~qe?>1f8oVI7~1l-k^VEL=s7%?nE_v1T(gEEuR33j$UUB+t4Oxg<}Va# z+!^eeBv_7{#1MQy1=ay>sm)9qWC9(yT;Z4-kUFxgSO6EFZ^~URH_-aQD&j~qX|J(t ziu)sj4ur%z+OyWY8qZFeRjEK)sNjE`CtgXs^zHBM%Xwi!u+EB}NY~L!Y}k*lpU`cy zWx{- zs@~`In5TT8loHc~ri05nf*UR%7lb>{9!vF%s<3iv;4}adG_;e7J{4v>=zih2gc-|h zt$QrlC^v~i558XQQz&fT)iO=_?FxC@bKE?!MzdoG$a0UJ)0zE#n)OZq>QDRXtIana zmn;o!J}%reEa?-eTuI&B)HwL0_UdVjIH{DzU=ts7Af~22?rdm{S|q_*w)`m%1H~n2 zUZtL-En?9D$%N=`y#<5V=4Ey#q(YoVTvtno*46tCk6f+1F;;-OX2#>GCGF>-CE9Ie z)efBAXGq;;zV()xXtj1@F6t*$)*03E33L|O<^>&ap53W;rG=Z3^Dx4sGRO2U9**=n zcxz_&_^rJyeyVG{2TjU4&+dx0)KWL9YKc;#33vx!=9+ v|Md(lsU=BI`U4Qp^GskbgHslsV;`xBDH_+m9?GSDvRFquH`|BSQ1ZV4T?Byv literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/sequential.png b/crates/resvg/tests-hinted/tests/text/tspan/sequential.png new file mode 100644 index 0000000000000000000000000000000000000000..a307cb9c2539b8efa98db2621f39044b9c4305d5 GIT binary patch literal 1906 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAcrHsC&U%VMSund2I5g84#f-% zTn$`6bNCwgASMep2)i`6NHj>WH?Ze6=2|sa1vCaQG&0CG$O1_qVs2oLZH#4S{~;{= zj)CF7i_2aj7UmF@4>g($R0yZiu-_6aP5*xcjOY1sN0T3}W{{fPGe4ij(O322> zMxaGpCiPN4=SGwS`2{mL{I~zV-{F8j!+V7f1px*V*59vBxbR@X`3?O759eRcFF4zN z_;u#QTK}E-@n4HypY3nI{&4o3+Vz>mOY{A|&cB|p;KGLb^Y_<32q<_zLEwXff<%oh@gqG}oSV)Xcxe z*ZMa#Rl{YPPUNPPlfT44STMDd>WgsZ!zulZ^{!F2EBH5%2wH_23~M|MuybjJRfRPqOH&CJicboaX? zN5ouJpKY{d&co78i=KWr@ijl)F{NV9H_xNameXo|jgMKK4RoDmxjoY{zK2CQ?53LF zmx#BsK7=3J_yqyynx!LZm@k*~PlWmSx$~lJnG<1kd zYqreW#9iZm&0*J+i<%~3jxBnZJ%uCfu7A*2rMo(8)3J2HL+XoGt>L@G(BzW6^|XQ$ zhwdehY2j;JH!awqA@-)~`EmA2R^FN#`8>sPim}T7)jEc~d9_zlce=@*^zAO%)tj2Tv#VA%XkydefS>1- zjyG^}XY6-NuY6*0A!5VZz?#N#Kl#r)4RTGVv#PS`M*@Xnr}_0UYL@=U?7bEsHc#Z$ z5AAXef36vLjA$Ez2|Jhkpk z`N{ZZv0+7n{<5_qr=v7fxL@g6o=~5$;Z$aJ*YVDCrJGJX{usUX-?}M6#Y;Kmev3|G zJ%0R4`JKQQ7Z|_n@X$Py6n?6SHB(gCQziYdGY6|xnZQ)5O$V5-&e`j%wRv>yH(8FPL-d@o9Oz;RZXzsP(noY<8@QS|Eu%gVhfXq zTfp*3aoL7hi{|hIIJx=-`-Dq}fov-$1c$YA&X}=iRtEo<1-5Or z)55-e+vXsdTwUzEp+QnZ;Y{F^h9|uVHr(2^dnX7)S8H>}*e%l7aEP64#tgm*M;prC z&R}DZU`t9^eCUM0KOJq+gZYu?1oE~mztX_XEv6H(A>m*X>tJJeLtHft>Ncngq3+z$ n!peOuhV|_6poqD8tzVg^8}4?fy#978sDATw^>bP0l+XkK)tey} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/style-override.png b/crates/resvg/tests-hinted/tests/text/tspan/style-override.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a2b7732cb453e9642b8813886a2c3cc501504a GIT binary patch literal 1701 zcmd5+dpOf;9N#S0Wi4!#(@sY5EXySo)#UP6a%rTjDVJS1C2|*$`AtObVMB`CLUy#d zCYtNWnHo#eqmCtYq!N`ilH;tL^Uryn^E~}|-sk&%KcDCGeBSr_dEP(X%dP}_bv11@ z5D291aLCRL1Oj8fZ54=IA(YeY&N9vh0)ZQWjdI16;c5riVE~LL;3@C%@$vG@<%8s+eB$4W0Rkm}K=Ka! zcm3miI&R${=N1uegrgv`53pk0VG=Ss=PJA*8H&F>`c@i#my_dvrl&P7&dz1;eZth#=f zhII}eNx@0!bfHb}n z$=Hd>@}Zt%SMU1bl(Pa6Y=zbg_|-%%6p@H4<|OCAbmrGjc>iV^ziNzIHYv?ST&MJ> zy0p;v1`=-B(Kjf=edRc8>~aBJFcbZuLsPK3n-f^{wx!i;SyNmJ`#oQFA-*Jk^k9GoNq^Ki3_8p9 z4|2#)gKth3cXO2P<)C}R_-D|>IqOi;X+;MGta}|o7cpTo&|_O$Mi|WZrDf^qVjmwt z*J+h9FZ+dCRv9Ds&M|~Z2v*XNM6zs(4i`RiEz+UWNQf5g`_+`SoV*D&(+OE^QwkoV z&e^!|r4h{1E`@VdpazF4^p_>!mX_OTrb(m)Q~*j~ew7-JJ7Lx77ON%5fhLbSG(%3H26YUH|aie>QT3?t|T2jAIkG|P)JhFhUAUK}I zTV_0aNgd|)xR5h~D|fKBY^4qZhjGZyo)#AId8zmZkvL?r?-Sd3D2GUys6MdLdwGM(o%`X|2vt9_9`fPHKF=c5x zqOCAD5CN4{hzyKk2~A=!v9@q>>T!TXaq#&L>cn~CBX46_*BycMQ2!+-*>h;EPQWNH z;P61!2H6aFs`;rlGUMVp%7h3t8T+0=F!s~C--~79kOTl{|@OX(I%JNlP9=7y?0k zeZ675Aw(QPYBgwSYHG&C#R0j>%E~|kl^c}dY*|@ZWW~Y_!pK}Wn~MwNYj$>axCoHT z+`tUs+W1?%0`mPzg8YIV7z6|q6buaP?H&9B0^;Kn5)v}Avhwo_3W`hW8yea>I{GI} zm^6F#>^XDh&tI@$>9Td}*RS6I1UvWdKXBme`STYp+`s?e;e*%j-+%b~)xx&cC6ew`~;mIiNDGXxw1ivx8WIDL}f9@kku^+(^U;pwM{7CcheQw|z z8k-n;^*Yxjs|~M2mNc<)i|Isc_@^DQA>m*Xt2dbBo(5tAC4l7Xs%D51s1QUQSQ8~8 zYs!H(MZF8;USp`Y3TV*R>ImK6E$xS9-QKshf7`bFe^%Fu*F5Nms1%LAlpf*TE_yxT zscphhU)iubtYP=qwBH|H7yH7D-#L)s-d6AAXR66*?@pcZz4t$}uA^UueOsU6JwdZc zvM(p+m*uWs#vPVb^wwhX&ZuaQpBp9}_Io69W&_7@?@ik#A5D~$bJf`vwl!r{wxMXY zTaRv_!s%_3w=CgG(Wr`evm>{%_{q~GXvNHa!3|Gd1Z4=mo8T6ad}(=2y2P=$SGpKaFTKI3d5G&eM|Wau z>2Z#k>lO>e>a1cpK0RRe`3mop4eMIY$Oiv8^=Rh9q@&g6en_bc?wm5sQ&~skq1npB zh-jari#_WFCO;~lS8_<`ZRp&I>X(_aPaa*grMyjO7u#H5`fxiTzHv(zm)NiNS;=d z|H8v9%DaIk@mx#_G$_5Yyld*4PNyR&YMHIA{$YlqJva28H9WohpyYySM%&cQ^ZWvV zdK$hw+8?p+$A$|3q_Y$9BHoH8B+9Ay-b#!-f85FIK-d2y-Xl`mC(6cd?0J6g-2)!( zy({O*|G1ogKeth%2QVjLsi)`nYuJOTRCNZXJ_6o3N(B-S)82;qNvP)q+R85)Ru) zXm?BQNss<$pkur!BE&u3isSSbOBHARm9s5!`!ud~sBUsSXrQ(+A((Sct|R}+?)H-% zNfQ~@YS;fas7mc+@Gj%^6je*{`XUl3=c)76=XJ%Dhl1X^7UEZhUaLI$WqFS~ulmt8 zk6fAk?Mkh!uhW;z`Z?dM&U4Mj179~6dDcE&?Yv~l*)&5Hr-&o()_h>_{<+*V|I)#) zZPvUhQ4uGCzI(2Dqx@FbT~Y1i*@`C{H43E;O`V;_H%)R!-M5odcKllQto*>N3h!&V z>aT_S)AlcL`pW%W`_a#POC@g2;+6c8U|spaW>22S>SG6wtp2RFW+ngmSI6GP&unU# z*2Liy;5)gb*+ukh;{k`jDMHtK-tCjOUBz&LPc{Nr5;-zh%at_UufKeWlTSlM*=3qe zFWsawGb@nM}QK}mZ1q7p1lJ~KZIELj;mUHx3vIVCg!02)2J Ae*gdg literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-2.png b/crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-2.png new file mode 100644 index 0000000000000000000000000000000000000000..035e35b7e597bac43858d2bdfbae671286feb9f9 GIT binary patch literal 2823 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 T65LMT8p>>}9Pq`KaMV8mxG3nu literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/transform.png b/crates/resvg/tests-hinted/tests/text/tspan/transform.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-1.png b/crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6cb2f1fa9766b47326f5d61bce481f27c9e515d9 GIT binary patch literal 3762 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 a8Y#~RC-+85C)BTHQNY&P!K%W7nfPanRU^6p literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-2.png b/crates/resvg/tests-hinted/tests/text/tspan/tspan-bbox-2.png new file mode 100644 index 0000000000000000000000000000000000000000..478c7f069bf7218dd65a0da4c42003a4cedd47ed GIT binary patch literal 1688 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAcrHsC&U%V1%U<-AyENkfVfRi z5rG;8js^yi3I?7U29^c}0f?GLkjlo!MutX)hK2@FuwZUuZcalEPy_@TKtya~Y)nH; zKx2S^gFizD3&?~u`;M)mj)LQXmA1PZ2%ctUtbSlYc*&A z8OqAaa8kH}fg9+sS_a-K21c-}fJOmjB^o3kTKF3HfDEn%E(jM$GB+>-6|>he2$eH% zRfDVs3i4MlFxG>ddiL4=Z$QewB*-t=fk8k(K|#U5-rfNU`~%|S6A}_Kv-0x`3W`f= z>wr!J1E4G0+dKLv%$_rU!P52XH*DB{016JDzi|Ej!w2s_d=*rC%Fn>S^1;)^F{I+w zn+qES9UKH04j9V|N(z;wHuG+u}SQ9*jf~M^uSbi>6DvtWko6O89kCSGq35c zPI{K%ENQjCK)mdNbn=sk)XE1BdJ9cAaBn*FGvjb1GmhIi?1zOruOCvt~Hvjl9X#%oevbP~Cbhg>tU*H_EpZ$1S~>{C@ge@KiBZO>-i|EW7?%zx~X zYqTIN@}}eqv&wn*?fGn`6bl~fjI#Uq4>{<#EPuaQ@5ZwuQ$K(6 zmFzCiI&y}k>#|kq&t;zf&abQZwX$G3_rAJcTLd)kKbc?oxqiyhg91~RZVH)pDkxIx z^}E!H@Be_rv^AfAtbH|-TX^O-p1Q=a4k$an_Wx;r`#(QkpI^S?e^&m~sikXo3Z9)3 zwq0K*q%8CA$sImc2f` zzhUh++Y9eszgag$NyH|g`*QQ2x%<*&OO*dkck@ap}(NH!a)bkqSAWBJ~WiQSisUC!NGLnz`k>be_gK(V0GT_tKtGF6zG%vr>)V(S`GmP pAFTzKQIodHx7tQdndI5|lkxnDH%(j4S*wAHS5H?zmvv4FO#qbt%+UY< literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/tspan-span-and-BIDI-reordering.png b/crates/resvg/tests-hinted/tests/text/tspan/tspan-span-and-BIDI-reordering.png new file mode 100644 index 0000000000000000000000000000000000000000..777d2c9888db8ef154419c02f7cc624e67641e7b GIT binary patch literal 3849 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 UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/with-dy.png b/crates/resvg/tests-hinted/tests/text/tspan/with-dy.png new file mode 100644 index 0000000000000000000000000000000000000000..9fff45e248820e42cf5640551f3c4b25892b3a12 GIT binary patch literal 1609 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`b-6XFV_8yXrK8ykTPG~nXm zf-J(t#l^?RCm|srEG*2<&Yqi_Yh`6sUtbT@9uN?alanJWD;pad%goFi6BC21k$5)K z-q*E2)%qnte!&b0@%se~CfrYGU%%i%{=@5s&%Vx_IA?Zk*3ROuCGr0A`|HndxDfDO z;X^^g0sH?BV%xfIGBB{(c)B=-RNQ)VA&}95L4egjfUV;1?M9aG_0cW7rz4LTJ<(Fi zzc!6&o4vL()_4<;Q z{(JvF=IyZfd{Qar{Uy)EOXm4YbwBK%tQr=0jc1xf-L5qntLrL%mZ$PMu^MpPx8ODA zSa=|s;p^NbE|Kv*@~O3!u2a4q-NK^lZEvH#evi$miB)&j-}RT|pAmR9n0bQFlZ7WQ zo#&M{iWCZQSUhzDcS+T+7YR(0r(kYG2S|yPy zGXxxswq!N@$`z6l-LvLuNOz0Oi93^f=cy$wU9^Vh#NW>=XI=PxVBM=mz1~eh4cFFw zH`0B&C9@&UHBwBWka5M+J&wQP0>jQ#OQ`Z}h}`8K`K)+TRKcpKDOY*z`ew_O&y`AD zI4x7UV0DDfhqudb*UT-xDV+NA{^i+Ab6Hgaua#6L+m$9a#VwV+;2xRf|Llg$T*kxE zQ~ej~Sl4e5o|n>U%5d~skrHpfv{ejzQ@YD$^IbA4ox(KZLP{t5q_9_4iqn>Ad%V=! z{$^T&^ei1ohY70s`ugWRnQv4Uhw$d*o|e>%+pqA_d3WN*^JZms)AsxpcivE5KIPu) z0*%`j7sUU_p7XU??|)UKb^HPMhMx~VPhRZ&;LD3=e{#~F{NGy`Y{B?0@9A%u{`rL^ zHCs0qS8n`V{X;KOzK(yo_@>JLg`KbY?dR>c3C@Z*^w06K!KtoICNt{8!m?YrR;*cY zb^C<>r#H#8$xm$6Tf9cUUE_84O6TcU*Ij>oa%0gN#`)#JrE}w^iKcQ+ zeR5#Ynm5Ips_vYgXR+zqntpl1DMwwWgsw{EQt6jWeS6X?(K5**_2{BC=T&NT9o8?i zNt-g&YfhbJQiPXIvG+ACi^xllfBPJ{z~H+}HJc+a?EIxUMapfHj*CP_c5Dh!J)3e; z;@AKBx7&P=F5>i^Rd zUaEh(U*g=S8PyL@3I(Z8u>A5X_hnq>|A`9I_ns9mdAVOl+x*y*tiG*#4VP`p|8++D zw$icBdzCHf?{58gQ{{1R{=e&dvJngnhaDJnm?rpY{q7I9I_NC=&dnln6SzFNRt=#+ zMGy@O7)5Xymx7i0Xz4v|%{`W1X@avtg%|P73%gTe~DWM4f#&WqI literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/with-filter.png b/crates/resvg/tests-hinted/tests/text/tspan/with-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/with-mask.png b/crates/resvg/tests-hinted/tests/text/tspan/with-mask.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/with-opacity.png b/crates/resvg/tests-hinted/tests/text/tspan/with-opacity.png new file mode 100644 index 0000000000000000000000000000000000000000..4da5aea0ed178dbaf0106ec63837b01523125a07 GIT binary patch literal 1822 zcmc(gdpOg39LIm=vP-!{);MG?om`e$HL;{w9M_m}7#ib5!kUKew%=G&J>`-`9$Iqg zCf}@JpI@AdA`r<{d_*}&*%H!`+J_`=b?=- zMgRby?d9o41^_k8=L=I;Rs70W9x4=*e1qIo{Pv@xqoXpbtAAdCLZP5gC?1bTAP@!y z2DY}grlzKrmX`kh{#Y!Q&1QojNFtF`T2-gh>27XrsxFmE{g&rA9FA(-h3HbLa_>wb z`vn4o)xDssaa+#Y657bi>(8Qn6CR=~z5 z9}{}#V3qrSXea&;M@fhVkMnNy}KgVa_ST*K3GsY&+YSiTzUEC4KiY$7v1m<|Ru zjS|8f=#mc%M{T>=w_*VzKa*7Sjsf#=Hp_Q(66((myEGb7%bf-y$}S^Z`eXz#|} zgNv`H&+}OtA?UdIWKQ{^R6m#O`)Sq2NX`4Ld4R-0`<&~sVS7|5_5*(( z!m(SrWkGhzn6khF(S5J!ij*|MI*hla#>&hNh3|ZI_zVp5r?x82;%Vv{w?r<}!}SpeW4P;kl=$(2{%iwR+3b}%o=AcGlMyPxhMruiQ5Z?edv7u|}n zUKpa~dYgeEI?Kh)30SVfeg|$04&tNEXymnITN);g=85$e#;(HQR#O+np0>~xo-d84 zRSaHD-xN!8l1U@vW@lSYiyzuh&S)T$U55ll$bN7aD%9wm5yigbI=-o(#xeouEK0A{ zxSVT%BV98?M&Wsy=Zq)|89Sx1TRdpJ(B%H4i|#y&vmu|1Deh9xYN=(;hyo|=f!np^ zFK#SMA0wBWWa3!o#|UJkyhpdQ3)Ih9Djw^SMQb`M*9$uYHO|~q>yc}u-tU3n!`)6L zyu596yA(g2AY1Np7IFlXmEU==!kg_tQmztLhc-4 zW>}cWywxP(!+U=mt-}ozp1iNDE%ga>xGPv2yg9Nzq0=U(AaP^9pQ~}^;_MBAU5Nj~ zKFMJ$N=80grFh*@bg13Spf`*S5oQKZ*+Zgw+3m%FYuc=nN{DEQ(IrX{R;H}^qfgtA zv6KKzDm%+AaGt*&|26w~{p9qqw1J^Fd9Ox`o^7oYF+^rG#rB5h49+4o{6ReP1zW

n^N3Q_5;NZ!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/without-attributes.png b/crates/resvg/tests-hinted/tests/text/tspan/without-attributes.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/xml-space-1.png b/crates/resvg/tests-hinted/tests/text/tspan/xml-space-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7f9ab70aeb81d79cfa24535910d8eae34092ef80 GIT binary patch literal 1594 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 AIsgCw literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/word-spacing/-5.png b/crates/resvg/tests-hinted/tests/text/word-spacing/-5.png new file mode 100644 index 0000000000000000000000000000000000000000..44c765b17c082c6dea827a911eaf52e3aa67d22a GIT binary patch literal 1723 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjaEC&U##jG4G0J@G&GcukYHzLx3aR5l9B?NP+woKrKP2*sR?AKrltbb zl$DhU3kyd^Mgn!o%F4#Z#&U6iTtzAfTGIatsK=rt$S;^7A%4F=fx-Lx3m(L;Uw{2; z`~1w>*@s_Gd_Q~6(q-50T|RvFeE-hkhxz^&_HQ^pAt2#Hy~2S8`~ME9Ov!o-46I$A zE{-7;x87Vh$m`%Bz;NK`+$NRm-|u@Ws^3gbS=Q1y(WH09< zFK1C%(e|~IH{59pwRyU25AUZdei_1-^QN9%EIWN>=+34;l{*hr^>2M`w|?@Iok79! z`?YTWoVa!C)_H;1OQkuEeO)m{>-zFbYhGGUtqIxFFg5t}^f+&&y^AJI-#5d)h`C2A zGvr&?x`{d;xB4_J=IJftd0pO7GJmSOn1vt1JTZ=a=AE*}jdxD3+01r1W@hAUlXD+R z`LB6x684xCr|k522G5fhoeBj$4bPLO=*eoVEwK$cEAN!kthBoKTjcEpJP~23yZ0TC z{;)h&X2Q;?rN(JY-AlKH`6mSRulcAI+^~4b>IKbH9ioimx!z1Nn^Izm#%zR(Wp-kz`ua#WryoqwZa)2^LEumx&xdzQU~Rc3w$&e(d$m zZP7DV#4q^0;fUrg-KP;eHB4WZB}9rAvc+9(eJSUwK7%i8zjmXm|I(7nJ)KE^>YUVG ziRTl!~Ztt2|4HSNXuWXQO>2Yp4R`k2 z@J{Ai?D3mLxbL3Unl1NZn4U_k5vb?zPGu3w<~MG+sw9-NtUgv><(*0LrTx-w`J7=| z)n$jgX2os{OWqJv(6)hT&!W!FNetdxTZGs@KPr=awDZx|vamZ-q%Z7lFRe5wU0ay1 zm=WM2z1CcC%HjFSoUGOXTskNfpo zFV}4OUwy>r{;HYJJ+#-B^JM=Po02A!)+yD#)LCj~+}z!7Cf#pZI>~35zp`fGyw!I- z-@n_HbZM`2)Y{Ys^=)5EWA>jDe_pV`Vt2mr_i}!-dGg*S>5AtRZLHfL#m=z}n0oK~ z>pp*RcAay6+q$1$IJf`7!*@@#&%FNeh4GyJE8qG}vp;<}{<1Li?wJDhdmsPE$gP^X zZk@aIuka1~dR|Z0-!1g#Pye>vyX0j5O^9#J)cAg1dS8&HNOi0I6MZG+dM zKZTo5+G>2?uuoaMs$UH#cWEW(wS|RW{#wM#`y_L4D<`PhZUT34v+@Pgg&e IbxsLQ0LMW10{{R3 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/word-spacing/0.png b/crates/resvg/tests-hinted/tests/text/word-spacing/0.png new file mode 100644 index 0000000000000000000000000000000000000000..218adbf5c98102eade60d91c53379deca81e31f3 GIT binary patch literal 1728 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhkNcC&U#>R#paN$Hm0~O-M~mt*@^KGL)5-Wo2cptgIv?B!q>94Gj%rV`Fo3 zbG5Xz*xA{+xVV^^nfdtmfXaxp5vZ)ed}lF`vMdSm3uZ`&-!GtG@czO5fCcgU*Z0r& zZ?AoS{_y2>*YC}lyeH6zTiNE{eOoIKdvM)FtB!e zx;TbZ+6Vn$^{E0Z6YLuAcRNyB-c8T6;|{ySzvjN<`yGD*Bd5(Xp0z2k>hX?ke7iMk zpQ@x4^IWTnoOb%US>?;OVb#}#^iQ9&NY=Q$|J~H}vVXQ2=!r9%c6H=L@n2u_Hp`ZA z^+p2|3Ht+D;dL!nU91@%`R{Sw@P}p1vPbJWKQFi)el%&CT*7g;OIWp62NvdEx5U`{OA=meIv+Y6IdM?BMv&{UnBz#o<;-l%`^mSIqpx?{R~0_%Eq zPR%EYMwfVxtO}1<<;i$#p7WC1$Cr9Zbl&Z|enRcgmd`(}H?*Xf@6MA=*e2A)ydmZB z$#u)hLfQqLuj;Sq-J{g3uq}sUYH){O#O~x1KT58=IW&n;_Vb?C0ui#eW!ge7o?3d$ zVa4yZ)TOI?9Ln1#td)7~op|!_Z$q5ec6$C;?3Cu zr*7YTvgIt$j~5FgL@Q*)esADu6tlkDs@gj5?CUJ28?`1rRjpG`yGj~O<1X@9>v!9LLrSjBd+N9;f2_RZ&?NZX|eDQmx4H9k|( znR+N??UXqG&$bb(nr=o_UT2(X$KuVK_)0rpBxQlsDG!^aZ~pfryj<;jYRSz%VlS*x zauQ7qE_=P6&zt?-Q2qRoGfAaV)BFmJtT!z2+w$qEVnlA~-2B6RSY{+;z-@6^}ayV1?QQS40WXTDo!t#8)usyw#LYvl^wefL@B zKkGkdn|@DCC#AUj_m`sI6xj7!VK;85t=hB?S}#vdhZKfQHo9*8|Da)Ko4mE@fq9D=RBmSy>4QiP+d! zVPRn{EiHC-cAyl{B4%c0K0ZF68e%MksNp?(a~F_hRTAVE%#aYjUqHd&{e$}f3*z^$ z@1NhEIlK1!`;NvNO(}a7LFzUk1mH5XWrT&EnzieOF}LpaLJgkP zwnl8+rvqfTW~{BL`!61C9e(j-T6&K7ouz-6#gELlne?1x)_)P5ST%-=RqNPFTA#8z z%wT+IFCTVPBO=pQa7~9!{@T9uqd);GJ~82gzxW>2pPji>l2v;i*R}oy`a%Ep=y<<3 zak!~*SMA+ym*-RV3EkWv$@zMN_UXGTukZPyXZ`uz(mgs?gR{f}rrlnv&U-4jecx;K zcTwk+7j3#K;(yIGd+(DKtp+9%_6vg7{ps-Y_BNkh^QgDssk+S8NhQ8H(YF&rbP``4 zoV;d3*12VsE}PUZZF5`76BaLj&40p+;xNXWYgVNRWHgGhCI-$FIHiz1SE|Q0XQgjk zic6J17<1&r*&;&R+6!Nsw$9wpbfILiivQtDzO25VAGPQ0Y4N!wp8FuxeX;T@vy8Mi zv%`dCKCms?Su|_n&$(ZXr!jT!eWxbm^y0Kr^SO!u&6zK91j3Z&uDCO4-9}F4<9^E0 z=NsnjzCSnenBV3}->w$UX*x66Z}~3XP(~JQe<%5(k6JH^o=q`WuC6uhsmPnDLh2Gt zQ;TOk^3l3JZQ>9*WmfmPmJ8J+dKWGLw!?x5w_;%Z1#8c7HW_EG z4h3z^Is9eAovo|WR8DCf{Bn4e+x{unmgs#vGI?s9)|&ldf-mz~y_daBQ#7ec6irUF zG+Xykb(kqJl~#ZWVj~AOglv}dh3F)+6_f3jve}xpt_e$r2k-1_jic~(ee#e%Nnb<+&L%q z&Q;2mbItqfpYuZMS&gmdKUwfqv2mIBG_Sz~QSw>HmRe@pE2vcJ033*P#fZ@A|5dOiQ^PhlsGIX6dqJ$y+sEKOkA z?tS0(Rq;%Fz2;nXVrZU?z0K|}@s@Y>&M)J*>?E&!uKT;~?wv!2pZ#qQes*~GZnJy) zrevIUnB?Xl?1eg){Met<{?JzrViTwD-=hkXZ5Yv;N+r|Cje4;(GP^ zd0Vom;qF6H0gI1L6NpdbUBP$l>EFbCEm6ELxU`RIT@8w+k2)7&saf zI*Q{j*h^?IFr+D;sa}0e;!$Y>E4P?V#D;`}O~{Nje^L3EDrhMJbqWi_WtUb!_1wv?H&EgXV1BE{oece@%8@a1>PHcn4nP5kZ}LO>#ThH{|<*DmwPfW zuuk%HaSW-r_2$Ax-WCH9)(!R7H+f7^O8xQMpDn2=yeXysfz<2^E9^MG&fRKtplZ`D zrY$;=o9@kQ1(GQzCt;(kUS$X=S`wEQ ze4lp2Y>E2q=8Z9_m+kicpS<>{%-jb5q|L0`J}&p1_3UQ>uZzon%Lpq!hFRBFN?qU# zo5u86X2$>KMAwUU8%&;U*dX=k)>Y0!kLGiGZx&zk;J}7`P9M(Or(gYjkc*$^HTR2i zL1w*=cYI+@T3xc+pqTqsq>BP$~tCN6RjKXP2cS zb)sa^?vp=ex;*pXVr$K`)eD)FFBk}{ zP(GLyDrULl)28!#Q~PeVr6w*{-Ih|F5V~P^!U5$M7Ac1}DBVk8kq=n0_+ZhcP`_16 z=lf+}oZqCHaCF63js#;eqnLHn0>g6rJbmmZy{p2p#m zetLCX#L>77S{G#h?B1}(;zWi-*k_BdoUg(@nM*?avCd^;4BJY&t&ORuNz5)Yd;`OKCme}#be z2PRGOIzQ=;a|Gj_tk6^IO0TB{-_)wSE&liITA2w?A0{Xsa$Z?H^I7Ao_NB)=4EAoA z@>Np%tDa7%;z_T7St@hyeh~Yl5&EqD)6EZi;`hh&iG9c{seTx)C-?5w&!>CO z=t-V@!1<>^UGnaodkS#`g_Uot>F z;_s<@{~jCK9h92z&}!bgbo~j_)gzc!2^emF#ggrjntSZxjVsIf+veE4{t#_llEBEo z!_2thaY|#zxA|*InwD$a=`El~`9geIwx%5D9w%T?h?`ndAGw$F%ULCp)olT?XUrHr TB(-!4fr@-jS3j3^P6xj7!VK;85t=hB?S}#vdhZKfQHo9*8|Da)Ko4mE@fq9D=RBmSy>4QiP+d! zVPRn{EiHC-cAyl{B4%c0K0ZF68e%MksNp?(a~F_hRTAVE%#aYjUqHd&{e$}f3*z^$ z@1NhEIlK1!`;NvNO(}a7LFzUk1mH5XWrT&EnzieOF}LpaLJgkP zwnl8+rvqfTW~{BL`!61C9e(j-T6&K7ouz-6#gELlne?1x)_)P5ST%-=RqNPFTA#8z z%wT+IFCTVPBO=pQa7~9!{@T9uqd);GJ~82gzxW>2pPji>l2v;i*R}oy`a%Ep=y<<3 zak!~*SMA+ym*-RV3EkWv$@zMN_UXGTukZPyXZ`uz(mgs?gR{f}rrlnv&U-4jecx;K zcTwk+7j3#K;(yIGd+(DKtp+9%_6vg7{ps-Y_BNkh^QgDssk+S8NhQ8H(YF&rbP``4 zoV;d3*12VsE}PUZZF5`76BaLj&40p+;xNXWYgVNRWHgGhCI-$FIHiz1SE|Q0XQgjk zic6J17<1&r*&;&R+6!Nsw$9wpbfILiivQtDzO25VAGPQ0Y4N!wp8FuxeX;T@vy8Mi zv%`dCKCms?Su|_n&$(ZXr!jT!eWxbm^y0Kr^SO!u&6zK91j3Z&uDCO4-9}F4<9^E0 z=NsnjzCSnenBV3}->w$UX*x66Z}~3XP(~JQe<%5(k6JH^o=q`WuC6uhsmPnDLh2Gt zQ;TOk^3l3JZQ>9*WmfmPmJ8J+dKWGLw!?x5w_;%Z1#8c7HW_EG z4h3z^Is9eAovo|WR8DCf{Bn4e+x{unmgs#vGI?s9)|&ldf-mz~y_daBQ#7ec6irUF zG+Xykb(kqJl~#ZWVj~AOglv}dh3F)+6_f3jve}xpt_e$r2k-1_jic~(ee#e%Nnb<+&L%q z&Q;2mbItqfpYuZMS&gmdKUwfqv2mIBG_Sz~QSw>HmRe@pE2vcJ033*P#fZ@A|5dOiQ^PhlsGIX6dqJ$y+sEKOkA z?tS0(Rq;%Fz2;nXVrZU?z0K|}@s@Y>&M)J*>?E&!uKT;~?wv!2pZ#qQes*~GZnJy) zrevIUnB?Xl?1eg){Met<{?JzrViTwD-=hkXZ5Yv;N+r|Cje4;(GP^ zd0Vom;qF6H0gI1L6NpdbUBP$l>EFbCEm6ELxU`RIT@8w+k2)7&saf zI*Q{j*h^?IFr+D;sa}0e;!$Y>E4P?V#D;`}O~{Nje^L3EDrhMJbqWi_WtEe%EG~&sHh_#cE~A0L8qm4gF^&Rpm76GfC(tx!U`1U;0B5dhylg_ zuFHLU`fDCLrVPC)5fBOXI+MbRPe=i2|I|)ue3pEmS5*ZJqnurvG(@!5}Ly1!YX8oy)xGKOCyg%{o jnu8Ily6VOT5!K9QPBL#-gv?0-CQ1fRS3j3^P6>R#paN$Hm0~O-M~mt*@^KGL)5-Wo2cptgIv?B!q>94Gj%rV`Fo3 zbG5Xz*xA{+xVV^^nfdtmfXaxp5vZ)ed}lF`vMdSm3uZ`&-!GtG@czO5fCcgU*Z0r& zZ?AoS{_y2>*YC}lyeH6zTiNE{eOoIKdvM)FtB!e zx;TbZ+6Vn$^{E0Z6YLuAcRNyB-c8T6;|{ySzvjN<`yGD*Bd5(Xp0z2k>hX?ke7iMk zpQ@x4^IWTnoOb%US>?;OVb#}#^iQ9&NY=Q$|J~H}vVXQ2=!r9%c6H=L@n2u_Hp`ZA z^+p2|3Ht+D;dL!nU91@%`R{Sw@P}p1vPbJWKQFi)el%&CT*7g;OIWp62NvdEx5U`{OA=meIv+Y6IdM?BMv&{UnBz#o<;-l%`^mSIqpx?{R~0_%Eq zPR%EYMwfVxtO}1<<;i$#p7WC1$Cr9Zbl&Z|enRcgmd`(}H?*Xf@6MA=*e2A)ydmZB z$#u)hLfQqLuj;Sq-J{g3uq}sUYH){O#O~x1KT58=IW&n;_Vb?C0ui#eW!ge7o?3d$ zVa4yZ)TOI?9Ln1#td)7~op|!_Z$q5ec6$C;?3Cu zr*7YTvgIt$j~5FgL@Q*)esADu6tlkDs@gj5?CUJ28?`1rRjpG`yGj~O<1X@9>v!9LLrSjBd+N9;f2_RZ&?NZX|eDQmx4H9k|( znR+N??UXqG&$bb(nr=o_UT2(X$KuVK_)0rpBxQlsDG!^aZ~pfryj<;jYRSz%VlS*x zauQ7qE_=P6&zt?-Q2qRoGfAaV)BFmJtT!z2+w$qEVnlA~-2B6RSY{+;z-@6^}ayV1?QQS40WXTDo!t#8)usyw#LYvl^wefL@B zKkGkdn|@DCC#AUj_m`sI6~H99LK*iv&>_3#u_4zh{hO|-!W+_DJ`_-a*X^8O?R_aevOW#dZ@{_^D9c@ z(Tx4D7L_*XCg&Q(aygOYXHG*(bliHlKkxeM{TftX=+g42m~T2DJd~AQJwIWC;rjO z-F4=++Hj%=1_S}r@U;%+m8ve%t4sXev-5BHPfF>6*0R#{CJwtg{PKaJ_+xnmw9Jam zL4ovLGF8SRtax|JuiXa#Sb`sMM=-N*s>{)kr2qoLxO2 zW_zZs#M)9{1U=;{Bl=Aaj+F?m>lvWf!`p-poTPkRTQ811h2WDyu>je5B@7xd14^xV z*hzta{Eb>Cy;B{+8-pJ^U9Hos_3~;i z*V#o>x5`32ax&IM`amO~KE#_3>qt+dD_|eH{jbt`FdckIEnJj$N0R$`mcXnUAtSFO z$YxnZdB22)3#uEorsE(}g{eEG#yq6T5`;|I2&U#JB4ZqU+**he*UBa#E0$y}o<_&q zcJPP}2#gd`HdT_diq4#uFNVk`mR{VV-=Kg@UMEeTUZCt+Fg%*`C+k}4B*3uQfrH;B ze%Q;<8^~$%^5zsi66qU>CugP-F_Yb`lf%OI%|vJUBu0b{qdX#zwYLpTJ=(7bN-3cv zeJ<4*9lAT_0tBEha?B!TJSoRxUjE=_60(ilIuouvEZhrt+?h6dyY8YA8f(}6TKEQO z9{KXfdNNElli9MUEvq@tF>frfR>KT&ju(=GUW#Mb0Bo5)bo>-g%aG@tabIs7 zPnmWEf1?X-0vqfj^+(UFo74Qh4n|#R)3nw6s2wr?Di*J@4Rt7~YC=AN3@jT=2nz73 z2D-qYu}SLdu>(bc)bKZoEV@Ivx=U+qHSygovnU)r4rcAdqj?M@C@N`8nX?S>5$5KL zpe!a^HKGm;IbOXxD_&~tJ=(1w)ppi1UB%Thc`xFGS%SYC8EwflJ*lMQn;~&}P^B>1 z3U6VDT88QrZ8&w$Hxlw>nVG1#P*SE7wyRw6EBOLVE1?N~R^nz>iU68Py!g^&s6lRY zumrYdYmgXXl?K)qD^iZ>`X{PP_k!mRZLOa!+BXL#+&UH|9DuYiO(}E?~3~=X>rBw!|tcomh(A- zQ_}bA$^)y+{^0g6n#SY|_Jz~=^$!sTxX&g6tO`#s8;s{wZpBpBTv;|u2aTf$s4f3D z&|ht}X|kKQ Dn}Wpl literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/horizontal-tb.png b/crates/resvg/tests-hinted/tests/text/writing-mode/horizontal-tb.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/inheritance.png b/crates/resvg/tests-hinted/tests/text/writing-mode/inheritance.png new file mode 100644 index 0000000000000000000000000000000000000000..7cfad8bd76e29af7affd02747ddca069edd06ecb GIT binary patch literal 1700 zcmbVMYfzGD6vkNdR$7y$V%ml226WN9tY+C-UVubXu}_5r3saG7y>wemu{6=4OgE^^ zNir<-Q$KZJR|_@G+;XP81i5(2N;X0>ODhavKdadv&Cbs5o|*GJ=RM~==lpo*eKG2J5=dTpDr4$cexuz}_Cg+}kMrs1P zN(-I_9e%TD#paeM+C5EQ5dvX&6u;|-&|`}60i&en-!IzH?Hjq9Kq_*bAUXJC6{PBm zS*1KOw7z(J^J4w-5i;L&Ro2HPPRe$XW74w}^@46mds1{RB?6$a4VMD6#s9#mVk0vg z)H2TuT<-8C_(n;=ZSlECT;)*V}*I*UWvs|X1pgm zH|_zw`?p_)JQS?Uz&;DA0^%uL2}?Rv0<4|f-wH(Gw#r|tYFi@Mj1C3tJv;4e7l7Q^ ztIohBiOk7H4IYAcoM?^}cIZ3B^*l1O|CRyRSHZj6?4flzJ(@hOSd%YyPEUj zd&5&%tLsG1M-11$6>fW4YdcYs@c!g_sQ8-oqg0x!s0ivE(8WyCj(wwmi*$mW`mH8(qIV3$TVW5J&_D3Jo-1BIMGpw{66Uyc`@QICt$2(Anh>1> z!BuS8I>18Hj!LAWkGc}l{7xifFi@bk1@*Te+VO2EIx|4I)4AqD3=SIVt8Hm?+Rqjv zVHs)KM;k1g8S;9g9XxKp6I4m0$W9$c*ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/japanese-with-tb.png b/crates/resvg/tests-hinted/tests/text/writing-mode/japanese-with-tb.png new file mode 100644 index 0000000000000000000000000000000000000000..7f84384c048c61d5f798b9979a4f9d4ebc182d00 GIT binary patch literal 1301 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAe9i{6XFV_F+pQvV?#p&vbc+j z3o=((SsBQMkjUbEe0<1UAp5}wStB4NUlQaO?7$$PU|=5*pOBDW(9qsLVg7>k>o;uJ zf8hLu>-QhL|KM9vZ^^*G;_B(*7*cWT?cMgi)fOV{h4P1&_q)USA zl7L8nWw8^Xbzi>z{CV-RmX^*u2_~pPb2j6%9qK}el3l$O%}0!Ynu}P#ny-~!zW#2* z%S>r@vFA{Q(`Hwn7L2(0Eb!ay#E%ul5m{5cC074_ znU^|^Wm=TwR;e!4=)bqU7_*<=nwA{5yEtU+kBxOsVT?M_E5qJIWNn>l5Eh}Gw5B1H z;k0$$&eSszS)nI0bmFz$bfQ;HmHqikp3>o ztezM#@0x#2#MFFKR_{-%<2o-Up1qPKHLd*Ks@#%@peEMpuPHllazO3mDhFi!d=rUbC?Araj}#K&Ji$n`S-) O6-S<~elF{r5}E)7xFGrf literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/lr-tb.png b/crates/resvg/tests-hinted/tests/text/writing-mode/lr-tb.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/lr.png b/crates/resvg/tests-hinted/tests/text/writing-mode/lr.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/mixed-languages-with-tb-and-underline.png b/crates/resvg/tests-hinted/tests/text/writing-mode/mixed-languages-with-tb-and-underline.png new file mode 100644 index 0000000000000000000000000000000000000000..e885cc1ff0aa6eec7d9052611bc1373a05f89ff6 GIT binary patch literal 1590 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/rl-tb.png b/crates/resvg/tests-hinted/tests/text/writing-mode/rl-tb.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/rl.png b/crates/resvg/tests-hinted/tests/text/writing-mode/rl.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6398aa914a94fe3ab079f7f071d120d0710d63 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhjsKC&U#<6A$?K_<)Lqg@u`! znU$55xwyDAH8mw9B&@8gfLudELw|q&;^JaQN5_VShWh$?EiElsSy>ksm)O`?ploh# zE>L?+OboUY?r*4HkZ?W!?AHws zmmQw8eooz@1GDEW-Put*JJY|UKmPUn^$*TpP?%sKa3DV6Udh%k3=FL4o-U3d6}R48 zILO;jf3^^c`t2+O(`cQsb;U&0a4!5 zFsV{|unM45B#05J0%L(xgN2A-SY403o%XeKqU!6^>v~&M(-SQkn4L?X6kG1oGrjfY z@BG}_L%EqoXR0>;xnBO}!|oR8D50=JUJ{OLW!iVI9?d&i>%ZnP z|Dmq)HAjDa^v#^NVNvjm7SXweiAR_FMO>WebEwO2>V`*`)z`de5Nu~{51w6n;&k}s z@S|3ohnvFpR?hhKR3yRorfF1QWo7NDj`x46d*9E}HF_t^?YEQj(yp&(tdvwgoLz3X zRQbN7@q3}yPCPHR9AdhY)5l`9FL3F-G7oo^^YZ#_ zF%R6g3DgQUdFUMC`uwXkD&>IFldcT`mo_-9J{Y&sp-E$*tqs|{yd ztaOT=^)#q=;i}WJAD1bIwj4BA)3NLde?i+< z=M`61xyJ15y;S8gGs2=Pky$8^E6MEIhOhgXPaJ8w^ZjTR%N$)~f4S}B`7hHMQMz5z;nzuqE=S*Re-(dwW?;ry1Tobo##Zq=+ML)5Cx5w*9o;DnqV& zzg>LO|7vY<@6X-5-A~1~&+ors-*J@b-)+V2sk+9Ui-x)1v9x0~)=Y_cn-YUf;= zsvCiucNxWQjdhux>*K$z`tRjuhn4%@z1?SPd$)bVv-RtBKWpvMI(vHQ-^#e?`Su(C z{(9B2W##ne&yA`s&k2gykZ`bxm0L__&@rH{Vu84g6XHT4h&xpyHq>!wcgIiMRJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb-and-punctuation.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb-and-punctuation.png new file mode 100644 index 0000000000000000000000000000000000000000..bf62f2cea062ff67efb6363dcccb663c19b65d2c GIT binary patch literal 1650 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dx-on-tspan.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dx-on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..aa564bd17aae5cc74241cae5b1316ea10ec765d2 GIT binary patch literal 1442 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb.png new file mode 100644 index 0000000000000000000000000000000000000000..7cfad8bd76e29af7affd02747ddca069edd06ecb GIT binary patch literal 1700 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 IbxsLQ0LwzHF8}}l literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/colrv1.png b/crates/resvg/tests-hinted/text/color-font/colrv1.png new file mode 100644 index 0000000000000000000000000000000000000000..7537da902e2bd7880bf088772829e4e1d9c63d8e GIT binary patch literal 6152 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/compound-emojis-and-coordinates-list.png b/crates/resvg/tests-hinted/text/color-font/compound-emojis-and-coordinates-list.png new file mode 100644 index 0000000000000000000000000000000000000000..b6ecffc1f2ed7cd7a20bb5e175ec700e47ddb147 GIT binary patch literal 5800 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/compound-emojis.png b/crates/resvg/tests-hinted/text/color-font/compound-emojis.png new file mode 100644 index 0000000000000000000000000000000000000000..6c6724eceacf0b5bf861d2cd4d1a516453e23097 GIT binary patch literal 822 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXOdU6XFV_|1$^x$u5Rg2&0{$ z8OZHqXl`t5Y-nfz3PQv?8JfU~`C43>nq35&%oco(A3V*1Z4a-opO2>08WMl1ko1d0QV`g^1v=q?7uk|4ie1_1#B zdwU0mfcS)j{QQD~`u2|g1?$&uIB@>{{nxMGfB0HIY%!e(2)W@Cr`Q_zqkL<+*^vZUKeYX^DDXcd-E%*BDY>&6^@1NOtZ~vPIQGZWKy*_#R#f8&v-_F@M zul$cq_L_8A`~UNduZ791?OD0_aG`C{xn0u_asgd;HsPQV?{4{~cOQ4=d{>Hay|b$; z+Imyjqib6yf1VW@`QUx(1}31Focrrv+8S(n2jN+l9sV-Ut!Trwc$ewdHXVz4-L`d} zY1sewvpwGD+h?!&VO;aoK=j*xw{UTIM-6?|&PBS5u1d-<-(!p#o@9jp zD4a>tm~C#Xql_a;p(bq&=Hc9`y+(iHv{!-pQ?6z3sm-yDUU}~0YG4Xv@O1TaS?83{ F1OPN2Ku!Pv literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/mixed-text-rtl.png b/crates/resvg/tests-hinted/text/color-font/mixed-text-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..4be0084c6085c178f063fdc02a3b938ff4893e0f GIT binary patch literal 764 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAe9i{6XFV_v4Y0NMxb~@LjzV> zh*W)jJuX?ecbsp`_Dgo z)=gFKWnf^^@pN$vskrs_M)SfPLk5R~F>7-3f35!{eLk|-k5gDZWoelX_tX`#tN$E$ z6}H9sZhXYl1+uFSG_i7v=|r3t)rr`UaIi@gOtN}|*sR>sfMjU?p{7!ZC`chhV&EBU zwGq3+j?DOfNa~Q+^;d225!pa~r{J}|ryI)FMT9;U3tOb~XO(pQlmn~cmtWjbH}@Xn zmQVHWNpDm)%(|Xwk{7qUoT2%{@*8F6y+TU!6ouWJ|ngH`khwW{dnO zTmPAyV_Fk(Q|(`tP{PvF>4tjhYZ*@054`Wev4iXkNGxt(fkY7}L`nz}T}wYF9c;R) nxz%}Ye8jDdUMI9}ZG2<>C-BkcLSNktp!DYH>gTe~DWM4ffuRO7 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/mixed-text.png b/crates/resvg/tests-hinted/text/color-font/mixed-text.png new file mode 100644 index 0000000000000000000000000000000000000000..6e31b50da82e0f528793a9307e8f77347352fcac GIT binary patch literal 1764 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjdkuC&U%V{eM0HjRbK|g9Jg0 zGayD|VT|N1Ox>5`}_Yt3l={OB3-}$ zqztSWXhMB`y`iBYTtrz}8O-(tlCrY0|IdIJ|4)NR2?>dJheCygh5v(%f=Kc4@j>kc ztNeN_=*P(bc6N5CMzAf+%*_A)|9|u1!J|7DfZ|^dd%WK5@@SL&ja62g7d4z;WO{U_ z!OH0cE2ib|nW!_rJ7IID`lb%`6%9)B%Vm3t?Wg5SPR*BS&M@dn7wJh8ZjR?~isP@0 zQK$^#DhL!v0|gsH{hSMPfRtxRkY6x^fPjL6fq}h)gMUCke0)MeLS|N0ettngaY=1m zeSJeidq@9-3A5+SnZIDc`t=(&?A*Wqz=6YO&z?Vj;llO%_a8iX`1;jPN=5r<%I$T!D(n&UZg+&;9&YQ>-*4blxf6cN^yDsCi%f`b%HI z`}NC2K3m%_=MG0CPC8=q-AG<@%2LMKc!x0g12PR;bOck)PS(Clzc1Xqa7|>6@$9I$ zmcJ^>$J(7EnRLAjJzlRma;r;O_S7lin-7jgrip!Bs3X32kI332lU2V{Tth>9jl>JL zI`ta!d$q1QG0WDPVbi6ud>^)lFF$L3zxqu%=K{k;_f3l)Z@4gZk5;~W)Q^x7hQmGq zOAja6NQp!iCCbiTR{3Jx#Y;?kHkmQzI4eBWn0Cg5VR2ks@uhc8^JNb@l<^)&vr*VI zZRgqEfRe|nKT1|l)8^sjIWF1F=e#T zWNkJj?dj2x`*_kRTJKiEZppTq5MGIC%q!B5sBIFdpX_k;zt=SB?Q2xj&$TQ{4)68& zm2z@>`q!XIifo;xIj6GE89ANI?q;6cIN|Ck)$(U^SBE);`SrSGpPA}&hUwF+S;fIe zIsZ7kiQKzKX0Ki3;Xa+6&FfzrQCn~_+sh?%x`e^LhBaaH*VwIJV`m{U@u`}?rWf@O z4?caVSZ-mp*QVgmhBa$W?z8#G6j{sHIKfr=&sxoj+PbL zd}6+K`RB=#Cx2Eqo_;9b&{5hzH^;U6R2P@xF0HnyvtHWm*I{*9s-=~6x=Zc$ssGVp zf92%%%*>P9>ALi-GIxUT%SD@JY-*Fqi*yOSHaRRKTygm5nw$t+8vs`{3GLLw3)-*!baP{6_<)4?Q zT>X31QGMb|+wt$I9lj|tp~8khG5@ClT3e@j z@rJg=Uu>B#^Y;>;Yy<DkTE?EG7`w415!oYzQKHd=NwOwNRD)#6zDAgA ziL$(rrLiQk%`o54`+nbdzCYe`zVCd`InTL&*LB_Z@43$Jy6^isPrRuK8pdp+dK$ulnW*17+uzB?=u&?#^4o^#zxo(ieHZ0rO~kKQ^G5i4)R5VhoD#zc43c z4=chM{=W|vL0 zIR^?MHtS;_e)a8KP(q?$NF>r<2!@0+M#ggsduS;Ry5$(uQ|9G4^+^c5e>P&~3pn(O zW{t;=0U;jtT3J(8De0x&Y-8MNA6)fKtxAF61NmNB_~5Br&gUsv`Jy{v7h{|5MrWhDJtcvry&04k2sI0dKu8E0^SuM zxf8F7>BgVpHxp+a2`T;ij$YT(PeyRzz%V!uvDR*1uvMh- zZIWeMf96F?0^yTmt=n*xALnj(n~#W*S2YeJ4piD>!o3e9wKv=@*@ihM9_Hc8Aq7}t zzFRS~iln1^p79e;xJ-!mhZXMIU6;v69CoxK~V2|Dm^L4P{mkiZz?AYa03G)y0 z1*ZC?A4(TgQy)58NbM4+GxRL^g4(t&wSM?IK}1f@y+fBHomSbs6O$V-VY+cj?b1ZO z#*+Z!_ky;Vs3u)3yDCl#jW5W+v?jg16D_5RbIrE zjyQP9)=UfY@LhN$5)o%}`a0rKm#(j9h=oV9IvB4)MK(qiFu)g+sW&v$pMnKlXNF!pxnG%t_aFyaw%3PweFT+Ml=6 z5@&Q}CN~wWGYBsx5wkgal-x?+XPxgZm6<;nIb}pliHKAB7zd#QUf7d(P|shMe>wE8UfDqDSwy+6;pG@fG#pNm0O+YSKZL{7d~f-2Xk5eM(n+?E$cZ&t}o zY--@v9cxyk3l1@khj^}Py{e+xgo>!c4(INv2D#*Tr8qXF4Wfk&Jzo-A#^n-Jww0J0 z_80A2BGqi)?ds5SG`$u>F4wOmlbWw_9KHBJr(8-)>|9vr1tI!{LH{Uvs1xVF2ySVp zW*D|=?yQ>^gRD{B*4Shrk&(Q9dI9pPR%JUS)YGQLka)( z(ypx>fS36kw{CJ+>J$vVv|#pAa0`-6U4f1xp4IuLa#^u&4mNbInp}wHS~w+S#SU7> zVmWIJX7B}Ni6iB%`X0RJHiuEHC$h1?C+x+tqkNHPj3g-slVMZN?!p&S;+sztX2mds zLmepEV$0mnJ8}_JQNC%W7l>lzfQXA;nw>vnVeLkt(s+nMU!@I=$S}*^zHK448PD|( zn0-+MQu?vSC!f2Dt|#$6#=XZC{LF@EFe(e+^Jhv7MM0&9W0=$Um~K#H$gO46aCv`r zUlBg-`6M9$F!g=uBqhQ~F4MB%KWnmPlmb3PW4hUe10sb->8~86%8w+Ad5^S*e2I7EB%u()yc2WqN=SzB$x0Zn%lD5UD;Pgt0 zl}0vlzK#M3Wvt36)DWEhkupSOK2eIlt27+-femA>)QR+UBBOmq1@sCZD;N zUQ;!0`tkE0D1&-=N(<7xIp)bU|BiZ6R@NLIugkcj?w>E8(pUQ&cZNGZbEz@X%HZe0R<}>4wl1Xv*oO(L6g0nh7x2u}Go2tFQLIc%saSrY27}k?UE3SQ2*I_F1_~UlCp_qF?>9`Ue>a(^Le}$K$E{3}1+aAFEyiU&x1S@yu(|*$ zX+PeR1!=5E-V87wK07dh6ed*SpY}-qY})cYC`k=(vLL=*TQ}|dO_%_w$C(?w~U(eTwK0rel*PkBe(tfk6}Xr#7b-tR=XI@+H4@o?55! z4k$`_Q>6*OO2?6YX8vmsAj8jQc47w{ z!7XpqlJTI96^i^Ffw0>d*vKX6=8e37)>JJo#VO#_blSG{*{LoK+rD_{sjkV}P_=jc zzVl|>?39q5p`N1{MXu9+M+ktztjESQ(SvvMF;DB zekKVVVF&#iO$0+ThH%l~UE%&+M22He&_9F!#O3Ao-Cg&+6BfB0EA;j|d4FbDS8p)$ YzY$fnF|{>d{0IU1XHCw$)OCvf2Ph8cIRF3v literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/svg.png b/crates/resvg/tests-hinted/text/color-font/svg.png new file mode 100644 index 0000000000000000000000000000000000000000..476deb87779d712237c1be7b8c0362eeb3e01ae4 GIT binary patch literal 1843 zcmb_cdr;Ep8paZH%L^spr6ox-Z5K;Dnb)IXkr_dRH(0Gmyp)~;l-JA>FEt5NSi+_& z;h|i`ED`g#UQ#Q;98lO=G09unhO3rkV&3R?$o9W8=Z~E^GvD{V&+|RcJM+%>$5VjE z1)Hz6TMGh#%tH?BBY;3g$S>D)wc!PK`$DjRtivA)LmMcd#DA@S0{IG+V*v#oP~dWM za)53ugTXN1FSc&%O2q;4m7~A`3WF2ZSAWa^27ifOp;*8$ZZIgYGaaD@)c|xd!it0g z0AOzRz3$`m)cDBgfNFF=+5c<%3ssvzRZ7LWCkG~*_sJT|q>X}6Nnp!;PRqS({Z+m% zs(kB&45iRhBFvVRxJ!%OL_g9id9;>7q<}@PD{z)vb`~)lDj5#EY`h=?E=Y&7Q}(cv z19>!CF3l$Iq#HW{%8s|nJ8qeK%<^nB;%vlP`Vj~n2c}`c@n60H6X9`ud4W8hSsZ>E zV}298+RL2DI3l;vo3G_h@dH;H}K($v=MMefo#zdD(Ovxc@O>_ z{WqTZ8PpnDN|tHE%dM1hsH-d^;oJO|p-@UcqHphgYwDVx$VlruiSv=zWNmb2tr=$% zj$)RY-h;6I-hx0XE$kg=^ll{HMf7&qV!QcK?qIEzzCR+-_^#wh z5z(R&TH(%I^wV;fzvnyypK;!j)^n6cykI{)tB3e$T~SDCcCL4S->^t_@KI3z)bly0 zi1_}oka(opB?3C>Q~nC=G~Sk)5ilf?F=HCtcAguU4vtMtZO}&F;(LCVJ-54$rr&=S$s!_69FC0vy6u~i-7XdB4gPGpFYSB!E+A}x%#&YY3_W7c0G;EU& z99VzB*#`4D^XZj|b?=Tw-TPJ8a0m8?s0baX|3zN7EoC2kg5Ko0g5_fOF6uFialVzTBk3%fzMLGS~RFt=!~@y=N*a*6NDXA2M(Co5w6_#J#Ha z5G1ZX5i3Fbuw@g==T%Zyln3yiZ&{=X;J8Qx2;wB4pp(y&mz+eYm#@)X zPU*&;C!Zr!E0sIG`N-Ux)h;&ucwHdiU#PZ@+e*IG7WfFfZ7D#3v0*#Tmr9G15bLK7 z&k`P$bd7fsep}V1Mi;P3EGHsfQ{1hfxtcCWg4y9jBbS?OJW{^|i$qQjZ?{JMvpaT{ z(v@^->|SN(sKVGE^*B}zW!dh?e`EKLQ!%GMXamD72Z@S9dreQ>a3vvojE*K*P%w6^ zdl_ZYs1q1lR^6^MXJHf!oTbhD9QHcq^qan2{s?_#X}cZg6wFB z*wc$D5xJ;~PV`?*cf9d|>izFHak^uZ&FfUZ6tWS>Y_*X%2+YwpxbjD~v=5p(WBzhh zt%TtJbBg1%vc!Ki^|r4mnzSQlft0@(W>vMObyn>^oZ(jgCH6zmxPAA7$hrRklzV(u literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/writing-mode=tb.png b/crates/resvg/tests-hinted/text/color-font/writing-mode=tb.png new file mode 100644 index 0000000000000000000000000000000000000000..98fdf53badbcc2535c88a08ec41525f0cd3f63c4 GIT binary patch literal 1473 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAcrZyC&U%V{eM0HLP8m*!Q3+e z|Ihd}Ha7l0>)X)KFuA7!$OS1o>kA||%**|M+HdcYEFcLKKe{sI+`2@dvUBSb>g((O zpYa6>UfU7}WIWmx`Tw-<^L=3;L6BnKPe+139}NO30J6Ux3;GIT`~Ls`|J#=jZ(lwH zvd)kHLb}o3d$^PaltIdlV&Mz|Ew5a~*OoNrv3sy|a-!oBXes{wBuK3NJ z>YF;$S2ifEXi%C~A27c{wx`6Qr`UdKzC=&DNKcw@b3A`j9Dikud}SC{L7+f>0DplW zYrZdQmKS>($oC8q*ZxfcQo1EUe!&a^0tyE94h{kF@d*i8`S}F}bq($P6DG}`J!j7R z1p`3u+Y-hc4$;robt&#W03SR6fF978H@y}97Z*uWsbU~tD&=I`PMf8L)L zOY{t5o2dHLEuc1SttsQ{xuNPTS2m@boTTb~ZT|@%IZY=LgIX;ORsfU&s{93&hG>F_ zLG;m1B(r)$y4bCWuN_1}X3U&9(~677*!b)J`qPsYA1p6@fALe^>O(6nL!7t0f2XP8 zSH8Thr7chLxKvcL{~FfjjA`X-enxW?Sii46RMfkbTWa?_b)Cx*%NeYeuT$4KAF+D@ zN97lRX{l=@ITGC}Z*A%}E#X$Y!^i0uUA8eyVT!0?#%aB4x-CW8EV(<6-fA$9Q`vDs zydt@1(v~+#vQ6zd3eOw^opL-rM8vD>?v8l=;Nk%%(P9S6HDVjs8_0i+SYN zRp#%s{;f)9^XZqGnKzFz^=AZE-G3FxaI>e0KXd0Xqvq^2*$Ng`%DR`ue`J__)jH_D zZ`r26|E%-2*zn7$?AnsuWwy)X|Aod)Z<2JIA8~f~Z}eFjxpd8|m@W>c^0^UiB; zt^BtrZCm>P!ooN2yG{RA-?%k1j`gUw{N?ZEdfzkO>~Ba4tvppHeqS{E+jQgYl{L&= zv$?ms3vZODtm_jIoSoO3`#$Y=%U`~Keajb`vHm&{BOm+AlC#V9;b!*;x%H8sw=eiS zDR@uD^c(3Mrxma1U6|9`?cXy$b6Vh<;03{%{Bvd+pEc@mwO!}O*LUt*AD@`}5pjvg zD>~f~-S^E|jk;0|SZ_tJ1uy7LHG(p}R&wcF1POp-rn3br{Em1AI+W z7QbKPQjHrCR!>BBBqg&N%wWo0GeL91djCeVX(vT8l3AA@2=lJ>Zu4t2yY}P%@&k+P zS^I8BSatsrSz*tayXJw&4Y%oKTw63R95VuH)k)&AkrKBuoAwi^^=I&duV1e(Kk)z7 zZf5R=g%VwhKCa|H!F0F&+$GLWBD%KuEzA$x5?I;4ZfI)$H9r}`sEX+4e-&z?t|Qvp z^(bEh(@Fvo}-_BoYA@Ja)LhiIrPSCt^dwL1Gze@F`4% z7&HxP8XLrHNr(ksKLKsI+Rl5;d>Zfe>|E)**pio;UsFDR&IOf5p00i_>zopr07zP$ AX#fBK literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/fonts/README.md b/crates/resvg/tests/fonts/README.md index 7108843b6..18d6d1515 100644 --- a/crates/resvg/tests/fonts/README.md +++ b/crates/resvg/tests/fonts/README.md @@ -14,4 +14,9 @@ Noto COLOR Emoji (COLRv1) 3. Run `fonttools ttx NotoColorEmojiCOLR.subset.ttf` 4. Go to the section and rename all instances of "Noto Color Emoji" to "Noto Color Emoji COLR" (so that we can distinguish them from CBDT in tests). -5. Run `fonttools ttx -f NotoColorEmojiCOLR.subset.ttx` \ No newline at end of file +5. Run `fonttools ttx -f NotoColorEmojiCOLR.subset.ttx` + +Roboto Flex (Variable Font) +1. Download: https://github.com/googlefonts/roboto-flex/raw/main/fonts/RobotoFlex%5BGRAD%2CXOPQ%2CXTRA%2CYOPQ%2CYTAS%2CYTDE%2CYTFI%2CYTLC%2CYTUC%2Copsz%2Cslnt%2Cwdth%2Cwght%5D.ttf +2. Run `pyftsubset RobotoFlex*.ttf --unicodes="U+0020-007E" --layout-features='*' --drop-tables= --output-file=RobotoFlex.subset.ttf` +3. Copy OFL license from https://github.com/googlefonts/roboto-flex/blob/main/OFL.txt diff --git a/crates/resvg/tests/fonts/RobotoFlex-LICENSE-OFL.txt b/crates/resvg/tests/fonts/RobotoFlex-LICENSE-OFL.txt new file mode 100644 index 000000000..5530c5720 --- /dev/null +++ b/crates/resvg/tests/fonts/RobotoFlex-LICENSE-OFL.txt @@ -0,0 +1,93 @@ +Copyright 2011 The Roboto Flex Project Authors (https://github.com/googlefonts/roboto-flex) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/crates/resvg/tests/fonts/RobotoFlex.subset.ttf b/crates/resvg/tests/fonts/RobotoFlex.subset.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fc9440d2e4d4dac5461e24417e00fdb66d299695 GIT binary patch literal 377180 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

NFbdwh_N@8V;oF_^vNF>v@7km??MY!oIxUps; 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ĂjkwrWWOT-3jqI z*;!eBceXw*DQUbYVQ4cmVS7!3g?XypGujxz9d3e=hPd%~rSp?w|?Ahx3H7CkYj$NUgW+Gh3dQuj%#P?yZ_<{Ib zDOD~tw9ZbCr#jW6e6b5Q(LZBGZg6TtV#cUGr{C+|E-WZ0eCh87gKQ|$N~-p+i^L0zFxwfkk7SwGs44tn>V`*nI#45vWJof`W36Yy}dh1 zs6&5)6za$`eT1`tsdBp&JT%WV>KkZnYj17kuiK${zj4HaM;!48ySqJMCTi?%!!on- z`DA1c3u_1tN`QLyebpS40y3L9t}Olb7N~8hycUw1T&JFxEfgVzpglpE|NT)J?tq0B z`}i^H#IW5F*b%&txkVEpAJI_G~lg>!iF46ZEVihO9{ zAWxG6EnEaGoChsTXdI0Ai8hCxn?F}5u58xXrSYSu6vdC4G^q^tFcO})y9hbH_k2jt z^Xv?#jC3-rmLP4CWr2OOx_8Bj`J8a$V9fLziJmR@+)UVc@C*Ux0luX{@ZW=6QhqEN5s=l*J;6EP^)|T z=_58FXYC_mBh9onk=(|P_>&UC$!`rEI@H~~{jIkS5?XyiQt!coK&9`Uiy6&(PT7v; z?HCdzh)2pw<@>c|QZKDvl#Em=`66e-b4dy`WD4=N#WMygQPm0OiV0~r`Bq|?^#teN zdh3{)nwl4PN5_mYNo1ylb9(_o5O%hm_SILalcSJ;Hda3N@cB?WzTVazdKmR4=;7oI z1Oj%q;*wHJW`g2`zS>&HErTVA><9Lq1;h%brnU-y&ahk=xZtzT_;>uX&yGXKV^eDc zPM%CCn2hVpAvG%te*;c;uEOF%T3=8@;$=q~sxG^KSxhYYa_`F_r($$SQg)hQ#!JIk znUz$;av5-cv@`spD(;XVH;_y{cZ-uHcD{d68RNKAUF5&696zFvxYt0x4%9)|&`Y>! zk1gULS^xUUF%sv*m&{&Lj`o0({209T;ZI(B?6Fj$CSEjqWNNCp7PRW9nz#{0ilIez z8Nv12tWK-d>Of|Dn=Dob+;&ZJk`$%H#>DyJ^b5r&i0aCnG6lba@q@p|pb!6x_={2= zR^y0qpjl0#r)q83*Iw5OkJ6uzEwrzQ*&T zPrEWF{dv8Y5m6i&mE3=3R2RT;CE4Rh;aP5v=hv@7QXnY5r8b&xI|&m66iq7_77Vb@ zTvsZ3LvqY|MJObGTP~WhN$XvK{|Ry=kCY|J7w%N~gdrs@&2XiqiLbxH>@B1%yn+zbiKCgnY=2|AgbL;>~7HyBgltql3ExK>Oakw5j?%NCV}AX;dh#6K9& z$r`i0q{B6$4*`(yU_5Ov9h%qDij=bH`0+*v$)={f?b{>ySUcrMwr}st#mpqP4|$Ra ztdANRk|r&j{608NZ{GL*`%Uxa%^R1kH#M0<)AE?#v$Z2fQsq8!cE%M=;Me$~xVT{9 zLOwIZJQi<~uPBXtiKksGjb_v{eitb#2U1c}vpv!kU2MEaG$4s_KKR}|NBI<4Ek(%` z5qqOdF`~~(N57Lkt4wZq7LNqijalMPiC~gH((j6x;_?geFknqdtuVVW~ zbdK|_&){@sI^`zo9*SXo*C}t?y88UH&(60F!PL!g%DvV;g*~=r{oT6Kx{A}DwmN}{ zI^(e?vog-DiTCVyWSM8D9z!Ds3o^;tLJ!5Y=PQ-O$DZw!A`(E3R)WlZStcn9)oZW1 zYQA$q1=8^fPOMbqo`uR}m{M6LD+@!V%Iyq`FD}PbMfZ~j7_8(tbwFk(*8338TDSs0 zn^b91>SqKbV3DFY8C}9$OPG989w7+>O@x#2{zr?AJBiGP?a>J3ZmyLsW?U1S&JvjM zQ+1`b0b}$yVq_~yzP)p&ov-du!(^E!;%m3zJ#{LYJ8s90ynuKY9cqRk@lGNKJKhp4@}IMx50oA;p=i<*hMaO#0@f^7_H+ys4>OCwGq; z72mY>9!VM5VI-_7F`L6&M>OA5ZY)K;tVND76aso)<>?KfhT^-Oq$enK;a$7C!+K*g zKbjj2Z;Y31Bn`#`DmF*ecog*qCYM!-iva--&~8})FIdGa54dyx@|o!J>83|OM9Z2)W~~ILG9Wn`QMsfz;8+%$YkdSJ(6B9cgZO#-OtmPqW|(sfIRJm88AoCc z`C9b=7F8UmrURsQVGr`#!TmUqa6m#%m^ub82H_<_N+zZ)iU>s!KD(oX2>TtvNR+nQ z>_-Rbitp%9Nk}Sb5Xra6X(Jm*l;-adtB*$#eOO7jFnkAXxm;p^K9 zG{t^6Ki@uyxx-02KVNMCr8lUcUmXi(-erGxB%C~s_<@nQ+;QVF@tHW@O{!4zE-_RD zX)LD^RJ@ez2tm z1rX+(CgndYv;BcU>>tqqoyi0-r4ChF>p)(gZZ;m#P8`t#VqmMrNVbi#AZJVBW;)zXd z2*$#`Zd=VF_bwc8IC%;J>w!cptrD7gdZ#O{N{a$%Sl-j?b^&GLM4~_jO(Lt&@Mz7hG0=RIww9k}6 z7@1IfT>~~${k63x`D(8V>vd9S-co0H>pJ*xpjkX>RC$i|%Ed-5sbp!F9wj%g6aV0p z=#k9O)XQ&P2)!c9hmN!0b0C1@qRw^B$f-Ma%op2~eC1lFWQZ>nx#u}Jq5q?NSGfu{ z6Kf=83Oya!_Zdz=y<@QWN{+*h=VZGF`+)B5&LjOnc#qJK=4J>LKXxE|H8mr^=#>c^ za5X~Y!Vd!Iyk}G?wJ8MrsU|vpG}>YKc~Fk10>O+KW`5|JLH2P(cFuz^-!W(495+zZ zmhclVLo^9UjmX!Q3)Zr{sl-pl+UZnVZ#9%kA4VC>@J?r$hFyMQjS*VHC%QSv$hf6K zhiMkiq>{^*Ma*QQWfq}>F=c35K;%Af_+FrLc9k@i3q?FGY|%{%1IAy1f(L0vF3c|ovCgW zNg%2505v3+kSagA5hj;_tt(Y)s{q&N)V$6ma=w`pmUeM9f3xSuHKNEwn(+J9Vrv&9$NV2usS*gIoj0TMoy&1dewa9PdoDKNk>> z&#^H$z;6_GbawpNV1-*Tgv9ayZ`W;CQFg+H5fwuL(tb zUlhR!&V-*0a$YjOlBlt4dZRc?a=dv^QX`x*a``=mD@sJ_k_GhYKYU8L;6HpMe>wxc zc^aJV40!LUXnoE?>oX5d_d@v5%i(m(;B;?;(_KjKOT;iy$X$oR>B=m8xp2Bexhj_y zlHhcQ!r=~u!<_<$E3*XTh#@>lK2_%5n?N1O`7uuiBR756ROrrGv*t`2mMaBwIm5<| zpE+ycIg_VKOPliz#jS`&_boy*b34G&G0}7+*C}{2->$7Wc1)C7y+)zuB!+)SPU?F5dcf}v zk3&vROCYj(5h%P6NosB<@wRvF#JN7N@slU{Y-#joO_;cI$BRcAJHyfoFR>?_-pwph zdR~A1^<9Z=f*1tSbISIH3F~FLjvkH9ysBKR#isgR_u6M(jn2Mto+D=?eYpGQQq_v%;8B*Bxo6cu|D?dcOQzIfuo!DE_deOartS*G|u_+s6RPGSYpdxx@gk%GaBRrNA^UQ4HTH8rWaAZ(m)?GDF?){L)Iy`L7}v zuN?EA`0n}pN8GRH&F3Gg931T{Id-MG^!ZIh!drsX$tjsYDUg6E(b2sl(;-y5O_`Z2 zugXv-Tz1=hv4#;^>o|ctCPLoJCPTscCtbFr62;A**}WE}!CmT&mrV$lil-U$mT-DI zAVEfrbGIe7wa{)nWU&HTN96Oi`y^mU(;lJQOKaX;<#PRDG0;e_$yCtNyc z&aYH>%{8R|1GGr+A}LJyUvq~p!r*5LxilM5EmmQs{A;KDivPc`f6ZPhK;6KYQRZ80 z4jbb8SEAYIQqEH@P%hxtGcZOkIN$QOENiK2oJV zpp9kA72R76u86iuW4`8PRX!=|-}dSs|M>Y}A@t4*v%9qwL*33`D-_6*OJZG;wLP6K_6Y*TQ z)Y|p!ei`Djg#;Mbs|@+N6pK3cEH=fZ^2k>h0~I;Pij;Uvdma{-@pMBBr2sA*vNS2I zB^A`}<1uTL)>;(qxEpJ+C+L(B`eKl)ejm06 z@ekC^w!uC1_H^^#N1<@MH2+E|35}Rm3MwGq7*mzb65j0)>kDD)FwPxe3i8PGR2AjrjY~?ie7;LBxo~)b3ds04 zk}>JZOD^^K<1&&)<21X#CQr1;a}!lFF_1m-iqbh#&%SC%4v9U**+x!M2W?2Bk^Xuh-cc)M5zui0{6L%! zCansXGNa;$at^N&e|By8_-%1crFflL>=f~~>#}&lvy`)NDDEGX7XwvF#jB`jq#=;i zaK#m!yve(ql5O82?y--@Z1>#jrmtRYd%{W^!fp|7IM`gXdKKMtVO#7$t)K)9flbm* z#wk-K78I>vEx%+>6a6yDbT8_vim+?T&d!zpvXbTh?ChNEvqt9dHL*l)(Qrs)W4>=< z-z~DG38UyUC4^|JQg-b+*S-k(Nm=wAqFH_(-5=c--C@nM-mvFr*ld1ru6+fuB4$SS zI)!+b(d|~5^&aYzUAu_b^#;1yeETe7#`#v3;sQBwVi`=^bt-Uvo}Fh^DjP+e%9xgk z$54@O+g7Fw5mhR{9!aA@D9m%QKg(1?$`Mspy~q+%loPOBsp3z>*XZs(SKPGPN)t_+d?k3nwb+n!>g=T%Qe=A6 z)W}IRC|J#)$tM0Dc>`(!I_Vixy8Sl3Adwoy?KcaPlCX$B+1xyIXkL=l2A^`E-O3(W zJhZu`ugkKNl7RPmLv8Kpop3+4;bX#1F32b-$Y@{o|Kn2A({z%+Tx!=>HQGL(OEZ-C zmKuzbO!47zF)Iv`TPDMsiS%l3gGkDf+L2+)sw6w+iq^_eVQnf(v7C1vpqLvDon?xz zv+Xn0M6GM37|L8Kb|&J~BY}W{LRtde#qs;0Ro~`JfnYitJ?}T&dC(Ut*#!o{6h;#aU$Z>*{T5 z>*0mDs@8<0@mAC%z&+5U&nxim30Nf}AIG^{=WUr?RG&4XL!8r|)~ zG)yBaDw?DiuTUsu){=0Q_R+SRS?qJ$eQdCc12CBc+N%ku%qw?Pvzf?N4P3ohC^;A# zTW#F%onZTYeFWc=oT)T6CGVhFWWtv2)h*K|<@7fun^`x{%++QtHVE|RtaA^f{ zZMjc#^ngSqeanh8t?~F*Uu@ody0N|W#J1+Gkn>swjOM+T{&SfugcTV@X8n4-hJhjGKh&g{NXhxT3A+Ro&IvUOnZ8peTVP0 zfBflIVD8_1>olPhO6?mAy|I9motSRKXI;dqpY1;K zDUjgRZVuE#^c?Fojledm^%TZ|(dN&!7BdhZJ$h7nx_^}>z3uWbd@7-ZCRkJ%>0(mA zyNP$zO)$MKIOYDP0#nV&xnrTISH7owpuC{01LD;yEy^w8r2Bl*ZmpZMP#jc#sWdp{ z1wfpQDu7?=UF9_*o=&$UPW9}iSqBK>+2r@;cUnfbAMv~_e*i0rz(7?&&LGgtt z>RHcf;UKozkk)f!;n!)=^ zzSwIKltM}gT!v>jVI>uz1|@m)br*HXH3L{YtZ4}jkp2N>daKq*O*D#Xj5I*Z_VP7x zNQ05#As|CW$H@*i&jZ+oDHnwVqyK|bWHxjzqT){Fd~3+o;w>T#Ab`cdi7p6uXl$t? zL|~K>HXGFmNLw*I5-RDQUJbLCu+k5HBAx&b6ZR_DWhjU;Ts3r_wD%^kQo=)-JD?xz z=uT;}u#nf$GsETahPculChi2E2qTPC2HiMv4?a=p;k`zWKmcKyLiUJ6b_NhR8lHU! zW<+%02oYAk2HLtMgKkF@LxyeB(C4UKw*3|224o(GY2AGWy6X$_xLe*#BO{nYiz61k zwvX-lFDz^OaauU?29Kk_g1V9vCBefPDI*Rxaz^h7+wSZKEGgz15n8B}h+;J1lF1&8 zTwwN~Rp?OU0@INTOh+z|hg={Rxj;Ia@HFHC0W{(HXu?a-gr}nk&qfoTh+II%b03Xd zppvIbKrS#0xxjqn0;O>IDM$j+;G{<)7Z?h+J(M$2g0ql7%!bb{6W(Ac$A?mLMH*J2 zG9#c4Cogr?BOP6HI^WX%GKH(p;v5-!!9$H%cLw3}7r^JsIFi_aQu9PAe0~yqegHl{ z5k6mL1dM~vN6JB+FB0MR6XEyM;rEl__mgQo8Gb(veqZLxN#l;G@cYSVv=P6ey3wRI zOjAR?g38K*_=0KE3Mvh+dq5!namNd>S7z@1k)1eLuC{Mc_by#3ciw=pW32qjz9l4$ zJHy(5r%w<2Hld*|==0QV+GK{(_Uwi9-LiL&c^x8;iii^T7_sF4KH;d$b2$GY?9+P*;7 z@G^0?AZ=+{htwT3Mmy5>?CD6C_et+S-sq0+AUWg)6m97p@uxRzFjHFtJGWdIviKfD4LsS~yY;ch%!f&^;PAm}AT%G|w*tFL>9=#Mb-D(bx};kJ zAp-9yGWZ_% zQg@jZS?2da14|h{6QW$atRyNBa5v49-{K}EF{BjKhLzd^g!w93KccDg+E;|iQMgXG zzk{d{*vDQ}fzBu7KKEL2?UeD$0gx-hjy4c~(CYL&q7d_O+j*aV?wxoUpNU?`#;}%V z<2U7d4ff2_73h2IHH`a<`iVL;VOUXGVq(!$tOd^Y6p3k^ido&Ru&*gKHSMb|uN!r$ z*my3+rT@hAGFCnn8_<2eNeR2BqSSn61jbS!G@M+V?Q*v=iyo1de)i?sp-cW2ERzaP zld(%PMB`HQ6$Ca*KcmY0=C>&0%`+-(ONnSC6061Y3+xeAb+k2BtcUEeQk%JemqwnwYYYHG9QKgPX|l6GG8hy<<9ez z-wc+y%KT8N@>BWr$vvzcB8QVJCK)Qmgnm`3d|(H3VqgrFC&9dlMh4nbhV1XtY)^K! zTp^k!wVImZiAs%`D`M9;*Yfz>4xtfap_mU#cgvN7|5GC@0Y0QEft?$Wva$iGpRl7E zcSPCN5z(Tq_;@EQH^Uk=d_;2=l7jcTtCqWn{2p){svOpDjA~(_zg3QE>wh__DWGZD z6iH8ruL)5LSxZwg;jzn5adt*>!b(}L;X~|(uZWr~a275`M~+%75CUU{)7ARdu(J8& zwR-jF(fVDuAvN!+7h9Q?y9_ZV?CR!)=NM`|R1wc5Lr1BBDI7t5>|s zz&1tPX<^@-_uqfNrB6+oGsleY+`f-kx8Y|tqtp8GuhMzYDeA7hK)XAQu(D+pSzE== z(V2iTeq1V6YkztVy^4V^y~wW;nWk7!71rW=3Ub0esiGP+yaiuyQ<-{grT80$lTH!a zwL7Qo+OCDbLo+!G~IA2(*$nEcR9k+3fpwNZaUt2;MW?mO^W#ZYLZuzUET zR}aVu5oXR1_nK*e(nP6#SbD2NDgmP&c1T9YZwdxf!c>i%&Pz3@KTU2)Wl9Y%Yw5!= zU)`#&zX_7!)ll`L%z@qmB7SR=7YgjerIsjmkZlI;wN?ZyCG37v_5&u$Mf;kRg*iK* zqGLC#_O&G?C25vwBT?WC?hxgn8IDLq#dS^Y>uN4agKRc*B{i=JiIv=^TDmK?&+C!2 ztK63}b4wlj!tUd{#-=-$$_FR%JjZd2h^u}$RH39nUrdKe5qu{KnLj2Y7)K4T&yR+} zCsKo6kp&Hv0u2=(oJ1Wh;-I0jprI0>q2i#SQiG$oI-7bX6V6;w5L9TRi1TMsgS44U zO`?)l1NtdG2*n2N6dxQ)&83c^mI!}v9_M6G)2V6H6p@Z4U?TdFMChhOD5YemtCXOd z{%IVW$aTZ0dC+&oe2=A1Q>Zdq#x%Ak(?%9GlbXuD5!4~<&!-NjPT<^;e2=G&BmMx> znvXssero)5F(ahK_jx*u`FNBr#nx{r-+QfHA#GE^v6+Vc(Nk|fwOM==(%v3=aK0gK zCr`9+4JuZ74iCn>jML7fY&fc5BEr_ek&q zA>$eM#%c(|^biRmEH`2IP1S#^KZf1Rkmk130Ymsgp~oKU?oLU$?z%EbQkXLPnA3YL zREeVQ*1_ss>c*i|SGCYQu^I|uwOCz6pa;)`4^Ex>$tO46R4q4dx#i=Jr%k)}-fHxX zswY&2*FjGBU+tBOdY))o2m@wOzZ8um_c76!m)cMVXExQzldly}=#G~d$jXFAA}pF7 z_eJ1~guJwn_QI%xmm2!`#94_G(yj<;O>upx#(XRWUPLPYqBv%6R07=PBjwR4rS=GL z3aQ0Q<``f1LOfq-Roc&5E2$OMg@)?ZEd$dYag}lzb&a_xkla+? z!$wz^j`617Urpkx*tmyW1-=5&7IKX{mAT_zZ$sHni4VE9<(wdw<(YSMX75(Hm*L{^ zc}jRaXYAxt%Ia*8g%{Y~*H_J5J3DmGK!04k(}kRz4zS$u<8lM`4wWsyKyL75I3rbk z5ADKl!JUS`zP0Vgx+)TK$$9v7he9qHFhmWxy4(YSulKs`LT};!^++KXk>KUIy{?E) z#NH2`U24!#`4|9O9o&QYv!9rVlAqW29^HF%kGdzMb-M@rhQ4vkmN6Te-wtVWj%2@Y zxYtD1MV{^~wSPlIJ1e3YZrD?lLaqYzuSY{5X@dYS_AarC`m{3jj*ynUzZjGrRysNi zDtB&Zh>JsNn;{1&YDu#Im*xyoadC6A-@kwVnQ>ukYUB`|nN#c!Bd}x>&HJ~11J0Mr zp_Ok!UhvIV4RIpukc*MU0_*Du@L%tZ3bHGOh+l5G1aZuirS}Z}H$1Ja9>QQGCp%q@ zjh@@(Y)H+%^sROJ#J8i5r#Fx-eMC@|yqJHyP-g4D?M0`o;l$13+KN!KMIxQ@#Ox{XpM%pl>|TH(kg)WOHdtp%!sIdUBv| zD$q9-=$i`k4FG+8KwlrwHvsev0DS{M-vH1z5$G#(*{1@5Q-Q##K;YD13ipd~uJJ(N zcpz{*5ZDI(6tzcd*wGIP(UkRxbyJs5ir`~^Rqu3Nui}ueq z%JF>vgZM~YQhRwwxi=_*t{ZBRk897s9u3Gd^7L%1DPp_EC5%&AL)w>V9|*Pg?p_II zWyQJzYR~^Gz-$O86bh*W0x0VVh1%NU1@}0yLRc0LLf9V_|W( z;XVUc`T6086DI;zV~a%NPSaw*wd(6VVhdN+irOkER*Heu1vW;lXExQd&bn6KKn)=& z54*Q{wx#D4Fbc;O8}7t0i6v=8AvM#TYE)vx{Q>m|OwsX>^2B+ic8LU{0i~qG5YJXv z4+A%UWj}A-fWuxKW-eD%DAzc!^IGM5;kd1zLgC z7Sd{yc6>dS`#blG_>eZVb>cU7+0L#>LJozLtV=j~cMKaiKL+6=z9oGUI?8)BHoEoW zC*)5F4yn%1!IgZs2)WtCXQ^D-%b~asGKF9|Y&_+@e%C-sI|9&hb$s2KKC91GLu9%P ze7&pCRVbh0=r^9C-h(;543)8_G>@gi0_M1O|eVky(LBi_pUvDf1;b4u( z&N(>y|BGEwTS7d@O#q&JVG=pfdNr-d`x8C7zdt$2u97cDia6bFxtkLuC+c(qaO|Aw zjz--Q*vZ4HIuLPjrsKgqA4qpSkPhjU7f@t!@%$xr^TJYI?iA*y{RYtD8pOIaQ^y zBqP&KRyo+}hNud9t#Yh${n)dBD-C1+|GU@97*)x&rgPS8u9L+zGx<*EoN+GCEPBd| z=qWFzrxY&Ft@M=RPU7EM}dKdRv8N%HOQ>l<1vydKhAU$TW8pzU@ zlJ{X5K+TL|8O-q`*)l?zeX<6Qoqpz-0|rcg>=y-77K2;vAF-tudmi^vi+qUK8towvO+KSk23qT zHy-$W)24=oF=P6>8f|*dr`uBsMvdLHY5m^K(0fdnCedKd@#8yol$LH<3&Cf5O49%c zJ_Bi(kp!FIlU!YGOt|odyYD{blt&+Z*?G!zoHM?R&z>6#Yf*ylx(7R)`_hrRx>`*n z{6#H|IkWFM=lt`Z3vfNaoT!#MI^UZb=^=gkKil&4*E<9=g5Fb_nF(3|?Xja{!h|8| zv0Xy&IUE@{a?)w+;OoXK0q;6bFr&3~&z{1_Q&CZohv!;nvsGGO?{Is) zFe}~b*KaxQ?kiNElJ3JFeD+ylQkt*RDO8^Xe@4H4`}dDJW$M(aeN5jztdo0iHaOY} z+2`Z?7f&ON$=ujnNb<7w!`KbJ(8C{y5##m8u@cG_`**yMeyx{(2;-+1Xzhz&ddm?> z>~{D#rpHZN2aOTaB{F$BtpM83==rxud_1Tz1mufH%6q_f<9wU>Gj2BdK9=?{e^#j# z#?Q_a=FbwIM`tic%=)0=@Sa>^*5&LaAO?}r?{I(ggO8aR2M#>DBF_GqAnYG#7pHPD z+-B55VgIZ$)!#3{);c}f8Lbyy53?Oy#$H=tf5y2#*RgJg9EdhVk3vWsAG=ol6_QK? zw^|?6`#)Pu_8_7)q45j;lNrj)U{H`z)FG-iYx3b#^Uvp&YoPuMOXxYdeN4DdGhD+D zf)_L!s_7rp<@%hZj4sxFj-q4(?tiOlg7Mw5aG~$R566soay3+-XHDM(s6cbE77ok+ z9@Y1=S2x^vFZ)4jQB$UD*g$OBpZ#o{>08G;^JRTa&Cza9^k-*dNFNyeJo;|*T`{T4 zcXStllYXRLu+*Q=#0ewK-X`1MBPddK>;m;Pw@TPseQ2wtx7JJHIMWYiqrq*^>AIip zCtMTx);`AlC)EX(x=1)CJK+TNwYT@vg>ZuIwK+lkgcGy`WJm}>je={DN~FfhNXHve zJEfxHlhoM~?yG|!Fj2w-dAF3qDm&)=^BkKPw2$b9GOv%el49g|^aJ_tJ{4KSA+1ye zhb%0$=|JuTqT>upl^B2!g3g8qbio;Tq+Jjv1X(g#G2QDVNCkex4v)&=Fs)(_YM#psZVZxekKDOJ%N?tcKdX}=wZV$GDeKJe7wVHrKArUK6}F0 zVZ+7_8CC!v=+~xBHG(UTvGRMup>LvMaWd5`BN69cgrV)MVd3C?**VmNO7hzz7TPs$W)c%)Tyl&mCLbi(o zBBRM+bo;JK;#tXjx9|OrJ~~*<<+?DWYH$7`N2fo_XF1XlWh@7Yim8;*RMw~^n0XvS z25tQUxFV=EWQ;?he!}_rm#J*%Ko~)J#bpEdRF`pZ%2M0V9aOtHa(53I=xpB1kD`}G zIwG}^+UQHsmxyf=|ItCvZfLP9~u&lwpih*(%}nP;p2Cc4#4 zaD7URQa}c`F_?KAJnJz1HT%H^`aL}N#rilQA(F7N#dNj4MVG2I!E$4iSz730A4gVo z_5S@sCvX{mc6&EAwS({$9qkmSvqOX@5?@IlVH2GBhT<%f^!`u*L#s-ubS6SeIh{lZ zX>IL_bAp6%BEc^)*jcMefm5~i;xOdix^-`}&KFitx>2+1>rIGQoz95O3hD}G5cfLw z$dRH!adOa6$UzOHi-#Rlnwlz+{fN#3W>)G89}s>}tuuY(&>;lA>~u$jAC%D1w10ng z_O?xM3J;sU9IW#)z$beb%i&~sBky=Ohx@zj!w+)!kRfet&EGzJ`^ks%D3X1PA9l8@ z8kb?ImXP|f`HkKF^2iSoe&hT)SRJJxDCP`idc!=LOSRmBqhai zGO$rtekSIVC0!T_gW%MF3i34F_6IFHYONy4k6`xNfqxVxQ)I>fLxju48ltRt8A;45 zi73TMm@w{QX<+k0_zPllu%mM!=hA=(*kSL(hcp<59=8}yn5u|Yd|$jTT}%Q>Z5DD( z;{3O?lkgl60P+zPAu;x$x(l-?91Es92xLIkS>jqIJHyT}h)XvFBd1l0NKR`5@QIS8 z-Vv3I=$&2KNir&V^SDbWMhQ`PKrUCOkc_%bpJc1T4TEX%w_0d*OT2}q8T+J#63Vfs zg?38|&CBa)p=oUi$9h|6f?a@~8wJbLl2j1d4)jsNJ@6Lv6aX)wZYLR<5KY3SPr|q& z`%~96F`p{xhMScXQhzWPi|!!sRnXa=;sNJH7K=)Qh0u0Q5Z|FlNJb^PNYn{-4?+~x z)Vw^LScI$^RzFn71F8GSgLj~zq5jZ;x;;$Qhw5sM9{uE#kG39`xT!)hdN!DlNxe`k z$(3@%^pSfA`Vle4V|Te8f8$G=YBaD&l8J=1a}@w_%=TRJ~~4q9Uuyvg_VU-VxTmJPj+`DHy#wYsi-oe47W zZaq(bpg&?3*yag6PJQh7iOo2oL)VX~MM(frKfZkT?&juUQPLk)s^|4D06xdM8BRW1 zvuhWzq#ciDWMovtE{^^Ps$NSq?~OId}*96dI+dy5m-6{8mfcpS_lBKGoAO* zuo?7gme5~-hA}+*9X^_vnc(nhV}S5=bT_cAC-jKgYpJ@$A(WZa)b{r5JiKmwhqJmt zj&y1~MG<#} zb4X7FZ{Fl_(cv*7)3F)^p5Zv6X>!&>sEH*_F*d4P_AD&DfLIEgg0j3+HSU!62sFAv)4LOqUyWV~4YM zm?}LZpAIZN72ajU4QHgIPsKYsc;niey1TbGuu}7?G#Ml4k@1HJNnOE&^uBxRs0Xee z>sqqvUr@I!>=GxVZrNBva!TT;Tkc7AUqRgxvHJ>hDW&8rjyZw4iQPB3WU4ACiKA}4 zcHfgxw+!sQ8Q6W@B^B%&N8ZHt>%sQx!S?%~P`6Ah8QEAeGO+n(W64PFLEXgW>nSN? zIf1$*fVzpz_hi(~^BtS7nn|oN-gV5rk}=C0o39scEsyRE zs1j4{H{DMS-!S|suqgN>Y8P0;N3j(u#PX4@SwP4KQ_VR6xosI-KX^-K07j-JkxVa~ zGvce%uSPTm)Lv5;E7dWL_@xU-R@GX8_``fsi(00Uuh0lfGAXkAI=$cRH$??yHAV_+`1WSMVsX#{hqmL|o$|)F; zNtYR@h#ra_LO`+Cq08rf0|iwDh&dM!CeGC8y>i^Rai(j*0zkI~un45xg2G5oDNI3n z9`Z=7za;sR^@YO%YPbn?z@5^ss9#Fv7{q>%Zffq6*zeU7ET8DL+;}BQlb`3RMJbhu8k368hR*?Y=Mpdnx^i zvUHM{xDzs!%Or60H|75RyXkUA-CgYKG&RX}zd>YO`o+JzsQh)UWwgmj6V9`0kz#!{Yfq&62(H&KturE?yxHxhzW@pYkf3I z4Xj;ju~ex|({v546g7I&gmV3NX$SHbkeg(YmMt}6(6uqV*{GDRtFtsvoIEh9Rca&- zSIG{t2>{IAxp$pSR?jZqtbS7`BCEx%^7N+v!&b=jIH$_ZV4v>2Z12^z7jJ|1_E<>D z1(QR-Rw)Q39r@obR9m||*!H%br)jbM+pB>Q#Om{5drnY_?-Y6+!LSlp68PWGBA+<^ zm&8#vubNFiC)vG+@Jk+xlVc3N#aa!PqDuKqViKjXq_QOQ+hmS8U3uwQeRLKc`bZBp zVGlN84>n;RHenz91t0(U=t+I-?dB{#dQu-YVbU$L>`H&K+!*m5+v)=Cj}Rwu@ghZT4ZW^69fu#k!#3~9Yd6xm1I&I5=f@!nx9vw zU21jEHGJ5x;p$>a_ot_x`V*y_&g%TRbLUe7&zXx%#IQwo$3o# z>iYMuQ^~A|t2zS+J8K2${FJjUt4 zv?Pf;dm7_(Dp-Mw)>KYw8b@o&WNVfx!J41Oaj7iHDvhx^S;Y~HUUqRBh=s6=3x70= z68)R0oYVfBDFej93u4ia)>#I&D_rB!l60;$n$~{`NP~wqpAQb<1|MoZZyv$z0OD$WzY|WZAW_iqOy1PmI?02M?-n?BOee}_x z6s#l2sv67`nbaBZ)W7_4R@S>uy-a3R7va5L?nA#(dSNADWuKARNffP|b1Jbx?~oZz z%`(${MKWz<&CWyq~>< zrTs4-ef+Vt%nM=HL45#?&WueW8j{55{Z;I?Xu~4VKexjT1E^O92?1-ma7NZuuBT~< z_pex{ug4xN_KzDSyV{LRgoHw(pj0T;FIA!zr!vpiukf;lY7aCuCKZh)2eD2*S8=dm#7P-jV5rH%*SOW8uC4^ zFEPcW0gSEYaZhqS&3}KC0JKo1oX=vyd#*foj$XA2+ivy`XQ@A_H|$wbh5u7M?Ytlx zy9K2Iey!PuO|we^<%knyO-(|A1?3j$N4zrRJwhKN#Hc&2eLC2PQLwF>r)DiPlTnYz z0J3}c?!(bcnllC#G|tu|ruRq^7RhAL`JRR>t(cRUUL0$}!-uEVf36S0Gd#FK;-4Of zH}-GsGh#$){f3kGp^*{$!|N<4C@dI)TB~~M3t)y?TX-+}S#;47Rfzv722jl&_!hdb zceR8GF=;K+X%5n=XPe%nL`;B5DZp%;!Pb!>Z}CXFx~i6;c?JnV&w&nJJO}1iYZ;+3 zSQpPjBti)#ks$U&C+eU}BnGG>1WT?GK}cH|^!P%AjXi875|soCZ(EmgVS5XS0uB^v zdb^!sisPIos)o7|(;&u2I-zhYimd7GYLg_)UDR=`r;h7lC+fIOp4c~aY!{KDh+)k1 zFpQxcMmj|Cb#-@;5xLv0Jg?h%;K2R^n|Tq*p)7$v9K_qribrylBFF=9nZDZf>p=?Z z_U+z~(7jb{Y*TIf+S_YYMt;5#>BJ)T#1l_^)!v81i23S$)17*N+c&Pk;)Tj2M~nNIWQVYp*#Y1X zQkDTUA@77}X<|yo1kUF|wz_Q2F7Z+kezD1r$|oe*;h>=O{x6YB5piAe-Uy{HrUO_) zc%!~|BmKMVC{GceG3fxI1-qyvJctqfgZyci)5N#JO)Do!1C7Z$$!9&c;IWUAouqZEccOuy6a5GdpJbE#!*l|nkx5eW%y&hY^!|KAG zSwty{deDuFl7o)qBH|#~wLmL3bq=7C3nYa5!ZcPYuN7p=9Kt6y%{4k%uU47E*m4 z63@wATB+P=8uE~MX{8}uikDV^6cOda$?Q9_vMis7fB-6{LQnOCE%C&v09mUv7B1Xc z8Jh`ad}{3aKza0a_9{0Oy4x0~6-a#Qsdq|OtWYC9+?uLt_^FF=<}OQb%Cl6>4Crwm zsb^xlLl4~X4 zN0q;I#E8Z>vorSbLyoC_V(F}HR)C1d5J8>4B@uS8Ja)D5{?~LJS94Z;J<=`R-oh?; zNa4zV4+(NBKt~@l&X6lV#y$s4NN>PNMj)_tx>!_b5_~!y4D`ve9)QDqJ2Ote@*PkG z6@33(f5HWBH-=(n$z#(^q>f@;$m^171S@D6GAkiRE zeQMCrw{TYtW#Iw?#8hG>6|P_Z-hd4o3bzD4iKrJj`4*nu&n#Wr&q~58s?Xrm)XbrM zMoq*m%0z=vUt4;_B;28d@%IVgs>j&hYul%(PMxL}1T<3e-sFZ?f3VFG-=zxuD}948fBu3>eX*WL=#k%ZX@Y1IJzq&cm_*C;5!()E)k)wx)Jo41 zf*`9-VrIf$?qY*?NkUU`ai6`##ZCMAX0}i^^t+jsPCbfG^^P4!N_Ol>I^}3n4nG_v z!lb2-761Dm#6|>Y;|LgAHmerE{1n&C-cZD#hOwbk%Iw z)v8=<$ER)-m(F8*=01p)ZynkKS^>Yr1RB+`ta#}ToA`2cM63rwYA^}Hh;hI}R!;eY z0TFGH|2Pwd9JaYEINez84K3C~BOnMP(R5LK8FQ8dWn77cWCThG15ma3eBpM#D@?^? zS=!lcCE$=0Cc3ttx5_$N(Sm*Kh>zgN!R>Qd8FNtp)QnU`Ex_Vz^?_T4gabMfP^cAm9 zs-?fKwUUmG8kMnb#E7Hns`~YWur#R)G!>rt$Cd+m{ekk>oxlOdD=@77%6MTFFYU$b zbg`)(we$z4@<=vg6jvEZd4=jKerPaNJ42}2vynh|n>JObRn5}&<$kPtvnsLuf;q*YO{lOSFJqx zrsJ?Gt?k*s9>p;ERZ4fy2CY018Qh~h9FCB>qorb>NSBB0FySH_A)YQx)GOP0K>X*h z|C&L>>9a)G1e(F{fUvOSJOBD+U>2(b3%?td?EJkO6OdD)I6!Hk&+@P^K6lar>A`$q z5Do(X4=!CubuK}a(1;xL_r!0oHvlmcZUty2nqY6hEnGzmy8Nzv@f~QhokvZ8wRRU9 zyi`p@b&`(57wc-14RrhqO-HTj+{;eNm(sHn?`@mBz0HaC1{F9%!}dlhz=N1?Y-=)? zB(lI@FNxdMl1jWPr6g`!^I#$Ilnmu}a`<2&@nIqHU?C9(d#|l6nIXVkGEE7KJxSpJ zf>huwIgR~FI3|rHm4%lM3yHr6&G3|zvrj)3#_S$6!&5>uwUX)Vo6Q2oQj*D%&N1J% z#o;`ml1p4%$HD$%I7fe$II7`=#qKSM`w@9TG(06USY~n_nEO~dlCX62`V)Cd`mpZ+ zmQgH&*$$(%WJH|8?KlzH~ zEZVoz5r`Z4gv$53-&M)iO*d63%z$OFGOIjRM#w34*`;1j6|~O1}-nMirS$=hkD~ zV&W~=UK=UMMm3|La$lh(m}pvCtCqy?Gg{OX&?9u-pXiWUNwYS#6DSAs2 z&=~Z=1i9E>xh(W}2UPG?0VE_xt!=sI&G=~4(N6+unrS@Pg^j+yc(*DEVhy{GW3XPA zt2O$o3FYbmG!0WqEVOticH}~r5)T|`f5(f88eo^T_uFEKke%XN1AHyynb}`GH-gb! z8@)I3t$#4FgG8wKDSA$%8ylrwpku_(i}qljKmKjmgA!dKc4o; zuiP=?LXr%v}dCxEBJ(n1aefg|JCay%bu2jivoy@gQXQ@zAdCvzU{g)t{mvF`s(KSkB z&*^Fs@A>Jx=atCS<-F(PIP(mo__@l%x%1Ukyyr8pY6=hg2gpl9kmCCy#rH*uABYs6 zj}$)yDPAH#mT+`Y$qbg6s+f1Zn0I{y?|NVMEVWD6hkfF)6(zc2U!?efBE=V@3Ok%$ z65SLHIpvf|Qz|OT%gfI`yKMOI!2<{MBji1fw50IB9Ai%>)-2D^p+oGyD*x8Six-ph zJ5W`%@FKEdN-FQO_&&q_J}Y(>aC-!j_K)rPT98XSGA(I^wj#G8t?27+ELZpII~f?4 z>Km^!J=gv0mv`QI+l|**o+p?8;h~5Au>8rYK=G z4`wygAK15V-`1@Rr5})>B+ipQ@yV9^zdc*ia8|qrb7U|mhDp||GHY(Q;fCw^yXvYh z@2IceS6yARckkW`B9?#VeRBHrv(BD-;U)9Sk%($&B`nU)ECob&EBN zINpN^@7l%$BQYXUQdm-t6>Qx2MYFMIrnZbkx0db53ReN$8Y-t8yWEKhqg2C;Bc8|TEtf@RO;_0PL@ zHW7Ya!$2qr8{X}_Vm}6NcYq;S)Lh{Gni)1s3NJQR?*J3i+H}L zLx{aI`itmI%s-F*?3?*2p7l_k{Dj!V*kl5E%tAgckN%9JJ@nYi@4WN!V-KBJvpna{ zC?7Vge8#y_P4W8CP8s#%)kOG#nD=Zb>+k9-_0O2EW4>0shrN0YTMd0(fTV7dC!0N= zP}2TkawY@^>O4MC-JBWaK{9&-FEHeURiKiz_5UPQ?{0hTP1bj#8`RFrFTeWEr@Ic;HTg4AGu0=Q>-LL@-rsfU zUA#a6_m!kR&%ELu%k#|ImZYSXe?C*C)?Nzj!FabRVsk!E(L>jN%x$^)5iEs6@yjyEtc=6Gt z7e$vx?~Objc{p-c+K4(;|R^^dWxyM&H z4o7X~nbF6hud?Mewp?a!xse^xJXaY z1xBLbCQM)$N>&(kiNGd=#%wai>VCR_{(k`d|6qNp9%U3QQ02x&Ji+EezkBMbM-Cmw znfTDFPd)Y5hKS|)>WdbwTfX?J%Jjrv1&48B&GJaXVEL$8WqL9)^Rlz^GBac?Gdnvg zGlQrL&`aycYT6JDLG>ojPH}NzVP4*$1o{bvG{U&2q5jJ~*OiqG7|^dD!&OVmFfm7qqtTa1oZ`as&tW?MLWZlGuK(#z zufK^g=8wzCWcb+fKmNZsMIeb@)yJP3>K_z4tP~+41WHe#+)k3j1d3@&i7W~J?(Vw7 zWKxi&zWz{WCoswJ&Q2|671L8wBY~J|YEG4E?%iC7i<-s8us_f%K! z-h}|Lb?YeNkhRv;?%BI8K6nr$mubTW)6=_Vc}5JQo|;FDuzN$d-E-j(&$kWsn5mLq zfHaBq!=1phJ9oZXA22|th=9b0Uhz}~0g`XjPpzPcap#AE{NA;^yr8$?@ZnvEBQ@1k zkLtW!OXua$IyP_Fwtf4yEt^lQS)TFZCyX6CVf=V$9i80-Tnu-2o>;RaFu#OcBwjqx z3EW^%{GC{{JRAXGITEfSse}N!^uI1BK{2r%@Gb{X>!Ab2Fk{B_AB6LaH3&=4ZzThf zAVl1+^xgItkQVm(yq-=6xft7B&0^uaWtgsG$4J?z0$DOT;3^R7e&?U}Exv!rZ+?64z4tCAIPo>!_W|J7 ze)!J&Wu{t8U)9^2RrMp8M1qecC3$n_=QM#YzCwWe?6c?UkLs?*18p7C{9?cJq@~Hb zo}SjbmX>CDs;fti88fuHx++29COX{y#MHDiCY^z+)NfeswS$A-hilG#$v53JHm_jd zppj#yl_whN7o6|ZQ~LGo+wYW9P0#6*2Qp1Q-ST|40e?UDr=L}29wj@_DHA7696zDp z+WD7WI&c2Gi!QpTLQb04Cp~M}h|yzapL-*@k3{mlP2l;SnKicD6Z^Go@)n~vAuEaJ zb$g|HNc_BrCvy8uRSCy=5gVGC>RidI|51T==1&|UD;SE4;rD2%u&ewVKYQQ~&X&LE=Z!1lGl#!u2_$g0ACq=mtB4J)i>Q_dEVTZTT+s{@lE=OtQ3Hk0UKR=*wzuPe>wYRhJQZ zRM%opudQXzf4u$b8*jY&_CI9ptvB9y^X-2Gea4*Gv(Gta_Ut)Ei2mZkcSXQ__d{8G z^`)0ydG|y1NJz~oF3w3!V2?mLF5!*M&E#Che)+KjW#nswT#K`#l}>S}9`b#$E= zkZ8ink&>9`$GHn9dT(-a0=bwv5)wHPu>m@G`Z{*M2Nx-(+}tYDbM84m|LISEe$Kf_ z=W~8aK)^X?BfcCwEa}S*A4Gf!5H~wLokSnWDP1Zn3xzi=i^yQnrVbe;I-1+gJBeC-g z#-2L@OUh^)M|I-AZ*Y9v&Qp%USHT(bu=C_%K@se8B-Wde*m+Vo+X(DDW7uN^S0keZ zO99I;79x|_mYwNp5O$ss*m*``=aG!*!?}{=&JY&mRIE6sVdoh^A2JO)&s4VNV&}n= z9vrre@8Nup=X(OnsVw6-%M6y8s+XQwyOC!IEN;<#}srjm@{j3)MEd6JUgXdFXGaG@%jX5d^pcMwbrHkCF< zXf|dYndijLjh!F6GNqRxGs$vJ$mGb5zm>BAvwY4%p1`_zE<1NK|bdMMa*OEc?_T9s(dwf z-+lL8ciwgDRhN~=D*fl4i?8h8(T+a-yj<-uYVa*(I7%e4zB`u0Y=Dt^tXZfw8|kI% znA^Y<4p*gMvX^0>m&exbb+UK;N1uNB#TR2c#!VbQdi46h3^Ieu{4j+2-Fx%gN17P2H55icDR5_|T!o#-U<&S^oIrD^@(Ve7WVh{wF{A@sDZPRRPld zwzjq$Z#;5vHgz_S`A7DAIdyXdNE0M};EVFuJf4F;nVhTGf-Fy0M{P|_oeo#Ub6oWl zmGWYRaJhN?eFi>~p_7UdasRuA_{xRShJP3Vhu<87I^X9L=HWLDYQ4=c9IAi+6 zaSsG+6N&eW&;IfH>u-Ow{-$ya@5{wG#x`x(pFu?G%phRW)|31a5eLbG)8@S}- ze?~Ld_18x%&n?#t?9*r11vhX>I5*+Wa4aozHl_`kJ@)LU*G|wr)vk^Q%e9lE$)LhC zYOIAuAk&u{sw9>&52{BVHVqtaf+T5khyi0?^ke3OVzzMn`TaNl#CKAn>@JU%ip7lN zVE^6&66RcR!TGb*g50!>yalA-CQ7l_lR!Q>lQ=ixV&=~9rlC;h*KR?09z|*jg=pZp^pb0@x#lNVTw!@uuX*sHhwgv!iK@Iz z7;J@o3;T2*Eyaq*z#Y;4zN6dmq~U-Gx$D-f`KPb1<=N8Ozp`@hkquZGW`onq9M8)7 z4)5;!0Yk%s;T_3-r0H&m)@T1qRV& zabw{4Y)Ad}?F~LRwvFR?{re}jG*p?H_WQ%bMot3x;7Lb-Iz!7%Z((7dq9Xd1?x6R; z{{8#*9XNQ<6I!0rh0Z-_=-|O+W!vps4qLw7vUSIf0bO)Awn_M*2Y+jM?C=dgyXj|D zIZ33+t3TRsw56qAOAG2!W;zu0q}`&apLg!uv(KIjbItSI>eXx3JpbHt-`PDoJ6m>7 z>fQa^lXriP-2-$yP|aK+DffNL$x4lnuh;F7n06%n?Cv5PWw;wwiAVB3%Vc>Ziik{f z{;1z|4Rv(~4;8gZG|)s}LSjl{4LmyPYU@@}tha9E@s1fImblYTuL7CxFq6k!m??^T zeM?LIv6r9TYAf?3e*>B*`U3%v8L75z-9G!WD%0D)47q+RUNGfist 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⪼#*7HRT!Q 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 Vec { + let opt = usvg::Options { + fontdb: GLOBAL_FONTDB.clone(), + hinting: usvg::HintingOptions { + enabled: hinting_enabled, + dpi: Some(96.0), + }, + ..usvg::Options::default() + }; + + let tree = usvg::Tree::from_data(svg_data, &opt).unwrap(); + let size = tree.size().to_int_size(); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap(); + resvg::render( + &tree, + tiny_skia::Transform::identity(), + &mut pixmap.as_mut(), + ); + + pixmap.take() +} + +/// Count the number of pixels that differ between two images. +fn count_different_pixels(img1: &[u8], img2: &[u8]) -> usize { + assert_eq!(img1.len(), img2.len()); + img1.chunks(4) + .zip(img2.chunks(4)) + .filter(|(p1, p2)| p1 != p2) + .count() +} + +/// Test that hinting produces different output than non-hinted rendering. +/// This demonstrates that hinting is actually being applied. +#[test] +fn hinting_produces_different_output() { + // Small text at 12px where hinting effects are most visible + let svg = br#" + + + Hinting Test + + + "#; + + let hinted = render_with_hinting(svg, true); + let unhinted = render_with_hinting(svg, false); + + let diff_count = count_different_pixels(&hinted, &unhinted); + + // Hinted and unhinted output should differ + // The exact number of different pixels depends on the font and size, + // but there should be a noticeable difference + assert!( + diff_count > 0, + "Hinted and unhinted output should differ, but they are identical" + ); + + // Log the difference for debugging + eprintln!( + "hinting_produces_different_output: {} pixels differ", + diff_count + ); +} + +/// Test that geometric-precision disables hinting even when hinting is enabled. +#[test] +fn geometric_precision_disables_hinting() { + let svg_geometric = br#" + + + Geometric Precision + + + "#; + + // With geometricPrecision, hinting should be disabled regardless of the option + let with_hinting_option = render_with_hinting(svg_geometric, true); + let without_hinting_option = render_with_hinting(svg_geometric, false); + + let diff_count = count_different_pixels(&with_hinting_option, &without_hinting_option); + + // Both should produce the same output since geometricPrecision disables hinting + assert_eq!( + diff_count, 0, + "geometricPrecision should produce identical output regardless of hinting option" + ); +} + +/// Test that optimizeLegibility enables hinting when the option is set. +#[test] +fn optimize_legibility_enables_hinting() { + let svg = br#" + + + Optimize Legibility + + + "#; + + let hinted = render_with_hinting(svg, true); + let unhinted = render_with_hinting(svg, false); + + let diff_count = count_different_pixels(&hinted, &unhinted); + + // optimizeLegibility with hinting enabled should differ from unhinted + assert!( + diff_count > 0, + "optimizeLegibility should produce different output when hinting is enabled" + ); +} + +/// Test hinting at various font sizes to demonstrate size-dependent effects. +#[test] +fn hinting_at_various_sizes() { + let sizes = [8, 10, 12, 14, 16, 20, 24, 32, 48]; + let mut results = Vec::new(); + + for size in sizes { + let svg = format!( + r#" + + + Size {} pixels + + + "#, + size, size + ); + + let hinted = render_with_hinting(svg.as_bytes(), true); + let unhinted = render_with_hinting(svg.as_bytes(), false); + + let diff_count = count_different_pixels(&hinted, &unhinted); + results.push((size, diff_count)); + + eprintln!("Size {}px: {} pixels differ", size, diff_count); + } + + // Verify that at least some sizes show hinting differences + let sizes_with_differences = results.iter().filter(|(_, diff)| *diff > 0).count(); + assert!( + sizes_with_differences > 0, + "Hinting should produce differences at various sizes" + ); +} + +/// Test that hinting works with different DPI settings. +#[test] +fn hinting_with_different_dpi() { + let svg = br#" + + + DPI Test + + + "#; + + let render_at_dpi = |dpi: f32| -> Vec { + let opt = usvg::Options { + fontdb: GLOBAL_FONTDB.clone(), + dpi, + hinting: usvg::HintingOptions { + enabled: true, + dpi: Some(dpi), + }, + ..usvg::Options::default() + }; + + let tree = usvg::Tree::from_data(svg, &opt).unwrap(); + let size = tree.size().to_int_size(); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).unwrap(); + resvg::render( + &tree, + tiny_skia::Transform::identity(), + &mut pixmap.as_mut(), + ); + pixmap.take() + }; + + let at_72dpi = render_at_dpi(72.0); + let at_96dpi = render_at_dpi(96.0); + let at_144dpi = render_at_dpi(144.0); + + // Different DPI values should produce different ppem values and thus different hinting. + // ppem = font_size * dpi / 72, so: + // - 72 DPI: ppem = 12 * 72 / 72 = 12 + // - 96 DPI: ppem = 12 * 96 / 72 = 16 + // - 144 DPI: ppem = 12 * 144 / 72 = 24 + let diff_72_96 = count_different_pixels(&at_72dpi, &at_96dpi); + let diff_96_144 = count_different_pixels(&at_96dpi, &at_144dpi); + + eprintln!("72 vs 96 DPI: {} pixels differ (ppem 12 vs 16)", diff_72_96); + eprintln!("96 vs 144 DPI: {} pixels differ (ppem 16 vs 24)", diff_96_144); + + // At least one pair should show differences due to different hinting grid alignment. + // Note: The exact differences depend on font hinting instructions, so we verify + // that different DPI values produce different rendering rather than requiring + // specific pixel counts. + assert!( + diff_72_96 > 0 || diff_96_144 > 0, + "Different DPI values should produce at least some hinting differences" + ); +} + +/// Test hinting with variable fonts (Roboto Flex). +#[test] +fn hinting_with_variable_font() { + let svg = br#" + + + Variable Font Hinting + + + "#; + + let hinted = render_with_hinting(svg, true); + let unhinted = render_with_hinting(svg, false); + + let diff_count = count_different_pixels(&hinted, &unhinted); + + eprintln!("Variable font hinting: {} pixels differ", diff_count); + + // Variable fonts should also show hinting differences + // (though the exact behavior depends on the font's hinting data) +} + +/// Test that auto text-rendering defaults to optimizeLegibility behavior. +#[test] +fn auto_text_rendering_uses_hinting() { + // SVG with auto (default) text-rendering + let svg_auto = br#" + + + Auto Text Rendering + + + "#; + + // SVG with explicit optimizeLegibility + let svg_legibility = br#" + + + Auto Text Rendering + + + "#; + + let auto_hinted = render_with_hinting(svg_auto, true); + let legibility_hinted = render_with_hinting(svg_legibility, true); + + let diff_count = count_different_pixels(&auto_hinted, &legibility_hinted); + + // Both should produce the same output since auto defaults to optimizeLegibility + assert_eq!( + diff_count, 0, + "auto and optimizeLegibility should produce identical output" + ); +} diff --git a/crates/resvg/tests/integration/main.rs b/crates/resvg/tests/integration/main.rs index b90eb5c6c..698952f1c 100644 --- a/crates/resvg/tests/integration/main.rs +++ b/crates/resvg/tests/integration/main.rs @@ -14,8 +14,13 @@ use usvg::fontdb; #[rustfmt::skip] mod render; +#[rustfmt::skip] +mod render_hinted; + mod extra; +mod hinting; + const IMAGE_SIZE: u32 = 300; static GLOBAL_FONTDB: Lazy> = Lazy::new(|| { @@ -34,11 +39,15 @@ static GLOBAL_FONTDB: Lazy> = Lazy::new(|| { }); pub fn render(name: &str) -> usize { - render_inner(name, TestMode::Normal) + render_inner(name, TestMode::Normal, HintingMode::Disabled) +} + +pub fn render_hinted(name: &str) -> usize { + render_inner(name, TestMode::Normal, HintingMode::Enabled) } pub fn render_extra_with_scale(name: &str, scale: f32) -> usize { - render_inner(name, TestMode::Extra(scale)) + render_inner(name, TestMode::Extra(scale), HintingMode::Disabled) } pub fn render_extra(name: &str) -> usize { @@ -46,14 +55,41 @@ pub fn render_extra(name: &str) -> usize { } pub fn render_node(name: &str, id: &str) -> usize { - render_inner(name, TestMode::Node(id)) + render_inner(name, TestMode::Node(id), HintingMode::Disabled) +} + +#[derive(Clone, Copy)] +pub enum HintingMode { + Disabled, + Enabled, } -pub fn render_inner(name: &str, test_mode: TestMode) -> usize { - let svg_path = format!("tests/{}.svg", name); - let png_path = format!("tests/{}.png", name); +pub fn render_inner(name: &str, test_mode: TestMode, hinting_mode: HintingMode) -> usize { + let (svg_path, png_path, diff_dir) = match hinting_mode { + HintingMode::Disabled => ( + format!("tests/{}.svg", name), + format!("tests/{}.png", name), + "tests/diffs", + ), + HintingMode::Enabled => ( + format!("tests/{}.svg", name), + format!("tests-hinted/{}.png", name), + "tests/diffs-hinted", + ), + }; let make_ref = std::env::var("MAKE_REF").is_ok(); + let hinting_options = match hinting_mode { + HintingMode::Disabled => usvg::HintingOptions { + enabled: false, + dpi: None, + }, + HintingMode::Enabled => usvg::HintingOptions { + enabled: true, + dpi: Some(96.0), + }, + }; + let opt = usvg::Options { fontdb: GLOBAL_FONTDB.clone(), resources_dir: Some( @@ -62,6 +98,8 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { .unwrap() .to_owned(), ), + #[cfg(feature = "text")] + hinting: hinting_options, ..usvg::Options::default() }; @@ -110,6 +148,12 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { }; let make_ref_fn = || -> ! { + // Create parent directory if needed (for tests-hinted/) + if let Some(parent) = std::path::Path::new(&png_path).parent() { + if let Err(e) = std::fs::create_dir_all(parent) { + eprintln!("Warning: failed to create directory {:?}: {}", parent, e); + } + } pixmap.save_png(&png_path).unwrap(); Command::new("oxipng") .args([ @@ -129,7 +173,7 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { if make_ref { make_ref_fn(); } else { - panic!("missing reference image"); + panic!("missing reference image: {}", png_path); } }; @@ -137,8 +181,8 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { if make_ref { make_ref_fn(); } else { - let _ = std::fs::create_dir_all("tests/diffs"); - diff_image.save_png(&format!("tests/diffs/{}.png", name.replace("/", "_"))); + let _ = std::fs::create_dir_all(diff_dir); + diff_image.save_png(&format!("{}/{}.png", diff_dir, name.replace("/", "_"))); pixel_diff } @@ -149,6 +193,10 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { /// Returns `Some` if there is at least one different pixel, and `None` if the images match. fn get_diff(expected_image: &TestImage, actual_image: &TestImage) -> Option<(TestImage, usize)> { + /// Pixel difference threshold for image comparison. + /// Value of 1 means any channel difference > 1 is considered a mismatch. + /// This is strict but necessary for detecting subtle font rendering changes. + /// Note: May need platform-specific adjustments if tests become flaky. const DIFF_THRESHOLD: u8 = 1; let width = max(expected_image.width, actual_image.width); diff --git a/crates/resvg/tests/integration/render.rs b/crates/resvg/tests/integration/render.rs index d5d651c8d..ad79dd7e5 100644 --- a/crates/resvg/tests/integration/render.rs +++ b/crates/resvg/tests/integration/render.rs @@ -1457,6 +1457,20 @@ use crate::render; #[test] fn text_font_style_oblique() { assert_eq!(render("tests/text/font-style/oblique"), 0); } #[test] fn text_font_variant_inherit() { assert_eq!(render("tests/text/font-variant/inherit"), 0); } #[test] fn text_font_variant_small_caps() { assert_eq!(render("tests/text/font-variant/small-caps"), 0); } +#[test] fn text_font_variation_settings_all_axes_combined() { assert_eq!(render("tests/text/font-variation-settings/all-axes-combined"), 0); } +#[test] fn text_font_variation_settings_auto_font_stretch_condensed() { assert_eq!(render("tests/text/font-variation-settings/auto-font-stretch-condensed"), 0); } +#[test] fn text_font_variation_settings_auto_font_style_oblique() { assert_eq!(render("tests/text/font-variation-settings/auto-font-style-oblique"), 0); } +#[test] fn text_font_variation_settings_auto_font_weight_700() { assert_eq!(render("tests/text/font-variation-settings/auto-font-weight-700"), 0); } +#[test] fn text_font_variation_settings_explicit_overrides_auto() { assert_eq!(render("tests/text/font-variation-settings/explicit-overrides-auto"), 0); } +#[test] fn text_font_variation_settings_grad_negative() { assert_eq!(render("tests/text/font-variation-settings/grad-negative"), 0); } +#[test] fn text_font_variation_settings_multiple_axes() { assert_eq!(render("tests/text/font-variation-settings/multiple-axes"), 0); } +#[test] fn text_font_variation_settings_opsz_144() { assert_eq!(render("tests/text/font-variation-settings/opsz-144"), 0); } +#[test] fn text_font_variation_settings_slnt_negative() { assert_eq!(render("tests/text/font-variation-settings/slnt-negative"), 0); } +#[test] fn text_font_variation_settings_wdth_151() { assert_eq!(render("tests/text/font-variation-settings/wdth-151"), 0); } +#[test] fn text_font_variation_settings_wdth_25() { assert_eq!(render("tests/text/font-variation-settings/wdth-25"), 0); } +#[test] fn text_font_variation_settings_wght_100() { assert_eq!(render("tests/text/font-variation-settings/wght-100"), 0); } +#[test] fn text_font_variation_settings_wght_700() { assert_eq!(render("tests/text/font-variation-settings/wght-700"), 0); } +#[test] fn text_font_variation_settings_xtra_extreme() { assert_eq!(render("tests/text/font-variation-settings/xtra-extreme"), 0); } #[test] fn text_font_weight_650() { assert_eq!(render("tests/text/font-weight/650"), 0); } #[test] fn text_font_weight_700() { assert_eq!(render("tests/text/font-weight/700"), 0); } #[test] fn text_font_weight_bold() { assert_eq!(render("tests/text/font-weight/bold"), 0); } diff --git a/crates/resvg/tests/integration/render_hinted.rs b/crates/resvg/tests/integration/render_hinted.rs new file mode 100644 index 000000000..cf4b06a06 --- /dev/null +++ b/crates/resvg/tests/integration/render_hinted.rs @@ -0,0 +1,387 @@ +// Copyright 2020 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// This file is auto-generated by gen-tests.py + +#![allow(non_snake_case)] + +use crate::render_hinted; + +#[test] fn hinted_text_alignment_baseline_after_edge() { assert_eq!(render_hinted("tests/text/alignment-baseline/after-edge"), 0); } +#[test] fn hinted_text_alignment_baseline_alphabetic() { assert_eq!(render_hinted("tests/text/alignment-baseline/alphabetic"), 0); } +#[test] fn hinted_text_alignment_baseline_auto() { assert_eq!(render_hinted("tests/text/alignment-baseline/auto"), 0); } +#[test] fn hinted_text_alignment_baseline_baseline() { assert_eq!(render_hinted("tests/text/alignment-baseline/baseline"), 0); } +#[test] fn hinted_text_alignment_baseline_before_edge() { assert_eq!(render_hinted("tests/text/alignment-baseline/before-edge"), 0); } +#[test] fn hinted_text_alignment_baseline_central() { assert_eq!(render_hinted("tests/text/alignment-baseline/central"), 0); } +#[test] fn hinted_text_alignment_baseline_hanging_and_baseline_shift_eq_20_on_tspan() { assert_eq!(render_hinted("tests/text/alignment-baseline/hanging-and-baseline-shift-eq-20-on-tspan"), 0); } +#[test] fn hinted_text_alignment_baseline_hanging_on_tspan() { assert_eq!(render_hinted("tests/text/alignment-baseline/hanging-on-tspan"), 0); } +#[test] fn hinted_text_alignment_baseline_hanging_on_vertical() { assert_eq!(render_hinted("tests/text/alignment-baseline/hanging-on-vertical"), 0); } +#[test] fn hinted_text_alignment_baseline_hanging_with_underline() { assert_eq!(render_hinted("tests/text/alignment-baseline/hanging-with-underline"), 0); } +#[test] fn hinted_text_alignment_baseline_hanging() { assert_eq!(render_hinted("tests/text/alignment-baseline/hanging"), 0); } +#[test] fn hinted_text_alignment_baseline_ideographic() { assert_eq!(render_hinted("tests/text/alignment-baseline/ideographic"), 0); } +#[test] fn hinted_text_alignment_baseline_inherit() { assert_eq!(render_hinted("tests/text/alignment-baseline/inherit"), 0); } +#[test] fn hinted_text_alignment_baseline_mathematical() { assert_eq!(render_hinted("tests/text/alignment-baseline/mathematical"), 0); } +#[test] fn hinted_text_alignment_baseline_middle_on_textPath() { assert_eq!(render_hinted("tests/text/alignment-baseline/middle-on-textPath"), 0); } +#[test] fn hinted_text_alignment_baseline_middle() { assert_eq!(render_hinted("tests/text/alignment-baseline/middle"), 0); } +#[test] fn hinted_text_alignment_baseline_text_after_edge() { assert_eq!(render_hinted("tests/text/alignment-baseline/text-after-edge"), 0); } +#[test] fn hinted_text_alignment_baseline_text_before_edge() { assert_eq!(render_hinted("tests/text/alignment-baseline/text-before-edge"), 0); } +#[test] fn hinted_text_alignment_baseline_two_textPath_with_middle_on_first() { assert_eq!(render_hinted("tests/text/alignment-baseline/two-textPath-with-middle-on-first"), 0); } +#[test] fn hinted_text_baseline_shift__10() { assert_eq!(render_hinted("tests/text/baseline-shift/-10"), 0); } +#[test] fn hinted_text_baseline_shift__50percent() { assert_eq!(render_hinted("tests/text/baseline-shift/-50percent"), 0); } +#[test] fn hinted_text_baseline_shift_0() { assert_eq!(render_hinted("tests/text/baseline-shift/0"), 0); } +#[test] fn hinted_text_baseline_shift_10() { assert_eq!(render_hinted("tests/text/baseline-shift/10"), 0); } +#[test] fn hinted_text_baseline_shift_2mm() { assert_eq!(render_hinted("tests/text/baseline-shift/2mm"), 0); } +#[test] fn hinted_text_baseline_shift_50percent() { assert_eq!(render_hinted("tests/text/baseline-shift/50percent"), 0); } +#[test] fn hinted_text_baseline_shift_baseline() { assert_eq!(render_hinted("tests/text/baseline-shift/baseline"), 0); } +#[test] fn hinted_text_baseline_shift_deeply_nested_super() { assert_eq!(render_hinted("tests/text/baseline-shift/deeply-nested-super"), 0); } +#[test] fn hinted_text_baseline_shift_inheritance_1() { assert_eq!(render_hinted("tests/text/baseline-shift/inheritance-1"), 0); } +#[test] fn hinted_text_baseline_shift_inheritance_2() { assert_eq!(render_hinted("tests/text/baseline-shift/inheritance-2"), 0); } +#[test] fn hinted_text_baseline_shift_inheritance_3() { assert_eq!(render_hinted("tests/text/baseline-shift/inheritance-3"), 0); } +#[test] fn hinted_text_baseline_shift_inheritance_4() { assert_eq!(render_hinted("tests/text/baseline-shift/inheritance-4"), 0); } +#[test] fn hinted_text_baseline_shift_inheritance_5() { assert_eq!(render_hinted("tests/text/baseline-shift/inheritance-5"), 0); } +#[test] fn hinted_text_baseline_shift_invalid_value() { assert_eq!(render_hinted("tests/text/baseline-shift/invalid-value"), 0); } +#[test] fn hinted_text_baseline_shift_mixed_nested() { assert_eq!(render_hinted("tests/text/baseline-shift/mixed-nested"), 0); } +#[test] fn hinted_text_baseline_shift_nested_length() { assert_eq!(render_hinted("tests/text/baseline-shift/nested-length"), 0); } +#[test] fn hinted_text_baseline_shift_nested_super() { assert_eq!(render_hinted("tests/text/baseline-shift/nested-super"), 0); } +#[test] fn hinted_text_baseline_shift_nested_with_baseline_1() { assert_eq!(render_hinted("tests/text/baseline-shift/nested-with-baseline-1"), 0); } +#[test] fn hinted_text_baseline_shift_nested_with_baseline_2() { assert_eq!(render_hinted("tests/text/baseline-shift/nested-with-baseline-2"), 0); } +#[test] fn hinted_text_baseline_shift_sub() { assert_eq!(render_hinted("tests/text/baseline-shift/sub"), 0); } +#[test] fn hinted_text_baseline_shift_super() { assert_eq!(render_hinted("tests/text/baseline-shift/super"), 0); } +#[test] fn hinted_text_baseline_shift_with_rotate() { assert_eq!(render_hinted("tests/text/baseline-shift/with-rotate"), 0); } +#[test] fn hinted_text_color_font_cbdt() { assert_eq!(render_hinted("tests/text/color-font/cbdt"), 0); } +#[test] fn hinted_text_color_font_colrv0() { assert_eq!(render_hinted("tests/text/color-font/colrv0"), 0); } +#[test] fn hinted_text_color_font_colrv1() { assert_eq!(render_hinted("tests/text/color-font/colrv1"), 0); } +#[test] fn hinted_text_color_font_compound_emojis_and_coordinates_list() { assert_eq!(render_hinted("tests/text/color-font/compound-emojis-and-coordinates-list"), 0); } +#[test] fn hinted_text_color_font_compound_emojis() { assert_eq!(render_hinted("tests/text/color-font/compound-emojis"), 0); } +#[test] fn hinted_text_color_font_mixed_text_rtl() { assert_eq!(render_hinted("tests/text/color-font/mixed-text-rtl"), 0); } +#[test] fn hinted_text_color_font_mixed_text() { assert_eq!(render_hinted("tests/text/color-font/mixed-text"), 0); } +#[test] fn hinted_text_color_font_sbix() { assert_eq!(render_hinted("tests/text/color-font/sbix"), 0); } +#[test] fn hinted_text_color_font_svg() { assert_eq!(render_hinted("tests/text/color-font/svg"), 0); } +#[test] fn hinted_text_color_font_writing_mode_eq_tb() { assert_eq!(render_hinted("tests/text/color-font/writing-mode=tb"), 0); } +#[test] fn hinted_text_direction_rtl_with_vertical_writing_mode() { assert_eq!(render_hinted("tests/text/direction/rtl-with-vertical-writing-mode"), 0); } +#[test] fn hinted_text_direction_rtl() { assert_eq!(render_hinted("tests/text/direction/rtl"), 0); } +#[test] fn hinted_text_dominant_baseline_alignment_baseline_and_baseline_shift_on_tspans() { assert_eq!(render_hinted("tests/text/dominant-baseline/alignment-baseline-and-baseline-shift-on-tspans"), 0); } +#[test] fn hinted_text_dominant_baseline_alignment_baseline_eq_baseline_on_tspan() { assert_eq!(render_hinted("tests/text/dominant-baseline/alignment-baseline=baseline-on-tspan"), 0); } +#[test] fn hinted_text_dominant_baseline_alphabetic() { assert_eq!(render_hinted("tests/text/dominant-baseline/alphabetic"), 0); } +#[test] fn hinted_text_dominant_baseline_auto() { assert_eq!(render_hinted("tests/text/dominant-baseline/auto"), 0); } +#[test] fn hinted_text_dominant_baseline_central() { assert_eq!(render_hinted("tests/text/dominant-baseline/central"), 0); } +#[test] fn hinted_text_dominant_baseline_complex() { assert_eq!(render_hinted("tests/text/dominant-baseline/complex"), 0); } +#[test] fn hinted_text_dominant_baseline_different_alignment_baseline_on_tspan() { assert_eq!(render_hinted("tests/text/dominant-baseline/different-alignment-baseline-on-tspan"), 0); } +#[test] fn hinted_text_dominant_baseline_dummy_tspan() { assert_eq!(render_hinted("tests/text/dominant-baseline/dummy-tspan"), 0); } +#[test] fn hinted_text_dominant_baseline_equal_alignment_baseline_on_tspan() { assert_eq!(render_hinted("tests/text/dominant-baseline/equal-alignment-baseline-on-tspan"), 0); } +#[test] fn hinted_text_dominant_baseline_hanging() { assert_eq!(render_hinted("tests/text/dominant-baseline/hanging"), 0); } +#[test] fn hinted_text_dominant_baseline_ideographic() { assert_eq!(render_hinted("tests/text/dominant-baseline/ideographic"), 0); } +#[test] fn hinted_text_dominant_baseline_inherit() { assert_eq!(render_hinted("tests/text/dominant-baseline/inherit"), 0); } +#[test] fn hinted_text_dominant_baseline_mathematical() { assert_eq!(render_hinted("tests/text/dominant-baseline/mathematical"), 0); } +#[test] fn hinted_text_dominant_baseline_middle() { assert_eq!(render_hinted("tests/text/dominant-baseline/middle"), 0); } +#[test] fn hinted_text_dominant_baseline_nested() { assert_eq!(render_hinted("tests/text/dominant-baseline/nested"), 0); } +#[test] fn hinted_text_dominant_baseline_no_change() { assert_eq!(render_hinted("tests/text/dominant-baseline/no-change"), 0); } +#[test] fn hinted_text_dominant_baseline_reset_size() { assert_eq!(render_hinted("tests/text/dominant-baseline/reset-size"), 0); } +#[test] fn hinted_text_dominant_baseline_sequential() { assert_eq!(render_hinted("tests/text/dominant-baseline/sequential"), 0); } +#[test] fn hinted_text_dominant_baseline_text_after_edge() { assert_eq!(render_hinted("tests/text/dominant-baseline/text-after-edge"), 0); } +#[test] fn hinted_text_dominant_baseline_text_before_edge() { assert_eq!(render_hinted("tests/text/dominant-baseline/text-before-edge"), 0); } +#[test] fn hinted_text_dominant_baseline_use_script() { assert_eq!(render_hinted("tests/text/dominant-baseline/use-script"), 0); } +#[test] fn hinted_text_font_font_shorthand() { assert_eq!(render_hinted("tests/text/font/font-shorthand"), 0); } +#[test] fn hinted_text_font_simple_case() { assert_eq!(render_hinted("tests/text/font/simple-case"), 0); } +#[test] fn hinted_text_font_family_bold_sans_serif() { assert_eq!(render_hinted("tests/text/font-family/bold-sans-serif"), 0); } +#[test] fn hinted_text_font_family_cursive() { assert_eq!(render_hinted("tests/text/font-family/cursive"), 0); } +#[test] fn hinted_text_font_family_double_quoted() { assert_eq!(render_hinted("tests/text/font-family/double-quoted"), 0); } +#[test] fn hinted_text_font_family_fallback_1() { assert_eq!(render_hinted("tests/text/font-family/fallback-1"), 0); } +#[test] fn hinted_text_font_family_fallback_2() { assert_eq!(render_hinted("tests/text/font-family/fallback-2"), 0); } +#[test] fn hinted_text_font_family_fantasy() { assert_eq!(render_hinted("tests/text/font-family/fantasy"), 0); } +#[test] fn hinted_text_font_family_font_list() { assert_eq!(render_hinted("tests/text/font-family/font-list"), 0); } +#[test] fn hinted_text_font_family_monospace() { assert_eq!(render_hinted("tests/text/font-family/monospace"), 0); } +#[test] fn hinted_text_font_family_noto_sans() { assert_eq!(render_hinted("tests/text/font-family/noto-sans"), 0); } +#[test] fn hinted_text_font_family_sans_serif() { assert_eq!(render_hinted("tests/text/font-family/sans-serif"), 0); } +#[test] fn hinted_text_font_family_serif() { assert_eq!(render_hinted("tests/text/font-family/serif"), 0); } +#[test] fn hinted_text_font_family_source_sans_pro() { assert_eq!(render_hinted("tests/text/font-family/source-sans-pro"), 0); } +#[test] fn hinted_text_font_kerning_arabic_script() { assert_eq!(render_hinted("tests/text/font-kerning/arabic-script"), 0); } +#[test] fn hinted_text_font_kerning_as_property() { assert_eq!(render_hinted("tests/text/font-kerning/as-property"), 0); } +#[test] fn hinted_text_font_kerning_none() { assert_eq!(render_hinted("tests/text/font-kerning/none"), 0); } +#[test] fn hinted_text_font_size_em_nested_and_mixed() { assert_eq!(render_hinted("tests/text/font-size/em-nested-and-mixed"), 0); } +#[test] fn hinted_text_font_size_em_on_the_root_element() { assert_eq!(render_hinted("tests/text/font-size/em-on-the-root-element"), 0); } +#[test] fn hinted_text_font_size_em() { assert_eq!(render_hinted("tests/text/font-size/em"), 0); } +#[test] fn hinted_text_font_size_ex_nested_and_mixed() { assert_eq!(render_hinted("tests/text/font-size/ex-nested-and-mixed"), 0); } +#[test] fn hinted_text_font_size_ex_on_the_root_element() { assert_eq!(render_hinted("tests/text/font-size/ex-on-the-root-element"), 0); } +#[test] fn hinted_text_font_size_ex() { assert_eq!(render_hinted("tests/text/font-size/ex"), 0); } +#[test] fn hinted_text_font_size_inheritance() { assert_eq!(render_hinted("tests/text/font-size/inheritance"), 0); } +#[test] fn hinted_text_font_size_mixed_values() { assert_eq!(render_hinted("tests/text/font-size/mixed-values"), 0); } +#[test] fn hinted_text_font_size_named_value_without_a_parent() { assert_eq!(render_hinted("tests/text/font-size/named-value-without-a-parent"), 0); } +#[test] fn hinted_text_font_size_named_value() { assert_eq!(render_hinted("tests/text/font-size/named-value"), 0); } +#[test] fn hinted_text_font_size_negative_size() { assert_eq!(render_hinted("tests/text/font-size/negative-size"), 0); } +#[test] fn hinted_text_font_size_nested_percent_values_1() { assert_eq!(render_hinted("tests/text/font-size/nested-percent-values-1"), 0); } +#[test] fn hinted_text_font_size_nested_percent_values_2() { assert_eq!(render_hinted("tests/text/font-size/nested-percent-values-2"), 0); } +#[test] fn hinted_text_font_size_percent_value_without_a_parent() { assert_eq!(render_hinted("tests/text/font-size/percent-value-without-a-parent"), 0); } +#[test] fn hinted_text_font_size_percent_value() { assert_eq!(render_hinted("tests/text/font-size/percent-value"), 0); } +#[test] fn hinted_text_font_size_simple_case() { assert_eq!(render_hinted("tests/text/font-size/simple-case"), 0); } +#[test] fn hinted_text_font_size_zero_size_on_parent_1() { assert_eq!(render_hinted("tests/text/font-size/zero-size-on-parent-1"), 0); } +#[test] fn hinted_text_font_size_zero_size_on_parent_2() { assert_eq!(render_hinted("tests/text/font-size/zero-size-on-parent-2"), 0); } +#[test] fn hinted_text_font_size_zero_size_on_parent_3() { assert_eq!(render_hinted("tests/text/font-size/zero-size-on-parent-3"), 0); } +#[test] fn hinted_text_font_size_zero_size() { assert_eq!(render_hinted("tests/text/font-size/zero-size"), 0); } +#[test] fn hinted_text_font_size_adjust_simple_case() { assert_eq!(render_hinted("tests/text/font-size-adjust/simple-case"), 0); } +#[test] fn hinted_text_font_stretch_extra_condensed() { assert_eq!(render_hinted("tests/text/font-stretch/extra-condensed"), 0); } +#[test] fn hinted_text_font_stretch_inherit() { assert_eq!(render_hinted("tests/text/font-stretch/inherit"), 0); } +#[test] fn hinted_text_font_stretch_narrower() { assert_eq!(render_hinted("tests/text/font-stretch/narrower"), 0); } +#[test] fn hinted_text_font_style_inherit() { assert_eq!(render_hinted("tests/text/font-style/inherit"), 0); } +#[test] fn hinted_text_font_style_italic() { assert_eq!(render_hinted("tests/text/font-style/italic"), 0); } +#[test] fn hinted_text_font_style_oblique() { assert_eq!(render_hinted("tests/text/font-style/oblique"), 0); } +#[test] fn hinted_text_font_variant_inherit() { assert_eq!(render_hinted("tests/text/font-variant/inherit"), 0); } +#[test] fn hinted_text_font_variant_small_caps() { assert_eq!(render_hinted("tests/text/font-variant/small-caps"), 0); } +#[test] fn hinted_text_font_variation_settings_all_axes_combined() { assert_eq!(render_hinted("tests/text/font-variation-settings/all-axes-combined"), 0); } +#[test] fn hinted_text_font_variation_settings_auto_font_stretch_condensed() { assert_eq!(render_hinted("tests/text/font-variation-settings/auto-font-stretch-condensed"), 0); } +#[test] fn hinted_text_font_variation_settings_auto_font_style_oblique() { assert_eq!(render_hinted("tests/text/font-variation-settings/auto-font-style-oblique"), 0); } +#[test] fn hinted_text_font_variation_settings_auto_font_weight_700() { assert_eq!(render_hinted("tests/text/font-variation-settings/auto-font-weight-700"), 0); } +#[test] fn hinted_text_font_variation_settings_explicit_overrides_auto() { assert_eq!(render_hinted("tests/text/font-variation-settings/explicit-overrides-auto"), 0); } +#[test] fn hinted_text_font_variation_settings_grad_negative() { assert_eq!(render_hinted("tests/text/font-variation-settings/grad-negative"), 0); } +#[test] fn hinted_text_font_variation_settings_multiple_axes() { assert_eq!(render_hinted("tests/text/font-variation-settings/multiple-axes"), 0); } +#[test] fn hinted_text_font_variation_settings_opsz_144() { assert_eq!(render_hinted("tests/text/font-variation-settings/opsz-144"), 0); } +#[test] fn hinted_text_font_variation_settings_slnt_negative() { assert_eq!(render_hinted("tests/text/font-variation-settings/slnt-negative"), 0); } +#[test] fn hinted_text_font_variation_settings_wdth_151() { assert_eq!(render_hinted("tests/text/font-variation-settings/wdth-151"), 0); } +#[test] fn hinted_text_font_variation_settings_wdth_25() { assert_eq!(render_hinted("tests/text/font-variation-settings/wdth-25"), 0); } +#[test] fn hinted_text_font_variation_settings_wght_100() { assert_eq!(render_hinted("tests/text/font-variation-settings/wght-100"), 0); } +#[test] fn hinted_text_font_variation_settings_wght_700() { assert_eq!(render_hinted("tests/text/font-variation-settings/wght-700"), 0); } +#[test] fn hinted_text_font_variation_settings_xtra_extreme() { assert_eq!(render_hinted("tests/text/font-variation-settings/xtra-extreme"), 0); } +#[test] fn hinted_text_font_weight_650() { assert_eq!(render_hinted("tests/text/font-weight/650"), 0); } +#[test] fn hinted_text_font_weight_700() { assert_eq!(render_hinted("tests/text/font-weight/700"), 0); } +#[test] fn hinted_text_font_weight_bold() { assert_eq!(render_hinted("tests/text/font-weight/bold"), 0); } +#[test] fn hinted_text_font_weight_bolder_with_clamping() { assert_eq!(render_hinted("tests/text/font-weight/bolder-with-clamping"), 0); } +#[test] fn hinted_text_font_weight_bolder_without_parent() { assert_eq!(render_hinted("tests/text/font-weight/bolder-without-parent"), 0); } +#[test] fn hinted_text_font_weight_bolder() { assert_eq!(render_hinted("tests/text/font-weight/bolder"), 0); } +#[test] fn hinted_text_font_weight_inherit() { assert_eq!(render_hinted("tests/text/font-weight/inherit"), 0); } +#[test] fn hinted_text_font_weight_invalid_number_1() { assert_eq!(render_hinted("tests/text/font-weight/invalid-number-1"), 0); } +#[test] fn hinted_text_font_weight_lighter_with_clamping() { assert_eq!(render_hinted("tests/text/font-weight/lighter-with-clamping"), 0); } +#[test] fn hinted_text_font_weight_lighter_without_parent() { assert_eq!(render_hinted("tests/text/font-weight/lighter-without-parent"), 0); } +#[test] fn hinted_text_font_weight_lighter() { assert_eq!(render_hinted("tests/text/font-weight/lighter"), 0); } +#[test] fn hinted_text_font_weight_normal() { assert_eq!(render_hinted("tests/text/font-weight/normal"), 0); } +#[test] fn hinted_text_glyph_orientation_horizontal_simple_case() { assert_eq!(render_hinted("tests/text/glyph-orientation-horizontal/simple-case"), 0); } +#[test] fn hinted_text_glyph_orientation_vertical_simple_case() { assert_eq!(render_hinted("tests/text/glyph-orientation-vertical/simple-case"), 0); } +#[test] fn hinted_text_kerning_0() { assert_eq!(render_hinted("tests/text/kerning/0"), 0); } +#[test] fn hinted_text_kerning_10percent() { assert_eq!(render_hinted("tests/text/kerning/10percent"), 0); } +#[test] fn hinted_text_lengthAdjust_spacingAndGlyphs() { assert_eq!(render_hinted("tests/text/lengthAdjust/spacingAndGlyphs"), 0); } +#[test] fn hinted_text_lengthAdjust_text_on_path() { assert_eq!(render_hinted("tests/text/lengthAdjust/text-on-path"), 0); } +#[test] fn hinted_text_lengthAdjust_vertical() { assert_eq!(render_hinted("tests/text/lengthAdjust/vertical"), 0); } +#[test] fn hinted_text_lengthAdjust_with_underline() { assert_eq!(render_hinted("tests/text/lengthAdjust/with-underline"), 0); } +#[test] fn hinted_text_letter_spacing__3() { assert_eq!(render_hinted("tests/text/letter-spacing/-3"), 0); } +#[test] fn hinted_text_letter_spacing_0() { assert_eq!(render_hinted("tests/text/letter-spacing/0"), 0); } +#[test] fn hinted_text_letter_spacing_1mm() { assert_eq!(render_hinted("tests/text/letter-spacing/1mm"), 0); } +#[test] fn hinted_text_letter_spacing_3() { assert_eq!(render_hinted("tests/text/letter-spacing/3"), 0); } +#[test] fn hinted_text_letter_spacing_5percent() { assert_eq!(render_hinted("tests/text/letter-spacing/5percent"), 0); } +#[test] fn hinted_text_letter_spacing_filter_bbox() { assert_eq!(render_hinted("tests/text/letter-spacing/filter-bbox"), 0); } +#[test] fn hinted_text_letter_spacing_large_negative() { assert_eq!(render_hinted("tests/text/letter-spacing/large-negative"), 0); } +#[test] fn hinted_text_letter_spacing_mixed_scripts() { assert_eq!(render_hinted("tests/text/letter-spacing/mixed-scripts"), 0); } +#[test] fn hinted_text_letter_spacing_mixed_spacing() { assert_eq!(render_hinted("tests/text/letter-spacing/mixed-spacing"), 0); } +#[test] fn hinted_text_letter_spacing_non_ASCII_character() { assert_eq!(render_hinted("tests/text/letter-spacing/non-ASCII-character"), 0); } +#[test] fn hinted_text_letter_spacing_normal() { assert_eq!(render_hinted("tests/text/letter-spacing/normal"), 0); } +#[test] fn hinted_text_letter_spacing_on_Arabic() { assert_eq!(render_hinted("tests/text/letter-spacing/on-Arabic"), 0); } +#[test] fn hinted_text_text_bidi_reordering() { assert_eq!(render_hinted("tests/text/text/bidi-reordering"), 0); } +#[test] fn hinted_text_text_complex_grapheme_split_by_tspan() { assert_eq!(render_hinted("tests/text/text/complex-grapheme-split-by-tspan"), 0); } +#[test] fn hinted_text_text_complex_graphemes_and_coordinates_list() { assert_eq!(render_hinted("tests/text/text/complex-graphemes-and-coordinates-list"), 0); } +#[test] fn hinted_text_text_complex_graphemes() { assert_eq!(render_hinted("tests/text/text/complex-graphemes"), 0); } +#[test] fn hinted_text_text_dx_and_dy_instead_of_x_and_y() { assert_eq!(render_hinted("tests/text/text/dx-and-dy-instead-of-x-and-y"), 0); } +#[test] fn hinted_text_text_dx_and_dy_with_less_values_than_characters() { assert_eq!(render_hinted("tests/text/text/dx-and-dy-with-less-values-than-characters"), 0); } +#[test] fn hinted_text_text_dx_and_dy_with_more_values_than_characters() { assert_eq!(render_hinted("tests/text/text/dx-and-dy-with-more-values-than-characters"), 0); } +#[test] fn hinted_text_text_dx_and_dy_with_multiple_values() { assert_eq!(render_hinted("tests/text/text/dx-and-dy-with-multiple-values"), 0); } +#[test] fn hinted_text_text_em_and_ex_coordinates() { assert_eq!(render_hinted("tests/text/text/em-and-ex-coordinates"), 0); } +#[test] fn hinted_text_text_escaped_text_1() { assert_eq!(render_hinted("tests/text/text/escaped-text-1"), 0); } +#[test] fn hinted_text_text_escaped_text_2() { assert_eq!(render_hinted("tests/text/text/escaped-text-2"), 0); } +#[test] fn hinted_text_text_escaped_text_3() { assert_eq!(render_hinted("tests/text/text/escaped-text-3"), 0); } +#[test] fn hinted_text_text_escaped_text_4() { assert_eq!(render_hinted("tests/text/text/escaped-text-4"), 0); } +#[test] fn hinted_text_text_fill_rule_eq_evenodd() { assert_eq!(render_hinted("tests/text/text/fill-rule=evenodd"), 0); } +#[test] fn hinted_text_text_filter_bbox() { assert_eq!(render_hinted("tests/text/text/filter-bbox"), 0); } +#[test] fn hinted_text_text_glyph_splitting() { assert_eq!(render_hinted("tests/text/text/glyph-splitting"), 0); } +#[test] fn hinted_text_text_ligatures_handling_in_mixed_fonts_1() { assert_eq!(render_hinted("tests/text/text/ligatures-handling-in-mixed-fonts-1"), 0); } +#[test] fn hinted_text_text_ligatures_handling_in_mixed_fonts_2() { assert_eq!(render_hinted("tests/text/text/ligatures-handling-in-mixed-fonts-2"), 0); } +#[test] fn hinted_text_text_mm_coordinates() { assert_eq!(render_hinted("tests/text/text/mm-coordinates"), 0); } +#[test] fn hinted_text_text_nested() { assert_eq!(render_hinted("tests/text/text/nested"), 0); } +#[test] fn hinted_text_text_no_coordinates() { assert_eq!(render_hinted("tests/text/text/no-coordinates"), 0); } +#[test] fn hinted_text_text_percent_value_on_dx_and_dy() { assert_eq!(render_hinted("tests/text/text/percent-value-on-dx-and-dy"), 0); } +#[test] fn hinted_text_text_percent_value_on_x_and_y() { assert_eq!(render_hinted("tests/text/text/percent-value-on-x-and-y"), 0); } +#[test] fn hinted_text_text_real_text_height() { assert_eq!(render_hinted("tests/text/text/real-text-height"), 0); } +#[test] fn hinted_text_text_rotate_on_Arabic() { assert_eq!(render_hinted("tests/text/text/rotate-on-Arabic"), 0); } +#[test] fn hinted_text_text_rotate_with_an_invalid_angle() { assert_eq!(render_hinted("tests/text/text/rotate-with-an-invalid-angle"), 0); } +#[test] fn hinted_text_text_rotate_with_less_values_than_characters() { assert_eq!(render_hinted("tests/text/text/rotate-with-less-values-than-characters"), 0); } +#[test] fn hinted_text_text_rotate_with_more_values_than_characters() { assert_eq!(render_hinted("tests/text/text/rotate-with-more-values-than-characters"), 0); } +#[test] fn hinted_text_text_rotate_with_multiple_values_and_complex_text() { assert_eq!(render_hinted("tests/text/text/rotate-with-multiple-values-and-complex-text"), 0); } +#[test] fn hinted_text_text_rotate_with_multiple_values_underline_and_pattern() { assert_eq!(render_hinted("tests/text/text/rotate-with-multiple-values-underline-and-pattern"), 0); } +#[test] fn hinted_text_text_rotate_with_multiple_values() { assert_eq!(render_hinted("tests/text/text/rotate-with-multiple-values"), 0); } +#[test] fn hinted_text_text_rotate() { assert_eq!(render_hinted("tests/text/text/rotate"), 0); } +#[test] fn hinted_text_text_simple_case() { assert_eq!(render_hinted("tests/text/text/simple-case"), 0); } +#[test] fn hinted_text_text_transform() { assert_eq!(render_hinted("tests/text/text/transform"), 0); } +#[test] fn hinted_text_text_x_and_y_with_dx_and_dy_lists() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-dx-and-dy-lists"), 0); } +#[test] fn hinted_text_text_x_and_y_with_dx_and_dy() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-dx-and-dy"), 0); } +#[test] fn hinted_text_text_x_and_y_with_less_values_than_characters() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-less-values-than-characters"), 0); } +#[test] fn hinted_text_text_x_and_y_with_more_values_than_characters() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-more-values-than-characters"), 0); } +#[test] fn hinted_text_text_x_and_y_with_multiple_values_and_arabic_text() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-multiple-values-and-arabic-text"), 0); } +#[test] fn hinted_text_text_x_and_y_with_multiple_values_and_tspan() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-multiple-values-and-tspan"), 0); } +#[test] fn hinted_text_text_x_and_y_with_multiple_values() { assert_eq!(render_hinted("tests/text/text/x-and-y-with-multiple-values"), 0); } +#[test] fn hinted_text_text_xml_lang_eq_ja() { assert_eq!(render_hinted("tests/text/text/xml-lang=ja"), 0); } +#[test] fn hinted_text_text_xml_space() { assert_eq!(render_hinted("tests/text/text/xml-space"), 0); } +#[test] fn hinted_text_text_zalgo() { assert_eq!(render_hinted("tests/text/text/zalgo"), 0); } +#[test] fn hinted_text_text_anchor_coordinates_list() { assert_eq!(render_hinted("tests/text/text-anchor/coordinates-list"), 0); } +#[test] fn hinted_text_text_anchor_end_on_text() { assert_eq!(render_hinted("tests/text/text-anchor/end-on-text"), 0); } +#[test] fn hinted_text_text_anchor_end_with_letter_spacing() { assert_eq!(render_hinted("tests/text/text-anchor/end-with-letter-spacing"), 0); } +#[test] fn hinted_text_text_anchor_inheritance_1() { assert_eq!(render_hinted("tests/text/text-anchor/inheritance-1"), 0); } +#[test] fn hinted_text_text_anchor_inheritance_2() { assert_eq!(render_hinted("tests/text/text-anchor/inheritance-2"), 0); } +#[test] fn hinted_text_text_anchor_inheritance_3() { assert_eq!(render_hinted("tests/text/text-anchor/inheritance-3"), 0); } +#[test] fn hinted_text_text_anchor_invalid_value_on_text() { assert_eq!(render_hinted("tests/text/text-anchor/invalid-value-on-text"), 0); } +#[test] fn hinted_text_text_anchor_middle_on_text() { assert_eq!(render_hinted("tests/text/text-anchor/middle-on-text"), 0); } +#[test] fn hinted_text_text_anchor_on_the_first_tspan() { assert_eq!(render_hinted("tests/text/text-anchor/on-the-first-tspan"), 0); } +#[test] fn hinted_text_text_anchor_on_tspan_with_arabic() { assert_eq!(render_hinted("tests/text/text-anchor/on-tspan-with-arabic"), 0); } +#[test] fn hinted_text_text_anchor_on_tspan() { assert_eq!(render_hinted("tests/text/text-anchor/on-tspan"), 0); } +#[test] fn hinted_text_text_anchor_start_on_text() { assert_eq!(render_hinted("tests/text/text-anchor/start-on-text"), 0); } +#[test] fn hinted_text_text_anchor_text_anchor_not_on_text_chunk() { assert_eq!(render_hinted("tests/text/text-anchor/text-anchor-not-on-text-chunk"), 0); } +#[test] fn hinted_text_text_decoration_all_types_inline_comma_separated() { assert_eq!(render_hinted("tests/text/text-decoration/all-types-inline-comma-separated"), 0); } +#[test] fn hinted_text_text_decoration_all_types_inline_no_spaces() { assert_eq!(render_hinted("tests/text/text-decoration/all-types-inline-no-spaces"), 0); } +#[test] fn hinted_text_text_decoration_all_types_inline() { assert_eq!(render_hinted("tests/text/text-decoration/all-types-inline"), 0); } +#[test] fn hinted_text_text_decoration_all_types_nested() { assert_eq!(render_hinted("tests/text/text-decoration/all-types-nested"), 0); } +#[test] fn hinted_text_text_decoration_indirect_with_multiple_colors() { assert_eq!(render_hinted("tests/text/text-decoration/indirect-with-multiple-colors"), 0); } +#[test] fn hinted_text_text_decoration_indirect() { assert_eq!(render_hinted("tests/text/text-decoration/indirect"), 0); } +#[test] fn hinted_text_text_decoration_line_through() { assert_eq!(render_hinted("tests/text/text-decoration/line-through"), 0); } +#[test] fn hinted_text_text_decoration_outside_the_text_element() { assert_eq!(render_hinted("tests/text/text-decoration/outside-the-text-element"), 0); } +#[test] fn hinted_text_text_decoration_overline() { assert_eq!(render_hinted("tests/text/text-decoration/overline"), 0); } +#[test] fn hinted_text_text_decoration_style_resolving_1() { assert_eq!(render_hinted("tests/text/text-decoration/style-resolving-1"), 0); } +#[test] fn hinted_text_text_decoration_style_resolving_2() { assert_eq!(render_hinted("tests/text/text-decoration/style-resolving-2"), 0); } +#[test] fn hinted_text_text_decoration_style_resolving_3() { assert_eq!(render_hinted("tests/text/text-decoration/style-resolving-3"), 0); } +#[test] fn hinted_text_text_decoration_style_resolving_4() { assert_eq!(render_hinted("tests/text/text-decoration/style-resolving-4"), 0); } +#[test] fn hinted_text_text_decoration_tspan_decoration() { assert_eq!(render_hinted("tests/text/text-decoration/tspan-decoration"), 0); } +#[test] fn hinted_text_text_decoration_underline_with_dy_list_1() { assert_eq!(render_hinted("tests/text/text-decoration/underline-with-dy-list-1"), 0); } +#[test] fn hinted_text_text_decoration_underline_with_dy_list_2() { assert_eq!(render_hinted("tests/text/text-decoration/underline-with-dy-list-2"), 0); } +#[test] fn hinted_text_text_decoration_underline_with_rotate_list_3() { assert_eq!(render_hinted("tests/text/text-decoration/underline-with-rotate-list-3"), 0); } +#[test] fn hinted_text_text_decoration_underline_with_rotate_list_4() { assert_eq!(render_hinted("tests/text/text-decoration/underline-with-rotate-list-4"), 0); } +#[test] fn hinted_text_text_decoration_underline_with_y_list() { assert_eq!(render_hinted("tests/text/text-decoration/underline-with-y-list"), 0); } +#[test] fn hinted_text_text_decoration_underline() { assert_eq!(render_hinted("tests/text/text-decoration/underline"), 0); } +#[test] fn hinted_text_text_decoration_with_textLength_on_a_single_character() { assert_eq!(render_hinted("tests/text/text-decoration/with-textLength-on-a-single-character"), 0); } +#[test] fn hinted_text_text_rendering_geometricPrecision() { assert_eq!(render_hinted("tests/text/text-rendering/geometricPrecision"), 0); } +#[test] fn hinted_text_text_rendering_on_tspan() { assert_eq!(render_hinted("tests/text/text-rendering/on-tspan"), 0); } +#[test] fn hinted_text_text_rendering_optimizeLegibility() { assert_eq!(render_hinted("tests/text/text-rendering/optimizeLegibility"), 0); } +#[test] fn hinted_text_text_rendering_optimizeSpeed() { assert_eq!(render_hinted("tests/text/text-rendering/optimizeSpeed"), 0); } +#[test] fn hinted_text_text_rendering_with_underline() { assert_eq!(render_hinted("tests/text/text-rendering/with-underline"), 0); } +#[test] fn hinted_text_textLength_150_on_parent() { assert_eq!(render_hinted("tests/text/textLength/150-on-parent"), 0); } +#[test] fn hinted_text_textLength_150_on_tspan() { assert_eq!(render_hinted("tests/text/textLength/150-on-tspan"), 0); } +#[test] fn hinted_text_textLength_150() { assert_eq!(render_hinted("tests/text/textLength/150"), 0); } +#[test] fn hinted_text_textLength_40mm() { assert_eq!(render_hinted("tests/text/textLength/40mm"), 0); } +#[test] fn hinted_text_textLength_75percent() { assert_eq!(render_hinted("tests/text/textLength/75percent"), 0); } +#[test] fn hinted_text_textLength_arabic_with_lengthAdjust() { assert_eq!(render_hinted("tests/text/textLength/arabic-with-lengthAdjust"), 0); } +#[test] fn hinted_text_textLength_arabic() { assert_eq!(render_hinted("tests/text/textLength/arabic"), 0); } +#[test] fn hinted_text_textLength_inherit() { assert_eq!(render_hinted("tests/text/textLength/inherit"), 0); } +#[test] fn hinted_text_textLength_negative() { assert_eq!(render_hinted("tests/text/textLength/negative"), 0); } +#[test] fn hinted_text_textLength_on_a_single_tspan() { assert_eq!(render_hinted("tests/text/textLength/on-a-single-tspan"), 0); } +#[test] fn hinted_text_textLength_on_text_and_tspan() { assert_eq!(render_hinted("tests/text/textLength/on-text-and-tspan"), 0); } +#[test] fn hinted_text_textLength_zero() { assert_eq!(render_hinted("tests/text/textLength/zero"), 0); } +#[test] fn hinted_text_textPath_closed_path() { assert_eq!(render_hinted("tests/text/textPath/closed-path"), 0); } +#[test] fn hinted_text_textPath_complex() { assert_eq!(render_hinted("tests/text/textPath/complex"), 0); } +#[test] fn hinted_text_textPath_dy_with_tiny_coordinates() { assert_eq!(render_hinted("tests/text/textPath/dy-with-tiny-coordinates"), 0); } +#[test] fn hinted_text_textPath_invalid_link() { assert_eq!(render_hinted("tests/text/textPath/invalid-link"), 0); } +#[test] fn hinted_text_textPath_invalid_textPath_in_the_middle() { assert_eq!(render_hinted("tests/text/textPath/invalid-textPath-in-the-middle"), 0); } +#[test] fn hinted_text_textPath_link_to_rect() { assert_eq!(render_hinted("tests/text/textPath/link-to-rect"), 0); } +#[test] fn hinted_text_textPath_m_A_path() { assert_eq!(render_hinted("tests/text/textPath/m-A-path"), 0); } +#[test] fn hinted_text_textPath_m_L_Z_path() { assert_eq!(render_hinted("tests/text/textPath/m-L-Z-path"), 0); } +#[test] fn hinted_text_textPath_method_eq_stretch() { assert_eq!(render_hinted("tests/text/textPath/method=stretch"), 0); } +#[test] fn hinted_text_textPath_mixed_children_1() { assert_eq!(render_hinted("tests/text/textPath/mixed-children-1"), 0); } +#[test] fn hinted_text_textPath_mixed_children_2() { assert_eq!(render_hinted("tests/text/textPath/mixed-children-2"), 0); } +#[test] fn hinted_text_textPath_nested() { assert_eq!(render_hinted("tests/text/textPath/nested"), 0); } +#[test] fn hinted_text_textPath_no_link() { assert_eq!(render_hinted("tests/text/textPath/no-link"), 0); } +#[test] fn hinted_text_textPath_path_with_ClosePath() { assert_eq!(render_hinted("tests/text/textPath/path-with-ClosePath"), 0); } +#[test] fn hinted_text_textPath_path_with_subpaths_and_startOffset() { assert_eq!(render_hinted("tests/text/textPath/path-with-subpaths-and-startOffset"), 0); } +#[test] fn hinted_text_textPath_path_with_subpaths() { assert_eq!(render_hinted("tests/text/textPath/path-with-subpaths"), 0); } +#[test] fn hinted_text_textPath_side_eq_right() { assert_eq!(render_hinted("tests/text/textPath/side=right"), 0); } +#[test] fn hinted_text_textPath_simple_case() { assert_eq!(render_hinted("tests/text/textPath/simple-case"), 0); } +#[test] fn hinted_text_textPath_spacing_eq_auto() { assert_eq!(render_hinted("tests/text/textPath/spacing=auto"), 0); } +#[test] fn hinted_text_textPath_startOffset_eq__100() { assert_eq!(render_hinted("tests/text/textPath/startOffset=-100"), 0); } +#[test] fn hinted_text_textPath_startOffset_eq_10percent() { assert_eq!(render_hinted("tests/text/textPath/startOffset=10percent"), 0); } +#[test] fn hinted_text_textPath_startOffset_eq_30() { assert_eq!(render_hinted("tests/text/textPath/startOffset=30"), 0); } +#[test] fn hinted_text_textPath_startOffset_eq_5mm() { assert_eq!(render_hinted("tests/text/textPath/startOffset=5mm"), 0); } +#[test] fn hinted_text_textPath_startOffset_eq_9999() { assert_eq!(render_hinted("tests/text/textPath/startOffset=9999"), 0); } +#[test] fn hinted_text_textPath_tspan_with_absolute_position() { assert_eq!(render_hinted("tests/text/textPath/tspan-with-absolute-position"), 0); } +#[test] fn hinted_text_textPath_tspan_with_relative_position() { assert_eq!(render_hinted("tests/text/textPath/tspan-with-relative-position"), 0); } +#[test] fn hinted_text_textPath_two_paths() { assert_eq!(render_hinted("tests/text/textPath/two-paths"), 0); } +#[test] fn hinted_text_textPath_very_long_text() { assert_eq!(render_hinted("tests/text/textPath/very-long-text"), 0); } +#[test] fn hinted_text_textPath_with_baseline_shift_and_rotate() { assert_eq!(render_hinted("tests/text/textPath/with-baseline-shift-and-rotate"), 0); } +#[test] fn hinted_text_textPath_with_baseline_shift() { assert_eq!(render_hinted("tests/text/textPath/with-baseline-shift"), 0); } +#[test] fn hinted_text_textPath_with_big_letter_spacing() { assert_eq!(render_hinted("tests/text/textPath/with-big-letter-spacing"), 0); } +#[test] fn hinted_text_textPath_with_coordinates_on_text() { assert_eq!(render_hinted("tests/text/textPath/with-coordinates-on-text"), 0); } +#[test] fn hinted_text_textPath_with_coordinates_on_textPath() { assert_eq!(render_hinted("tests/text/textPath/with-coordinates-on-textPath"), 0); } +#[test] fn hinted_text_textPath_with_filter() { assert_eq!(render_hinted("tests/text/textPath/with-filter"), 0); } +#[test] fn hinted_text_textPath_with_invalid_path_and_xlink_href() { assert_eq!(render_hinted("tests/text/textPath/with-invalid-path-and-xlink-href"), 0); } +#[test] fn hinted_text_textPath_with_letter_spacing() { assert_eq!(render_hinted("tests/text/textPath/with-letter-spacing"), 0); } +#[test] fn hinted_text_textPath_with_path_and_xlink_href() { assert_eq!(render_hinted("tests/text/textPath/with-path-and-xlink-href"), 0); } +#[test] fn hinted_text_textPath_with_path() { assert_eq!(render_hinted("tests/text/textPath/with-path"), 0); } +#[test] fn hinted_text_textPath_with_rotate() { assert_eq!(render_hinted("tests/text/textPath/with-rotate"), 0); } +#[test] fn hinted_text_textPath_with_text_anchor() { assert_eq!(render_hinted("tests/text/textPath/with-text-anchor"), 0); } +#[test] fn hinted_text_textPath_with_transform_on_a_referenced_path() { assert_eq!(render_hinted("tests/text/textPath/with-transform-on-a-referenced-path"), 0); } +#[test] fn hinted_text_textPath_with_transform_outside_a_referenced_path() { assert_eq!(render_hinted("tests/text/textPath/with-transform-outside-a-referenced-path"), 0); } +#[test] fn hinted_text_textPath_with_underline() { assert_eq!(render_hinted("tests/text/textPath/with-underline"), 0); } +#[test] fn hinted_text_textPath_writing_mode_eq_tb() { assert_eq!(render_hinted("tests/text/textPath/writing-mode=tb"), 0); } +#[test] fn hinted_text_tref_link_to_a_complex_text() { assert_eq!(render_hinted("tests/text/tref/link-to-a-complex-text"), 0); } +#[test] fn hinted_text_tref_link_to_a_non_SVG_element() { assert_eq!(render_hinted("tests/text/tref/link-to-a-non-SVG-element"), 0); } +#[test] fn hinted_text_tref_link_to_a_non_text_element() { assert_eq!(render_hinted("tests/text/tref/link-to-a-non-text-element"), 0); } +#[test] fn hinted_text_tref_link_to_an_external_file_element() { assert_eq!(render_hinted("tests/text/tref/link-to-an-external-file-element"), 0); } +#[test] fn hinted_text_tref_link_to_text() { assert_eq!(render_hinted("tests/text/tref/link-to-text"), 0); } +#[test] fn hinted_text_tref_nested() { assert_eq!(render_hinted("tests/text/tref/nested"), 0); } +#[test] fn hinted_text_tref_position_attributes() { assert_eq!(render_hinted("tests/text/tref/position-attributes"), 0); } +#[test] fn hinted_text_tref_style_attributes() { assert_eq!(render_hinted("tests/text/tref/style-attributes"), 0); } +#[test] fn hinted_text_tref_with_a_title_child() { assert_eq!(render_hinted("tests/text/tref/with-a-title-child"), 0); } +#[test] fn hinted_text_tref_with_text() { assert_eq!(render_hinted("tests/text/tref/with-text"), 0); } +#[test] fn hinted_text_tref_xml_space() { assert_eq!(render_hinted("tests/text/tref/xml-space"), 0); } +#[test] fn hinted_text_tspan_bidi_reordering() { assert_eq!(render_hinted("tests/text/tspan/bidi-reordering"), 0); } +#[test] fn hinted_text_tspan_mixed_font_size() { assert_eq!(render_hinted("tests/text/tspan/mixed-font-size"), 0); } +#[test] fn hinted_text_tspan_mixed_xml_space_1() { assert_eq!(render_hinted("tests/text/tspan/mixed-xml-space-1"), 0); } +#[test] fn hinted_text_tspan_mixed_xml_space_2() { assert_eq!(render_hinted("tests/text/tspan/mixed-xml-space-2"), 0); } +#[test] fn hinted_text_tspan_mixed_xml_space_3() { assert_eq!(render_hinted("tests/text/tspan/mixed-xml-space-3"), 0); } +#[test] fn hinted_text_tspan_mixed() { assert_eq!(render_hinted("tests/text/tspan/mixed"), 0); } +#[test] fn hinted_text_tspan_multiple_coordinates() { assert_eq!(render_hinted("tests/text/tspan/multiple-coordinates"), 0); } +#[test] fn hinted_text_tspan_nested_rotate() { assert_eq!(render_hinted("tests/text/tspan/nested-rotate"), 0); } +#[test] fn hinted_text_tspan_nested_whitespaces() { assert_eq!(render_hinted("tests/text/tspan/nested-whitespaces"), 0); } +#[test] fn hinted_text_tspan_nested() { assert_eq!(render_hinted("tests/text/tspan/nested"), 0); } +#[test] fn hinted_text_tspan_only_with_y() { assert_eq!(render_hinted("tests/text/tspan/only-with-y"), 0); } +#[test] fn hinted_text_tspan_outside_the_text() { assert_eq!(render_hinted("tests/text/tspan/outside-the-text"), 0); } +#[test] fn hinted_text_tspan_pseudo_multi_line() { assert_eq!(render_hinted("tests/text/tspan/pseudo-multi-line"), 0); } +#[test] fn hinted_text_tspan_rotate_and_display_none() { assert_eq!(render_hinted("tests/text/tspan/rotate-and-display-none"), 0); } +#[test] fn hinted_text_tspan_rotate_on_child() { assert_eq!(render_hinted("tests/text/tspan/rotate-on-child"), 0); } +#[test] fn hinted_text_tspan_sequential() { assert_eq!(render_hinted("tests/text/tspan/sequential"), 0); } +#[test] fn hinted_text_tspan_style_override() { assert_eq!(render_hinted("tests/text/tspan/style-override"), 0); } +#[test] fn hinted_text_tspan_text_shaping_across_multiple_tspan_1() { assert_eq!(render_hinted("tests/text/tspan/text-shaping-across-multiple-tspan-1"), 0); } +#[test] fn hinted_text_tspan_text_shaping_across_multiple_tspan_2() { assert_eq!(render_hinted("tests/text/tspan/text-shaping-across-multiple-tspan-2"), 0); } +#[test] fn hinted_text_tspan_transform() { assert_eq!(render_hinted("tests/text/tspan/transform"), 0); } +#[test] fn hinted_text_tspan_tspan_bbox_1() { assert_eq!(render_hinted("tests/text/tspan/tspan-bbox-1"), 0); } +#[test] fn hinted_text_tspan_tspan_bbox_2() { assert_eq!(render_hinted("tests/text/tspan/tspan-bbox-2"), 0); } +#[test] fn hinted_text_tspan_with_clip_path() { assert_eq!(render_hinted("tests/text/tspan/with-clip-path"), 0); } +#[test] fn hinted_text_tspan_with_dy() { assert_eq!(render_hinted("tests/text/tspan/with-dy"), 0); } +#[test] fn hinted_text_tspan_with_filter() { assert_eq!(render_hinted("tests/text/tspan/with-filter"), 0); } +#[test] fn hinted_text_tspan_with_mask() { assert_eq!(render_hinted("tests/text/tspan/with-mask"), 0); } +#[test] fn hinted_text_tspan_with_opacity() { assert_eq!(render_hinted("tests/text/tspan/with-opacity"), 0); } +#[test] fn hinted_text_tspan_with_x_and_y() { assert_eq!(render_hinted("tests/text/tspan/with-x-and-y"), 0); } +#[test] fn hinted_text_tspan_without_attributes() { assert_eq!(render_hinted("tests/text/tspan/without-attributes"), 0); } +#[test] fn hinted_text_tspan_xml_space_1() { assert_eq!(render_hinted("tests/text/tspan/xml-space-1"), 0); } +#[test] fn hinted_text_tspan_xml_space_2() { assert_eq!(render_hinted("tests/text/tspan/xml-space-2"), 0); } +#[test] fn hinted_text_unicode_bidi_bidi_override() { assert_eq!(render_hinted("tests/text/unicode-bidi/bidi-override"), 0); } +#[test] fn hinted_text_word_spacing__5() { assert_eq!(render_hinted("tests/text/word-spacing/-5"), 0); } +#[test] fn hinted_text_word_spacing_0() { assert_eq!(render_hinted("tests/text/word-spacing/0"), 0); } +#[test] fn hinted_text_word_spacing_10() { assert_eq!(render_hinted("tests/text/word-spacing/10"), 0); } +#[test] fn hinted_text_word_spacing_2mm() { assert_eq!(render_hinted("tests/text/word-spacing/2mm"), 0); } +#[test] fn hinted_text_word_spacing_5percent() { assert_eq!(render_hinted("tests/text/word-spacing/5percent"), 0); } +#[test] fn hinted_text_word_spacing_large_negative() { assert_eq!(render_hinted("tests/text/word-spacing/large-negative"), 0); } +#[test] fn hinted_text_word_spacing_normal() { assert_eq!(render_hinted("tests/text/word-spacing/normal"), 0); } +#[test] fn hinted_text_writing_mode_arabic_with_rl() { assert_eq!(render_hinted("tests/text/writing-mode/arabic-with-rl"), 0); } +#[test] fn hinted_text_writing_mode_horizontal_tb() { assert_eq!(render_hinted("tests/text/writing-mode/horizontal-tb"), 0); } +#[test] fn hinted_text_writing_mode_inheritance() { assert_eq!(render_hinted("tests/text/writing-mode/inheritance"), 0); } +#[test] fn hinted_text_writing_mode_invalid_value() { assert_eq!(render_hinted("tests/text/writing-mode/invalid-value"), 0); } +#[test] fn hinted_text_writing_mode_japanese_with_tb() { assert_eq!(render_hinted("tests/text/writing-mode/japanese-with-tb"), 0); } +#[test] fn hinted_text_writing_mode_lr_tb() { assert_eq!(render_hinted("tests/text/writing-mode/lr-tb"), 0); } +#[test] fn hinted_text_writing_mode_lr() { assert_eq!(render_hinted("tests/text/writing-mode/lr"), 0); } +#[test] fn hinted_text_writing_mode_mixed_languages_with_tb_and_underline() { assert_eq!(render_hinted("tests/text/writing-mode/mixed-languages-with-tb-and-underline"), 0); } +#[test] fn hinted_text_writing_mode_mixed_languages_with_tb() { assert_eq!(render_hinted("tests/text/writing-mode/mixed-languages-with-tb"), 0); } +#[test] fn hinted_text_writing_mode_on_tspan() { assert_eq!(render_hinted("tests/text/writing-mode/on-tspan"), 0); } +#[test] fn hinted_text_writing_mode_rl_tb() { assert_eq!(render_hinted("tests/text/writing-mode/rl-tb"), 0); } +#[test] fn hinted_text_writing_mode_rl() { assert_eq!(render_hinted("tests/text/writing-mode/rl"), 0); } +#[test] fn hinted_text_writing_mode_tb_and_punctuation() { assert_eq!(render_hinted("tests/text/writing-mode/tb-and-punctuation"), 0); } +#[test] fn hinted_text_writing_mode_tb_rl() { assert_eq!(render_hinted("tests/text/writing-mode/tb-rl"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_alignment() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-alignment"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_dx_on_second_tspan() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-dx-on-second-tspan"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_dx_on_tspan() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-dx-on-tspan"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_dy_on_second_tspan() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-dy-on-second-tspan"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_rotate_and_underline() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-rotate-and-underline"), 0); } +#[test] fn hinted_text_writing_mode_tb_with_rotate() { assert_eq!(render_hinted("tests/text/writing-mode/tb-with-rotate"), 0); } +#[test] fn hinted_text_writing_mode_tb() { assert_eq!(render_hinted("tests/text/writing-mode/tb"), 0); } +#[test] fn hinted_text_writing_mode_vertical_lr() { assert_eq!(render_hinted("tests/text/writing-mode/vertical-lr"), 0); } +#[test] fn hinted_text_writing_mode_vertical_rl() { assert_eq!(render_hinted("tests/text/writing-mode/vertical-rl"), 0); } diff --git a/crates/resvg/tests/tests/text/color-font/colrv0.png b/crates/resvg/tests/tests/text/color-font/colrv0.png index e4b090d246bd147d84b237c40fa9a734630f7754..087615997b220fe19d74abfd292be9e4cbb0162b 100644 GIT binary patch literal 1561 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAaydpC&U#H#Z<4z{<)>R#sL*LV}&09ms&la&d71O{=f3H#9V4W@ZMeiHV6378d@`zyL=; zm2fsO42XKT?YJ0E3}+Sq<(x}`{DK)0;sp%Oe+W1*|Neyf;`ROeGixXAJp6iBy#K@5 zb7p^?RC4yngcXM$1gs2vkn*rn^1mUcih}@4K4Za#3kvTSG$h#ncW?+ewUB{2Vf*GrYu{@NiK8EtZ$9MfC_j2QCXcyqu5IQ2_9)X`fp>50 z^;!8#{M?lKUvC=rduSFO`?ZQIal*sZR>_iqT|atC_tboy!aRY^VNML2RQj5ldB6Yv zpJT7zuuYHgh|1HGiEA6r{+hiZY_n?3UR#^JB|dBoil%*QI+I z8@3!4@@<)XxN5fU{pt3p=cCSCIQppN+~y~y!JYnR!#7{exmZ7YO5=y5zrn@_#c!Rt zD9Si_R=9fO)hjB&C2Oax{;GTLdiI-H6PA2S=xkYHYakSMZl3x&&rOoNVF#;}{)F8L zU6{S=NLuGnncYHi2Zb2fBiPvQo-MNQ?{{ln>dAH}U({@s*25_iLRV`&PUvjV36+kz zZ*;)%vZX;qm7}H9niC;QK1PKy39LQu#XRBE!Ch*+4JS5zuSveWicx^^fSUZtc~>`l ztC3l~cy;ja{c!S2FkNWs=3}k> zWyXI`xHqY0Fr2N*j%*d1Yh1`T&9u-d;{4vM6Fg;;qrQe+V}9NLdt-v)H3y%f{j*zy zn%{Iz)(f*Q+?1!QBjwBYP4j%xJiSlf&qi$6Bq1>C&i_SX6R)od-m|Frs{fo-D=(au zxa4p<{?>$r>4yIHab^fU!T>ZUx3P+Mf=a$V{5_}teb#~91X11hDd4b3^j&`>< z{9E%DAGma&{+ee+^CZbNYdUXh9sVJ(dj5`{WeeJ-%FLNA#d$kxP6S)Rt#3+q`O^M8 zcjcVQx7c~jIj;XrJwD9V%nrZ(%0-X$sCxWZEZHH_!K# z2JU&!F21Z*Vl@8!BC7pjt71dhiy15o5^PKfit~)7{}2yd(KO%auBXL7Wm5uWgBYar pz)D@y0y_Gu>IM7m3v;BLzA_wl5|B{QN^1rcnVznGF6*2Ung9+ak=OtL literal 1591 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAax_aC&U#<{|92?$i~J-h~kEZ z1_&cJHy2rZY;0^yOiVyP0J0!5+X@VT+6@g2>+9>`_QDymU;yVzNJt0^3nQC=%;w_a zVrOSZ7GY*)hH(4R6Mg|raVrV(3uX`yP*5;1u(x+`@b?c0h>wp?NJz-c&o3w_E~%}r zZ)oW6pDyC;@{RsFU0aqr46&0 zV-~+|RS#dg&{$`BWplA_-TVKty)$NNZ2J}SF)vpI`HIqFwH~7xPl%uSEQN zl~;X7Zu;Roskgo&ua}3Z{=f97Z=cM&XxkXpu!~+>Z)uOWM0UmzJEk)I2+3=H8H{k>YQP&bykI8$|7!IF~o<9p9wxC|RBvI%!WCXZvl4 zQ(=G7SetTuVJPDhhVB%;h`rvYcdXgowSHRve%{k39=rE8R{T!*`R(KDBDn~Qrw>kv zwB`Kf4-*YsQ?#U`a+8c&`kf;g;`i;8?HG{&;)l(dgdGg8U-SUimVsPK4KF&Z~C!9Iu-=Aqlzh`+ad%4!^ zm0QH&BTrqI2^g&{Ug2YKXs+?|@V84U6Doh`?Pw7Xxg{v#b0_yzNPH5n@b<~KPY9>D ze-BFMT$9%I)WO%RqhiI=N8c9(t$hEoUSogM-_C$} za!`3`K5=Ziut6QrT01j(#RIW4`MOf769k0>?txZL}}<14~H;Pgg&e IbxsLQ0LwzHF8}}l diff --git a/crates/resvg/tests/tests/text/color-font/colrv1.png b/crates/resvg/tests/tests/text/color-font/colrv1.png index 7537da902e2bd7880bf088772829e4e1d9c63d8e..23bb63a05b00f896290c1a5baaf584cead684658 100644 GIT binary patch delta 5872 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 literal 6152 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 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/all-axes-combined.png b/crates/resvg/tests/tests/text/font-variation-settings/all-axes-combined.png new file mode 100644 index 0000000000000000000000000000000000000000..c4222be24253023b7a1de08bd344465db5c9296e GIT binary patch literal 1262 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`&yA>EaktaqG>6M%Duk z0xSp4etZzUI4M6gr_5!Wek!pPKiz zIn!f5U+5EMVbU<3vBNI)E${RH`#&G$b$2`X<(S+%O|f5FgLo?HH$7RpqbxSirY5$O z_tCwSShia$Ql@-mI_YBFrSW=7$mK@0Q&x@>yhT$h4|dvgXq6?0tShCe?V-?2}K|a%*z4+$(Pjh}Pl{i0U<;#v~3r{=w>OIok^kwFn zmut=kwCicB9}b#sEZH`9%|>-^`@G%Nk+tXZbu-UvODix>zq-ks>syM$v=z_Xguk`V zHi+y_*(mbb_{p9>It7t`cv&Q~rzSmW=-lkrGI48WL{6Npf3M9?+Y>>%^=Bk?_HAtO zpY~wys(bJHe#cK`NJ%|@O013NNco9N49xlyqj`QT|5BYIsGle=ka~Bb&Oh1zhLPRj z*JK)WW}Iv|?!Vv>%`-2Q{As= zX=_xj*Eu@>+oYw_4kWiKaEn>Td@Xp{VLMe-Qfo`I7WbZTF;OGQ2%Up$HBZD8nkFng z;eIxsy{~G&PT!ODp2v6`Pc&V;ukruGfu{MBLO-j|pUkSH9eM6m-)8j(!JAapT#@T+ zJn`v9P`aXJjaL|_dBGA}TNY*R4XWoR-I{Qbvtql>)1CERk5+6D+uT{EczBMY!KS+4 zr2=+J+?Re@K9~@ zqe6o$f9$>e51d3}zPmW3oOGH7&Q*hiT9XgT>Z;z?<}v-= + Multiple custom axes combined + + Combo + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.png b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa2879425233d786a580a01ec1be9d29dee4430 GIT binary patch literal 1589 zcmd6n{Wp{e6vxNQ5Mz*K5F>ROyEC5Mq_!<mU@I7Bnkt7pB2_zuVK2*Clwlf9>RSZ zMS83okSP8q#Q^`Rkxx^p@}1;;n?Y0TaxcS0-m(#z1x1!9+1*IsAJ!P6WR(v_?E&yg zLV!62svpNNgt7ihs&1I>ckWq>3kY+=e%lIw(*unhX*J8HhgZGNj4JFi>x4U&-~ZL3 zvS3an5i5vy3C#lMn_)X0AMQfm>U!f?W->HTymGJi3|8yo{BpZ{=X8cr0B4{iwUXDI&oM#1$PR*To*zuG-FFV6Rr zZ~MZm8TGL?qLpwH9hV2U1z+y|xNDw!9D*geTh42FY!|R>*f@wCvfF^#fRyP>+e6BL z+1sH`A9{I*50)(L1^UT8HY5i19#1{|-BLX3aslnv2~`U1Xj}hPlDwBW=x43?T}ZxO zf58$XQO691M_xKstAXT4OU<$8AZ1AtbHv_aqc{A3;9WF8GbcjsRz#TI29Qd=hpF>l zHqr~c#(Fo^j}6}<;8#M${I5)i5HlOE1vq&7UW!thZ-e!4?Hyhtf6n@Nc6c1Adv4|C zzp*_lPqi1Q)hx^s{eWgv&?`cVa%UdxiNO z)3BJ?cxhq${p-gB>m`OAi}E0y3JVzBBiWkX?o34DYYwO(h4pY?=Kn} zSh0t=Z1-|t8bxs&${AeLhs`E5v*LXx7NDAIBiY9KW&CNPM3DSta9F+QPSKvXC z)|TwJg%o{WyMkt5J+6Dels?{Jzt_oyMA-xDTX?0uXEYQy*swz=%mzKtDRNq(M?7x+ z1Ft4O>8gnnz*WmqS64LYd7LqR0x(z7U(s~6ht5W&S*@L)^iw|`5y(kN?0)$6sAYoa zWfdT9Hh_%4&W7&g@n8JUW;AGeaGmlBo-^;Dm1%Yf&%ET?nDdwOA$nw%gU0bi%RCkV@h6N=7^Bv^D$NBNf^HE=i z56J3P-xmyYmbI<2QuP4@JIR`Tz3la}L7;=MkbNxqNmdHrUwy3W{{^VeKTdZ}MBsV4 Z_aFu3IXKrLqGJ8|lMa!cD-X~)e***H#lrvq literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.svg b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.svg new file mode 100644 index 000000000..919945f3a --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-stretch-condensed.svg @@ -0,0 +1,9 @@ + + font-stretch condensed auto-maps to wdth axis + + Narrow + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.png b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.png new file mode 100644 index 0000000000000000000000000000000000000000..36cd4484f502b55c1dce5fd06a25194b120c93e1 GIT binary patch literal 1537 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`$zj>EaktaqG=EKIXOwyd)k_alUt4 zYmLkL=!0DLj30UVvwkQn-q5Bi)*92&@X0rSsR^I=wuGG$$*m1>|o%)0WIMVol$N!9(#HFlA_Y17cdq8Yr?t1M{c?-}o>giXG~t7oGd zRHAuD`RDPOq00geg-ni(n9`r2!5+HgLGfa5)g^Yzx9^^j-kTaRW&OF?%SGS(nQG{^ zd`=LnP}ou@-ouMxR{LwmiEHXeOP`{I!F>s&g z!JZp${-pl=XYiWCL6!Ms{jSgHvSK0UCTp)fD{%FkhW1yEoY26TTUOp`U;0{p|J3Po z?Rs)cn6BUR3^wKW4sU)`!u9>Tl$Gu*hKz*9H6P~|$p79@!aPq?CVivfi%k=6#>`gS zf1_1&SNEpy4KtQ}jnp~i#+LPearms3rS%Kjj-HD@xhm3f&bl+n-Qv(8JF$&;SxES~iI zQu2do|Ns7(85&`6voWh*g}48+Y16W-lU|SWt?MJ+ZxG(Be(6Z7QDphQO?@hn{*3(us37-r^>bP0l+XkK>8q&X literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.svg b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.svg new file mode 100644 index 000000000..28079ceb6 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-style-oblique.svg @@ -0,0 +1,9 @@ + + font-style oblique auto-maps to slnt axis + + Slant + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.png b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.png new file mode 100644 index 0000000000000000000000000000000000000000..90e0d815f6fdb93e2692331920609e07dda1bde7 GIT binary patch literal 1187 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`%Up)5S5Q;?|oB?FVyQfv05ocb9FE*5qg{ zyu%!E+%bIZs>O4@*PqMv%VeUiNpGRi(WpcwqN>lYsAwH>sPIcxyZlz z=J&c&Ke9Jwwb{O#Rlv!;C9K6OVuz=oM&d&?Csmy}z7fwih8ro7Q-Zg8ddZ_sIeR6B9rVb7~a+(ji$e^|P~$|f`O)FQc~ z!Gg(OA9d{8wzXTjTi)E>eQjevu5xNbP3ML!3vTuW#NLT`_$@bHf4j~Mr8OVY<;`{( zCbzEtpnRje)3Cv`iT9+?!)uP|yq_=g#V!0Dam_S;s?_10*3xABSK zSJQn~El1NbxGXn*OV*LLpBDAx?QN$uA4S5%?87EJ*d8ntcG#|W{hF3m_m7t{ZCgX* z7*-#TP_2?O6R(%Lq~gA{Dy#N3N4Gi;v)~WR5uYxt$yohl#fDq2c9$hg4BpM%YHz>g z)auYP4iQ^Al;0hz;VG;?Kgr(u?GFuafz>;%O%M9yg&v*3A zQ)_3#gugn;uRpF{rYADjQ}k=Nn_ p>U34_Yg>hY8J30ju!(?)?WeU2Z|=;EoDM2#JYD@<);T3K0RU=A_+S74 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.svg b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.svg new file mode 100644 index 000000000..9f718eaea --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/auto-font-weight-700.svg @@ -0,0 +1,9 @@ + + font-weight auto-maps to wght axis + + Bold + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.png b/crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..650ae9d86e7c7f35d964cab52c13aaaa3328f5df GIT binary patch literal 790 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxV5EbAP;tHgx2#zdT76~*?vLwha z*nvSn!N5KsJ|VxLzG1@r1?xBLKXCs3gZCeHFi)7tz`zve>EaktaqI0h*F&of7#a>v z*u_2TxBQpuyVAb5{4_J|@aYwBpQ+h4!6^90p;_#yCjSp|wHk44NI2NU%6&~U0!WJK zL~LLIlL?$4cEUj+FxjLEVmGmRLljQ~YZ21{X#^^xqQ>8vYm|?6*Uh{nbZz0MRaatc zTfQ!`p7A|`IpStS>8wMij(Yu!4~lr4+A_8As}aOa++u4iq(m)y-8Mdtn5^}8OMHx% z&-dfit6#oP{Czob@6lOX&t^#_ah#4_rG9i}s?|O1dj8k@_@rxOw|Tx@GC!j5wvT_m z^UQ1g8{hH2Rt#HH7Jh%FQLlXB(N%k_a;7h{J+jK|XlV1gx|Xf`Ep^ID|8KYzTX@-q z_x;9OpT2F#l={ZEy7T+$+4qu5`T1t=*3eCgx|eKgCmJ@f^J;EF?a3*T5viPz0EGq? zBm^OW`)f7T1CWYQroQH;hveD14O1dH3^g|Y;5-}srFYe*-xEQp+tbz0Wt~$(6952G B8~p$P literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.svg b/crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.svg new file mode 100644 index 000000000..66f953d39 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/explicit-overrides-auto.svg @@ -0,0 +1,10 @@ + + Explicit settings override font-weight auto-map + + Thin + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/grad-negative.png b/crates/resvg/tests/tests/text/font-variation-settings/grad-negative.png new file mode 100644 index 0000000000000000000000000000000000000000..133a33f07eea974746ae518fce14d83bb05114aa GIT binary patch literal 1484 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`)Ak>EaktaqG=EKIXOwyd)gY-6Cg?_asa7ohxg50 zYreuMQ6i1`ScLNwExsRj|L4A2+1xd0*1L&z|J>JJKKOb|gv89$={lGHADGy^?QdYj zFS`%(zPbKA%WnRmc|!teuqF z>{@ke?>0Xj#=Ol2?eC7lYbAG z;tgK1guOaxtqs(MZM=M>U_bkVeFsn3ez_)bo4I@@kJt_8h)tmh!kC|SpE0#hMEG#s$UBlVr9|} zwCYb}o%U(Qg6E2t4qRg2Sa2}U@t~oRPHxJFrii4iJ^NdJFKbloOIo>sd0CQZ$Cug1 z7tBf1VLX}^v$S4h+V4dtbR5r2_~jUwHSX8A9B!nt8LA6m9VRN z!LpJ+S|SqU5?;r3ZC{zPrD~%2h}A*_Zo=j1(S4e2!22IH6+h z(|rd{<(2-PnAf>fJ|XhNp*>5QOds|ow>m!zb$PL=`{@l|sffOZ))70|-LiWsyenn0 zi>xoM{IYppV<x$0*-Pgms?rN?INb>GW7Y0xe54Te#BZ`}w|c1m?!BHf z%kPQtf7O-Lxw*MK=HcU|&L1KlXp8xjOxm5$In{aN%CDbHHr(6t$9u;czP()uCp-Q0 z)H$nn?zypQ>(jY)S2u3T){R_#L36IM?3SvX51uWYbkQ%<&fod8^p~Q$Z?|y&dF>#7 zM*7y%Gq1KbtF3+i;5293Z`0Ey(_-JrURdEize7Zr=k43DatG0A*_)W+@9XJr59dz{ z-X4D7_1FGqXKEW(db|}EyY%JE%ig}P57PU$`-JViJ9BkZh{^obhx28_RwtTh9lif< z#U+X7TFFJFIn{yFoZP<_C;Moo_= z!YXnTu;ggf89dZhYp`2XSMOn&GSl@!VGO%tIP;lzE;@NfoFqVHvZt$`%Q~loCIJ8K Bq2T}k literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/grad-negative.svg b/crates/resvg/tests/tests/text/font-variation-settings/grad-negative.svg new file mode 100644 index 000000000..b9fc20712 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/grad-negative.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "GRAD" -200` + + Grade + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/multiple-axes.png b/crates/resvg/tests/tests/text/font-variation-settings/multiple-axes.png new file mode 100644 index 0000000000000000000000000000000000000000..bd0a21e00b46f5993d0854e27f07ba2d7581ebd7 GIT binary patch literal 1143 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`(rO)5S5Q;?|oB?u-Wl zM3@(p%-z@e{C?W>CJqM9l>HiSPfqbL(iXWke`>E&%E?Kp-qY5!=|C6*NPXRq?|!

}J>Zu$7tZMmu&e)`%5xs4HZ-=(JIMBI$HvA6ti)saV?ob$fF^3gBaP;vkJqGgt+ zOC;8r?I_atXe{>sPxza-O$9nRk{i7&6)Hchuc5B3sU{Y(i)vBlP*Ro zd=Eb@kjTj)p1J42Qs(rwa}R>|{M`6Nu<5ANEUB;$H)?%1yqKNpq_gDf)P&Oa?L4CtPf1 zzEmqWkMEE~qUWAfZ+Abei~F@9VTrWDDdvlQn=;lMylAW|{ASJ5#%UtmA%{CYJxyHu z>P!`b+l6;lSIa+5=eE$e*5LpDpTOVMeV=t|Cg(i*_WRqCE0-5VZ7B2WOF2|g*=-uq z`SfV0QvTMqBiCh_P4+SA9Ny@*FZt9$?}U$YMb2%j(6OGRly~^I(qGqE(g$9w%h1U` ztFqW=Bg3%`^Z#FKd>auV5>_|k+Oep$k#1`fqO#R)*<1b1ZP(*sU}IunIJ>s~{#;gz z-%c!PpcF2)37ozM4;6Z1lIm+~=?_oWxapkUW|G9cD(JoCk{KT_f{G7MS3j3^P6 + `font-variation-settings: "wght" 700, "wdth" 75` + + Bold + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/opsz-144.png b/crates/resvg/tests/tests/text/font-variation-settings/opsz-144.png new file mode 100644 index 0000000000000000000000000000000000000000..01f85188825ba27ce4e744de8a25da51a95f81de GIT binary patch literal 1630 zcmc(g|3A|S9LF~uooOf*H|ASuYM-l}blM|@p?uHR^;yD9L~9btmobEvTB$iR=j2Ow zshikb#c?+ZiA5t8L(@^TvH8-29pTphaF0jt$K(Bez8~-R`|*DN_Il_0`5uGAkT3`Y z0{3ut4S+zPz!(2^le*%2mwrr*AV2RQH#PrvGaS!oR4+A23h)hdg6Lad9sR;d=i@W8 z3T~BG)bUzcUx}pS%DKR{ZBY=2<{b}L=b#kHjL09V9@gY-cFL2N8|-Y%49Sf;^|Ntd z)ozcn*zwQxws!i&`qN!3Yx(k*=*0%U60FpxiS~z*8%Aw(b0awHZz6d3tN$XDYtkw4 z%?UFupTd#gEQQHGC7AfrJvC0gS7kC0E3_l~iW@94aa1WonG<{~ioU#Hzu#$|%Fjwh z*Cmn>4MF@6Xn-KzGxbHjbxVNHQOr&ju>{TD_2J|R3(q?SUV)qbpxwAgCO#y{F&*WtZvXU6yidZQ+*0o*FKSXLpLrk2OH$|fS=qDihB+KR7-GHlnki zU(!>kz};w~<+OfZSXJSE@I%bu^NE44AHgz=YZThzU*$WJZAceNohdm{yO_S-uTWzZ zX0o^;B0&4T*9^7bEkXh&iXzI7MSDQk#L=l5q$<9dXSIdK-{U?^ZNwd93*4Jj8Q@F@ z3-NpB;Kzb1MHR!OKQ*)F85=0VyeT(Dc}&sgsUvx7x3YYJ=dj{mpLPm5zSy&dBlHzk z4;=xRekeE>AKoJulz3zQG7^s6zfyVKF^6!vKh~5~bT{HL_B+5Q#t8C3R=_(-y6?J} z72Fn+HoYUFM?~e@RT3fBioroGOf>2?xkQZ1c0>|1bBjUAUUbVw94D#Q7%20TxR`I@ zGTgSXeLzb^dT)I-AM7|GOw3z}0TH5eJUlTiF|=9m3^{9%9y#TG`+!s@$jXe6j0No5 ztW0XSvBeaQ(uKKD`WAaq#EEd5reC|1008zH9osQ@3Qr4F#iy!dwt$W-x&pguyFYh= z^dJ}$Qq%2yb7}p_GkS=qbPX7MA$~v}t0O?S;|#?i{m0Mp@bpDJ?X#%Mh6!=afw1)T z{?F~C!FXyVPM3|5o?!+H+zQ_goXzd}NEdsqR2H3~&B5pXwNCNSXE4JEoTsSSk#5S4 z5McK1)Up?Gy^-09OuA}W)6hQ>6{P5SV*AOwxWKI9b#TpfWMem + `font-variation-settings: "opsz" 144` + + Display + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.png b/crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.png new file mode 100644 index 0000000000000000000000000000000000000000..36cd4484f502b55c1dce5fd06a25194b120c93e1 GIT binary patch literal 1537 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`$zj>EaktaqG=EKIXOwyd)k_alUt4 zYmLkL=!0DLj30UVvwkQn-q5Bi)*92&@X0rSsR^I=wuGG$$*m1>|o%)0WIMVol$N!9(#HFlA_Y17cdq8Yr?t1M{c?-}o>giXG~t7oGd zRHAuD`RDPOq00geg-ni(n9`r2!5+HgLGfa5)g^Yzx9^^j-kTaRW&OF?%SGS(nQG{^ zd`=LnP}ou@-ouMxR{LwmiEHXeOP`{I!F>s&g z!JZp${-pl=XYiWCL6!Ms{jSgHvSK0UCTp)fD{%FkhW1yEoY26TTUOp`U;0{p|J3Po z?Rs)cn6BUR3^wKW4sU)`!u9>Tl$Gu*hKz*9H6P~|$p79@!aPq?CVivfi%k=6#>`gS zf1_1&SNEpy4KtQ}jnp~i#+LPearms3rS%Kjj-HD@xhm3f&bl+n-Qv(8JF$&;SxES~iI zQu2do|Ns7(85&`6voWh*g}48+Y16W-lU|SWt?MJ+ZxG(Be(6Z7QDphQO?@hn{*3(us37-r^>bP0l+XkK>8q&X literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.svg b/crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.svg new file mode 100644 index 000000000..74f60b6fa --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/slnt-negative.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "slnt" -10` + + Slant + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wdth-151.png b/crates/resvg/tests/tests/text/font-variation-settings/wdth-151.png new file mode 100644 index 0000000000000000000000000000000000000000..0065f0758965ebe91d28be6e7d89a3f8c62aca90 GIT binary patch literal 1582 zcmd6njZe}E7{`AeWrB;kOHb3#T4ygx#+88|7b;A$Q{G^zxv47ZV-ja}26r?riVK^y7Sbe}rN2Ud(2mgBzr& zX}|y1*RZP?&71>>V5JGaePZXx+Pr%LRwVf*1P~>5JRG*0{S~5(v{33Y>&|R>+LPPc zi?(TCxgfGJZ2vmh4m)>_3xdH`y{euziuBkH8) zJ**<^7kJp%xciMMCp3+;gBr*&`tngj3(EYCo6khiMni0dx>ouwQ{ABY5U)e@c%?tB zBhmKqm>E#4p!7@esAI;G?5yYOC=w+Zv{*8RVNv4IW3*`Ftr1$z-xTcsFGRtr6MZWYXF z!Ch#StH)0^K0;BmdMmqc*ty`ns0y6Az#QUI*#2j)u=?++W<*7>TyStKTo>O$5wxA= zjZHvq!Sh@Y_(1jr&IXmOcvAPeqI}j?LoxNVa--LoN2%eJx+p@QtDt>edO;gSiuBo7 zzM{ACG0R_ei;_dTsRf7gzMjwZEIyR8%pp75n;+yCN=fzt!l5{_^SEAKL1@?o(W}6U zq`Pj-2j=-0wr8&51XBM;84i8OBLtu%u|qg{d_q)ZWt^Z3IS72N6xYZiLMe1@ZXndH zYHOo-Pvoo?go1SQVtre&Xp+7VDbGnLUl=1{L@cMJWtkK(WoGHIPnAA3{s&*R!}RsNjf|W-&Z5Lf~Yd#O{PYzmuQ$_`B7g-I`}ae-cx(X5<6T&h-`=KeG?&8SB27 z0ee8roF>?KTd!i*L7as4-C$UEeUJ& za1wi4No+x$um!DNc{ z3RBA;xFJh~r>(;~re4*~*YLFq-fx)w_lFE7$$&m=xf5| + `font-variation-settings: "wdth" 151` + + Wide + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wdth-25.png b/crates/resvg/tests/tests/text/font-variation-settings/wdth-25.png new file mode 100644 index 0000000000000000000000000000000000000000..91c5718550ed89ac63a86d9aa5fe627dd0655e41 GIT binary patch literal 1407 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_sSZRQ)b0QpDqRxf z7wo_wpkQF{ACQn=P~Xr$Vg7>k8}=VKf8qXv_a8LY{%>PoVA=2K;uunK>&=BgMxbKW z4eSoBujdP^?5K}!NsXB$F?o@u=iJN(e>NFim~cP+;ESO8){@SpP|LFYx-|NqxUANKQGhEZ_y~VuMiA^g%O_tPIy|eqq?`jf>xNA zg<8gE|3wic)me?2)72IHbNjkYU0)qA+Hfy%VZ_cQ^HX&eFHc#Y`e)x$C%NTwz8Qoz zsW$9?9l2fOaMrn9>$W|;T-wT@8E<%{NpxW~!$hMs9~!Q{Om1pTNwB+F1)`DJJbC>eB0NVp2MRBe!1 zpisv4Yr6Cvo|$&fT2ot=$>~HMn4=&o@U(Od!{Up8L;3Yxw+d}h{R_TWEj zxBYWNNXu0xD@UORbq%SE(+|A;(A*dzJdM?Fg5ZSd8$aDUoxR0??M3#XNt|C^=pWCL z-!LoL=}h@#cD5I*4!u&8i?7i6|(qUK8UA*4Ee|IL6 z!>U7@4qRuG-+x$$p?X*DBK;{}=d`ZW)A8&QZO{|8J$g#)q4#=sUh9Sk$*=$&_BHjL z)$#j}7csmKyTiUAvi9&9r9}^>CQ2TiD_o^V^`J0#n{D+@RkbWVFyk{KL7t UPilu8Qb5J1r>mdKI;Vst04yU>_y7O^ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wdth-25.svg b/crates/resvg/tests/tests/text/font-variation-settings/wdth-25.svg new file mode 100644 index 000000000..6b690ab48 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/wdth-25.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "wdth" 25` + + Narrow + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wght-100.png b/crates/resvg/tests/tests/text/font-variation-settings/wght-100.png new file mode 100644 index 0000000000000000000000000000000000000000..650ae9d86e7c7f35d964cab52c13aaaa3328f5df GIT binary patch literal 790 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxV5EbAP;tHgx2#zdT76~*?vLwha z*nvSn!N5KsJ|VxLzG1@r1?xBLKXCs3gZCeHFi)7tz`zve>EaktaqI0h*F&of7#a>v z*u_2TxBQpuyVAb5{4_J|@aYwBpQ+h4!6^90p;_#yCjSp|wHk44NI2NU%6&~U0!WJK zL~LLIlL?$4cEUj+FxjLEVmGmRLljQ~YZ21{X#^^xqQ>8vYm|?6*Uh{nbZz0MRaatc zTfQ!`p7A|`IpStS>8wMij(Yu!4~lr4+A_8As}aOa++u4iq(m)y-8Mdtn5^}8OMHx% z&-dfit6#oP{Czob@6lOX&t^#_ah#4_rG9i}s?|O1dj8k@_@rxOw|Tx@GC!j5wvT_m z^UQ1g8{hH2Rt#HH7Jh%FQLlXB(N%k_a;7h{J+jK|XlV1gx|Xf`Ep^ID|8KYzTX@-q z_x;9OpT2F#l={ZEy7T+$+4qu5`T1t=*3eCgx|eKgCmJ@f^J;EF?a3*T5viPz0EGq? zBm^OW`)f7T1CWYQroQH;hveD14O1dH3^g|Y;5-}srFYe*-xEQp+tbz0Wt~$(6952G B8~p$P literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wght-100.svg b/crates/resvg/tests/tests/text/font-variation-settings/wght-100.svg new file mode 100644 index 000000000..43c6c8358 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/wght-100.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "wght" 100` + + Thin + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wght-700.png b/crates/resvg/tests/tests/text/font-variation-settings/wght-700.png new file mode 100644 index 0000000000000000000000000000000000000000..90e0d815f6fdb93e2692331920609e07dda1bde7 GIT binary patch literal 1187 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc|q6XFV_X#x1APtFCJD^n8W z7wo_wpkQF{9}u6AUr^uBKVklY^&9pdIDg^(gZCfiSKNBcz`%Up)5S5Q;?|oB?FVyQfv05ocb9FE*5qg{ zyu%!E+%bIZs>O4@*PqMv%VeUiNpGRi(WpcwqN>lYsAwH>sPIcxyZlz z=J&c&Ke9Jwwb{O#Rlv!;C9K6OVuz=oM&d&?Csmy}z7fwih8ro7Q-Zg8ddZ_sIeR6B9rVb7~a+(ji$e^|P~$|f`O)FQc~ z!Gg(OA9d{8wzXTjTi)E>eQjevu5xNbP3ML!3vTuW#NLT`_$@bHf4j~Mr8OVY<;`{( zCbzEtpnRje)3Cv`iT9+?!)uP|yq_=g#V!0Dam_S;s?_10*3xABSK zSJQn~El1NbxGXn*OV*LLpBDAx?QN$uA4S5%?87EJ*d8ntcG#|W{hF3m_m7t{ZCgX* z7*-#TP_2?O6R(%Lq~gA{Dy#N3N4Gi;v)~WR5uYxt$yohl#fDq2c9$hg4BpM%YHz>g z)auYP4iQ^Al;0hz;VG;?Kgr(u?GFuafz>;%O%M9yg&v*3A zQ)_3#gugn;uRpF{rYADjQ}k=Nn_ p>U34_Yg>hY8J30ju!(?)?WeU2Z|=;EoDM2#JYD@<);T3K0RU=A_+S74 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/wght-700.svg b/crates/resvg/tests/tests/text/font-variation-settings/wght-700.svg new file mode 100644 index 000000000..f5e426f90 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/wght-700.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "wght" 700` + + Bold + + + + diff --git a/crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.png b/crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.png new file mode 100644 index 0000000000000000000000000000000000000000..c4e2511c514b5aa18803a77d726796f1b7775478 GIT binary patch literal 1672 zcmd6o`#aMM9LK*dW7#2(GUbv8pifW9!UTa!F`R z*-o-!Nn`F6+Or6Urc|DE8O!Aq9Xfx*InVh#&*ynPpU)4U_Yd#qd4DeZEd-b*H)G;n48(i;tfw)5c!{07U5Hg*lWqK0oXr_YesvAXAT4tFPPf)mJErnCDi$ znKn2h<{n5-yC;F+zI68awI}nHaHmCm{UK^U+T`BK99~1O0$~TA7lP~oe)IntH zL+Ka;o&2V#Rwf07ZvR4ILnAx1j*Yhb=@3LXXlFN++-m=VRh`oVKEBjmPua{#Kb=f}wsWq}5-mfD?ICI^J< zj3DI{4lf`{2}cI#V+H zRfNqe!uY(xkhDeZuD4~|LPJMerk$?GDIlVzv!$e&CZ(!lO!TvqtA-Xwz%P`&&5=iv zHCgkOHM zex^LJHnDoAR=(;p2y*#_Vx3GCjGiJ%?ZmeWdgTRzER?U(V3nBE^sY;Z(Vm%`jAaxc zJkj|UHoZ4Q+hZgv#r5qS;~=52%BaZW_I`SALjk<{8Z+=sQEk*(DA8Hw56jFEfGv{} zlC=gxF2KpS<`x>5TnkvXMyrSnGRqaO;-%VdU5tBi}rC5kZAS7p+P6)?`e)B$cEw8$Nquq|H-Or{I8 zhh=28ylcT@9T>*XduS9X$WQg?ug>RHCBcFUuO#4TJO2{?IDlw-StvQ zC!j+O`@U^q^E0gs6A>s&ae&DOQD*?Ro{#L|RzBpeSY$ez8Sj?U(%gzki67>{P;51n zYiius#|;%as{X)HbP%Os5dlYezT)&nJ;!t4#&)FAX10P&~Di+dTJZbKmT}*W7 zG4eN!jzqu{g6AP(+$~`q!-X6kE=xLBkNe#HHMf^q;l>wrso;t}>IrYTfZ_Wj>pERo z_VK3#WP?tSm@KBPvV@80%tz_SRkB4>{?zn{ZMh0~#rfIOmWw>3)kOI3d1fti!iM{% z3%#8a{MlkBiL}3nx8|CTZ`oo?~hTd?M}G%2>~+ z&?g7gi)NQd9VwTvEkJA;jk;s;T@%F5f0ZnG4N`8(gGPB+{KU&NV>5Wp1;@5WI?iUW zp&_=qtB~538#PcoT`N;(M{1WQdv*|h^q^G=W8Q37k=;&7Auu q{QehUfBPQ2Y?tjz5d>e8E3f4vY^lWk=$3)af8vA1d)@W`bN>b>XV=>R literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.svg b/crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.svg new file mode 100644 index 000000000..a2f20e5c1 --- /dev/null +++ b/crates/resvg/tests/tests/text/font-variation-settings/xtra-extreme.svg @@ -0,0 +1,10 @@ + + `font-variation-settings: "XTRA" 603` + + Wide + + + + diff --git a/crates/resvg/tests/tests/text/text/zalgo.png b/crates/resvg/tests/tests/text/text/zalgo.png index 3e7ca99db98789a447878be9306e34e53b6852b2..b0ae2b0fd3aa24395d369f536385529e243ff38e 100644 GIT binary patch literal 3104 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 L#^mvF*XaKMVMUGX diff --git a/crates/usvg/Cargo.toml b/crates/usvg/Cargo.toml index f9c1778e5..844551fff 100644 --- a/crates/usvg/Cargo.toml +++ b/crates/usvg/Cargo.toml @@ -37,20 +37,27 @@ siphasher = "1.0" # perfect hash implementation # text fontdb = { version = "0.23.0", default-features = false, optional = true } -rustybuzz = { version = "0.20.1", optional = true } +harfrust = { version = "0.5", optional = true } unicode-bidi = { version = "0.3", optional = true } unicode-script = { version = "0.5", optional = true } unicode-vo = { version = "0.1", optional = true } +# skrifa for font metrics, outlines, and COLR (via harfrust's read-fonts) +skrifa = { version = "0.40", optional = true } + [dev-dependencies] once_cell = "1.5" [features] default = ["text", "system-fonts", "memmap-fonts"] # Enables text-to-path conversion support. -# Adds around 400KiB to your binary. -text = ["fontdb", "rustybuzz", "unicode-bidi", "unicode-script", "unicode-vo"] +# Uses harfrust (HarfBuzz port) for shaping and skrifa for font access. +text = ["fontdb", "harfrust", "skrifa", "unicode-bidi", "unicode-script", "unicode-vo"] # Enables system fonts loading. system-fonts = ["fontdb/fs", "fontdb/fontconfig"] # Enables font files memmaping for faster loading. memmap-fonts = ["fontdb/memmap"] +# Enables font hinting via skrifa. +# Uses skrifa for outline extraction with grid-fitting support. +# Controlled by text-rendering CSS property. +hinting = ["text"] diff --git a/crates/usvg/codegen/attributes.txt b/crates/usvg/codegen/attributes.txt index 32cac0622..3ed557d77 100644 --- a/crates/usvg/codegen/attributes.txt +++ b/crates/usvg/codegen/attributes.txt @@ -40,6 +40,7 @@ font font-family font-feature-settings font-kerning +font-optical-sizing font-size font-size-adjust font-stretch @@ -51,6 +52,7 @@ font-variant-east-asian font-variant-ligatures font-variant-numeric font-variant-position +font-variation-settings font-weight fr fx diff --git a/crates/usvg/src/main.rs b/crates/usvg/src/main.rs index 84ae50250..a329eff9c 100644 --- a/crates/usvg/src/main.rs +++ b/crates/usvg/src/main.rs @@ -431,6 +431,7 @@ fn process(args: Args) -> Result<(), String> { image_href_resolver: usvg::ImageHrefResolver::default(), font_resolver: usvg::FontResolver::default(), fontdb: Arc::new(fontdb), + hinting: usvg::HintingOptions::default(), style_sheet, }; diff --git a/crates/usvg/src/parser/converter.rs b/crates/usvg/src/parser/converter.rs index 7f5758ca9..479c13786 100644 --- a/crates/usvg/src/parser/converter.rs +++ b/crates/usvg/src/parser/converter.rs @@ -11,7 +11,7 @@ use fontdb::Database; #[cfg(feature = "text")] use fontdb::ID; #[cfg(feature = "text")] -use rustybuzz::ttf_parser::GlyphId; +use skrifa::GlyphId; use svgtypes::{Length, LengthUnit as Unit, PaintOrderKind, TransformOrigin}; use tiny_skia_path::PathBuilder; diff --git a/crates/usvg/src/parser/mod.rs b/crates/usvg/src/parser/mod.rs index b3fbccdd6..ec9d0eac5 100644 --- a/crates/usvg/src/parser/mod.rs +++ b/crates/usvg/src/parser/mod.rs @@ -21,6 +21,8 @@ mod text; #[cfg(feature = "text")] pub(crate) use converter::Cache; pub use image::{ImageHrefDataResolverFn, ImageHrefResolver, ImageHrefStringResolverFn}; +#[cfg(feature = "text")] +pub use options::HintingOptions; pub use options::Options; pub(crate) use svgtree::{AId, EId}; @@ -136,6 +138,8 @@ impl crate::Tree { (opt.font_resolver.select_fallback)(c, used_fonts, db) }), }, + #[cfg(feature = "text")] + hinting: opt.hinting, ..Options::default() }; diff --git a/crates/usvg/src/parser/options.rs b/crates/usvg/src/parser/options.rs index fcf70b114..95217f803 100644 --- a/crates/usvg/src/parser/options.rs +++ b/crates/usvg/src/parser/options.rs @@ -8,6 +8,45 @@ use std::sync::Arc; use crate::FontResolver; use crate::{ImageHrefResolver, ImageRendering, ShapeRendering, Size, TextRendering}; +/// Font hinting configuration. +/// +/// Controls how font outlines are grid-fitted for better rendering at small sizes. +#[cfg(feature = "text")] +#[derive(Debug, Clone, Copy)] +pub struct HintingOptions { + /// Whether to enable font hinting. + /// + /// When enabled, uses skrifa to apply grid-fitting to glyph outlines. + /// The actual hinting behavior is controlled by the `text-rendering` CSS property: + /// - `optimizeLegibility` / `optimizeSpeed`: Full hinting + /// - `geometricPrecision`: No hinting (preserve exact outlines) + /// + /// Default: `true` (matching browser behavior) + pub enabled: bool, + + /// DPI to use for ppem calculation when hinting. + /// + /// If `None`, uses the global `Options::dpi` value. + /// + /// ppem (pixels per em) = font_size * dpi / 72.0 + /// + /// Default: `None` (use Options::dpi) + pub dpi: Option, +} + +#[cfg(feature = "text")] +impl Default for HintingOptions { + fn default() -> Self { + Self { + // When the hinting feature is compiled, enable hinting by default + // (matching browser behavior). CSS text-rendering property controls + // per-element hinting: geometricPrecision disables, optimizeLegibility enables. + enabled: true, + dpi: None, + } + } +} + /// Processing options. #[derive(Debug)] pub struct Options<'a> { @@ -95,6 +134,14 @@ pub struct Options<'a> { /// be the same as this one. #[cfg(feature = "text")] pub fontdb: Arc, + + /// Font hinting configuration. + /// + /// Controls grid-fitting of glyph outlines for better rendering at small sizes. + /// Available when the `text` feature is enabled. + #[cfg(feature = "text")] + pub hinting: HintingOptions, + /// A CSS stylesheet that should be injected into the SVG. Can be used to overwrite /// certain attributes. pub style_sheet: Option, @@ -118,6 +165,8 @@ impl Default for Options<'_> { font_resolver: FontResolver::default(), #[cfg(feature = "text")] fontdb: Arc::new(fontdb::Database::new()), + #[cfg(feature = "text")] + hinting: HintingOptions::default(), style_sheet: None, } } diff --git a/crates/usvg/src/parser/svgtree/mod.rs b/crates/usvg/src/parser/svgtree/mod.rs index 3591fd8f3..5aeadb33c 100644 --- a/crates/usvg/src/parser/svgtree/mod.rs +++ b/crates/usvg/src/parser/svgtree/mod.rs @@ -710,12 +710,14 @@ impl AId { | AId::FloodOpacity | AId::FontFamily | AId::FontKerning // technically not presentation + | AId::FontOpticalSizing // technically not presentation | AId::FontSize | AId::FontSizeAdjust | AId::FontStretch | AId::FontStyle | AId::FontVariant | AId::FontWeight + | AId::FontVariationSettings | AId::GlyphOrientationHorizontal | AId::GlyphOrientationVertical | AId::ImageRendering @@ -786,6 +788,7 @@ impl AId { | AId::FloodOpacity | AId::FontFamily | AId::FontKerning + | AId::FontOpticalSizing | AId::FontSize | AId::FontStretch | AId::FontStyle diff --git a/crates/usvg/src/parser/svgtree/names.rs b/crates/usvg/src/parser/svgtree/names.rs index 1e6e2590c..d2afec152 100644 --- a/crates/usvg/src/parser/svgtree/names.rs +++ b/crates/usvg/src/parser/svgtree/names.rs @@ -205,6 +205,7 @@ pub enum AId { FontFamily, FontFeatureSettings, FontKerning, + FontOpticalSizing, FontSize, FontSizeAdjust, FontStretch, @@ -216,6 +217,7 @@ pub enum AId { FontVariantLigatures, FontVariantNumeric, FontVariantPosition, + FontVariationSettings, FontWeight, Fr, Fx, @@ -375,261 +377,264 @@ pub enum AId { } static ATTRIBUTES: Map = Map { - key: 3347381344252206323, + key: 3213172566270843353, disps: &[ - (0, 111), - (0, 2), - (0, 45), - (0, 5), + (0, 63), + (4, 146), + (0, 0), + (3, 42), + (2, 197), + (0, 0), (0, 1), - (2, 56), - (0, 5), - (2, 99), - (13, 198), - (0, 61), - (0, 52), - (1, 29), - (0, 21), - (0, 70), - (0, 164), - (2, 60), - (3, 52), + (0, 0), + (0, 0), + (0, 18), + (0, 11), + (1, 20), + (0, 8), + (17, 110), + (1, 112), + (1, 108), + (5, 94), + (2, 128), + (4, 95), + (0, 63), + (0, 96), + (0, 0), + (1, 110), (0, 1), - (0, 86), - (0, 10), + (40, 30), + (17, 157), + (0, 61), + (0, 16), + (7, 16), + (0, 80), + (0, 107), + (6, 111), + (0, 153), + (6, 202), + (18, 86), + (0, 194), (0, 0), - (0, 4), - (2, 175), - (6, 59), - (1, 14), - (0, 13), - (3, 175), - (1, 10), - (2, 76), - (0, 53), - (0, 24), - (123, 202), - (0, 14), - (0, 30), - (0, 62), - (0, 98), - (11, 193), - (8, 79), - (0, 17), - (22, 5), - (36, 106), - (1, 1), + (0, 7), + (0, 69), + (0, 5), + (0, 19), + (0, 0), + (4, 65), ], entries: &[ - ("mask-border-source", AId::MaskBorderSource), - ("stop-opacity", AId::StopOpacity), - ("stroke-linejoin", AId::StrokeLinejoin), - ("dominant-baseline", AId::DominantBaseline), - ("spreadMethod", AId::SpreadMethod), - ("order", AId::Order), - ("stroke", AId::Stroke), - ("stitchTiles", AId::StitchTiles), - ("height", AId::Height), - ("font-size", AId::FontSize), - ("background-color", AId::BackgroundColor), - ("tableValues", AId::TableValues), - ("x1", AId::X1), - ("y", AId::Y), - ("width", AId::Width), - ("text-indent", AId::TextIndent), - ("fill-opacity", AId::FillOpacity), - ("word-spacing", AId::WordSpacing), - ("cy", AId::Cy), - ("scale", AId::Scale), - ("x2", AId::X2), + ("alignment-baseline", AId::AlignmentBaseline), + ("fx", AId::Fx), + ("targetY", AId::TargetY), + ("clip-path", AId::ClipPath), ("lengthAdjust", AId::LengthAdjust), - ("glyph-orientation-horizontal", AId::GlyphOrientationHorizontal), - ("opacity", AId::Opacity), - ("mask-border", AId::MaskBorder), - ("font-stretch", AId::FontStretch), - ("stroke-dashoffset", AId::StrokeDashoffset), - ("fill", AId::Fill), - ("space", AId::Space), - ("baseline-shift", AId::BaselineShift), - ("text-align-last", AId::TextAlignLast), - ("font-variant-east-asian", AId::FontVariantEastAsian), - ("mask-border-mode", AId::MaskBorderMode), - ("font-variant-caps", AId::FontVariantCaps), + ("mask-size", AId::MaskSize), + ("unicode-bidi", AId::UnicodeBidi), + ("z", AId::Z), + ("font-variant-numeric", AId::FontVariantNumeric), + ("clip-rule", AId::ClipRule), + ("font", AId::Font), ("gradientUnits", AId::GradientUnits), - ("exponent", AId::Exponent), - ("text-decoration-color", AId::TextDecorationColor), - ("refX", AId::RefX), - ("enable-background", AId::EnableBackground), - ("mask-border-width", AId::MaskBorderWidth), + ("style", AId::Style), + ("font-stretch", AId::FontStretch), + ("intercept", AId::Intercept), + ("mask-border-slice", AId::MaskBorderSlice), + ("y", AId::Y), + ("xChannelSelector", AId::XChannelSelector), ("numOctaves", AId::NumOctaves), - ("kerning", AId::Kerning), + ("x1", AId::X1), + ("fill-rule", AId::FillRule), + ("image-rendering", AId::ImageRendering), + ("surfaceScale", AId::SurfaceScale), + ("seed", AId::Seed), ("mix-blend-mode", AId::MixBlendMode), - ("mask-clip", AId::MaskClip), - ("mask-mode", AId::MaskMode), - ("type", AId::Type), - ("class", AId::Class), - ("font", AId::Font), + ("path", AId::Path), ("mask-border-repeat", AId::MaskBorderRepeat), + ("transform", AId::Transform), + ("stroke", AId::Stroke), + ("refX", AId::RefX), + ("text-orientation", AId::TextOrientation), + ("line-height", AId::LineHeight), + ("display", AId::Display), + ("kerning", AId::Kerning), + ("transform-origin", AId::TransformOrigin), + ("shape-subtract", AId::ShapeSubtract), + ("width", AId::Width), ("stroke-miterlimit", AId::StrokeMiterlimit), + ("dy", AId::Dy), + ("text-decoration-color", AId::TextDecorationColor), + ("white-space", AId::WhiteSpace), + ("diffuseConstant", AId::DiffuseConstant), ("text-decoration-stroke", AId::TextDecorationStroke), - ("z", AId::Z), + ("values", AId::Values), + ("font-size", AId::FontSize), + ("shape-image-threshold", AId::ShapeImageThreshold), + ("href", AId::Href), + ("cy", AId::Cy), + ("mask-image", AId::MaskImage), + ("unicode-range", AId::UnicodeRange), + ("specularConstant", AId::SpecularConstant), + ("baseline-shift", AId::BaselineShift), + ("k3", AId::K3), + ("text-anchor", AId::TextAnchor), + ("mask-border-mode", AId::MaskBorderMode), + ("requiredFeatures", AId::RequiredFeatures), + ("color-rendering", AId::ColorRendering), + ("amplitude", AId::Amplitude), + ("mask-border-width", AId::MaskBorderWidth), + ("stroke-linecap", AId::StrokeLinecap), + ("paint-order", AId::PaintOrder), + ("lighting-color", AId::LightingColor), ("dx", AId::Dx), - ("clip-path", AId::ClipPath), - ("markerHeight", AId::MarkerHeight), - ("text-underline-position", AId::TextUnderlinePosition), - ("stdDeviation", AId::StdDeviation), + ("markerWidth", AId::MarkerWidth), + ("scale", AId::Scale), ("id", AId::Id), - ("paint-order", AId::PaintOrder), - ("elevation", AId::Elevation), - ("specularConstant", AId::SpecularConstant), - ("result", AId::Result), - ("font-size-adjust", AId::FontSizeAdjust), - ("mask-origin", AId::MaskOrigin), + ("color", AId::Color), + ("in2", AId::In2), + ("targetX", AId::TargetX), ("direction", AId::Direction), - ("font-variant-numeric", AId::FontVariantNumeric), - ("startOffset", AId::StartOffset), - ("maskUnits", AId::MaskUnits), - ("font-variant", AId::FontVariant), - ("text-orientation", AId::TextOrientation), - ("amplitude", AId::Amplitude), - ("rx", AId::Rx), - ("mask-type", AId::MaskType), - ("filter", AId::Filter), - ("in", AId::In), - ("display", AId::Display), - ("seed", AId::Seed), - ("unicode-range", AId::UnicodeRange), - ("color-profile", AId::ColorProfile), - ("x", AId::X), - ("href", AId::Href), - ("font-feature-settings", AId::FontFeatureSettings), - ("fill-rule", AId::FillRule), - ("fr", AId::Fr), - ("font-variant-ligatures", AId::FontVariantLigatures), - ("text-decoration-style", AId::TextDecorationStyle), - ("radius", AId::Radius), - ("xChannelSelector", AId::XChannelSelector), - ("orient", AId::Orient), - ("isolation", AId::Isolation), - ("gradientTransform", AId::GradientTransform), - ("transform-box", AId::TransformBox), - ("pointsAtY", AId::PointsAtY), - ("text-decoration-line", AId::TextDecorationLine), - ("requiredFeatures", AId::RequiredFeatures), - ("patternContentUnits", AId::PatternContentUnits), + ("pointsAtX", AId::PointsAtX), + ("stitchTiles", AId::StitchTiles), + ("patternUnits", AId::PatternUnits), ("shape-padding", AId::ShapePadding), - ("text-overflow", AId::TextOverflow), - ("clipPathUnits", AId::ClipPathUnits), - ("azimuth", AId::Azimuth), - ("line-height", AId::LineHeight), - ("viewBox", AId::ViewBox), - ("preserveAspectRatio", AId::PreserveAspectRatio), - ("path", AId::Path), + ("k2", AId::K2), + ("font-optical-sizing", AId::FontOpticalSizing), ("k4", AId::K4), - ("systemLanguage", AId::SystemLanguage), + ("vector-effect", AId::VectorEffect), + ("mask-composite", AId::MaskComposite), ("stroke-width", AId::StrokeWidth), - ("specularExponent", AId::SpecularExponent), - ("writing-mode", AId::WritingMode), - ("transform-origin", AId::TransformOrigin), - ("stroke-linecap", AId::StrokeLinecap), - ("points", AId::Points), - ("style", AId::Style), - ("pointsAtZ", AId::PointsAtZ), - ("targetX", AId::TargetX), - ("font-synthesis", AId::FontSynthesis), - ("maskContentUnits", AId::MaskContentUnits), - ("text-align", AId::TextAlign), - ("cx", AId::Cx), - ("alignment-baseline", AId::AlignmentBaseline), - ("font-kerning", AId::FontKerning), - ("requiredExtensions", AId::RequiredExtensions), - ("clip-rule", AId::ClipRule), + ("font-variation-settings", AId::FontVariationSettings), ("mask-border-outset", AId::MaskBorderOutset), - ("primitiveUnits", AId::PrimitiveUnits), - ("textLength", AId::TextLength), + ("in", AId::In), + ("stroke-linejoin", AId::StrokeLinejoin), + ("stop-opacity", AId::StopOpacity), + ("inline-size", AId::InlineSize), + ("mask-type", AId::MaskType), + ("filterUnits", AId::FilterUnits), + ("color-profile", AId::ColorProfile), + ("space", AId::Space), ("text-decoration-fill", AId::TextDecorationFill), - ("fy", AId::Fy), - ("mask-size", AId::MaskSize), - ("k3", AId::K3), - ("marker-start", AId::MarkerStart), - ("mode", AId::Mode), - ("k1", AId::K1), - ("refY", AId::RefY), - ("y1", AId::Y1), - ("shape-rendering", AId::ShapeRendering), - ("operator", AId::Operator), - ("mask-image", AId::MaskImage), - ("marker-end", AId::MarkerEnd), - ("rotate", AId::Rotate), - ("limitingConeAngle", AId::LimitingConeAngle), - ("surfaceScale", AId::SurfaceScale), - ("intercept", AId::Intercept), - ("font-variant-position", AId::FontVariantPosition), + ("font-kerning", AId::FontKerning), + ("offset", AId::Offset), + ("pointsAtZ", AId::PointsAtZ), + ("text-align", AId::TextAlign), ("clip", AId::Clip), - ("fx", AId::Fx), - ("visibility", AId::Visibility), - ("shape-margin", AId::ShapeMargin), - ("font-style", AId::FontStyle), - ("y2", AId::Y2), - ("dy", AId::Dy), + ("y1", AId::Y1), + ("mask-origin", AId::MaskOrigin), + ("mask-mode", AId::MaskMode), ("yChannelSelector", AId::YChannelSelector), - ("ry", AId::Ry), - ("color-rendering", AId::ColorRendering), - ("white-space", AId::WhiteSpace), - ("patternUnits", AId::PatternUnits), - ("shape-subtract", AId::ShapeSubtract), - ("markerWidth", AId::MarkerWidth), - ("d", AId::D), - ("shape-inside", AId::ShapeInside), - ("preserveAlpha", AId::PreserveAlpha), - ("shape-image-threshold", AId::ShapeImageThreshold), - ("image-rendering", AId::ImageRendering), + ("font-variant-caps", AId::FontVariantCaps), ("marker-mid", AId::MarkerMid), - ("filterUnits", AId::FilterUnits), - ("bias", AId::Bias), - ("mask-border-slice", AId::MaskBorderSlice), - ("pointsAtX", AId::PointsAtX), + ("shape-rendering", AId::ShapeRendering), + ("text-rendering", AId::TextRendering), + ("fill-opacity", AId::FillOpacity), + ("word-spacing", AId::WordSpacing), + ("fill", AId::Fill), + ("mask-clip", AId::MaskClip), + ("font-feature-settings", AId::FontFeatureSettings), + ("radius", AId::Radius), ("kernelMatrix", AId::KernelMatrix), - ("color-interpolation", AId::ColorInterpolation), - ("glyph-orientation-vertical", AId::GlyphOrientationVertical), - ("color", AId::Color), - ("patternTransform", AId::PatternTransform), ("kernelUnitLength", AId::KernelUnitLength), + ("mask-border-source", AId::MaskBorderSource), + ("k1", AId::K1), + ("mask", AId::Mask), + ("opacity", AId::Opacity), ("markerUnits", AId::MarkerUnits), + ("visibility", AId::Visibility), + ("spreadMethod", AId::SpreadMethod), + ("pointsAtY", AId::PointsAtY), + ("d", AId::D), + ("slope", AId::Slope), + ("side", AId::Side), + ("tableValues", AId::TableValues), + ("order", AId::Order), + ("text-align-last", AId::TextAlignLast), + ("font-size-adjust", AId::FontSizeAdjust), + ("rotate", AId::Rotate), + ("shape-margin", AId::ShapeMargin), + ("limitingConeAngle", AId::LimitingConeAngle), ("font-weight", AId::FontWeight), - ("overflow", AId::Overflow), + ("text-decoration-line", AId::TextDecorationLine), ("stop-color", AId::StopColor), + ("requiredExtensions", AId::RequiredExtensions), + ("enable-background", AId::EnableBackground), + ("systemLanguage", AId::SystemLanguage), + ("clipPathUnits", AId::ClipPathUnits), + ("stroke-dashoffset", AId::StrokeDashoffset), + ("ry", AId::Ry), + ("overflow", AId::Overflow), + ("class", AId::Class), + ("mask-border", AId::MaskBorder), + ("specularExponent", AId::SpecularExponent), + ("text-decoration", AId::TextDecoration), + ("startOffset", AId::StartOffset), + ("stroke-dasharray", AId::StrokeDasharray), + ("fr", AId::Fr), + ("mask-position", AId::MaskPosition), + ("writing-mode", AId::WritingMode), + ("font-synthesis", AId::FontSynthesis), + ("isolation", AId::Isolation), + ("rx", AId::Rx), + ("bias", AId::Bias), + ("markerHeight", AId::MarkerHeight), + ("edgeMode", AId::EdgeMode), ("r", AId::R), - ("k2", AId::K2), - ("text-anchor", AId::TextAnchor), - ("inline-size", AId::InlineSize), - ("unicode-bidi", AId::UnicodeBidi), + ("stroke-opacity", AId::StrokeOpacity), + ("maskContentUnits", AId::MaskContentUnits), + ("height", AId::Height), + ("font-variant-position", AId::FontVariantPosition), + ("operator", AId::Operator), ("font-family", AId::FontFamily), - ("color-interpolation-filters", AId::ColorInterpolationFilters), - ("slope", AId::Slope), - ("baseFrequency", AId::BaseFrequency), - ("transform", AId::Transform), - ("text-rendering", AId::TextRendering), - ("divisor", AId::Divisor), - ("edgeMode", AId::EdgeMode), + ("fy", AId::Fy), + ("dominant-baseline", AId::DominantBaseline), + ("y2", AId::Y2), + ("shape-inside", AId::ShapeInside), ("letter-spacing", AId::LetterSpacing), + ("azimuth", AId::Azimuth), + ("stdDeviation", AId::StdDeviation), ("flood-color", AId::FloodColor), - ("in2", AId::In2), - ("side", AId::Side), - ("mask-composite", AId::MaskComposite), - ("offset", AId::Offset), - ("values", AId::Values), - ("vector-effect", AId::VectorEffect), - ("mask", AId::Mask), - ("pathLength", AId::PathLength), - ("lighting-color", AId::LightingColor), - ("mask-position", AId::MaskPosition), - ("stroke-dasharray", AId::StrokeDasharray), - ("text-decoration", AId::TextDecoration), - ("stroke-opacity", AId::StrokeOpacity), - ("targetY", AId::TargetY), ("flood-opacity", AId::FloodOpacity), - ("diffuseConstant", AId::DiffuseConstant), + ("type", AId::Type), + ("font-variant-east-asian", AId::FontVariantEastAsian), + ("points", AId::Points), + ("refY", AId::RefY), + ("text-underline-position", AId::TextUnderlinePosition), + ("patternContentUnits", AId::PatternContentUnits), + ("baseFrequency", AId::BaseFrequency), + ("color-interpolation", AId::ColorInterpolation), + ("font-variant-ligatures", AId::FontVariantLigatures), + ("font-style", AId::FontStyle), + ("filter", AId::Filter), + ("text-decoration-style", AId::TextDecorationStyle), + ("preserveAlpha", AId::PreserveAlpha), + ("mode", AId::Mode), + ("divisor", AId::Divisor), + ("cx", AId::Cx), + ("patternTransform", AId::PatternTransform), + ("background-color", AId::BackgroundColor), + ("preserveAspectRatio", AId::PreserveAspectRatio), + ("gradientTransform", AId::GradientTransform), + ("x2", AId::X2), + ("pathLength", AId::PathLength), + ("marker-start", AId::MarkerStart), + ("glyph-orientation-horizontal", AId::GlyphOrientationHorizontal), + ("maskUnits", AId::MaskUnits), + ("textLength", AId::TextLength), + ("viewBox", AId::ViewBox), + ("text-overflow", AId::TextOverflow), + ("glyph-orientation-vertical", AId::GlyphOrientationVertical), + ("result", AId::Result), + ("primitiveUnits", AId::PrimitiveUnits), + ("exponent", AId::Exponent), + ("x", AId::X), + ("font-variant", AId::FontVariant), + ("elevation", AId::Elevation), + ("color-interpolation-filters", AId::ColorInterpolationFilters), + ("text-indent", AId::TextIndent), + ("marker-end", AId::MarkerEnd), + ("transform-box", AId::TransformBox), + ("orient", AId::Orient), ], }; diff --git a/crates/usvg/src/parser/text.rs b/crates/usvg/src/parser/text.rs index 743756a05..1b74cdcb3 100644 --- a/crates/usvg/src/parser/text.rs +++ b/crates/usvg/src/parser/text.rs @@ -140,7 +140,16 @@ pub(crate) fn convert( layouted: vec![], }; - if text::convert(&mut text, &state.opt.font_resolver, cache).is_none() { + let hinting_ctx = if state.opt.hinting.enabled { + Some(crate::text::flatten::HintingContext { + enabled: true, + dpi: state.opt.hinting.dpi.unwrap_or(state.opt.dpi), + }) + } else { + None + }; + + if text::convert(&mut text, &state.opt.font_resolver, cache, hinting_ctx).is_none() { return; } @@ -263,6 +272,12 @@ fn collect_text_chunks_impl( apply_kerning = false; } + // Parse font-optical-sizing (defaults to auto to match browser behavior) + let font_optical_sizing = match parent.find_attribute::<&str>(AId::FontOpticalSizing) { + Some("none") => crate::FontOpticalSizing::None, + _ => crate::FontOpticalSizing::Auto, // "auto" or missing = Auto (browser default) + }; + let mut text_length = parent.try_convert_length(AId::TextLength, Units::UserSpaceOnUse, state); // Negative values should be ignored. @@ -284,6 +299,7 @@ fn collect_text_chunks_impl( font_size, small_caps: parent.find_attribute::<&str>(AId::FontVariant) == Some("small-caps"), apply_kerning, + font_optical_sizing, decoration: resolve_decoration(parent, state, cache), visible: visibility == Visibility::Visible, dominant_baseline, @@ -392,6 +408,49 @@ fn convert_font(node: SvgNode, state: &converter::State) -> Font { let style: FontStyle = node.find_attribute(AId::FontStyle).unwrap_or_default(); let stretch = conv_font_stretch(node); let weight = resolve_font_weight(node); + let mut variations = parse_font_variation_settings(node); + + // Auto-map standard font properties to variation axes if not explicitly set. + // This allows variable fonts to work with regular font-weight/font-stretch properties. + let has_wght = variations.iter().any(|v| &v.tag == b"wght"); + let has_wdth = variations.iter().any(|v| &v.tag == b"wdth"); + let has_ital = variations.iter().any(|v| &v.tag == b"ital"); + let has_slnt = variations.iter().any(|v| &v.tag == b"slnt"); + + // Map font-weight to wght axis (if not already set) + if !has_wght && weight != 400 { + variations.push(FontVariation::new(*b"wght", weight as f32)); + } + + // Map font-stretch to wdth axis (if not already set) + // CSS font-stretch percentages: ultra-condensed=50%, condensed=75%, normal=100%, expanded=125%, ultra-expanded=200% + if !has_wdth { + let wdth = match stretch { + FontStretch::UltraCondensed => 50.0, + FontStretch::ExtraCondensed => 62.5, + FontStretch::Condensed => 75.0, + FontStretch::SemiCondensed => 87.5, + FontStretch::Normal => 100.0, + FontStretch::SemiExpanded => 112.5, + FontStretch::Expanded => 125.0, + FontStretch::ExtraExpanded => 150.0, + FontStretch::UltraExpanded => 200.0, + }; + if wdth != 100.0 { + variations.push(FontVariation::new(*b"wdth", wdth)); + } + } + + // Map font-style: italic to ital axis (if not already set) + if !has_ital && style == FontStyle::Italic { + variations.push(FontVariation::new(*b"ital", 1.0)); + } + + // Map font-style: oblique to slnt axis (if not already set) + // Default oblique angle is typically 12-14 degrees + if !has_slnt && style == FontStyle::Oblique { + variations.push(FontVariation::new(*b"slnt", -12.0)); + } let font_families = if let Some(n) = node.ancestors().find(|n| n.has_attribute(AId::FontFamily)) { @@ -421,9 +480,99 @@ fn convert_font(node: SvgNode, state: &converter::State) -> Font { style, stretch, weight, + variations, } } +/// Parses the `font-variation-settings` CSS property. +/// +/// Syntax: `normal | [ ]#` +/// Example: `"wght" 700, "wdth" 50` +fn parse_font_variation_settings(node: SvgNode) -> Vec { + let value = if let Some(n) = node + .ancestors() + .find(|n| n.has_attribute(AId::FontVariationSettings)) + { + let v = n.attribute(AId::FontVariationSettings).unwrap_or(""); + log::debug!("Found font-variation-settings: '{}'", v); + v + } else { + return Vec::new(); + }; + + // "normal" means no variations + if value.eq_ignore_ascii_case("normal") || value.is_empty() { + return Vec::new(); + } + + let mut variations = Vec::new(); + + // Parse comma-separated list of "tag" value pairs + for part in value.split(',') { + let part = part.trim(); + if part.is_empty() { + continue; + } + + // Find the tag (quoted string) and value + // Format: "wght" 700 or 'wght' 700 + let mut chars = part.chars().peekable(); + + // Skip whitespace + while chars.peek().map_or(false, |c| c.is_whitespace()) { + chars.next(); + } + + // Parse quoted tag + let quote = match chars.next() { + Some('"') => '"', + Some('\'') => '\'', + _ => continue, // Invalid format + }; + + let mut tag_str = String::new(); + for c in chars.by_ref() { + if c == quote { + break; + } + tag_str.push(c); + } + + // Tag must be exactly 4 characters + if tag_str.len() != 4 { + log::warn!( + "Invalid font-variation-settings tag: '{}' (must be 4 characters)", + tag_str + ); + continue; + } + + // Skip whitespace before value + while chars.peek().map_or(false, |c| c.is_whitespace()) { + chars.next(); + } + + // Parse the numeric value + let value_str: String = chars.collect(); + let value_str = value_str.trim(); + + let value = match value_str.parse::() { + Ok(v) => v, + Err(_) => { + log::warn!("Invalid font-variation-settings value: '{}'", value_str); + continue; + } + }; + + let tag_bytes = tag_str.as_bytes(); + let tag = [tag_bytes[0], tag_bytes[1], tag_bytes[2], tag_bytes[3]]; + + variations.push(FontVariation::new(tag, value)); + } + + variations +} + // TODO: properly resolve narrower/wider fn conv_font_stretch(node: SvgNode) -> FontStretch { if let Some(n) = node.ancestors().find(|n| n.has_attribute(AId::FontStretch)) { diff --git a/crates/usvg/src/text/colr.rs b/crates/usvg/src/text/colr.rs deleted file mode 100644 index b6d2ddf2b..000000000 --- a/crates/usvg/src/text/colr.rs +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2024 the Resvg Authors -// SPDX-License-Identifier: Apache-2.0 OR MIT - -use crate::parser::OptionLog; -use rustybuzz::ttf_parser; - -struct Builder<'a>(&'a mut String); - -impl Builder<'_> { - fn finish(&mut self) { - if !self.0.is_empty() { - self.0.pop(); // remove trailing space - } - } -} - -impl ttf_parser::OutlineBuilder for Builder<'_> { - fn move_to(&mut self, x: f32, y: f32) { - use std::fmt::Write; - write!(self.0, "M {} {} ", x, y).unwrap(); - } - - fn line_to(&mut self, x: f32, y: f32) { - use std::fmt::Write; - write!(self.0, "L {} {} ", x, y).unwrap(); - } - - fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) { - use std::fmt::Write; - write!(self.0, "Q {} {} {} {} ", x1, y1, x, y).unwrap(); - } - - fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) { - use std::fmt::Write; - write!(self.0, "C {} {} {} {} {} {} ", x1, y1, x2, y2, x, y).unwrap(); - } - - fn close(&mut self) { - self.0.push_str("Z "); - } -} - -trait XmlWriterExt { - fn write_color_attribute(&mut self, name: &str, ts: ttf_parser::RgbaColor); - fn write_transform_attribute(&mut self, name: &str, ts: ttf_parser::Transform); - fn write_spread_method_attribute(&mut self, method: ttf_parser::colr::GradientExtend); -} - -impl XmlWriterExt for xmlwriter::XmlWriter { - fn write_color_attribute(&mut self, name: &str, color: ttf_parser::RgbaColor) { - self.write_attribute_fmt( - name, - format_args!("rgb({}, {}, {})", color.red, color.green, color.blue), - ); - } - - fn write_transform_attribute(&mut self, name: &str, ts: ttf_parser::Transform) { - if ts.is_default() { - return; - } - - self.write_attribute_fmt( - name, - format_args!( - "matrix({} {} {} {} {} {})", - ts.a, ts.b, ts.c, ts.d, ts.e, ts.f - ), - ); - } - - fn write_spread_method_attribute(&mut self, extend: ttf_parser::colr::GradientExtend) { - self.write_attribute( - "spreadMethod", - match extend { - ttf_parser::colr::GradientExtend::Pad => &"pad", - ttf_parser::colr::GradientExtend::Repeat => &"repeat", - ttf_parser::colr::GradientExtend::Reflect => &"reflect", - }, - ); - } -} - -// NOTE: This is only a best-effort translation of COLR into SVG. -pub(crate) struct GlyphPainter<'a> { - pub(crate) face: &'a ttf_parser::Face<'a>, - pub(crate) svg: &'a mut xmlwriter::XmlWriter, - pub(crate) path_buf: &'a mut String, - pub(crate) gradient_index: usize, - pub(crate) clip_path_index: usize, - pub(crate) palette_index: u16, - pub(crate) transform: ttf_parser::Transform, - pub(crate) outline_transform: ttf_parser::Transform, - pub(crate) transforms_stack: Vec, -} - -impl<'a> GlyphPainter<'a> { - fn write_gradient_stops(&mut self, stops: ttf_parser::colr::GradientStopsIter) { - for stop in stops { - self.svg.start_element("stop"); - self.svg.write_attribute("offset", &stop.stop_offset); - self.svg.write_color_attribute("stop-color", stop.color); - let opacity = f32::from(stop.color.alpha) / 255.0; - self.svg.write_attribute("stop-opacity", &opacity); - self.svg.end_element(); - } - } - - fn paint_solid(&mut self, color: ttf_parser::RgbaColor) { - self.svg.start_element("path"); - self.svg.write_color_attribute("fill", color); - let opacity = f32::from(color.alpha) / 255.0; - self.svg.write_attribute("fill-opacity", &opacity); - self.svg - .write_transform_attribute("transform", self.outline_transform); - self.svg.write_attribute("d", self.path_buf); - self.svg.end_element(); - } - - fn paint_linear_gradient(&mut self, gradient: ttf_parser::colr::LinearGradient<'a>) { - let gradient_id = format!("lg{}", self.gradient_index); - self.gradient_index += 1; - - let gradient_transform = paint_transform(self.outline_transform, self.transform); - - // TODO: We ignore x2, y2. Have to apply them somehow. - // TODO: The way spreadMode works in ttf and svg is a bit different. In SVG, the spreadMode - // will always be applied based on x1/y1 and x2/y2. However, in TTF the spreadMode will - // be applied from the first/last stop. So if we have a gradient with x1=0 x2=1, and - // a stop at x=0.4 and x=0.6, then in SVG we will always see a padding, while in ttf - // we will see the actual spreadMode. We need to account for that somehow. - self.svg.start_element("linearGradient"); - self.svg.write_attribute("id", &gradient_id); - self.svg.write_attribute("x1", &gradient.x0); - self.svg.write_attribute("y1", &gradient.y0); - self.svg.write_attribute("x2", &gradient.x1); - self.svg.write_attribute("y2", &gradient.y1); - self.svg.write_attribute("gradientUnits", &"userSpaceOnUse"); - self.svg.write_spread_method_attribute(gradient.extend); - self.svg - .write_transform_attribute("gradientTransform", gradient_transform); - self.write_gradient_stops( - gradient.stops(self.palette_index, self.face.variation_coordinates()), - ); - self.svg.end_element(); - - self.svg.start_element("path"); - self.svg - .write_attribute_fmt("fill", format_args!("url(#{})", gradient_id)); - self.svg - .write_transform_attribute("transform", self.outline_transform); - self.svg.write_attribute("d", self.path_buf); - self.svg.end_element(); - } - - fn paint_radial_gradient(&mut self, gradient: ttf_parser::colr::RadialGradient<'a>) { - let gradient_id = format!("rg{}", self.gradient_index); - self.gradient_index += 1; - - let gradient_transform = paint_transform(self.outline_transform, self.transform); - - self.svg.start_element("radialGradient"); - self.svg.write_attribute("id", &gradient_id); - self.svg.write_attribute("cx", &gradient.x1); - self.svg.write_attribute("cy", &gradient.y1); - self.svg.write_attribute("r", &gradient.r1); - self.svg.write_attribute("fr", &gradient.r0); - self.svg.write_attribute("fx", &gradient.x0); - self.svg.write_attribute("fy", &gradient.y0); - self.svg.write_attribute("gradientUnits", &"userSpaceOnUse"); - self.svg.write_spread_method_attribute(gradient.extend); - self.svg - .write_transform_attribute("gradientTransform", gradient_transform); - self.write_gradient_stops( - gradient.stops(self.palette_index, self.face.variation_coordinates()), - ); - self.svg.end_element(); - - self.svg.start_element("path"); - self.svg - .write_attribute_fmt("fill", format_args!("url(#{})", gradient_id)); - self.svg - .write_transform_attribute("transform", self.outline_transform); - self.svg.write_attribute("d", self.path_buf); - self.svg.end_element(); - } - - fn paint_sweep_gradient(&mut self, _: ttf_parser::colr::SweepGradient<'a>) { - println!("Warning: sweep gradients are not supported."); - } -} - -fn paint_transform( - outline_transform: ttf_parser::Transform, - transform: ttf_parser::Transform, -) -> ttf_parser::Transform { - let outline_transform = tiny_skia_path::Transform::from_row( - outline_transform.a, - outline_transform.b, - outline_transform.c, - outline_transform.d, - outline_transform.e, - outline_transform.f, - ); - - let gradient_transform = tiny_skia_path::Transform::from_row( - transform.a, - transform.b, - transform.c, - transform.d, - transform.e, - transform.f, - ); - - let gradient_transform = outline_transform - .invert() - .log_none(|| log::warn!("Failed to calculate transform for gradient in glyph.")) - .unwrap_or_default() - .pre_concat(gradient_transform); - - ttf_parser::Transform { - a: gradient_transform.sx, - b: gradient_transform.ky, - c: gradient_transform.kx, - d: gradient_transform.sy, - e: gradient_transform.tx, - f: gradient_transform.ty, - } -} - -impl GlyphPainter<'_> { - fn clip_with_path(&mut self, path: &str) { - let clip_id = format!("cp{}", self.clip_path_index); - self.clip_path_index += 1; - - self.svg.start_element("clipPath"); - self.svg.write_attribute("id", &clip_id); - self.svg.start_element("path"); - self.svg - .write_transform_attribute("transform", self.outline_transform); - self.svg.write_attribute("d", &path); - self.svg.end_element(); - self.svg.end_element(); - - self.svg.start_element("g"); - self.svg - .write_attribute_fmt("clip-path", format_args!("url(#{})", clip_id)); - } -} - -impl<'a> ttf_parser::colr::Painter<'a> for GlyphPainter<'a> { - fn outline_glyph(&mut self, glyph_id: ttf_parser::GlyphId) { - self.path_buf.clear(); - let mut builder = Builder(self.path_buf); - match self.face.outline_glyph(glyph_id, &mut builder) { - Some(v) => v, - None => return, - }; - builder.finish(); - - // We have to write outline using the current transform. - self.outline_transform = self.transform; - } - - fn push_layer(&mut self, mode: ttf_parser::colr::CompositeMode) { - self.svg.start_element("g"); - - use ttf_parser::colr::CompositeMode; - // TODO: Need to figure out how to represent the other blend modes - // in SVG. - let mode = match mode { - CompositeMode::SourceOver => "normal", - CompositeMode::Screen => "screen", - CompositeMode::Overlay => "overlay", - CompositeMode::Darken => "darken", - CompositeMode::Lighten => "lighten", - CompositeMode::ColorDodge => "color-dodge", - CompositeMode::ColorBurn => "color-burn", - CompositeMode::HardLight => "hard-light", - CompositeMode::SoftLight => "soft-light", - CompositeMode::Difference => "difference", - CompositeMode::Exclusion => "exclusion", - CompositeMode::Multiply => "multiply", - CompositeMode::Hue => "hue", - CompositeMode::Saturation => "saturation", - CompositeMode::Color => "color", - CompositeMode::Luminosity => "luminosity", - _ => { - println!("Warning: unsupported blend mode: {:?}", mode); - "normal" - } - }; - self.svg.write_attribute_fmt( - "style", - format_args!("mix-blend-mode: {}; isolation: isolate", mode), - ); - } - - fn pop_layer(&mut self) { - self.svg.end_element(); // g - } - - fn push_transform(&mut self, transform: ttf_parser::Transform) { - self.transforms_stack.push(self.transform); - self.transform = ttf_parser::Transform::combine(self.transform, transform); - } - - fn paint(&mut self, paint: ttf_parser::colr::Paint<'a>) { - match paint { - ttf_parser::colr::Paint::Solid(color) => self.paint_solid(color), - ttf_parser::colr::Paint::LinearGradient(lg) => self.paint_linear_gradient(lg), - ttf_parser::colr::Paint::RadialGradient(rg) => self.paint_radial_gradient(rg), - ttf_parser::colr::Paint::SweepGradient(sg) => self.paint_sweep_gradient(sg), - } - } - - fn pop_transform(&mut self) { - if let Some(ts) = self.transforms_stack.pop() { - self.transform = ts; - } - } - - fn push_clip(&mut self) { - self.clip_with_path(&self.path_buf.clone()); - } - - fn pop_clip(&mut self) { - self.svg.end_element(); - } - - fn push_clip_box(&mut self, clipbox: ttf_parser::colr::ClipBox) { - let x_min = clipbox.x_min; - let x_max = clipbox.x_max; - let y_min = clipbox.y_min; - let y_max = clipbox.y_max; - - let clip_path = format!( - "M {} {} L {} {} L {} {} L {} {} Z", - x_min, y_min, x_max, y_min, x_max, y_max, x_min, y_max - ); - - self.clip_with_path(&clip_path); - } -} diff --git a/crates/usvg/src/text/flatten.rs b/crates/usvg/src/text/flatten.rs index 89929a08e..b2111db84 100644 --- a/crates/usvg/src/text/flatten.rs +++ b/crates/usvg/src/text/flatten.rs @@ -5,14 +5,22 @@ use std::mem; use std::sync::Arc; use fontdb::{Database, ID}; -use rustybuzz::ttf_parser; -use rustybuzz::ttf_parser::{GlyphId, RasterImageFormat, RgbaColor}; +use harfrust::Tag; +use skrifa::{ + bitmap::BitmapData, + instance::{LocationRef, Size as SkrifaSize}, + outline::{pen::ControlBoundsPen, DrawSettings, HintingInstance, OutlinePen, Target}, + raw::TableProvider, + setting::VariationSetting, + FontRef, GlyphId, MetadataProvider, +}; use tiny_skia_path::{NonZeroRect, Size, Transform}; -use xmlwriter::XmlWriter; -use crate::text::colr::GlyphPainter; use crate::*; +/// Points per inch - standard typographic conversion factor for ppem calculation. +const POINTS_PER_INCH: f32 = 72.0; + fn resolve_rendering_mode(text: &Text) -> ShapeRendering { match text.rendering_mode { TextRendering::OptimizeSpeed => ShapeRendering::CrispEdges, @@ -45,10 +53,46 @@ fn push_outline_paths( } } -pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZeroRect)> { +/// Hinting context for controlling font hinting behavior. +#[derive(Clone, Copy, Debug)] +pub struct HintingContext { + /// Whether hinting is enabled globally. + pub enabled: bool, + /// DPI for ppem calculation. + pub dpi: f32, +} + +impl HintingContext { + /// Calculate pixels per em from font size. + pub fn ppem(&self, font_size: f32) -> f32 { + // ppem = font_size * dpi / 72 (converting points to pixels) + font_size * self.dpi / POINTS_PER_INCH + } +} + +/// Convert positioned glyphs to path outlines. +pub(crate) fn flatten( + text: &mut Text, + cache: &mut Cache, + hinting_ctx: Option, +) -> Option<(Group, NonZeroRect)> { + flatten_impl(text, cache, hinting_ctx) +} + +fn flatten_impl( + text: &mut Text, + cache: &mut Cache, + hinting_ctx: Option, +) -> Option<(Group, NonZeroRect)> { let mut new_children = vec![]; let rendering_mode = resolve_rendering_mode(text); + let hinting_mode = HintingMode::from_text_rendering(text.rendering_mode); + + // Determine if we should use hinting + let use_hinting = hinting_ctx + .map(|ctx| ctx.enabled && hinting_mode == HintingMode::Full) + .unwrap_or(false); for span in &text.layouted { if let Some(path) = span.overline.as_ref() { @@ -104,20 +148,15 @@ pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZ let transform = if img.is_sbix { glyph.sbix_transform( - img.x as f32, - img.y as f32, - img.glyph_bbox.map(|bbox| bbox.x_min).unwrap_or(0) as f32, - img.glyph_bbox.map(|bbox| bbox.y_min).unwrap_or(0) as f32, - img.pixels_per_em as f32, + img.x, + img.y, + img.glyph_bbox.map(|bbox| bbox.x_min as f32).unwrap_or(0.0), + img.glyph_bbox.map(|bbox| bbox.y_min as f32).unwrap_or(0.0), + img.pixels_per_em, img.image.size.height(), ) } else { - glyph.cbdt_transform( - img.x as f32, - img.y as f32, - img.pixels_per_em as f32, - img.image.size.height(), - ) + glyph.cbdt_transform(img.x, img.y, img.pixels_per_em) }; let mut group = Group { @@ -128,11 +167,41 @@ pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZ group.calculate_bounding_boxes(); new_children.push(Node::Group(Box::new(group))); - } else if let Some(outline) = cache - .fontdb_outline(glyph.font, glyph.id) - .and_then(|p| p.transform(glyph.outline_transform())) - { - span_builder.push_path(&outline); + } else { + // For variable fonts, we need to extract the outline with variations applied. + // We can't use the cache here since the outline depends on variation values. + // Also handle auto-opsz for variable fonts. + let needs_variations = !glyph.variations.is_empty() + || glyph.font_optical_sizing() == crate::FontOpticalSizing::Auto; + + let outline = if use_hinting { + // Use skrifa for hinted outline extraction + let ppem = hinting_ctx.map(|ctx| ctx.ppem(glyph.font_size())); + extract_outline_skrifa( + &cache.fontdb, + glyph.font, + glyph.id, + &glyph.variations, + glyph.font_size(), + glyph.font_optical_sizing(), + ppem, + hinting_mode, + ) + } else if needs_variations { + cache.fontdb.outline_with_variations( + glyph.font, + glyph.id, + &glyph.variations, + glyph.font_size(), + glyph.font_optical_sizing(), + ) + } else { + cache.fontdb_outline(glyph.font, glyph.id) + }; + + if let Some(outline) = outline.and_then(|p| p.transform(glyph.outline_transform())) { + span_builder.push_path(&outline); + } } } @@ -159,11 +228,171 @@ pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZ Some((group, stroke_bbox)) } -struct PathBuilder { +/// Extract glyph outline using skrifa with optional hinting. +fn extract_outline_skrifa( + fontdb: &fontdb::Database, + font_id: fontdb::ID, + glyph_id: GlyphId, + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, + ppem: Option, + hinting_mode: HintingMode, +) -> Option { + fontdb.with_face_data(font_id, |data, face_index| -> Option { + let font = FontRef::from_index(data, face_index).ok()?; + let outlines = font.outline_glyphs(); + let glyph = outlines.get(glyph_id)?; + + // Build variation coordinates if needed, using avar-aware normalization + let needs_variations = !variations.is_empty() + || font_optical_sizing == crate::FontOpticalSizing::Auto; + + let location = if needs_variations { + let axes = font.axes(); + let mut coords: Vec = + vec![Default::default(); axes.len()]; + + // Build variation settings including auto-opsz + let mut settings: Vec = variations + .iter() + .map(|v| VariationSetting::new(Tag::new(&v.tag), v.value)) + .collect(); + + // Auto-set opsz if font-optical-sizing is auto and not explicitly set + if font_optical_sizing == crate::FontOpticalSizing::Auto { + let has_explicit_opsz = variations.iter().any(|v| v.tag == *b"opsz"); + if !has_explicit_opsz { + // Check if font has opsz axis + let has_opsz_axis = axes.iter().any(|a| a.tag() == Tag::new(b"opsz")); + if has_opsz_axis { + settings.push(VariationSetting::new(Tag::new(b"opsz"), font_size)); + } + } + } + + // Use location_to_slice which applies avar (axis variations) table remapping. + // This differs from ttf-parser's set_variation() which used raw user-space values. + // Avar remapping transforms user-space axis values to design-space coordinates, + // which is required for correct variable font rendering (especially for fonts + // like Roboto Flex that rely heavily on avar for intermediate axis values). + axes.location_to_slice(&settings, &mut coords); + + Some(coords) + } else { + None + }; + + let location_ref = location + .as_ref() + .map(|c| LocationRef::new(c)) + .unwrap_or_default(); + + // Choose drawing settings based on hinting + // Hinted output is in pixel units (scaled by ppem), while unhinted is in font units. + // We scale hinted output back to font units so outline_transform() can apply consistent scaling. + if let (Some(ppem_val), HintingMode::Full) = (ppem, hinting_mode) { + let size = SkrifaSize::new(ppem_val); + // Create hinting instance for smooth rendering. + // Note: HintingInstance is created per-glyph. For performance optimization, + // consider caching instances keyed by (font_id, ppem, location) if profiling + // shows this is a bottleneck. + let hinting_options = Target::Smooth { + mode: skrifa::outline::SmoothMode::Normal, + symmetric_rendering: true, + preserve_linear_metrics: false, + }; + + if let Ok(hinting_instance) = HintingInstance::new( + &outlines, + size, + location_ref, + hinting_options, + ) { + // Use hinted drawing with the hinting instance + // Output is in pixel units at ppem scale, so we need to scale back to font units + let scale_back = font.head().unwrap().units_per_em() as f32 / ppem_val; + let mut pen = ScalingPen::new(scale_back); + let settings = DrawSettings::hinted(&hinting_instance, false); + glyph.draw(settings, &mut pen).ok()?; + return pen.finish(); + } + } + + // Fallback to unhinted drawing (font units) + let mut pen = SkrifaPen::new(); + let settings = DrawSettings::unhinted(SkrifaSize::unscaled(), location_ref); + glyph.draw(settings, &mut pen).ok()?; + pen.finish() + })? +} + +/// Pen adapter for skrifa's OutlinePen trait -> tiny_skia_path::PathBuilder +struct SkrifaPen { builder: tiny_skia_path::PathBuilder, } -impl ttf_parser::OutlineBuilder for PathBuilder { +impl SkrifaPen { + fn new() -> Self { + Self { + builder: tiny_skia_path::PathBuilder::new(), + } + } + + fn finish(self) -> Option { + self.builder.finish() + } +} + +/// Pen that scales coordinates by a factor (used to convert hinted pixel coords back to font units) +struct ScalingPen { + builder: tiny_skia_path::PathBuilder, + scale: f32, +} + +impl ScalingPen { + fn new(scale: f32) -> Self { + Self { + builder: tiny_skia_path::PathBuilder::new(), + scale, + } + } + + fn finish(self) -> Option { + self.builder.finish() + } +} + +impl OutlinePen for ScalingPen { + fn move_to(&mut self, x: f32, y: f32) { + self.builder.move_to(x * self.scale, y * self.scale); + } + + fn line_to(&mut self, x: f32, y: f32) { + self.builder.line_to(x * self.scale, y * self.scale); + } + + fn quad_to(&mut self, cx: f32, cy: f32, x: f32, y: f32) { + self.builder.quad_to( + cx * self.scale, cy * self.scale, + x * self.scale, y * self.scale, + ); + } + + fn curve_to(&mut self, cx1: f32, cy1: f32, cx2: f32, cy2: f32, x: f32, y: f32) { + self.builder.cubic_to( + cx1 * self.scale, cy1 * self.scale, + cx2 * self.scale, cy2 * self.scale, + x * self.scale, y * self.scale, + ); + } + + fn close(&mut self) { + self.builder.close(); + } +} + +impl OutlinePen for SkrifaPen { fn move_to(&mut self, x: f32, y: f32) { self.builder.move_to(x, y); } @@ -172,12 +401,12 @@ impl ttf_parser::OutlineBuilder for PathBuilder { self.builder.line_to(x, y); } - fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) { - self.builder.quad_to(x1, y1, x, y); + fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) { + self.builder.quad_to(cx0, cy0, x, y); } - fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) { - self.builder.cubic_to(x1, y1, x2, y2, x, y); + fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) { + self.builder.cubic_to(cx0, cy0, cx1, cy1, x, y); } fn close(&mut self) { @@ -185,20 +414,58 @@ impl ttf_parser::OutlineBuilder for PathBuilder { } } +/// Hinting mode derived from CSS text-rendering property +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum HintingMode { + /// No hinting (text-rendering: geometricPrecision) + None, + /// Full hinting (text-rendering: optimizeLegibility) + Full, +} + +impl HintingMode { + /// Convert CSS TextRendering to HintingMode + pub fn from_text_rendering(text_rendering: TextRendering) -> Self { + match text_rendering { + TextRendering::OptimizeSpeed => HintingMode::Full, + TextRendering::OptimizeLegibility => HintingMode::Full, + TextRendering::GeometricPrecision => HintingMode::None, + } + } +} + pub(crate) trait DatabaseExt { fn outline(&self, id: ID, glyph_id: GlyphId) -> Option; + fn outline_with_variations( + &self, + id: ID, + glyph_id: GlyphId, + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, + ) -> Option; fn raster(&self, id: ID, glyph_id: GlyphId) -> Option; fn svg(&self, id: ID, glyph_id: GlyphId) -> Option; fn colr(&self, id: ID, glyph_id: GlyphId) -> Option; } +/// Bounding box for a glyph (x_min, y_min, x_max, y_max) +#[derive(Clone, Copy, Debug)] +#[allow(dead_code)] +pub(crate) struct GlyphBbox { + pub x_min: i16, + pub y_min: i16, + pub x_max: i16, + pub y_max: i16, +} + #[derive(Clone)] pub(crate) struct BitmapImage { image: Image, - x: i16, - y: i16, - pixels_per_em: u16, - glyph_bbox: Option, + x: f32, + y: f32, + pixels_per_em: f32, + glyph_bbox: Option, is_sbix: bool, } @@ -206,44 +473,139 @@ impl DatabaseExt for Database { #[inline(never)] fn outline(&self, id: ID, glyph_id: GlyphId) -> Option { self.with_face_data(id, |data, face_index| -> Option { - let font = ttf_parser::Face::parse(data, face_index).ok()?; + let font = FontRef::from_index(data, face_index).ok()?; + let outlines = font.outline_glyphs(); + let glyph = outlines.get(glyph_id)?; + + let mut pen = SkrifaPen::new(); + let settings = DrawSettings::unhinted(SkrifaSize::unscaled(), LocationRef::default()); + glyph.draw(settings, &mut pen).ok()?; + pen.finish() + })? + } - let mut builder = PathBuilder { - builder: tiny_skia_path::PathBuilder::new(), - }; + #[inline(never)] + fn outline_with_variations( + &self, + id: ID, + glyph_id: GlyphId, + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, + ) -> Option { + self.with_face_data(id, |data, face_index| -> Option { + let font = FontRef::from_index(data, face_index).ok()?; + let outlines = font.outline_glyphs(); + let glyph = outlines.get(glyph_id)?; + + // Build variation coordinates using avar-aware normalization + let axes = font.axes(); + let mut coords: Vec = vec![Default::default(); axes.len()]; + + // Build variation settings including auto-opsz + let mut settings: Vec = variations + .iter() + .map(|v| VariationSetting::new(Tag::new(&v.tag), v.value)) + .collect(); + + // Auto-set opsz if font-optical-sizing is auto and not explicitly set + if font_optical_sizing == crate::FontOpticalSizing::Auto { + let has_explicit_opsz = variations.iter().any(|v| v.tag == *b"opsz"); + if !has_explicit_opsz { + let has_opsz_axis = axes.iter().any(|a| a.tag() == Tag::new(b"opsz")); + if has_opsz_axis { + settings.push(VariationSetting::new(Tag::new(b"opsz"), font_size)); + } + } + } - font.outline_glyph(glyph_id, &mut builder)?; - builder.builder.finish() + // Use location_to_slice which applies avar (axis variations) table remapping. + // This differs from ttf-parser's set_variation() which used raw user-space values. + // Avar remapping transforms user-space axis values to design-space coordinates, + // which is required for correct variable font rendering (especially for fonts + // like Roboto Flex that rely heavily on avar for intermediate axis values). + axes.location_to_slice(&settings, &mut coords); + + let location = LocationRef::new(&coords); + let mut pen = SkrifaPen::new(); + let settings = DrawSettings::unhinted(SkrifaSize::unscaled(), location); + glyph.draw(settings, &mut pen).ok()?; + pen.finish() })? } fn raster(&self, id: ID, glyph_id: GlyphId) -> Option { self.with_face_data(id, |data, face_index| -> Option { - let font = ttf_parser::Face::parse(data, face_index).ok()?; - let image = font.glyph_raster_image(glyph_id, u16::MAX)?; + let font = FontRef::from_index(data, face_index).ok()?; + + // Try to get bitmap strikes + let strikes = font.bitmap_strikes(); + // Get the largest available strike (use partial_cmp for f32) + let strike = strikes + .iter() + .max_by(|a, b| a.ppem().partial_cmp(&b.ppem()).unwrap_or(std::cmp::Ordering::Equal))?; + + let bitmap_glyph = strike.get(glyph_id)?; + let bitmap_data = bitmap_glyph.data; + + // Handle PNG data + if let BitmapData::Png(png_data) = bitmap_data { + // Get PNG dimensions using imagesize + let (width, height) = if let Ok(size) = imagesize::blob_size(png_data) { + (size.width as u32, size.height as u32) + } else { + // Fallback: estimate from strike ppem + let ppem = strike.ppem(); + (ppem as u32, ppem as u32) + }; + + // Get the glyph outline bounding box for SBIX positioning. + // SBIX requires the outline bbox for proper vertical alignment. + let glyph_bbox = { + let outlines = font.outline_glyphs(); + outlines.get(glyph_id).and_then(|glyph| { + let mut bounds_pen = ControlBoundsPen::new(); + let settings = DrawSettings::unhinted(SkrifaSize::unscaled(), LocationRef::default()); + glyph.draw(settings, &mut bounds_pen).ok()?; + bounds_pen.bounding_box().map(|bb| GlyphBbox { + x_min: bb.x_min as i16, + y_min: bb.y_min as i16, + x_max: bb.x_max as i16, + y_max: bb.y_max as i16, + }) + }) + }; + + // Detect SBIX format by checking if the font has an sbix table. + // The previous heuristic using inner_bearing was unreliable. + let is_sbix = font.table_data(Tag::new(b"sbix")).is_some(); + + log::warn!( + "Bitmap glyph: bearing=({}, {}), inner_bearing=({}, {}), ppem={}, bbox={:?}, is_sbix={}, height={}", + bitmap_glyph.bearing_x, bitmap_glyph.bearing_y, + bitmap_glyph.inner_bearing_x, bitmap_glyph.inner_bearing_y, + strike.ppem(), glyph_bbox, is_sbix, height + ); + + // Use skrifa's inner_bearing values directly for both SBIX and CBDT. + // inner_bearing_x/y contain the glyph positioning offsets we need. + let (x, y) = (bitmap_glyph.inner_bearing_x, bitmap_glyph.inner_bearing_y); - if image.format == RasterImageFormat::PNG { let bitmap_image = BitmapImage { image: Image { id: String::new(), visible: true, - size: Size::from_wh(image.width as f32, image.height as f32)?, + size: Size::from_wh(width as f32, height as f32)?, rendering_mode: ImageRendering::OptimizeQuality, - kind: ImageKind::PNG(Arc::new(image.data.into())), + kind: ImageKind::PNG(Arc::new(png_data.to_vec())), abs_transform: Transform::default(), - abs_bounding_box: NonZeroRect::from_xywh( - 0.0, - 0.0, - image.width as f32, - image.height as f32, - )?, + abs_bounding_box: NonZeroRect::from_xywh(0.0, 0.0, width as f32, height as f32)?, }, - x: image.x, - y: image.y, - pixels_per_em: image.pixels_per_em, - glyph_bbox: font.glyph_bounding_box(glyph_id), - // ttf-parser always checks sbix first, so if this table exists, it was used. - is_sbix: font.tables().sbix.is_some(), + x, + y, + pixels_per_em: strike.ppem(), + glyph_bbox, + is_sbix, }; return Some(bitmap_image); @@ -254,71 +616,158 @@ impl DatabaseExt for Database { } fn svg(&self, id: ID, glyph_id: GlyphId) -> Option { - // TODO: Technically not 100% accurate because the SVG format in a OTF font - // is actually a subset/superset of a normal SVG, but it seems to work fine - // for Twitter Color Emoji, so might as well use what we already have. - - // TODO: Glyph records can contain the data for multiple glyphs. We should - // add a cache so we don't need to reparse the data every time. + // Parse SVG table manually since skrifa doesn't expose SVG table access yet. + // SVG table format (OpenType spec): + // - Header: version (u16), svgDocListOffset (u32), reserved (u32) + // - Document list at offset: numEntries (u16), entries[] + // - Each entry: startGlyphID (u16), endGlyphID (u16), svgDocOffset (u32), svgDocLength (u32) self.with_face_data(id, |data, face_index| -> Option { - let font = ttf_parser::Face::parse(data, face_index).ok()?; - let image = font.glyph_svg_image(glyph_id)?; - let tree = Tree::from_data(image.data, &Options::default()).ok()?; - - // Twitter Color Emoji seems to always have one SVG record per glyph, - // while Noto Color Emoji sometimes contains multiple ones. It's kind of hacky, - // but the best we have for now. - let node = if image.start_glyph_id == image.end_glyph_id { - Node::Group(Box::new(tree.root)) - } else { - tree.node_by_id(&format!("glyph{}", glyph_id.0)) - .log_none(|| { - log::warn!("Failed to find SVG glyph node for glyph {}", glyph_id.0); - }) - .cloned()? - }; + let font = FontRef::from_index(data, face_index).ok()?; + + let svg_table = font.table_data(Tag::new(b"SVG "))?; + let svg_data = svg_table.as_ref(); + + // Need at least header (10 bytes) + if svg_data.len() < 10 { + return None; + } - Some(node) + // Parse header + let _version = u16::from_be_bytes([svg_data[0], svg_data[1]]); + let doc_list_offset = u32::from_be_bytes([svg_data[2], svg_data[3], svg_data[4], svg_data[5]]) as usize; + + // Navigate to document list + if doc_list_offset + 2 > svg_data.len() { + return None; + } + + let doc_list = &svg_data[doc_list_offset..]; + let num_entries = u16::from_be_bytes([doc_list[0], doc_list[1]]) as usize; + + // Each entry is 12 bytes + let entries_start = 2; + let glyph_id_val = glyph_id.to_u32() as u16; + + // Find the entry for this glyph + for i in 0..num_entries { + let entry_offset = entries_start + i * 12; + if entry_offset + 12 > doc_list.len() { + break; + } + + let entry = &doc_list[entry_offset..entry_offset + 12]; + let start_glyph = u16::from_be_bytes([entry[0], entry[1]]); + let end_glyph = u16::from_be_bytes([entry[2], entry[3]]); + let svg_doc_offset = u32::from_be_bytes([entry[4], entry[5], entry[6], entry[7]]) as usize; + let svg_doc_length = u32::from_be_bytes([entry[8], entry[9], entry[10], entry[11]]) as usize; + + if glyph_id_val >= start_glyph && glyph_id_val <= end_glyph { + // Found the entry - extract SVG document + // Offset is relative to start of SVG table + let abs_offset = doc_list_offset + svg_doc_offset; + if abs_offset + svg_doc_length > svg_data.len() { + return None; + } + + let svg_doc_data = &svg_data[abs_offset..abs_offset + svg_doc_length]; + + // Handle gzip compression (SVG documents may be gzip compressed) + let svg_bytes: std::borrow::Cow<[u8]> = if svg_doc_data.starts_with(&[0x1f, 0x8b]) { + // Gzip compressed + use std::io::Read; + let mut decoder = flate2::read::GzDecoder::new(svg_doc_data); + let mut decompressed = Vec::new(); + if decoder.read_to_end(&mut decompressed).is_err() { + return None; + } + std::borrow::Cow::Owned(decompressed) + } else { + std::borrow::Cow::Borrowed(svg_doc_data) + }; + + // Parse the SVG document + let tree = crate::Tree::from_data(&svg_bytes, &crate::Options::default()).ok()?; + + // If this record covers a single glyph, return the whole tree + // Otherwise, look for the specific glyph by ID + let node = if start_glyph == end_glyph { + Node::Group(Box::new(tree.root)) + } else { + // Multi-glyph record - find the specific glyph by ID + let glyph_node_id = format!("glyph{}", glyph_id_val); + tree.node_by_id(&glyph_node_id).cloned()? + }; + + return Some(node); + } + } + + None })? } fn colr(&self, id: ID, glyph_id: GlyphId) -> Option { - self.with_face_data(id, |data, face_index| -> Option { - let face = ttf_parser::Face::parse(data, face_index).ok()?; - - let mut svg = XmlWriter::new(xmlwriter::Options::default()); - - svg.start_element("svg"); - svg.write_attribute("xmlns", "http://www.w3.org/2000/svg"); - svg.write_attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); - - let mut path_buf = String::with_capacity(256); - let gradient_index = 1; - let clip_path_index = 1; - - svg.start_element("g"); - - let mut glyph_painter = GlyphPainter { - face: &face, - svg: &mut svg, - path_buf: &mut path_buf, - gradient_index, - clip_path_index, - palette_index: 0, - transform: ttf_parser::Transform::default(), - outline_transform: ttf_parser::Transform::default(), - transforms_stack: vec![ttf_parser::Transform::default()], - }; - - face.paint_color_glyph( - glyph_id, - 0, - RgbaColor::new(0, 0, 0, 255), - &mut glyph_painter, - )?; - svg.end_element(); + // Use skrifa-based COLR painting + // This provides COLRv1 support (sweep gradients, advanced blend modes) + let result = self.with_face_data(id, |data, face_index| { + super::skrifa_colr::paint_colr_glyph(data, face_index, glyph_id) + })?; + result + } +} - Tree::from_data(svg.end_document().as_bytes(), &Options::default()).ok() - })? +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_skrifa_variable_font() { + // Test that skrifa properly applies variable font axes + let font_path = concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../crates/resvg/tests/fonts/RobotoFlex.subset.ttf" + ); + let font_data = std::fs::read(font_path).expect("Font not found"); + + let font = FontRef::new(&font_data).expect("Failed to parse font"); + let outlines = font.outline_glyphs(); + + // Get glyph for 'N' + let charmap = font.charmap(); + let glyph_id = charmap.map('N').expect("Glyph not found"); + let glyph = outlines.get(glyph_id).expect("Outline not found"); + + // Get axes + let axes = font.axes(); + + // Find wdth axis + let wdth_idx = axes.iter().position(|a| a.tag() == Tag::new(b"wdth")).expect("wdth axis not found"); + + // Draw with default location + let mut pen1 = SkrifaPen::new(); + let settings1 = DrawSettings::unhinted(SkrifaSize::unscaled(), LocationRef::default()); + glyph.draw(settings1, &mut pen1).expect("Draw failed"); + let path1 = pen1.finish().expect("Path failed"); + let bounds1 = path1.bounds(); + + // Draw with wdth=25 (narrow) + let mut coords = vec![skrifa::instance::NormalizedCoord::default(); axes.len()]; + coords[wdth_idx] = axes.get(wdth_idx).unwrap().normalize(25.0); + + let location = LocationRef::new(&coords); + let mut pen2 = SkrifaPen::new(); + let settings2 = DrawSettings::unhinted(SkrifaSize::unscaled(), location); + glyph.draw(settings2, &mut pen2).expect("Draw failed"); + let path2 = pen2.finish().expect("Path failed"); + let bounds2 = path2.bounds(); + + // The narrow version should have a smaller width + assert!( + bounds2.width() < bounds1.width(), + "wdth=25 should be narrower than default! default width: {}, wdth=25 width: {}", + bounds1.width(), + bounds2.width() + ); } } + diff --git a/crates/usvg/src/text/layout.rs b/crates/usvg/src/text/layout.rs index 2261f66bb..4c0572ab0 100644 --- a/crates/usvg/src/text/layout.rs +++ b/crates/usvg/src/text/layout.rs @@ -6,9 +6,9 @@ use std::num::NonZeroU16; use std::sync::Arc; use fontdb::{Database, ID}; +use harfrust::Tag; use kurbo::{ParamCurve, ParamCurveArclen, ParamCurveDeriv}; -use rustybuzz::ttf_parser; -use rustybuzz::ttf_parser::{GlyphId, Tag}; +use skrifa::{GlyphId, MetadataProvider}; use strict_num::NonZeroPositiveF32; use tiny_skia_path::{NonZeroRect, Transform}; use unicode_script::UnicodeScript; @@ -45,9 +45,23 @@ pub struct PositionedGlyph { /// The ID of the font the glyph should be taken from. Can be used with the /// [font database of the tree](crate::Tree::fontdb) this glyph is part of. pub font: ID, + /// Font variation settings for variable fonts. + pub variations: Vec, + /// Font optical sizing mode for auto-opsz computation. + pub font_optical_sizing: crate::FontOpticalSizing, } impl PositionedGlyph { + /// Returns the font size for this glyph. + pub fn font_size(&self) -> f32 { + self.font_size + } + + /// Returns the font optical sizing mode. + pub fn font_optical_sizing(&self) -> crate::FontOpticalSizing { + self.font_optical_sizing + } + /// Returns the transform of glyph. pub fn transform(&self) -> Transform { let sx = self.font_size / self.units_per_em as f32; @@ -66,18 +80,17 @@ impl PositionedGlyph { .pre_concat(Transform::from_scale(1.0, -1.0)) } - /// Returns the transform for the glyph, assuming that a CBTD-based raster glyph + /// Returns the transform for the glyph, assuming that a CBDT-based raster glyph /// is being used. - pub fn cbdt_transform(&self, x: f32, y: f32, pixels_per_em: f32, height: f32) -> Transform { + pub fn cbdt_transform(&self, x: f32, y: f32, pixels_per_em: f32) -> Transform { self.transform() .pre_concat(Transform::from_scale( self.units_per_em as f32 / pixels_per_em, self.units_per_em as f32 / pixels_per_em, )) - // Right now, the top-left corner of the image would be placed in - // on the "text cursor", but we want the bottom-left corner to be there, - // so we need to shift it up and also apply the x/y offset. - .pre_translate(x, -height - y) + // The y value from skrifa's inner_bearing_y points to the top of the glyph. + // We negate it to convert from font coordinates (y-up) to image coordinates (y-down). + .pre_translate(x, -y) } /// Returns the transform for the glyph, assuming that a sbix-based raster glyph @@ -899,6 +912,9 @@ fn process_chunk( font, span.small_caps, span.apply_kerning, + &span.font.variations, + span.font_size.get(), + span.font_optical_sizing, resolver, fontdb, ); @@ -953,10 +969,25 @@ fn process_chunk( let mut clusters = Vec::new(); for (range, byte_idx) in GlyphClusters::new(&glyphs) { if let Some(span) = chunk_span_at(chunk, byte_idx) { + // Compute effective variations including auto-opsz to match what was used during shaping. + // This ensures the glyph outlines use the same variations as the advance/position calculations. + let font_id = fonts_cache + .get(&span.font) + .map(|f| f.id) + .unwrap_or_else(|| glyphs[range.start].font.id); + let effective_variations = compute_effective_variations( + &span.font.variations, + span.font_size.get(), + span.font_optical_sizing, + font_id, + fontdb, + ); clusters.push(form_glyph_clusters( &glyphs[range], &chunk.text, span.font_size.get(), + &effective_variations, + span.font_optical_sizing, )); } } @@ -1127,7 +1158,13 @@ fn apply_word_spacing(chunk: &TextChunk, clusters: &mut [GlyphCluster]) { } } -fn form_glyph_clusters(glyphs: &[Glyph], text: &str, font_size: f32) -> GlyphCluster { +fn form_glyph_clusters( + glyphs: &[Glyph], + text: &str, + font_size: f32, + variations: &[crate::FontVariation], + font_optical_sizing: crate::FontOpticalSizing, +) -> GlyphCluster { debug_assert!(!glyphs.is_empty()); let mut width = 0.0; @@ -1157,6 +1194,8 @@ fn form_glyph_clusters(glyphs: &[Glyph], text: &str, font_size: f32) -> GlyphClu font: glyph.font.id, text: glyph.text.clone(), id: glyph.id, + variations: variations.to_vec(), + font_optical_sizing, }); x += glyph.width as f32; @@ -1189,89 +1228,21 @@ pub(crate) trait DatabaseExt { fn has_char(&self, id: ID, c: char) -> bool; } +// Skrifa-based implementation for font metrics impl DatabaseExt for Database { #[inline(never)] fn load_font(&self, id: ID) -> Option { - self.with_face_data(id, |data, face_index| -> Option { - let font = ttf_parser::Face::parse(data, face_index).ok()?; - - let units_per_em = NonZeroU16::new(font.units_per_em())?; - - let ascent = font.ascender(); - let descent = font.descender(); - - let x_height = font - .x_height() - .and_then(|x| u16::try_from(x).ok()) - .and_then(NonZeroU16::new); - let x_height = match x_height { - Some(height) => height, - None => { - // If not set - fallback to height * 45%. - // 45% is what Firefox uses. - u16::try_from((f32::from(ascent - descent) * 0.45) as i32) - .ok() - .and_then(NonZeroU16::new)? - } - }; - - let line_through = font.strikeout_metrics(); - let line_through_position = match line_through { - Some(metrics) => metrics.position, - None => x_height.get() as i16 / 2, - }; - - let (underline_position, underline_thickness) = match font.underline_metrics() { - Some(metrics) => { - let thickness = u16::try_from(metrics.thickness) - .ok() - .and_then(NonZeroU16::new) - // `ttf_parser` guarantees that units_per_em is >= 16 - .unwrap_or_else(|| NonZeroU16::new(units_per_em.get() / 12).unwrap()); - - (metrics.position, thickness) - } - None => ( - -(units_per_em.get() as i16) / 9, - NonZeroU16::new(units_per_em.get() / 12).unwrap(), - ), - }; - - // 0.2 and 0.4 are generic offsets used by some applications (Inkscape/librsvg). - let mut subscript_offset = (units_per_em.get() as f32 / 0.2).round() as i16; - let mut superscript_offset = (units_per_em.get() as f32 / 0.4).round() as i16; - if let Some(metrics) = font.subscript_metrics() { - subscript_offset = metrics.y_offset; - } - - if let Some(metrics) = font.superscript_metrics() { - superscript_offset = metrics.y_offset; - } - - Some(ResolvedFont { - id, - units_per_em, - ascent, - descent, - x_height, - underline_position, - underline_thickness, - line_through_position, - subscript_offset, - superscript_offset, - }) + self.with_face_data(id, |data, face_index| { + super::skrifa_metrics::load_font_metrics(data, face_index, id) })? } #[inline(never)] fn has_char(&self, id: ID, c: char) -> bool { - let res = self.with_face_data(id, |font_data, face_index| -> Option { - let font = ttf_parser::Face::parse(font_data, face_index).ok()?; - font.glyph_index(c)?; - Some(true) - }); - - res == Some(Some(true)) + self.with_face_data(id, |font_data, face_index| { + super::skrifa_metrics::has_char(font_data, face_index, c) + }) + .unwrap_or(false) } } @@ -1281,11 +1252,23 @@ pub(crate) fn shape_text( font: Arc, small_caps: bool, apply_kerning: bool, + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, resolver: &FontResolver, fontdb: &mut Arc, ) -> Vec { - let mut glyphs = shape_text_with_font(text, font.clone(), small_caps, apply_kerning, fontdb) - .unwrap_or_default(); + let mut glyphs = shape_text_with_font( + text, + font.clone(), + small_caps, + apply_kerning, + variations, + font_size, + font_optical_sizing, + fontdb, + ) + .unwrap_or_default(); // Remember all fonts used for shaping. let mut used_fonts = vec![font.id]; @@ -1314,6 +1297,9 @@ pub(crate) fn shape_text( fallback_font.clone(), small_caps, apply_kerning, + variations, + font_size, + font_optical_sizing, fontdb, ) .unwrap_or_default(); @@ -1371,10 +1357,75 @@ fn shape_text_with_font( font: Arc, small_caps: bool, apply_kerning: bool, + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, fontdb: &fontdb::Database, ) -> Option> { fontdb.with_face_data(font.id, |font_data, face_index| -> Option> { - let rb_font = rustybuzz::Face::from_slice(font_data, face_index)?; + let hr_font = harfrust::FontRef::from_index(font_data, face_index).ok()?; + + // Build the list of variations to apply + let mut final_variations: Vec = variations + .iter() + .map(|v| harfrust::Variation { + tag: Tag::new(&v.tag), + value: v.value, + }) + .collect(); + + // Automatic optical sizing: if font-optical-sizing is auto and the font has + // an 'opsz' axis that isn't explicitly set, auto-set it to match font size. + // This matches browser behavior (CSS font-optical-sizing: auto). + if font_optical_sizing == crate::FontOpticalSizing::Auto { + let has_explicit_opsz = variations.iter().any(|v| v.tag == *b"opsz"); + if !has_explicit_opsz { + // Check if font has opsz axis using skrifa + if let Ok(skrifa_font) = skrifa::FontRef::from_index(font_data, face_index) { + let axes = skrifa_font.axes(); + let has_opsz_axis = axes.iter().any(|axis| axis.tag() == Tag::new(b"opsz")); + if has_opsz_axis { + log::debug!( + "Auto-setting opsz={} (font-optical-sizing: auto)", + font_size + ); + final_variations.push(harfrust::Variation { + tag: Tag::new(b"opsz"), + value: font_size, + }); + } + } + } + } + + // Log variations if any + if !final_variations.is_empty() { + log::debug!( + "Applying {} font variations for shaping", + final_variations.len() + ); + for v in &final_variations { + log::debug!( + " Setting variation {:?} = {}", + std::str::from_utf8(&v.tag.into_bytes()).unwrap_or("????"), + v.value + ); + } + } + + // Create shaper data and instance + let shaper_data = harfrust::ShaperData::new(&hr_font); + let shaper_instance = if !final_variations.is_empty() { + Some(harfrust::ShaperInstance::from_variations(&hr_font, final_variations)) + } else { + None + }; + + // Build shaper with optional instance + let shaper = shaper_data + .shaper(&hr_font) + .instance(shaper_instance.as_ref()) + .build(); let bidi_info = unicode_bidi::BidiInfo::new(text, Some(unicode_bidi::Level::ltr())); let paragraph = &bidi_info.paragraphs[0]; @@ -1390,31 +1441,37 @@ fn shape_text_with_font( } let ltr = levels[run.start].is_ltr(); - let hb_direction = if ltr { - rustybuzz::Direction::LeftToRight + let hr_direction = if ltr { + harfrust::Direction::LeftToRight } else { - rustybuzz::Direction::RightToLeft + harfrust::Direction::RightToLeft }; - let mut buffer = rustybuzz::UnicodeBuffer::new(); + let mut buffer = harfrust::UnicodeBuffer::new(); buffer.push_str(sub_text); - buffer.set_direction(hb_direction); + buffer.set_direction(hr_direction); + // Set script based on the first character's script for proper shaping + // This is critical for Arabic and other complex scripts + if let Some(first_char) = sub_text.chars().next() { + let script = unicode_script_to_harfrust(first_char.script()); + buffer.set_script(script); + } let mut features = Vec::new(); if small_caps { - features.push(rustybuzz::Feature::new(Tag::from_bytes(b"smcp"), 1, ..)); + features.push(harfrust::Feature::new(Tag::new(b"smcp"), 1, ..)); } if !apply_kerning { - features.push(rustybuzz::Feature::new(Tag::from_bytes(b"kern"), 0, ..)); + features.push(harfrust::Feature::new(Tag::new(b"kern"), 0, ..)); } - let output = rustybuzz::shape(&rb_font, &features, buffer); + let output = shaper.shape(buffer, &features); let positions = output.glyph_positions(); let infos = output.glyph_infos(); - for i in 0..output.len() { + for i in 0usize..output.len() { let pos = positions[i]; let info = infos[i]; let idx = run.start + info.cluster as usize; @@ -1433,7 +1490,7 @@ fn shape_text_with_font( byte_idx: ByteIndex::new(idx), cluster_len: end.checked_sub(start).unwrap_or(0), // TODO: can fail? text: sub_text[start..end].to_string(), - id: GlyphId(info.glyph_id as u16), + id: GlyphId::new(info.glyph_id as u32), dx: pos.x_offset, dy: pos.y_offset, width: pos.x_advance, @@ -1548,7 +1605,7 @@ pub(crate) struct Glyph { impl Glyph { fn is_missing(&self) -> bool { - self.id.0 == 0 + self.id.to_u32() == 0 } } @@ -1597,6 +1654,33 @@ pub(crate) fn is_word_separator_characters(c: char) -> bool { } impl ResolvedFont { + /// Creates a new ResolvedFont with all required metrics. + pub(crate) fn new( + id: ID, + units_per_em: NonZeroU16, + ascent: i16, + descent: i16, + x_height: NonZeroU16, + underline_position: i16, + underline_thickness: NonZeroU16, + line_through_position: i16, + subscript_offset: i16, + superscript_offset: i16, + ) -> Self { + Self { + id, + units_per_em, + ascent, + descent, + x_height, + underline_position, + underline_thickness, + line_through_position, + subscript_offset, + superscript_offset, + } + } + #[inline] pub(crate) fn scale(&self, font_size: f32) -> f32 { font_size / self.units_per_em.get() as f32 @@ -1744,3 +1828,81 @@ impl ByteIndex { text[self.0..].chars().next().unwrap() } } + +/// Converts unicode_script::Script to harfrust::Script +fn unicode_script_to_harfrust(script: unicode_script::Script) -> harfrust::Script { + use unicode_script::Script::*; + match script { + Arabic => harfrust::script::ARABIC, + Armenian => harfrust::script::ARMENIAN, + Bengali => harfrust::script::BENGALI, + Bopomofo => harfrust::script::BOPOMOFO, + Cyrillic => harfrust::script::CYRILLIC, + Devanagari => harfrust::script::DEVANAGARI, + Georgian => harfrust::script::GEORGIAN, + Greek => harfrust::script::GREEK, + Gujarati => harfrust::script::GUJARATI, + Gurmukhi => harfrust::script::GURMUKHI, + Han => harfrust::script::HAN, + Hangul => harfrust::script::HANGUL, + Hebrew => harfrust::script::HEBREW, + Hiragana => harfrust::script::HIRAGANA, + Kannada => harfrust::script::KANNADA, + Katakana => harfrust::script::KATAKANA, + Khmer => harfrust::script::KHMER, + Lao => harfrust::script::LAO, + Latin => harfrust::script::LATIN, + Malayalam => harfrust::script::MALAYALAM, + Myanmar => harfrust::script::MYANMAR, + Oriya => harfrust::script::ORIYA, + Sinhala => harfrust::script::SINHALA, + Syriac => harfrust::script::SYRIAC, + Tamil => harfrust::script::TAMIL, + Telugu => harfrust::script::TELUGU, + Thai => harfrust::script::THAI, + Tibetan => harfrust::script::TIBETAN, + _ => harfrust::script::COMMON, + } +} + +/// Computes effective font variations including automatic optical sizing. +/// +/// If `font_optical_sizing` is `Auto` and the font has an `opsz` axis that isn't +/// explicitly set in `variations`, this function adds `opsz=font_size` to match +/// browser behavior (CSS font-optical-sizing: auto). +fn compute_effective_variations( + variations: &[crate::FontVariation], + font_size: f32, + font_optical_sizing: crate::FontOpticalSizing, + font_id: ID, + fontdb: &fontdb::Database, +) -> Vec { + let mut effective = variations.to_vec(); + + // Automatic optical sizing: if font-optical-sizing is auto and the font has + // an 'opsz' axis that isn't explicitly set, auto-set it to match font size. + if font_optical_sizing == crate::FontOpticalSizing::Auto { + let has_explicit_opsz = variations.iter().any(|v| v.tag == *b"opsz"); + if !has_explicit_opsz { + // Check if font has opsz axis + let has_opsz_axis = fontdb + .with_face_data(font_id, |font_data, face_index| { + if let Ok(font) = skrifa::FontRef::from_index(font_data, face_index) { + font.axes().iter().any(|axis| axis.tag() == Tag::new(b"opsz")) + } else { + false + } + }) + .unwrap_or(false); + + if has_opsz_axis { + effective.push(crate::FontVariation { + tag: *b"opsz", + value: font_size, + }); + } + } + } + + effective +} diff --git a/crates/usvg/src/text/mod.rs b/crates/usvg/src/text/mod.rs index 4b48274e1..9e844885c 100644 --- a/crates/usvg/src/text/mod.rs +++ b/crates/usvg/src/text/mod.rs @@ -11,10 +11,13 @@ use crate::{Cache, Font, FontStretch, FontStyle, Text}; pub(crate) mod flatten; -mod colr; /// Provides access to the layout of a text node. pub mod layout; +// Skrifa-based implementations for font metrics and COLR +mod skrifa_metrics; +mod skrifa_colr; + /// A shorthand for [FontResolver]'s font selection function. /// /// This function receives a font specification (families + a style, weight, @@ -201,13 +204,18 @@ impl std::fmt::Debug for FontResolver<'_> { /// is not based on the outlines of a glyph, but instead the glyph metrics as well /// as decoration spans). /// 2. We convert all of the positioned glyphs into outlines. -pub(crate) fn convert(text: &mut Text, resolver: &FontResolver, cache: &mut Cache) -> Option<()> { +pub(crate) fn convert( + text: &mut Text, + resolver: &FontResolver, + cache: &mut Cache, + hinting_ctx: Option, +) -> Option<()> { let (text_fragments, bbox) = layout::layout_text(text, resolver, &mut cache.fontdb)?; text.layouted = text_fragments; text.bounding_box = bbox.to_rect(); text.abs_bounding_box = bbox.transform(text.abs_transform)?.to_rect(); - let (group, stroke_bbox) = flatten::flatten(text, cache)?; + let (group, stroke_bbox) = flatten::flatten(text, cache, hinting_ctx)?; text.flattened = Box::new(group); text.stroke_bounding_box = stroke_bbox.to_rect(); text.abs_stroke_bounding_box = stroke_bbox.transform(text.abs_transform)?.to_rect(); diff --git a/crates/usvg/src/text/skrifa_colr.rs b/crates/usvg/src/text/skrifa_colr.rs new file mode 100644 index 000000000..4ee87bde8 --- /dev/null +++ b/crates/usvg/src/text/skrifa_colr.rs @@ -0,0 +1,396 @@ +// Copyright 2024 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! COLRv1 color glyph painting using skrifa's ColorPainter. +//! +//! This module provides an alternative to ttf-parser for rendering COLR glyphs, +//! using skrifa's ColorPainter trait. This enables full COLRv1 support including +//! sweep/conic gradients. + +use skrifa::{ + color::{Brush, ColorGlyphFormat, ColorPainter, CompositeMode}, + instance::LocationRef, + outline::OutlinePen, + raw::types::BoundingBox, + FontRef, GlyphId, MetadataProvider, +}; +use xmlwriter::XmlWriter; + +use crate::{Options, Tree}; + +/// Skrifa-based pen for building SVG path data. +struct SvgPathPen<'a> { + path: &'a mut String, +} + +impl<'a> SvgPathPen<'a> { + fn new(path: &'a mut String) -> Self { + Self { path } + } + + fn finish(&mut self) { + if !self.path.is_empty() { + self.path.pop(); // remove trailing space + } + } +} + +impl OutlinePen for SvgPathPen<'_> { + fn move_to(&mut self, x: f32, y: f32) { + use std::fmt::Write; + write!(self.path, "M {} {} ", x, y).unwrap(); + } + + fn line_to(&mut self, x: f32, y: f32) { + use std::fmt::Write; + write!(self.path, "L {} {} ", x, y).unwrap(); + } + + fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) { + use std::fmt::Write; + write!(self.path, "Q {} {} {} {} ", cx0, cy0, x, y).unwrap(); + } + + fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) { + use std::fmt::Write; + write!(self.path, "C {} {} {} {} {} {} ", cx0, cy0, cx1, cy1, x, y).unwrap(); + } + + fn close(&mut self) { + self.path.push_str("Z "); + } +} + +/// COLR glyph painter that outputs SVG using skrifa's ColorPainter. +pub(crate) struct SkrifaGlyphPainter<'a> { + font: FontRef<'a>, + svg: &'a mut XmlWriter, + path_buf: &'a mut String, + gradient_index: usize, + clip_path_index: usize, + transform_stack: Vec, + current_transform: skrifa::color::Transform, +} + +impl<'a> SkrifaGlyphPainter<'a> { + pub fn new( + font: FontRef<'a>, + svg: &'a mut XmlWriter, + path_buf: &'a mut String, + ) -> Self { + Self { + font, + svg, + path_buf, + gradient_index: 1, + clip_path_index: 1, + transform_stack: Vec::new(), + current_transform: skrifa::color::Transform::default(), + } + } + + fn get_color(&self, palette_index: u16) -> Option { + // TODO: SVG 2 allows specifying color palette via CSS font-palette property. + // Currently we always use palette 0 (the default). Supporting font-palette + // would require passing the palette index through the rendering pipeline. + self.font + .color_palettes() + .get(0)? + .colors() + .get(palette_index as usize) + .copied() + } + + fn write_color(&mut self, name: &str, palette_index: u16, alpha: f32) { + if let Some(color) = self.get_color(palette_index) { + self.svg.write_attribute_fmt( + name, + format_args!("rgb({}, {}, {})", color.red, color.green, color.blue), + ); + let opacity = (color.alpha as f32 / 255.0) * alpha; + if opacity < 1.0 { + let opacity_name = if name == "fill" { + "fill-opacity" + } else { + "stop-opacity" + }; + self.svg.write_attribute(opacity_name, &opacity); + } + } + } + + fn write_transform(&mut self, name: &str, ts: skrifa::color::Transform) { + // Check if it's an identity transform (no transformation) + if ts.xx == 1.0 && ts.yx == 0.0 && ts.xy == 0.0 && ts.yy == 1.0 && ts.dx == 0.0 && ts.dy == 0.0 { + return; + } + + self.svg.write_attribute_fmt( + name, + format_args!( + "matrix({} {} {} {} {} {})", + ts.xx, ts.yx, ts.xy, ts.yy, ts.dx, ts.dy + ), + ); + } + + fn paint_solid(&mut self, palette_index: u16, alpha: f32) { + self.svg.start_element("path"); + self.write_color("fill", palette_index, alpha); + self.write_transform("transform", self.current_transform); + self.svg.write_attribute("d", self.path_buf); + self.svg.end_element(); + } + + fn paint_linear_gradient( + &mut self, + p0: skrifa::raw::types::Point, + p1: skrifa::raw::types::Point, + stops: &[skrifa::color::ColorStop], + extend: skrifa::color::Extend, + ) { + let gradient_id = format!("lg{}", self.gradient_index); + self.gradient_index += 1; + + self.svg.start_element("linearGradient"); + self.svg.write_attribute("id", &gradient_id); + self.svg.write_attribute("x1", &p0.x); + self.svg.write_attribute("y1", &p0.y); + self.svg.write_attribute("x2", &p1.x); + self.svg.write_attribute("y2", &p1.y); + self.svg.write_attribute("gradientUnits", &"userSpaceOnUse"); + self.write_spread_method(extend); + self.write_transform("gradientTransform", self.current_transform); + self.write_gradient_stops(stops); + self.svg.end_element(); + + self.svg.start_element("path"); + self.svg + .write_attribute_fmt("fill", format_args!("url(#{})", gradient_id)); + self.svg.write_attribute("d", self.path_buf); + self.svg.end_element(); + } + + fn paint_radial_gradient( + &mut self, + c0: skrifa::raw::types::Point, + r0: f32, + c1: skrifa::raw::types::Point, + r1: f32, + stops: &[skrifa::color::ColorStop], + extend: skrifa::color::Extend, + ) { + let gradient_id = format!("rg{}", self.gradient_index); + self.gradient_index += 1; + + self.svg.start_element("radialGradient"); + self.svg.write_attribute("id", &gradient_id); + self.svg.write_attribute("cx", &c1.x); + self.svg.write_attribute("cy", &c1.y); + self.svg.write_attribute("r", &r1); + self.svg.write_attribute("fr", &r0); + self.svg.write_attribute("fx", &c0.x); + self.svg.write_attribute("fy", &c0.y); + self.svg.write_attribute("gradientUnits", &"userSpaceOnUse"); + self.write_spread_method(extend); + self.write_transform("gradientTransform", self.current_transform); + self.write_gradient_stops(stops); + self.svg.end_element(); + + self.svg.start_element("path"); + self.svg + .write_attribute_fmt("fill", format_args!("url(#{})", gradient_id)); + self.svg.write_attribute("d", self.path_buf); + self.svg.end_element(); + } + + fn paint_sweep_gradient( + &mut self, + c0: skrifa::raw::types::Point, + start_angle: f32, + end_angle: f32, + stops: &[skrifa::color::ColorStop], + extend: skrifa::color::Extend, + ) { + // SVG doesn't have native sweep gradient support. + // We approximate with a conic gradient in CSS or fall back to first stop color. + // For now, use the first stop color as a fallback. + log::warn!( + "Sweep gradient at ({}, {}) from {}° to {}° - using fallback", + c0.x, c0.y, start_angle, end_angle + ); + + if let Some(first_stop) = stops.first() { + self.paint_solid(first_stop.palette_index, first_stop.alpha); + } + + // Consume extend to suppress unused warning + let _ = extend; + } + + fn write_spread_method(&mut self, extend: skrifa::color::Extend) { + let method = match extend { + skrifa::color::Extend::Pad => "pad", + skrifa::color::Extend::Repeat => "repeat", + skrifa::color::Extend::Reflect => "reflect", + _ => "pad", // Default to pad for unknown values + }; + self.svg.write_attribute("spreadMethod", &method); + } + + fn write_gradient_stops(&mut self, stops: &[skrifa::color::ColorStop]) { + for stop in stops { + self.svg.start_element("stop"); + self.svg.write_attribute("offset", &stop.offset); + self.write_color("stop-color", stop.palette_index, stop.alpha); + self.svg.end_element(); + } + } + + fn clip_with_path(&mut self, path: &str) { + let clip_id = format!("cp{}", self.clip_path_index); + self.clip_path_index += 1; + + self.svg.start_element("clipPath"); + self.svg.write_attribute("id", &clip_id); + self.svg.start_element("path"); + self.write_transform("transform", self.current_transform); + self.svg.write_attribute("d", &path); + self.svg.end_element(); + self.svg.end_element(); + + self.svg.start_element("g"); + self.svg + .write_attribute_fmt("clip-path", format_args!("url(#{})", clip_id)); + } +} + +impl<'a> ColorPainter for SkrifaGlyphPainter<'a> { + fn push_transform(&mut self, transform: skrifa::color::Transform) { + self.transform_stack.push(self.current_transform); + self.current_transform = self.current_transform * transform; + } + + fn pop_transform(&mut self) { + if let Some(ts) = self.transform_stack.pop() { + self.current_transform = ts; + } + } + + fn push_clip_glyph(&mut self, glyph_id: GlyphId) { + self.path_buf.clear(); + let outlines = self.font.outline_glyphs(); + if let Some(glyph) = outlines.get(glyph_id) { + let mut pen = SvgPathPen::new(self.path_buf); + let settings = skrifa::outline::DrawSettings::unhinted( + skrifa::instance::Size::unscaled(), + LocationRef::default(), + ); + let _ = glyph.draw(settings, &mut pen); + pen.finish(); + } + self.clip_with_path(&self.path_buf.clone()); + } + + fn push_clip_box(&mut self, clip_box: BoundingBox) { + let x_min = clip_box.x_min; + let x_max = clip_box.x_max; + let y_min = clip_box.y_min; + let y_max = clip_box.y_max; + + let clip_path = format!( + "M {} {} L {} {} L {} {} L {} {} Z", + x_min, y_min, x_max, y_min, x_max, y_max, x_min, y_max + ); + + self.clip_with_path(&clip_path); + } + + fn pop_clip(&mut self) { + self.svg.end_element(); // g with clip-path + } + + fn fill(&mut self, brush: Brush<'_>) { + match brush { + Brush::Solid { palette_index, alpha } => { + self.paint_solid(palette_index, alpha); + } + Brush::LinearGradient { p0, p1, color_stops, extend } => { + self.paint_linear_gradient(p0, p1, color_stops, extend); + } + Brush::RadialGradient { c0, r0, c1, r1, color_stops, extend } => { + self.paint_radial_gradient(c0, r0, c1, r1, color_stops, extend); + } + Brush::SweepGradient { c0, start_angle, end_angle, color_stops, extend } => { + self.paint_sweep_gradient(c0, start_angle, end_angle, color_stops, extend); + } + } + } + + fn push_layer(&mut self, mode: CompositeMode) { + self.svg.start_element("g"); + + let mode_str = match mode { + CompositeMode::SrcOver => "normal", + CompositeMode::Screen => "screen", + CompositeMode::Overlay => "overlay", + CompositeMode::Darken => "darken", + CompositeMode::Lighten => "lighten", + CompositeMode::ColorDodge => "color-dodge", + CompositeMode::ColorBurn => "color-burn", + CompositeMode::HardLight => "hard-light", + CompositeMode::SoftLight => "soft-light", + CompositeMode::Difference => "difference", + CompositeMode::Exclusion => "exclusion", + CompositeMode::Multiply => "multiply", + CompositeMode::HslHue => "hue", + CompositeMode::HslSaturation => "saturation", + CompositeMode::HslColor => "color", + CompositeMode::HslLuminosity => "luminosity", + _ => { + log::warn!("Unsupported blend mode: {:?}", mode); + "normal" + } + }; + self.svg.write_attribute_fmt( + "style", + format_args!("mix-blend-mode: {}; isolation: isolate", mode_str), + ); + } + + fn pop_layer(&mut self) { + self.svg.end_element(); // g + } +} + +/// Paint a COLR glyph using skrifa's ColorPainter and return the resulting SVG tree. +pub fn paint_colr_glyph(data: &[u8], face_index: u32, glyph_id: GlyphId) -> Option { + let font = FontRef::from_index(data, face_index).ok()?; + + let mut svg = XmlWriter::new(xmlwriter::Options::default()); + + svg.start_element("svg"); + svg.write_attribute("xmlns", "http://www.w3.org/2000/svg"); + svg.write_attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"); + + let mut path_buf = String::with_capacity(256); + + svg.start_element("g"); + + let skrifa_glyph_id = GlyphId::new(glyph_id.to_u32()); + let color_glyphs = font.color_glyphs(); + + // Try COLRv1 first, then fall back to COLRv0 + let color_glyph = color_glyphs + .get_with_format(skrifa_glyph_id, ColorGlyphFormat::ColrV1) + .or_else(|| color_glyphs.get_with_format(skrifa_glyph_id, ColorGlyphFormat::ColrV0))?; + + let mut painter = SkrifaGlyphPainter::new(font, &mut svg, &mut path_buf); + + // Paint the glyph - this calls our ColorPainter implementation + let _ = color_glyph.paint(LocationRef::default(), &mut painter); + + svg.end_element(); // g + + Tree::from_data(svg.end_document().as_bytes(), &Options::default()).ok() +} diff --git a/crates/usvg/src/text/skrifa_metrics.rs b/crates/usvg/src/text/skrifa_metrics.rs new file mode 100644 index 000000000..091637dd8 --- /dev/null +++ b/crates/usvg/src/text/skrifa_metrics.rs @@ -0,0 +1,105 @@ +// Copyright 2024 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Font metrics extraction using skrifa. +//! +//! This module provides an alternative to ttf-parser for extracting font metrics, +//! using skrifa's MetadataProvider trait. This is used when the `hinting` feature +//! is enabled to reduce double font parsing. + +use std::num::NonZeroU16; + +use fontdb::ID; +use skrifa::{ + instance::LocationRef, instance::Size as SkrifaSize, raw::TableProvider, FontRef, + MetadataProvider, +}; + +use super::layout::ResolvedFont; + +/// Load font metrics using skrifa's MetadataProvider. +/// +/// Returns a ResolvedFont containing all necessary metrics for text layout. +pub fn load_font_metrics(data: &[u8], face_index: u32, id: ID) -> Option { + let font = FontRef::from_index(data, face_index).ok()?; + let metrics = font.metrics(SkrifaSize::unscaled(), LocationRef::default()); + + let units_per_em = NonZeroU16::new(metrics.units_per_em)?; + + // skrifa provides ascent/descent as f32 in font units (when using unscaled size) + let ascent = metrics.ascent as i16; + let descent = metrics.descent as i16; + + // x_height is optional in skrifa + let x_height = metrics + .x_height + .and_then(|x| u16::try_from(x as i32).ok()) + .and_then(NonZeroU16::new); + let x_height = match x_height { + Some(height) => height, + None => { + // If not set - fallback to height * 45%. + // 45% is what Firefox uses. + u16::try_from((f32::from(ascent - descent) * 0.45) as i32) + .ok() + .and_then(NonZeroU16::new)? + } + }; + + // Get strikeout/line-through position from skrifa's strikeout decoration + let line_through_position = match metrics.strikeout { + Some(decoration) => decoration.offset as i16, + None => x_height.get() as i16 / 2, + }; + + // Get underline metrics from skrifa + let (underline_position, underline_thickness) = match metrics.underline { + Some(decoration) => { + let thickness = u16::try_from(decoration.thickness as i32) + .ok() + .and_then(NonZeroU16::new) + // skrifa guarantees that units_per_em is >= 16 + .unwrap_or_else(|| NonZeroU16::new(units_per_em.get() / 12).unwrap()); + + (decoration.offset as i16, thickness) + } + None => ( + -(units_per_em.get() as i16) / 9, + NonZeroU16::new(units_per_em.get() / 12).unwrap(), + ), + }; + + // Get subscript/superscript metrics from OS/2 table, fall back to calculation + // 0.2 and 0.4 are generic offsets used by some applications (Inkscape/librsvg). + let mut subscript_offset = (units_per_em.get() as f32 / 0.2).round() as i16; + let mut superscript_offset = (units_per_em.get() as f32 / 0.4).round() as i16; + + // Try to get actual values from OS/2 table + if let Ok(os2) = font.os2() { + subscript_offset = os2.y_subscript_y_offset(); + superscript_offset = os2.y_superscript_y_offset(); + } + + Some(ResolvedFont::new( + id, + units_per_em, + ascent, + descent, + x_height, + underline_position, + underline_thickness, + line_through_position, + subscript_offset, + superscript_offset, + )) +} + +/// Check if a font contains a glyph for the given character using skrifa's charmap. +pub fn has_char(data: &[u8], face_index: u32, c: char) -> bool { + let font = match FontRef::from_index(data, face_index) { + Ok(f) => f, + Err(_) => return false, + }; + + font.charmap().map(c).is_some() +} diff --git a/crates/usvg/src/tree/text.rs b/crates/usvg/src/tree/text.rs index 10898bb3c..c1739b901 100644 --- a/crates/usvg/src/tree/text.rs +++ b/crates/usvg/src/tree/text.rs @@ -66,6 +66,39 @@ impl From for fontdb::Stretch { } } +/// A font variation axis setting. +/// +/// Used for variable fonts to specify axis values like weight, width, etc. +#[derive(Clone, Copy, Debug)] +pub struct FontVariation { + /// The 4-byte axis tag (e.g., b"wght" for weight). + pub tag: [u8; 4], + /// The axis value. + pub value: f32, +} + +impl FontVariation { + /// Creates a new font variation. + pub fn new(tag: [u8; 4], value: f32) -> Self { + Self { tag, value } + } +} + +impl PartialEq for FontVariation { + fn eq(&self, other: &Self) -> bool { + self.tag == other.tag && self.value.to_bits() == other.value.to_bits() + } +} + +impl Eq for FontVariation {} + +impl std::hash::Hash for FontVariation { + fn hash(&self, state: &mut H) { + self.tag.hash(state); + self.value.to_bits().hash(state); + } +} + /// A font style property. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum FontStyle { @@ -113,6 +146,7 @@ pub struct Font { pub(crate) style: FontStyle, pub(crate) stretch: FontStretch, pub(crate) weight: u16, + pub(crate) variations: Vec, } impl Font { @@ -137,6 +171,11 @@ impl Font { pub fn weight(&self) -> u16 { self.weight } + + /// Font variation settings for variable fonts. + pub fn variations(&self) -> &[FontVariation] { + &self.variations + } } /// A dominant baseline property. @@ -218,6 +257,24 @@ impl Default for LengthAdjust { } } +/// A font optical sizing property. +/// +/// Controls automatic adjustment of the `opsz` axis in variable fonts +/// based on font size. Matches CSS `font-optical-sizing`. +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum FontOpticalSizing { + /// Automatically set `opsz` to match font size (browser default). + Auto, + /// Do not automatically adjust `opsz`. + None, +} + +impl Default for FontOpticalSizing { + fn default() -> Self { + Self::Auto + } +} + /// A text span decoration style. /// /// In SVG, text decoration and text it's applied to can have different styles. @@ -281,6 +338,7 @@ pub struct TextSpan { pub(crate) font_size: NonZeroPositiveF32, pub(crate) small_caps: bool, pub(crate) apply_kerning: bool, + pub(crate) font_optical_sizing: FontOpticalSizing, pub(crate) decoration: TextDecoration, pub(crate) dominant_baseline: DominantBaseline, pub(crate) alignment_baseline: AlignmentBaseline, @@ -346,6 +404,15 @@ impl TextSpan { self.apply_kerning } + /// Font optical sizing mode. + /// + /// When `Auto` (default), the `opsz` axis will be automatically set + /// to match the font size for variable fonts that support it. + /// This matches the CSS `font-optical-sizing: auto` behavior. + pub fn font_optical_sizing(&self) -> FontOpticalSizing { + self.font_optical_sizing + } + /// A span decorations. pub fn decoration(&self) -> &TextDecoration { &self.decoration

udMbz_H0qVgRatW{PR7k*sLY@>dOxQCzE`|)eYd1iO;eQU(jN#p7F zsi{u~`#XIfg70K&;N~M}+Heedx7Mm^M$-S{9 z{906Pw$OtX5QzElO}!gd*!k_Z<{Z7UjP$aHHDO13JAP+VWA$`uJnz?k6tQR*gFVuc z?AP%a&K5DsuTw@1{pn%2YOfw&CHe zmxbSMYO^jbB+^yRq|_htOjb+rkS?UfI@L)ao8K0O+b z$3&jK7)L(8m-YJ5p|%JmA(DvNdcp}|h1^s9$a(Ff{u6Tb)1EGJ zj3543tZzIR*naacCO2$_9#dmWusBcGzUL~55dq{PWf zL7#IO(RPiE)?9bvv8HQadAk4hVH%TuB6q|12pMZ}zp5*%rx0H^BF|IsIw-co!-)B1QFm1f^PQ2A zZpqE@i-4@x!Hkq3jWz+Nwbl(ZzmZ})fWuG5Ca?5c}v^S{5 z`W3y94~ zLhs@9MQWTBn@3rXTLSs4F~^GLDQsq3Jww?rHg^S_THeP1SD`j713e8PLNIN>c2Zoj zN+NwuG~?SQsaeL#Q|7W_4ivnv6lvnf4&mP~f!Q?**kPis$c-h|(X8O#rHBk{Z$qY) z;hahXztDYWjO>Y@B@&w3!KV#(17Nw}o z{$AC4w%XzNnwyph3VPmv)uJ4HoteWlR+jAel;(0p0BHwj7Y=MClulEw@4r4|z`82D zALaT=zZ!RtB7!i@Pcc$Jq*?rUNN=UAH{WfO#AX?yQZDYD7!X;Z4~* z#w5{S9ym`@K%0y&2F;y#iy%_OyROj=jy~VNtZMsE%dUEOx8Ryf#k8PYy2l;dA|bc! z_RE3NCwcjGSpU3kzs+jSa~|Tjo(*Z9x(q%kZypqJ>yeva95*X*PzXiK?4N4T>HD&> z^vR3lIzr3O7;(8O2N!Q5g#d#Pd``%+V4x`UQQ0-V1)VV>Y zCPEvjD$+7lQ8dGCD|p-jkKWWQgK%|+jpE^`6VF|%2ALO8245HiB@Ac-E_EDj7^vqE zmYxPe-&e5EDUYS2|As|t{`1w73^vmNwH)x44 z2B#9Q=&EbH3pY=$8(Fd8U}2|Y%Nd#G>E4f82Np~z3)OUQ}*z-FuQ73EE>K67h| zVSh!MgIeox6C~4m1SSya73w5c%&R5T+Z|`^vY}Zo#=tBO#j+Mao;lAM$ed#Fix*+A&$Rkwa&ux>Jp8o3W5pxtS`~Hn67O&EP7#*D2Wk z#79Gd_SA4LA$`ing#781hI2ZycIP!HtNp69d+-BK0cFAvF(M{yae3thjTnFFfmu<| zBukJb)X3)|Pj!L)C71!hi}A>P-bm1 zin3s>gH^_|JS2{b22R@>g?$v&C=aRvGu#wS3Ap^P(<@ofnLE978h8qyl|#@r>8x~8Q`3 zym58kyFW`}g$4?6k)`$_B+hwGwI z-FWQjcnsS5UIBa>+Pd>Akzm>MNybojSHn6pE@q>n!RhWaC{WrcBZRza)bOMaiyv}= zBgm7bVCiQ{V?8j%+o#_Pv<~_7Sv5oz_u{d~lv1JjkPB|RGDarPwz~Jm3l>javd5H5 zIz5!>?wpO@zU2+_m-a?hbbf+d3srkO?i4h@ zz_`}h*TD_K^rq?Jv|0hY;Z4qx12Ly$c{WDJdV^5X2O39{;_s*ho6&+8X=&2Ai$U`5 zgvHyo7YwUlD1yhZ4shuGUma1fRwnKjDsg=pT*DBF_608x*o*(Xv2VhWdi6Rk@&5vu C`3bN9 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/lengthAdjust/vertical.png b/crates/resvg/tests-hinted/tests/text/lengthAdjust/vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..801ec787bea2ed2ae76341c29cf0ed736bc5855f GIT binary patch literal 1675 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 Ib4q9e0FCvi5C8xG literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/-3.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/-3.png new file mode 100644 index 0000000000000000000000000000000000000000..be8812a0078f7733a5fc6ad585d32d7e552ce723 GIT binary patch literal 1630 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 VeJlMEM5lm?aZgu2mvv4FO#nVc#hL&B literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/1mm.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/1mm.png new file mode 100644 index 0000000000000000000000000000000000000000..18e668cc5cb87b4cb82b6275103ee8533832b4f4 GIT binary patch literal 1715 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhj;QC&U#VF6<^r{|v$La_Pmn9SXZ=o~BCC=hzhH*_4GHlA z0Tb@u-|%34eg4C<*RT68E7|b%@SM8#otIBf%6h-_`NYG;nfI;wc{SQa8o+OKhJ&z3bhg_RD@vHajOWNoDwE3>=*2|e5dPIENX|2cHw^L;o z0g0PG4wXeZ*Cg&=I&4p#_Z8#S;pJ(2&DilNP9W33Y{FcfZev@4GkcyS?4J0&eEPMEY3kih z$t_dFqStA5sD4fRd9o%4_FXB&Q=-1NvH`W96@MT}~A(GO1flj(Q}Y?>_Wb$Z76Uol1=gPchR^efMT9*4ew} zPjE-rJ64-@nu^|$a*qQAmbf(Sty3$D+~wF58&MwFl6r6Y+%=D+Q$F66Fq^Pi=j+@Q z$@VvM*Vm>PZt<9-_}y}KxRPC21K-ZmK_7U3eCYeH*L~khIcjb>d;Fp6!H>^)+@JP! z>qF5;ocZ?p`y)~`y6-(!;Cjfz5gYVcCiUwf)2=fv-{&^E-JG&`jbFrj*S4=uKTq7J zZy#xurEw%iGm^frHZFMb)Iap`&Z_8=VPvZ-9zS6c}bhjNK{T$lDV(um3gsZ$DbsjO+TX9)^ciJ zmCik$!PI?BV1?LA-p-SY_VdcdH?31!X5qZHdc*t;HCw~Iva&Y4>ENEc|M?QD`VEf` zul;TK?}qu`{SSMzg(e=ouU}ePnr)Z4>+ky_I~FlLA){Bl2ctG$l~Or(Rd>(xzxiA3 zSR*ei>=2LoeqmMMhO6IBOl;G6;T9P7qAh;s-Pcx!Ls!pkNo}+}x#`EXSnlK7)V4)g ztLboWnUq?%d5-99^P^#}gQvL8kaM0hg>%b0tt7cEIa{CoI-GJh=QIEJC;Kgmg-`A- zd-u>`kpjY0C&U#UxD3Z7o=_NW3zRc03GxeO*uOs^USPug2MZF`&yTh!c+-EYRhwadQ2np3=X`3iTxu1{yAJP+>JWTfE{xhdu3B-PjRKqNPW zgF;<>S4rF`$dCH||` z{+Rdu{day_V7Slgw#kg4yVttUS*9vXd$cF8eyT+Ft!3&i5eRV@w z#7?G&Z+|B3UAgPdnfR8gA}bGXT7IxTq}0s7WOnQ4x|zJQtL@>|2=~5-v4Z9OPcv1enFK+jXK9y$Rs(C^QHB(4iSvhaa`#H5Zn$$f$l7NAmK9Ix^&f6u!Y$VS zCShKbzq;hl4;&XJ8b!Dttdc8`J!aC~t{Z-dZFTBm-5+1rrWM-c1b_GwDZR$cfIX#g zZG^!mvt`zk%pzi1_g;}U5S;MVE-Z`Tqg2Awq$@`>Cb-G{IId*!D`D#gs{=FiV%#q1_6l@+tS+Q3{M@#9_i+YM%SHus%Moaz@cA&qIx!i&7w zk8iThzd9*v{?*IjA`U0DNVVH58E<1CtgFY)Ue`6~yN-h~;ccy4$n zrW2Ii*gCy``))RNv6ZY5rCu9!UdZ0fy1SlxsjY z8gZrENGIWLvCyr3?h|rnYUvn#HH%oz`nr$nVpGoYCkY#wj+M&t)-**qJ$k&AEycQQ z|LvXZ+U-pS42yRkEX>*6u;Bl-q}zM$KYV=V4%0vOgw{Us`{l;FBJ4}bPWmj`AH5~^ zcCGQYiYR{BH9KoGi!-*Ld~_}8?aQ~bH#8mZW`7^Hb4r)q`57I{idrA+y?raUY-57b ztkciZzxUiTSuP@`6R{!TU=u6%U}H>!x(ezxs0&#j?&K6(Bc51VmA>Sh$m=~O$GG^< b`8*VqP&~xcw#?iSRH%Ep`njxgN@xNA&}`JL literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/5percent.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/5percent.png new file mode 100644 index 0000000000000000000000000000000000000000..e2091d179fd739bf434d9989eae0ff5a6859822d GIT binary patch literal 1705 zcmd5-do+{@6#tOHphJvMro6WBX^4~9L4=W!SB1|G1|zQqHCU0sloQEwHQ5ld2(wJ% zu`18eGT!g^dlX4ggw|_zdYt`l&uRbLd(J(-`}o~^fB)S$8!L<`Tow)hfap1M6FUIl z0YAGSAGczaN5*g=)5h|mDHs2%?ccv&LPA1QQJRL!^z3X>FDUFs;U|q8p2>OSy|brsHpF`6&)STWpeEm+441aKs(6J>H=_vV;EK6 zuyWMqeIPwD2X8&xnc=fepCzR(HDv}poz5TMUKvhu4ahF*o|*1R)(~^W*ZYVa%>n@a z*mEXE7emM1_B8VF@Q48Ps!zZnAQI0RZQun0TLt5Smn>+COBMvedaByTE=UF^U$2Fw zf)FcJ`CowMypx&*LJUIdR|+Tn3-h1+dxOf?6ITXDXwRIR=f12O3Jbh;iAuB0syX4; zXFv~tsqSZ=kw*4A<_(3ox^0fs`VNY`-L4-u8r>@zIL()K_T~`)n<8zvn&c7WRjpq$ zqC4U1nKgyN8ti_M_wzXKlS{2^S50slI^j3aKIXaZ3q1z|1{fhwrOVKXk_+6@lhGW| zK$}Qj*lyt@F&=cbva`F;{gLr?H};N_Wu_xBJ6g?M+W|?Wd5PxAHgJk?Q&sex>L3vYCqIlbPVMWoF{5 zg*0z5aps-=WW-heFbq~ikZmW39eV^e4&qS|_1*@7S66-ZASG7p;c;=ufzRxqWI<$FV&@IvUf@Z~wRthRyKXF|Ix$8=;(^`slmcyBZ;B7R$sUWX z_BDtlCa1@O9i((|A>n-gs~hOerG_{blUY3fC`5=qOne~os()*kg$Y&E6o)+D%knDY zRnJ!_iJT}?ur^}lGE!Dt$uh?g&|@|G5pTUE`{OV+@`II`6objEGB)CEsxVHFpDJP* z!vz*kzPP^Cl2x8@>%Dm^>zZJa<6Vmbk2Qx#g1T~0KHYy`R*F`*>`itM!7Vk>{k5ki zB|T;Xl!v_j!sGrRXHgCnDhUfL*c#_kjkd&=(+CJNGd1A^w6ux}WR~QM4tOXXdS7`` zGpf*;dTN9k0@-=N$DFCS@&;vFNJs4~TyM=}wl6JMNq@_r1dFvFQRz`!0eCagz&{(q zsxigA%tFqU$H!K;WLBEPtjwu3m4yQ1>xkR+cemljx|$V1EtKu?ap=}WnEdp*b0dotpsaxgFB@EDP7J&eyo6G9i}gD%OYFc$~)cp8srxAjLS$4JVl^CzS{ zICnOQLUVGQE=i6V<6WJfS?rqa!I30gt~agJ?2K-f*@&FkCRJzeTNPYogi8D- z=hO;jT-`VxiHJ4@qzTlg~uot literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/filter-bbox.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/filter-bbox.png new file mode 100644 index 0000000000000000000000000000000000000000..fca6ebe93851a62380b9ffdc5f0586ee6384beae GIT binary patch literal 1059 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAmtk16XFV_(LnLj(gu00V;u1A_wtg9QVF0Rw{u1A_tsg9HPE00RRD0}%YPQvu2_u$2V)1v@YZ z*yk6l+3;^R0|Rrrr;B4q#jUruUQSzN!O##`#hvHEG3k5#6~m%q$rm?Yc-gz`-S^!w zMcpkDxps9?GwsZL<7UpXzBWD0_1C8ZS#}w&ygCsZ5)L+PT@55yxu=0iF&z+FOeX?D zZeRhiHzaU^$%8@=9jah`tll8qBxw}A=LpdQF%D`+!ogqf6JjszFKyYX^Q`_g%j>xb zTMg&cy)v2e&T0ExpTpkgJ}%e$pgBGKhCB0`uf7|?%Fk^GyZ)au;<&|-$;%GRe=U_hv1Qcs}KSp2f9u^JL=R6d#SYy8mhRw$7{1r!OmB@nY6{+qt)m z-Wb*-8~$gE(43yP(*I{*>$Rrk7kvG9ZJnFc^E5MP&TXYI9fy|!Uej0dY)*SvHMe4U z&3bOrrMdbaj+-l6i>zIE>(7rpr-E)MUkh;CCQ&S{C3V`R#_v#Be?;!V%DLrFH|=QY z;=BCE%LQ8f4N4$NB)y;3a-hLxj42 z_Ytm@pZ;xq^CM=>zUPM%;}@8Bo320gSbFVy%My*)^#8v?6E{bE{#*BIUeI*K+Vh3i zK0B=b7jM30_EE0nx+%XT9vg)978hDnt%~P(o|`M5Y@a8j9rHQcG~#sj%b$N;=l;4A zwx3J-v-kFON!K?-EIsz>@8QZ@CSflHp36U8vd}tgoypyB_21V6f^SbPFY=x{-}9HR zCL~3HlUy`EC|OW9#gUy<(KYHegWb5nu0Cp_o&AQeWy^lvSmPuApQ&F{)<){$$u*$N N>gnp|vd$@?2>{1;z~cY_ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/large-negative.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/large-negative.png new file mode 100644 index 0000000000000000000000000000000000000000..1b8172c236220d470b8d77172630d14b353908ad GIT binary patch literal 736 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAe9i{6XFV_F+pQvBT%rRp&=(H z2QKU4;sRt_Sy=(a>+9=*Y%MJ>V`l{z9h&m z*nvSn!N5KsK0YBUzo4Og!lc=A7A)PcYyW}s7p~ub@Oo|j2B1-Zm~2u7vP-Lg{3eJZAfvP&B#+?3C1}OS<=e1nt8zl>>;tFDTc+j-2tK~% z%^M+F+W+w;N0_VNhD*I}-5n9VaatR+v>&qbL%acY;F{e>vfNzc!!~uyIOMgh-@-iM zsnjv=*=O^(wJ$2&+hw}uTx!&OrAHgy{HeA-^eT4Q%{}EaW$y2O&46SEBphhvH&VmV z8xr)>pb-Go4vdUzt~I?F1^yiz`%0X)5S5Q;?|oB zjjRm;5^M+7&-eIHR{5J>-1h_HqTPae#X+-Dg1t6{bFDGgc5gf}N!5FrPUL?j5V~vnxoRvz8 zAAJ95zr)(0CsmAX`|Hl9pV>`CJ8Hj+#{HY8=n9`mjNr;riO^gXqs0{{8dNRCaOLL_*OJu{YOD?cbGaJ=%U=tfR%uT* zY*~CTiDB3O7inu6T{XWr=rG!3P{a=?iZ@t{Nm2J__oSlpfN9O;$$mg0pJ=i;`b<>tjkGQ`r zi%3fmVwkj3W#5S$qnoN>+?%-H^p&4+WuMl*OQv+?@s+y!4h2qGC3N8L`i)EY6V%SR zb33Nrv|M%Pn0s$U^PIgRCpIR#eAbzErP1}5$I+BNquk(XBgTds!pq|sIO_DLU4GNB z>Uhx>_p8?|U*}abeE1X4f3~u{>W^gT{JER$^5!%C`BC@WB7VQ++rL}wWw!N~|Bw0d zrRGNc{}&}+o--b}+hhkW)0^VXm#*{?3lk1w_@TRc z!qx5z%Q(9kJ6>K*Dih(&IHWXl(c8nXS6J-o_}LP=gemKwQ%a{Vd31| zTxDftJceURO>#N;3@B<`666=musj47+)(hO`ei#1y zZP%Xrph4(;?}t_LZM%xvJf6NW*sy=i6^5VY-qUnaPEJzAL9GcjkKP28k0gfieIm#x zqLdP29IBet@nvV6%!?!#7KL5kz;pC)(v6bG|Nrl}-Eh}!ddRw2wsM|nv(h7Othp|) zInyEg`}V_^gd`g@GY(FguX^lJLhWo3v1ZGnRU$t(C!Ea{(P{Kd%)I}qzsWUKX3f(r z8(2#I*XT3uTz>xXng*u}$r|NHyu}?NT@NnO=3K+3w^MhO(1fZNeN!C*C7q9{s5B(x z|4(A$4s4ITE6!jb9CtWoU(T_VRkH4q$2`THQa716r6=0-wqD-3L~ujKMD68lw}iTz ztfwxNvM}3O79;jpZ|31UJM+${uGyS;bmfvIO!>z1gDt{+e;#w8q=B$ zTO8b#HTx$SZrHUu#ekukPx*VTQsUXbYgKv%51zPe*i(Nsx}`=oEGz3HM}%zYWc~wE z&Xe{EPRm?!xV!z+mJKuJ+nE1r=sjF?;bOe3&qIE16P^3&zoa(Boi(~1px(N)=C-BQ z|9L%!lq!XIy&Zpt>q&)OVc!43{(~b^S3$_!-AA`<$k}=CZCGO7tkYi&t<~2b6wU7h0VU0EuWf@qu|=3n{(aZ3R&?6Iy302oN63Y5&MEepRn@Shc=?7qFTNk1wRP97 z`%E|D&hL@a=etq&X=k;~)j;vQ+K+FU3o3TZ|N3P1*RMZH`eyGwF0VcB!nd1zUn(u^ zZESwca*VZOsJnRG{J_tnsgv)?z50>8ebVZicNxWfKgDi17Zp4A@3uqj-@m@!{d@QS z^Q#j6|Nkl8nCZ-!$a$ka!myiNrO5Z+;VuEuYhCY?WM!M>=Wbxw;(XkNp}|1lfW)rr zT;cy8?QlMrZ=fQiM5P?@)tH+3$_bK9u~Lr;fs%VUznoPvS=|;O`!reVnW(kvVo;go M>FVdQ&MBb@04DQN;s5{u literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/non-ASCII-character.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/non-ASCII-character.png new file mode 100644 index 0000000000000000000000000000000000000000..ea4c7f2e3265194987cabb8e76a8813055427eb4 GIT binary patch literal 908 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQc^`4pOBDWP~Xtr(LZ6qhW!W5U$}n% z!TS##39;uH7?=)tx;TbZ+}zLbbt3BRA*z5f zRAFQb&%b@3iS_mWlHL3Cjz`Hoi`^RW_Ojx!;OMTaN1t!|J~e6WqYIlvvL)NqrY4m> zw-7nCVV6Zop7zl!xyKh4>K-`77S*{hSX!3IUn#UfUgPZz;%%KXOXm+N?Aw)j7?u@2cFU#!$_$YCpca8rPKga$}aL zb0*ogi6*UTzbZ4?MdIMCI$N^?yZl9N%V^72?`FFeKBr=S@>BKjh?^f3kDpRgT=Pb2 zazopr06T6;u>b%7 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/normal.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/normal.png new file mode 100644 index 0000000000000000000000000000000000000000..fd8649fc540f627e1d3735cfc4a9ef31e30b3630 GIT binary patch literal 1670 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT>Y0C&U#yj)Oi;LRe|`P@{Qm1_XZt_Q{91f{ z!_GPh1wn{?ex4M$D2o13PndQa1d++;TyNTeu& z*{D=h&15x*@X1N4uf;c~04X@1c*a?^!`JF(mr6|E^lmax{~Ei!6GDrU?(58ud7fzS z=H!}37mokA%PT9=RQmS+|Lc6k`Hq3F-X?CTWD{$uGb>sevHRoupN=WE#lmm?cFaCh z=N-9Q-s9Srr~GwCYRcO}!%XJJr@BsFx9QQz@W_i_>ZXeNZa&quJTBGMIc~0w)il>n zjq~HbKl2XKn(VqhyWa1g@%O9h^C#qgd7h$jbY}gj!fPo{RLde4=xDK@*U(uVxnRJ6ic&neqL`DQ4MC9&&+4^NRmXb!Ft=!5F(~#Wy3< zkDFTAmH3^4G`ZKY6lLq35a=j&ydhb-X~ya^xlSB&Z~qkL)Q)j$l4-GC931x4G0UGT zwmaT@O_3mzpyLkp6}<8{oIafR{9#^Q;wCGLlX{QOD&1q#o?|k#X#($IU2Dx$W}6FN z)oy5=Vcj-&T2Mjfu9QTPnTY~RN)BC~arsKV@g>dfw%~ndZ^oRxp3t41@k;V-uV19! zj3Y}AM=Htha7dqW>eTVG)eE_tWV||S&ectpT)N5XVP?Ymh1(9jC{%gck-m15fR)Pn zp1OpD=uM|3wNgK>@eAv_AXt#}?8^4X(|##&@Vl+n(RNkj$hq{WbB{I9r`oF@pYL50 zY*(Hi^ekk)4$ncUPRYm?2Ob^yV2$kVwMxZOR`o~ciJU%k%_XJmkzeHg=}D2z{cM{m zl=y=dM^39}DPnJqv0uMw2g}a7xKz%GZ+Z@BanID$kWeJyCXE!}rYZ%aHFfF*^@79GK8~*fc-8kpV{?Z+jSjA?H)fi*r_pprR%>1zGC-t&MFs%zu#c>gg-0Q^v&C@o(a3Y z*G!CBsnh*t_PaAubGCTso_IA~`?ZN-`1hsnW-=!F?P)&AdYUUR^+V2YGxLZuG7rTx zy5AdoaZB4*JDW90`G4Rm)zh2gwprcmo11-~?Qc&7|3vO-sdLy>eeXw_?l{?hVcL@7 zt3}yI9J;5pCN?y_Ty%f+AFadhBY$tZ^6f0oW6ro`I@{(=opRi;t?&3IFSSz(qcWT) z-P$MkZb3zDP5t)c_fK2txQe}QpIGSh>RiT=KZ&oGN6gW2j@+}RAbAeEX8i)6b{*&4 z5s_2wYfQ+|e#&3FyC8Bw_T!XLozm&d8`G6Tlul2$UENqF{lFyYXQldI`<|0cW*fKZ_~q1Ts!xtlwW%vzb=M5d|lZ5wI6P;2tTy1 z=bp)O5iy;J4G9OESh)uqV;a;|P`5!{$O3UEr`Q_y#M<&ckNe4M9$ymBekVKg5#vFn VeJlMEM5lm?aZgu2mvv4FO#nVc#hL&B literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/on-Arabic.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/on-Arabic.png new file mode 100644 index 0000000000000000000000000000000000000000..7e39c013f1053082c8fff80d056187315095583d GIT binary patch literal 1690 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAhkNcC&U#<6A4^gT!1RIw6ys6 z_?VfQB_t%cxVU6xWn*Jwg@uJRH8leQ0@&Hvt*oq+m6Z(*4T0)oVq$`WgIQTwWn^S> za&mxD4Gj%IExEb5Ks7|#3slzF*a*~U^xW45$gwO5@(X5g_-|j(aNvEygbx=s1hnTb zz5ey^!=1%vm({+WxM5C5$=06_vL?;mmAT$Oe*J^}{qyhFpI@M0AP}E$-iPxM0|RTS zr;B4q#jQ6N97S6UL|6{m@4hJVVLgu=*RvVUTbt@kf3M$U`*Wp^{91yOV7`9BvF z%b5GM(_yFVCbdKL`zI{a`^@cJT-U{^}u97+4 z`SeB1T{=~|$$gHE&N_wj=B-ox85Jt>jhI7I*wo_rv>mQm2|ur#<0t&> z>9ZS&Pfu91CFHWY?qfTA|Jl6c_T=Lnp&|QJbabj$T{$VY!F`f1qr>l*&l?XbW&E47 z%QOCbx9BEIBj=q?F6RrXnL_2Br363ysM~W#H@!=g@9UR+Le)zB)olxTdh|j*emu-H zU)44LiG$)dfsd*8S}XWZGt0WI$-S5yR`N?ic>zI(7fIkYdAyb*8ThKI`7{+ZGbXVK8|Ct3lxD$}4*PrH{`` z+ssrI-ZiVvJEA-G&Y#-x-+=l7xT&A{ps`aPZt+# zej&2w%$LTx_jwnkYwy3`DLw7=pY)r?2c}+92!<`yojGw**v4IL77?E`R(127*!W`p!S`){_s0}ANjy$_ zo;X)+tFEL`(yXes!V|;T&Rta=&!jjyGM~)Md~jJfSCwJU;}%nc^@}SGr3=@s zPThUXrl;{lkgUqR85LI;0zc`LwJbHTyp-Ef@vWeAst=>*d5MFUI2<%qsMU2asm9*$ zwcUM4sc_Ei3GY6-Ii%jYlz(C6*On4h(=T(*$9uicJE-CO`)5UB$HYjrGsjnF*u@on z5xiFa_Cg~og8>iA0XOy&W;g4%T;iO!sKETt$w{i-({v&?r3^UZ^<1DcCO}++m9m?x k>K&HPRJ)nu>MSJ__Q|#tFE5I9Yap00i_>zopr0M4Au00000 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/coordinates-list.png b/crates/resvg/tests-hinted/tests/text/text-anchor/coordinates-list.png new file mode 100644 index 0000000000000000000000000000000000000000..8fd778edad355b2a96d57a87c8abde2ddd0c709a GIT binary patch literal 1036 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAXO3I6XFV_;UJWO!I*);mVtqv zfuWj#L56`LgMq<~fgz89AqlL=l$lwUkuj5jL5qp0EpaHa(fgzWHp|PlJ|1y)|1l9&Pu+{T5SFz z>&UH;s%End2?v{4xvzZ})rkNxRly{yH$-?EP^9$#hrLN4HDVAI^k?Xux^mWc=B|dX zmtNTf^S)jx`+B3@%hwx~*IW;s^eK1$X0Q*ixNgnw^Ot;!ivLGe>91)&e_6iXu4djG z59@vH5HIYDUUOx`J(29+&muOI<@d0z&Q4tW*8A?W4Zl;5+)~R8_m!Qz?ACO%V$n6H z&;0#&Tg#-(>(@Fh$!62XOEgojtL+bazRT{WUc6uWrl3jtcxt~#EPqm9eoJPO(f`Y3 zlOJuA>Mp-_MRDiqWA7%_-89NoJIZ%$@>};AE9bjy=PbDWb+yu(owrlIKfWXRddr>U zw|bhQYnE$OuG%D|*3Nb9^4qwM(5s%`Hq2Y;*|&V>{{L2I9b#vvaKBbErj z`}xF!S@RC>@_qGIi6uLC{+7GO5x>pe?#r6ADe3EmXO>skrI)?_&se!|UDuq6&r3l$(9_k=Wt~$(69AF3t2F=s literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/end-on-text.png b/crates/resvg/tests-hinted/tests/text/text-anchor/end-on-text.png new file mode 100644 index 0000000000000000000000000000000000000000..bbd2f5cea948fbb502a33eb32201a51afb325c6c GIT binary patch literal 1408 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=StC&U#<6A6@+m4PZ99xmT^vIyZoRqS%6Py)fMLU+p&BEqs$-46w&JFg zlTrq+6R+D8$Xrik@VdPBp?u=5Zk>DoE9$w8eN0ruPJNsD=K|Aeh6)AIRXwG#|FbuB zX)Q^&yvqI{{qYCm|5Yyo{w~{M?HBn`XZf0n4^u>at50<;w@f{1JZICQ!Wo@9TK}u% zUjKUf^QyDQ$qA-yjL)VrbD!3pvPkFqro|ifPKxW;z$g9 zR)uYJRrvDARrMi{yUX+@zQ9k3kP&XV?K&Uw{k5OY?-yc z;)F+7vdWA#FA7rsU3f2W{O5_HKede$B3pU)vUa{GI~RMxQ;a>#ecNF-_vqT$EptzM zT~j-m(t0hyr|^!-Ll(=EMOt_DWZaz3cfL^J6hGl5X8p3~=ac^dSNXqI+w2RB+f>yl zVEu$ITfZVC$w)ggCS~swsntdelKB}5#*rDx+!KEtTqX5j%2jEz8Rwp>opwJF^x1&@ ziQ4KN(PE0m4M#Ok+nvu;ylkTLZkJ1H+4Pr8_KqrB7H>$^THWN4wP)ce-)pny@VG0a zN6ZZSu=nrvw8u-OVk;${s;+)`o=<6k@3{?nw~p;e`Drb-)@^>eY~;yZDp&k2h8`B0 zlUo@qrmE@fw4`&bloi*xZDzq?6Th{##!k3>{rs6Fx~Fr3XKh-NIN#y%KGDYR)JQqk zC7Rq-Df2j)UX<=G`~K_K%qNqg{J+gurSodSP5INa+jFBY)IQd`7x6Lsb+6}J{YkY^ zn-;tXxbaH=fwlaqwo~g=r&N9my)KaIcEU z7$N#_moMayQ z^zp8~t0uud#=h3aPJZ3Ho-5&C6DzlvPQ->m$KZsxN(kaMRfr3{A?}=(aImXoYOeT_ joMTZlCY_z2<8xSc^VPR+*{tWi2NiOju6{1-oD!Ml@npCr+3>d(Qj?OV_X8uyg-` zv*#~dzyI*T`ww3uQntQeU|_!Q>EaktaqI1^_M*inq#6R7iqG9-V~_Rxy#N32*q%_G zd5pT!d)q#T2JtPwvUXXw%Izx$HmPv(>a5(rH;M7(f@5Bn7&RMNxy5uMHY^hb5(x*J zRKX;xH;B#3Jq<{1-OCMDajX@h5-b7ILPJKZNbSL2tgCzW{fmy+@agg6KheC0H)*bl zJH717{P!wKKbHyDgs8sUf0KL7!KaMb1?(Hzz8jUTdGceSM%V1QI&bx~SDm{QmVTAD zf4`m0?fI@(y#vb)oz~2aToZLC8o8^Kc%|ZELq*vF(X}8{>hUi-*(xqye%z#&H3-sP50|0 z^mAL@HI{F9=bF4nxF$JZyI`n#W_tfwhcn`Wg%kbwv%meUzVCKqP5Pd5uN!wrwXA>n zWrLYg(#)m4mH*dFRa-6p(DCmK&ZO8sf7WkXb3E~Xvv{Q~2md9`q`iOs96eon`C_(< zh^xz#mm(YOrrlmE_FBX2(c)CQz%_lRwz8l6dc@RqO^rcVHTO5exhi3o?z!jg^7y?< z{rim6$w#u@$wmm4@?Sn`_0#!x)#(+tW~*GYQOdjAnCo)&py%FOvy`soy6jnUc-43H zQ~jR%W++_?JHO!7tE8=mPEF4~{_gkQ>cvOArvLq)XWQPkzq}yg+LXmdtU6b<`$yd^ zd3*L^(cFUC=Nubnr9N8}Ir;f-{nYnr4~?>OXWv^B{q%m1u=Z^C*uvtPnwT?6i{7Z- zc(w1_PMv$RL-oszrKQ7W+45Q3%FONCw%ynIcK5Qv#H(-5F24FY?tIv}J*|^rE4@AnF;yLqK@q2;&l%HG@mx8ukC&sU#*{dV1iXZ7;C z>tBAV`kr0nw^Fzu5tMLgoIc63f)nB@AsjjFm(rTQXBjj1ACsCfNyVFO*_;23y=VUT SKC|Qol^C9`elF{r5}E*`j}&eI literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-1.png b/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-1.png new file mode 100644 index 0000000000000000000000000000000000000000..76c599107806d2f2c29edf7bc1e7b8a37c41bc32 GIT binary patch literal 2390 zcmc&$e>~Ic9-nqJjk9DXKiUa19gNJSg;Hrk%d8PijN3Ikau%U3C)#(S!YM?vQg`C| zH8X3%iTsLHV&=y|Qp3oP5Tz-zpj7N z`lrLXfUfc`6o6s@tOMWx2jEJ?19%3D;ScyD0VEgzE0M$^;qiC?0GLcBmWc)Z_dz0& zbai!MFc=bv387gYiyr68hWq@wkG`KgqxpDWrTuWUOC#To3$2dixy-w8A>l3Z-&)nqe8H&AZVl^mDu_B$V z&qP3FjPndG&9LoBtSCX9rlRR$UdcG5qn z;n4wkA)|N7y7y+=%ISG?Fwr4A+^a9Q%jAvhLlju?^L~$GktS_i=lrW;J3B{$R0c7o z!nEeS8DB{ri1uh($iu$dux?0Ljyq-5Vq}lFb+&QG8#2fC%94F$lgU*0W>Hr21u8p! zvJZai+TzT$wBT54nuKyl*msGSP*>LH{+UcM(rj@RYzTVoZa)ahkcxOZ=T4X%(_?Sh zbvNr9;K4bBiovnk=6frfj-DUe-C^0~c7>HW8L5TmP8zW7OqZXkHILU1uC$;_Celnh zCQ*5XW?@zbgHVVlCmEf5$)GW%vR&16$bTR`+3IG5fUkfGsoRj2&kL@}2bxT@Z7dgZ z)q1)ugOan%rS!Y2`frCir7LbC$CVQ}`wF*wFnd2o!AaG~ne?%~ ziJ=m?NWY9S+SIDF$}Ke1mAEV2%RFo&M)ARCKcCt3#z}27m3C$py2(qBy_^%KuCiI0 zv*oyJ)kqS+Rd8;emOWRc+~VFareeNt>00s$8SKq@!NDz)DUBWTg>dyP5pRttNA?WO zoE2YE`DQWZQ-DuHZ>w62XOwuMW5bMO&@tG4W-OkOKr30D_SH9*pKfO)V{Y&l{0o6G zJDrktpO*xk3Jn#fli>Q;dpGk(>iE>ivI8cO&$nlED{7b~so8Fs`9vXxfs&H07`cv^ zQM5K*@2@=xAM(|yAV#YuWjwriEkNML5yf%Tz(pP@n>V^pLY znZQuCUBL{?L@`C>FD=_@Pxz<`&FvGDUp??RJD^J8&RNuQB?bO3eJpNSze_y>3?&{;TM59todWi0|XEX_(WvR6a$*Kg6 zy)szcM5+Il{@hewCpg~2mY65>O7GP&#lM}}o0|Cq!@9#$lV8q6vzBBOj=INOBEMm| zKZz{Y4vu%RJ)GCMi&hz<7ji!;;iVP@o3hV;8=7_^XeC0#Uwgv8doXRgS`kgMWMawc z_ZdzLaYyF2 z8Dg9UA#HnL@}9bS+3VP?4IW8CKCBC$+9f)Eb;WOMJ)w5s@cXN7y0sV!)L;9SEOG^- z3`v^!4wZSd-MM<=SvQ1IS6Dn@W$b9k;~A?TU)n)?rw;F(_M5HYh3Vymz0bwE1Zm9-J3pzC6Xh1YNxd70@D#2NL;7h)0(|u=JckXv^Z|{Qq8a_ zPh80q@PABSd2D1W^SjL!m-{@<63>S|#&tAN`|#);E)?GFKV$FgD!BjTVgf%VN&7+r zR`xk#XNARL!fR9Sj!bmi)GTPVRbW5tqpN!KCwoHinNx$X!QzJ5web8Os`ds(FoyI3 zdq3Q7$Qmk4E)#k(IN$eJ|e@|ymGZra#wcO(4w>d?mI^FOP>7+C>=wxr@$mc+voCpKR#-B%{Tn*Eb>##+RUko z(nHOoUgtdi7JQKIjP5=!Ciqz3;~MU_i3=8u33NpD2euo1Z$()$`c7qa)eq!{CAb3) zr7=T(-&qLS`D<&FA%v^}{K8xj(xF%dl*j@-e#DnFptZDLLa1el{}@ugn?Q=o7|QR2 v-{#o=N>Tsf{YQx!qA=~mrIO0boTESvc}A&wYt|iq{dcb*-%poCul3B4+I literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-2.png b/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-2.png new file mode 100644 index 0000000000000000000000000000000000000000..576a1a04dc16f3477e0197e313a9d85aa8327616 GIT binary patch literal 1247 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`S)6XFV_At00?6v*&q2x)9= zY-nhJ2)Z(a6oeMpF$5=BW&%l|czu1nB}0$}Ly(VbtPz91i%6sngD()NGI$zs1;{hF zYO?z%vARnz*h?`x2s2m;F8lR9~P+mQG%9Po2RBnGCD9YuxwxsaQ$DWaPV)g;IzVJCTi)OHj(aJGVx(;OcPbT zr|Cp)`sWHFQ%*WzP_Na%3Q|r^f~ce~W7kf@!>Xo<8a;iJH`-q^%hg<4UKo7#o!hC( z|LkjyX>WL-@yaj##9vV%8)M67+%1u(qfTv@R(`T5*{^Ps%;BQ)lamb9?IX=(xGzkb zyG4QXed^Tjg*u6C)nWyw->zP`=D6k0Q@83Stnv7_iAP@f^rXf$OZf%%UR@#J&&-%& z-xan)>9m}MqvfZ0o23e#X{~lTJ^Na~`RIg2Yr@>NN)$E~J<~hw{MfaIdA7(dww$N} z-n07xyV|3^g~m+Q*Eo6h+JHQ$)Q zo~pUr%<^Q^&UGb8Vd^z;*Gl@BH$UVFrbw_QrM4}I`z|_gd+3cm(EfD%(e&Un3 zMX25;u2{#vMJx543}eGMOXn|qGs7Zp;#qG^BOd=*^On|LY^pls{nFrkRoMjQ zYq|01m;GN|G}z}vvlcs}8Bu`gAmvv4FO#tMc1w#M; literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-3.png b/crates/resvg/tests-hinted/tests/text/text-anchor/inheritance-3.png new file mode 100644 index 0000000000000000000000000000000000000000..39d61c3c7e33f3e327304951b86d5a1924b8307a GIT binary patch literal 1644 zcmbW1c{J2(9LC?F5q@Tx%NS!U#ci<+ErhIPW*TFR7#edWGov`jt}e2ZrOp)*LnAF3 zoXlm&QkF0{$I@~w=_pI(l3Oa28ja;nx_@`h?LFsxzR&x<&-4EIIq%|3MkwMG0RRY! z1Cb5@4F7G*%SvyYOB2Y_QQ+d_PLfU&0FsiDl9Q980EhrUPZ|KgAAtR`vH<{iB9WRf zm^7BaVr_xJ&YGJ$%FFwp(f;b{@no{TjLbneJVZw)iOoK3V4wwqanNY#Z;6SCF=l3T z2nyBFk#?o)1OOobcmd!8z+nJv0MOhx#saVffM5WQe$Q>FUy1mT)a*M=cXk6G*eq+0 z&yO;e(x0xNBG>X~A9SQGf2fP#uRP=x7reL=7Rn2)DtgxDSm+&PFM-TuBkHasxw;5 znG5&XSG{L8i~0zZSYI(`(z4`WMENbaM z2KhOdD?o`7dMC1A+`BPn=-s%n4J;qUJXGxz!@X1R&?P;X+csO-IdT+*KL-t90c4V^ z&#_lKDbf`P=VTaqSv^kv`FJMN=2j$^j;lSU!)ick{n0}!%y(k;cAwVRHsL)F%oM%B+6HWgBbYZ z8p>H$Rv0@4b#EIL(AC?N37G@fb0S=S0#7}Bf@dzu%&;HOFB01G(_>!|Oc%e-^C${w z_3l;2jA)}nAzeiAZ`<)oWRhuVxGpjaW&&#_GWF8xi!uHIg%?mujs}9R$cXWB?a*|E z<0!~5Zw0XfX=s6UJ+Y2g#njf_7U9s3*M?G7?|3n>(?ScmO@2i690+O*0-TC`{D$hK0NzYlj-f45$2Lk z@)NCw#}|)uQz>r3uvk_a30Z6TJB9W+2hmCIv7Urex6(2KU%v79HCTibn-zA-a1VHq z_ZT7#_bVAbU`DB8V&WvT54$4AhWFqFK3N5#CJ!Yz+4ADW)Ln5Jsr;RPy?IjKv~=CH zpu9KW)q=`G8HUr5$(w1+7-&2(=6j=S$m>ORe6~1eSQEd9jVt~dHPbJe9PcY7^x4Yv zjt$S7q6kw)l4aS6v%6kXWnFguY2{vD;jQEF=&9@V2W`!rPVbg8Oc7M|cw@YZp~fv@ zzjvS}rf&X)!D4;oXKIOe6Ozu>&(p6GFT!!*IqX-~d6GO~NSyy`Z2?wZ1eD~C)VxEZ zK23TBX_!w=g-4YqtHj|Y)T7|p*>s}fjx-qEA8v`9yelpH^gi0{bxX~O)luJB{X peMK=6qe*Wb*Hls61jFLK%U1vaM@qqB+3atWrjVS8Rrc(Ze*x-Jt|R~e literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/invalid-value-on-text.png b/crates/resvg/tests-hinted/tests/text/text-anchor/invalid-value-on-text.png new file mode 100644 index 0000000000000000000000000000000000000000..704550448ec072ce89011c030dbe1ee0cdcba23d GIT binary patch literal 1442 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<6AzS?m0et1goTBf znVGGutbiH~!5}v`mz|wmOG_&@HZ~w2z~A2=DAmx=P+wo4lamt@69eSR%E|)u611za zu@R`zT*0gwsMM$=$S;_|;lF*u{($!i9|{&sSf9V4{p{CC{j=v}zFt~fTNgijPF9Kk z&W`%|7ZUDocyQpnfk1qM-J0?V3=Axto-U3d6}R48Fl9X8Ai%Jp`R!4WKi%4zJN9uuT7t7=$f=-*C!n+1gE)B3G?R;aI&U<(HQB+~lcK z&n*^-JbSwT`a0|SJthK=X65&6wB-3X_2rLny|ZjjHM;HW3Lbwn6exavO;m*a-AtFM z$DXKnuVZeDIr)0tjNd+RP>9^CW$@lbeX9Jn!oKz58lGauSI^w~=Bi9doq?lZl$K}M`dc$2 z=SCgz?SEkNexXX_aor~O?blXJx2SflXjzoP8v=RkIH+k5o)K#A_WEX|2$r z!&R=~du@VVc69s91s0J&#xD`ZgoK$ZM-*i>IbesAQ8; zy0LTT%Jk^mH=1pyy{GZbdM@a6Z|=o6!OfSGe4cQ;(J+quHS^k6+0NO|iul^%mEY^T zt4+|ztk0r z)qa|EROZd(O;+}HFWb*FU%qIX9QmM6F!r=9#{&0+EiI?2~i_~w~Reru_>iXr^x9{2gdBwF#yDhW3S1dl=-F|$}z2K17|McF!*IxB? zs`=`N|6I@h`?vg{*0sy8qYa(q?}w*f&D(#!Tar5~H8JR=!I?GhV?_@%v2u&)L~KYn zIM^6M5Lc-}+~y5&;WVf_4>oPpT64LgsU+&~EQ3}@F~1p`j9zyCnEqUnF%wk!dAj6beWzu4Pv;FJ( z4^J#UJ9~ZR^@r^n&Of+tKViZF1A+L2iHp>3GBB`A^mK6yskrs#f+^#X01<`_=hOPm z@85pu#>?JT7pF_xg}(Ui6qqu7%|uR#=rBLVC)KGZC#iZ*(@DWWef@p<)?|=^$W2fs z)ML!Eb-A``szBr>y&0;nuU6YfhvgaXezx$b8js7xkH)h3Rqt(=WqtZDzdco8jiWQ4 zAOE9ySytaOjwFAWA>$<1^YiH@iR*vfUrc0A{Jwj!^QMzge*1uU>&d8|gKF7^7uB*Y z-vaRm*K7YC?%kbO@%>)w%oDfDH*E8Fub(7v=$}~J;x%vLdKzCf`KPi9@NIt2>AU_^ z>UO)xo3TC>si~a0Em8H~7VZh0EyJjvGE;)jec#lnOLr)q%U}r?=n;L@y2h%_DTgg` ziUUWc3$vn9f6CPtn)}%tFYs-%qdWWrm%W*j zdi0`V%Y_e}?Lvo`)Aji0D*2pHj+_{jaOCcdsyEA85{eGYv6*yqeFk7+siM-N#Xecic6 zis`b*W4^g|_8~dl250w7N@e%<)C-$dHbJd1U~>4ToOgC_Vs|;6zS^F${hfBD+Ut(W zEs-maI2_z}^3cppn@awz&7W-g`8{7suSrv|brs=ZH{xjEH!gUgdlNjC0%?<~sB zeoxKa^rNG(t9EkeJoVL$6CSngev+z@D}KsL;fY{NOHIw)gGP}uw@tESkI#(Xq*S|6 zPg}<9*}m;hle^X8m9#(YoqzRu;Y>r9!^B%#56_W2DKp>O-4^*d~`(F(Mk?++SL* zGaNjXBDj6V!t0ioJ@oE=+;+HQ>PaD{7d_RyZC})iYqU1T?bW&Uw4m~P%9lIbClrJJ zJ(;$oKK$DD`Ompq^fyb_)cogEx2gO4@9pRGP0x5+v{xowX1%(&C27(mtveE-rp^x5 z<$(T2ff z?$p}%s~E&|A~qx(Y+~geY>a78S3%tdbs-DHot$E8rfrz^S^mqKr!IXS5n7j@2g8bnIfdjJ_#H*}dr(+f4Y*cTbD z^1jK+kdP1+lDz2i)4%ug&Z?H^TnLvi_`1O4bQi?FSQNJH~q5zR^-FKNqM$5Yq|pevTw>4*S4@*)B5$|41M3|C*QLd zUCJ%KxN@h--Rs{2uE$*QTl@H$N$(x;Ts{up<)>+TDZ}XjfS5+C7P7}%b z!Vq@W?sn5D#vcXstK3|6{bzWPJo^fpB&URJ^NaP)hqWGjD`@KVj#$SN6*MP)`UU65 z$5o@6r@Gr@n_jJXe!g%?m*H3QGhzupM7-j>(*mr%_1r#kzrAg#&W^C>%a;3XuR7wz zRazu2G1=BJ>-3v<-=BD$;ht^z(d5$gFJ86JJ_^r?Y+|a{{$w`$D0hYD#Eua4jgF@$ z@Vt(ZPxu!egK&DX&Z<+jbG z)4zyKyL>Q+amuWB8x;1nsjhp$xu!DTy(iI5c8%ndMN73E_BV-sT%Q=rX&r98s_S9S zhEIj1sgurmeV3VL6yl%I+LLl)r_kn2Cz#Y5wr+9NS}X3us4079ePZYjz0%K1-mUt4 zeXrRR*HxNkN!zj~9$q3NeT{3%ySfPd24>@x*EdXIZ4Lr>U967T;clku<16Bro9he>|6iC*6eHBPu*$955GwNC2;LS zx|M93{p9iwb`b}fSh>Y?A~qx(9Bd3Bh^tf~Zu5q?a2nK|2b;b+M_gVWz9h5x>#mT* e-uYio9aHuF^J&ucKWt&3^2yWH&t;ucLK6UAH#f5Y literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan-with-arabic.png b/crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan-with-arabic.png new file mode 100644 index 0000000000000000000000000000000000000000..28a2a589a4674c504fa73368ea0f39ea266d62ab GIT binary patch literal 2405 zcma)82~bl@7EOqX0tQ7yj1V>vFky=ci=qM|OF%@H$3s9N39>{)2@!E4m_Y;yJNScP z{Sy}R5FX&5g5nwt$YSubD2Vuhd_j?Y9pOi|CtsS7bo4QoXl{O#->s3 zt{w>MmHm%cCgX))-Kx^sy9RE~FrJQvRz_9b8-C2Ynb30hctmPtY(f8rw#L%|8#Ipx zB*oFa5s0;JPIfk)=iYv9cR)U}UW=$g^+qk3ckx*(x=MuE;!utBL(gvBu}6&-Y-V3g z({;|l`!IsEzC$(bzW|!b_>oaf6MZMpx|*Nld-4xOO0ctIj3Z26-@@@XVD+HPC((n_ zFO z%Z!x4tunMpH&hxON{>|%pvI3-Irwa=EM!FpbR;GFMX~>NVJ;1f*%1bLUp<-;iYEfM z&Z!G}Fr1lgWqM7jSZ3RT8pliKrc7Z6m}@WWlSFzK#m;EvXnNcvt;zr-)~W>i9fM+Jb)9cYBS79YN8p38KdD^*l0m%duvpt<1M3!{>z@DQePs+U0GI zcMNxGM3uH7=sk>S$V}M1fA)0cp3ZQKc#+kE=3T!;Ln+KOJ=+th-H?KK&ga5A`>olf zs7ph%t+4F?+sGp~#MuCY<4|=mxYteBg=A(K5!mTa3cFWa!{D+Hx`#rxR6eQ{R^Mxm)g-Hp69Un-rh3nOo(?_d&0VVX#0Vr!P<1DEVm8z0nsCvd$rX|}C;3tN zO|bNSzH2HUZU@T&49;KPm8we!AOgiKAz31lRw;nRLsH#7AL~r@;bb?3;5jpr7h*63 z@Pk0jBWLR&B@1``5BXqWyORf;L!MoJsQ&w0A?kZpW0Sk zXa35{%BNk+Q(p^~)nf0I4q%IoST}o{l7!@qvme+(av<8;AlSE$)=w=#f-`x!?&QKm z@%04%c2K)-`FH26`D#IFoAag8aAZ3f+P@~WP@k0Zx7nA1+4EEbdiomlHbf=tdjI#C zw})f;4N$z=E$Sqojf=0lmu~YCsq^~wb``|JMkoYYdUZyZ-TCzB6S-0tyUwPS@>_IL zG3@S=M+9UzeE6~h#+e$5moj3GPz?SIhIm49Cy`)4>h#!{%;VZp_x@(9PHQiO^9hg0 z=h0V$=XX35Ha!l3NEr36TEb{UJfpLcYyv z)XH=(2qPQA@mvO8^6Nj>bgFJu3sw`f4tmeGe?HauQe{s+IArRWs~_><1p z*LKhKe2`HDjrS}tq-1aKHbK>--x&Xf#vq_?Axf|#EP=>kt4(DZr{?$Q?6Opz6ou{d zY&FYa`{jqWPQ9^6^OfaYi`NvVi?~I(p?IX34R+!52inqvuIEd`!k#aIjh5C~yAGIj zfmn-%#v9F-x>fwDBCpHe!)pTemG2v36A5dLjWx{I2QN>&q2_y!O%At`fN{Uwr(2>a zDLgfHFTrIu*Up&1(an=+70krD06k42U-%9kK_9f;*AFUn^?EaHlm_u(Trpv;w<^ZA z{Fwf&)z3$`X3aa7L_3?S3FQ09zzx84P%{i777gpy5rG;~v~M7>li#wBEPrzBPIYxJ z_)alWfHGTc9TPlaP}d7?Rpa?3KK~Yxa7M9RM4?)`7W;)Qy3RJlUK8)SPy)zvy!yF% z-4Ifb-!_8d(6tj~(u%&*WX1ev)(qOB2D{f!ay?hFc%;dfBgM)^jfA zH&+{tG;#0m7+rZ=L`AU>s)&Gbr@7@=EP}45X{q(yf|>u}&;M@A|MKVmMQnfAz3Be{ n4#7o!@gl&-?R!y`Iye{~9yQ?B~ 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 TIwkq`qB-(#^LFL$CT08wu%M2i literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/start-on-text.png b/crates/resvg/tests-hinted/tests/text/text-anchor/start-on-text.png new file mode 100644 index 0000000000000000000000000000000000000000..704550448ec072ce89011c030dbe1ee0cdcba23d GIT binary patch literal 1442 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 SKH^_G0PfBNr^e&-x%w literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-no-spaces.png b/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-no-spaces.png new file mode 100644 index 0000000000000000000000000000000000000000..83c0ff98f49e61e73ec0fe7ef62618a98d03b56a GIT binary patch literal 2079 zcmc&#do-JA8h=A4H7Q1^P-SVcLZX-<)Lq@nL_}q!4G9uenxb@FR^yAPOR0M?6T{HD zRa}M{)mF!?VO&$RB~`UbY3a6$j*cn5P4w){IlE{7+jHhQ@AtgF=lA^1?|uGyz6>J4 zRSu604;_@@B#L)9SnEDyRo$ePi}92nCOJRore|X??*)D#IU!kM|!uTo442Jc(3nl zHcl*Fy1kJveAD~E>*w^d5q7i(J8;v7^10_t^yYEm>KddK3B$Px#!2=tOry6p*o6Ur zB)K~|oQ!+&`hhb7A|3$EM*0t^aWL91IX2a>hjf}7>T}d#!76-sPgVq(fM8Hs7z6n~ zH{rxt*Q4mauOBqag}a?yp+xe31JSwsX|&GDz$uR|1CPgo(Rj?QftbJ&QAK@h)g%lj zyw$aNLw1$w<~@a(iIfdofVRrG5?Oe%oJlPcNgM6u3!NS(j%+?dNqN=H8cjr3u2HOj3m^iLxm-yO`=<3^WhwVbua}bssRWby?@j z{lz$btoKMw9BKYy%_Rl3{dI$Rg#@x`0}q!*Deof{jj@h(gna3)6_svav^O1dHB4(o z#_Wkw_9iN=s@*KBiZ8=HWjT``ylR6jIY=$4%l+<+S}(5X{rK#g6rCZzE~Nl; zn9>^*cTy00JLq0zw}%||I_)TBj?Ifw6VjW|QR>37N*`r4`PP^8$%*`&mp49LX&mR} zjpW%0Y%5N-gj6O;sozKLkG-t+nX3-gs`!=*(t&5#?fqSd5tlFHF-GSSMXVY5dA|=7 zjK$N_o{8oqNS*in?;HAh=EB|fZ*W_h| zdQb9{a@DBY*&f{>$3v8ur4>>%>zrXy$w2;Q_kz@t4-H@C(vm&>JSQ8UQ*+s~=sSDI zH`SfXmGO5|U0Q1Q75ixCurgQ&qA4vdOLg1I21m@CEC(u|`di`GWG%BYyN~B76T*A6 z662d{3;5dY9a*h(^7KH!|Ms zuO(Xc=R)Jn?t6DHrJA}`pS!vANTD^TWkI&y=)&WQieL;&4mEIPL3SS}`%~NM!;hMC z`FX124^tDK9U65O^>#ow()UiD!oJX-_@eYa!Sd&nLN&})7utk%I5X6IE4bUV!xLSF z{5p_XFur=w`#!dgA9?3Se@*d#Wy-I{Ss|xm%0=d^FEa&O_hh{K3V*mNKlO<~G8* zxCLX@Jo9ScaDNyr1c|Mi=yYvS6)^L4;n2lXU7-;p$JDEutlKjRo$C&FTfFb_-f26d zXq+u_c>B0M;^CnnvH@kzVThscD|`!0wB;jb-E}faj_ll0W`@nh!e!&^0>6uZO#GbU z@=!UGmy7#KE$rPd$IKbz_tS}kpZQ{VIBja+twDU0)Zt8$v|PS<+OXLRPjqkWph2dp zm-jlg`Z-?e+acx*w>W3TDaD?u?HV@BGP6ZcjGiIi3GOnNaCTc8hq_RT!Ua=B@xqPh z-03N1Zz0f2_2EYNsr??8UY9=nG4y$3`9C9k+_&z2zxL;jYy9E}#{vsDeVT@cQx=|V z|1Gw5XF~WT!f4_4tj>9?V73z`uz9de+-6_mnx?NpU+LyFJZ%Ky$2Ouh+BB0_X;v|G z1dx?RG>;h`-=MX|B&UH`?b6@YCI5H$8}~~`59^%` SKH^_G0PfBNr^e&-x%w literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline.png b/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline.png new file mode 100644 index 0000000000000000000000000000000000000000..142b6a4a995356020def72e313f76d17acba589f GIT binary patch literal 2237 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 WXzflmx@T(RC&$JDWB$<8GxDD?qCR*4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/indirect.png b/crates/resvg/tests-hinted/tests/text/text-decoration/indirect.png new file mode 100644 index 0000000000000000000000000000000000000000..8106c982753876a183105f7d89522878fb685647 GIT binary patch literal 1503 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=kzC&U#2OAblxUeCsW9RI%UuTz0nzL-( zoXpoti{twr`nRvopT9oge!+);_Xhjx?f*Nxjr;YCfq`Y8r;B4q#jQ727}*Xx2((?y zH4iMB>^A$*jbAy%Ac|PIsmq9pTPhZDduI?Qx7eEhhhJ?~wGp{?i%|K?weS! z+hgMDn)l(ox4@q6t1zpwc52p$vI-fx0jp5Q>{6;OJ zQ<-L`m$(I2MZcMzTIn9P;X?8InF1GV8eG}uFuF?I5DL3;eKL>k{lt%TdM+Y~D&7(9 zTOQoHP}FpF{-ax>4=4I0s-C%Y>mPr@*TtQ-UDx@-!lH^hb7nM{e&_Fe*>boiA#nps zRQml_n~$Gz+1QB8(aT53e8E>vE|m``#eoL z^03$KjRkTg(%Uw?a??2y-nqGNE2H+cX_G_OWPZLa+rFzerMSsH@0eDpU()P|-D@L) z-v*sX39h=|(wZJ|F@e2*;Ulxek9$iOyS?XKd@tcugt$%Vfz7(k5h4bEYmP9zS!jLt zsMxf)0I6x-e~s68%1?Ts)pq#MoVWH#Yvb%6-<)>&_cp_g8UH_iXUu-}J$P#2w#O49 zZUp>aTsni5+blh&CgYTK$k&F543qVF8y}wDx{sAR);aF*o~fD}J}ii+SXTP;kjlgB z-?P_>MuDC1Z%+KU@7&Jm_dPc;tho_Y{F*|K9&TOCmcxH9QnzzqZZ=79e z{HyLGFiURjk2rZrOJq{3)&06P8%$jzHt_LgfBeIn2+Fh6&6*S$$O3T;wAc_rFJW>e oR!3YC5q%voYg0vum}zRd=&vcaw6ajg8%>k literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/line-through.png b/crates/resvg/tests-hinted/tests/text/text-decoration/line-through.png new file mode 100644 index 0000000000000000000000000000000000000000..829521b232a0a78a65b2ee62a76d8e033ea78323 GIT binary patch literal 2163 zcmcIlYdDna8h({SS!+<18AVA*#yAX;s2pO2nZ{6LN=|(tB_^`uF!PN=&WA+}N`z*X zupCCD>|#5#3?U{-ta50k10ALi!mMwy*ROr;UwiN8y1(bSpZmR^_qyIc&zDRl9Yo1) zmIVNy9PDjf0Fc0mzjbR7g;YvAh%{s}@rWJLiUa;TBP8~3&JgPi1_Lkv48vj%41yRz zNGlGc1>gkZga_mP!diibt3W>97@0P}pW@X=&v|_VV)f zhE4|uhlGTN#n9+*Vp3*S_O+rL?8>U@>YAFn_nKSU+S=ONyL^;)&Q-u=SQwC%TVt&{h++H*b8xqMrlkU7pAC*0PpxOI3JrJyzPa%eqKsbuMGL?H9!(^F8I_pEV(!PP!TIi}}P*Q<4l5ux=RV8og8akZA^4wz+ z{7z_OIpfdUnxR{p-@O|jZnk`ByK{U82B(^hwMa61pm@^HiTSiO8Kad)2~e6ac{2Xx zMk?oKqs4?UWZvG@#6@coA~F4DmhD?Vst`L}p2ubVL5!1>4b1yeg9@Ug3#{DMm-6%1 zEgQE6SR2|ncMf>#*-Rz7-`wY4hV@_;$xwduYc%8&YrH20rgEyV`%&E?T*99Gcx~vD z{(B>Q-=~O9JdRmhKH+9b6JZd{(w-}EcX$8mjl*$&e2CJgnFhB`qfWvaY; z%~QjLsXgx;Y0zNQ_(c2YiBuzV)2$}zg#K}D#oB&(+rcaq3YI;=qo)hJ#}y)RgrLJ^ zLynr`KM}c^xJ7|V(yQ!D<^|R6jk9rmQs^HEnx`_L!NeJMJ!*)zhFijWmCTztU6g(2 zcgULgBC92@t8n&>c0^a3liF_Rfd&5u#nIp}bLw;^z1O#IW$CT%QqNH*HF}{y|F}WL z#lUmxPo8bY89(1xuqA7k@Q!4Z4CHg>8I7_z2R~wfYM8jNw^R!A z5l>2Kf=a{eg#pIbT;v~QY@0|cX5S|?Ks`O7d#*tE^7&g^dssL%`Kzysf1s57s`_(0 zifK%7{S*MZ+`C&Gpvn8?jmEA_&h{fb?#6wU)Xp4CeKZ%_KN%U4=g8a<>0Z-uTl*lV zJ@239B&`a&Ls$E2Gd5kgT)&r#B|o!MPpD*-=qUF*EaMh5p$~!O1&%VCYDxG;8}1vp zGP+B&eS}=3omwv4-OirQt~pc6@k*1t*PZ1)LCQ~WT0bkRI9ER6zT=cmqDlVO z5W+A}+%uYfu5T< zDzqK*r=z;Ma4}}=GSuOEAk4Q?|5i1hWoUNXY?-AMySY0XCuEnlNFI|>BKr4tum8@Otxbc4v4cL>%D=N&`>J=$Zd~QCE3sK$4QfDl;buR6G()xyRg4hYc5q zau~m#leIU+DfzjfolOkS$L(|&8@9UEeGhdMJ0!LF>|)wkt?p6A9Vw2!mn42=um8gH zCa*Q@_l^7i2(5g{P_vBAF}N=>CiYg#8;BAuZks&3?mC?=SLiPH(of*-6u?ht%&M%w z6xY34(mfabcmW-o`1M?KeHvYOA#qG1Kg#!|O7fV6T8u`+!n|M*<2OYww>nkO+98_G z4K968AMz1tD2o~n$e=-sl|oC#L5cb0M7`@{H>`|oAnv>W&x-x8cXsFM=Kl|6*5Zs4 gBZi`t?T~!;C+M5*PW@l@iT`*Gb|l*>8}Hb^0HIa19RL6T literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/outside-the-text-element.png b/crates/resvg/tests-hinted/tests/text/text-decoration/outside-the-text-element.png new file mode 100644 index 0000000000000000000000000000000000000000..8106c982753876a183105f7d89522878fb685647 GIT binary patch literal 1503 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=kzC&U#2OAblxUeCsW9RI%UuTz0nzL-( zoXpoti{twr`nRvopT9oge!+);_Xhjx?f*Nxjr;YCfq`Y8r;B4q#jQ727}*Xx2((?y zH4iMB>^A$*jbAy%Ac|PIsmq9pTPhZDduI?Qx7eEhhhJ?~wGp{?i%|K?weS! z+hgMDn)l(ox4@q6t1zpwc52p$vI-fx0jp5Q>{6;OJ zQ<-L`m$(I2MZcMzTIn9P;X?8InF1GV8eG}uFuF?I5DL3;eKL>k{lt%TdM+Y~D&7(9 zTOQoHP}FpF{-ax>4=4I0s-C%Y>mPr@*TtQ-UDx@-!lH^hb7nM{e&_Fe*>boiA#nps zRQml_n~$Gz+1QB8(aT53e8E>vE|m``#eoL z^03$KjRkTg(%Uw?a??2y-nqGNE2H+cX_G_OWPZLa+rFzerMSsH@0eDpU()P|-D@L) z-v*sX39h=|(wZJ|F@e2*;Ulxek9$iOyS?XKd@tcugt$%Vfz7(k5h4bEYmP9zS!jLt zsMxf)0I6x-e~s68%1?Ts)pq#MoVWH#Yvb%6-<)>&_cp_g8UH_iXUu-}J$P#2w#O49 zZUp>aTsni5+blh&CgYTK$k&F543qVF8y}wDx{sAR);aF*o~fD}J}ii+SXTP;kjlgB z-?P_>MuDC1Z%+KU@7&Jm_dPc;tho_Y{F*|K9&TOCmcxH9QnzzqZZ=79e z{HyLGFiURjk2rZrOJq{3)&06P8%$jzHt_LgfBeIn2+Fh6&6*S$$O3T;wAc_rFJW>e oR!3YC5q%voYg0vum}zRd=&vcaw6ajg8%>k literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/overline.png b/crates/resvg/tests-hinted/tests/text/text-decoration/overline.png new file mode 100644 index 0000000000000000000000000000000000000000..ff79f34ea697d9a84325c7debbcf82c95a53bb26 GIT binary patch literal 2117 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 E3(c?!KmY&$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-4.png b/crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-4.png new file mode 100644 index 0000000000000000000000000000000000000000..f3966be6051474ab85b46ef019ef58dd0c7a1a03 GIT binary patch literal 2113 zcma)-c{J4PAIAw7MT8MI%gvH);#x{sTCOdI8Hwp@9oty0B9c8@maKCdnJ#0?){SAl zL(wSv)+9?|kTl{_86#`%XG$+tzSZg! zBt9H4yUch;9O8dkoPVk7guyL`JGVKg5#(a)NT6wtD5yt_qw#iajQ*VMvvv7XE6G^K ziWWgHz#6~YBuTKVoD?7|_cWRH2!h!1=u9UL!g7KYczkCL;~4zPPdga!)%0}BCwr_( zfAI2sY^!n7HEa6}to2O-aIAYJY%qP=?rt4oDiNJ7I~JrBTVkKRw4oZlJ>WjAdALvp zbU>7cDFD++(>V3-rOFpweq`IL;wXfawVxmEt4f79 zOo*7b7$1y3_Doqad=R3!&>s@mwT%M1P~RvvZ5II`kbf@ZywwCe&h1`h@2>RL5~>#gZ8!47LEdH>MN z1gI#PLjRD>Ma2UU|3oWN#NwEw%2LfswCcQt2GRspq$EtwNuE;rtKZ1iEKv@6vbF5l z>*gg(k}2RZKIV0o#vhtGU<#NxjkH!*V8P|KF2o+u)|%$2bhJymf;C@P`de`vM!-}m zJj-<}N-vV?8ZYJZ zAq?-8D2GEC**rt!#L`cUKJrhn;qCPEiIPv6As-+kGiq^XmWOve!-#t3!9Mp+b$j^~ovb)vbT&g}cX zlbI4Ab3G?=oB8f)*gWco z0@9;1bGVUVp3d@~JOIU}$&AR33^Pyy@KLLsmAZ^tye_mhtD4m7pt*$!)T$kWW=W8q zM;4U0_!$s%n0o4=WfxSeSMP6u&;5%>(~ZHvLs5Cd-Lf7M7tolgFuOtBW(~xGN%Xa5 zBmK;nDdS`&3zg?CgdRvR22K;3xT4{PwMmHq;4o&3E_>*5lD&ILnJ z^WTx_$sx}bgA2)2&Pek~t}gg0hOn|&0J?%@PdV+8fwK6Q*|gvtb8kl>s^Ik+NdGJ+ zthV;z`_LgvAtYocJo3@+YQWp-BD4^)PL5z)GfujT7FT)Hru1iAn(AJk+cr9%n7PjJ zMU-W|(3F;dg$lCX0Xy*Tkr$=UJ!wnMSz5Jr5A2$;o;ULbWNd{*)oiyt9D8*+nz3pp zWE+uU)GQ~W04Zdr$wCwe9&^b`aw@y#4Y(=e91?x5`2)Ap+gAd+_s}f}$&U=~1E<#K z(lbNtKWH3WJ0f0QRPy3>(lvPdqR7Ap8SN4SAzY4&4SH@o^siw#sOG%ygT9Xmdd4$y z1X<#2^9b@h5H>NTz@FkVIv&tj1x^SnC!jm$`MNq2%18TF1=adz(jaX)f#L zq_x+{TlPR6trqEos-QqpPzCv6x$3D8haHff_NRi9-!8Uc)21miqf+oozPo2I1zK>WsvYP;a) zLuVdWPGa2SN-SU`P8hTQ)n!K56LM1QV#`EOe>pIQszD?u6!u$X>f?ee;^+=|@vct4 z(<$bD4~p{wIwodtv86$tq4_H}-06|D!$Fs3)RteC^nBu;LfSCNc3G?2C;An4?&WH% zt!$fc@6xj=Kwt3Rshl0^EL6*2@zJ0uDjM=5to~(zh0rdV-)Q;@VfWl$W26tx$3mM!t z@2j`_cB|gjzTIE@qi>z=+vnWA)%~OE-cN7U6bbQY@c;k-p|a9T4FCYh^|yh8^=HL5 zFy0FQpzczBDW~PLa4=m(*eUzyu11`c0{hE)pA);w;k&ld9^>!izj*&!p+6D-9_57dKj8mC_&LZ&9?+?+9AvLjcAwLN1$LfeHsZ3eg>Li~tem;>C- zF-DPtQF=;7om>pY=%{0>ivFzC^n7(=(rAAbgJX4+A_zVCc~5f1g?!o5auaLhtc+x# zPI)YD-sEk3sV?u?0Ig6psjN`605mLHnivD{fW3z^jdcXf!LmWO`&xWy&*iOCs?)&98gPHv5nd>P*4sm?Ct6cn2ZMQxB0Iho%MOIx zk4fj^QUB(5x)IzsdMN2XX0Cx5(r%g%(lOGH*X+(xyiRRB#g9yJ?m2$3=)9bgTwx?u z@8g1N4D(aDJVUHOJR$)t6*Yke@2?wCC4|j8%`?DE$HSK4*~sQ1lTm6iq(@BNudmJe zR${oO=jj)vz4&2^OQ>=dUg0t}eKZ+4U!nH=b4Y!&@d^t$hYW8r{b2r*-nbvox=}0P%nK6`q*qRVso#;APO)b9q36}F?DVEbNKU7n z^LXp@x(bFB5R1PenJRTF`8QWTLr|_@X73EPrRdzVj0CrFNWgQRR1U${o(Y&`mlejT zH-Zi@bko&r3M5?OXHn3de2EwG$G6$aV3sA-H>+%_VBXs6W2Z@$E7`6O*grzWHw*0H z)s_gj#21r7h2AQia^d=}xPX8!yP4APGTZOr89HStXD>E;v41q5&2+a3*;U8T3h~Pb zBKgiw7wTy|dE3Ip(XJULTk1xA8QR=ONt-vSJS`Wi@&$V*@84$ zBTCcb9DyV2%tH;JibIJS zT)PIN)y>P*O#5M_4WAJL#<`!1vX#VA67)mX_{Egdp_{tl-HELsC(u4iVZg<$|+0D}h zcY>Ch=t6GWaiBlPZ?wZutld~$ z7l*iMhQ1adfTTFWrN3znEi280v(OkGd++m2`VMi=Z&K>nCZ72z^o?+0qe3XA!s-xx zIy5-ObxR@Sjv9a@l-L(8nUN>HhHfT~@2J2I*pv9*9OTzS;Vki(G`kbOVv6tHoQp(T zICZ^mg;hgZjw_$s^tgy6grBFB%|=@#W2SByH}1vU6(e2>PbX~9SysN^7-o8yBg_(h z`zzjD%-Qq7is;^xLVq*oacl}EaLCH^{uc|K=#f~c_?UIQsidh-kE<1m*h=}?CFiav z&uRS5;WPYpQa^9jJ~}n?Rrx9XWx;s#n2V%~8Ta^L|67CHs272Hnz6VZ|%yQ#-N*X8v__5vs6c_ zbpp~gH@LAOS5L)mrj7Q+Fg7@4_^rmPDG>uVmP z9Zk3~w`)+Cz`0JXLpF!}Iv7N)SB7G=2Nf0^8+i(=&{albOKFgfRps!IKvE5YtFXtZ z!Y&RB`lORJ^yJfCcAS+N0j20l9Q4pPz~x}^C>|3zos{HmtHJfsiA&w|cDjb*D?yub zRe4R=V|rALtvqq>7oL0`53$(r1=u;PlAC!K#X8LweMs$#l@hvGd_46Tn1?yh6Y%kqXiPuDM*Xj?W17;B$Sq#l~+C^yaZz`c2JF+-k-M<^T~S>>D1X50T1V z2evl@#&W2tkb@0jmY9I(!$yw;YFyq>IQ$6w>G)(+f^0Yg)lHUr1Ul&`!6GE8kO4zV z3kpm|>tRvhfHw+WTS`(ry{$e23q;Z`hC^*BJcmE_r?7Da0Zq{)&{&Q}N5btdaRl8h z1n;f<-SzaKqLMue3uEbC6p8cYb(I6)WzF-t-?L~cZ{KClA%@-gF-M@v<9g}_pckj0 zlRPxA8R0JE@wn=NsFU3FG(SP_b0PCDFy=tpMoO}!ZurEiGOr+1dSgX+O8NSVYTBBy z$*o~b9G{S@eXx@a@G2yo~7TA&p^{+9FwrQ-=f!&iFR3*Tkz&65uwwIqdhdu{-U8+sL&EjJ58I3hBm`9 zSJkBp0`YE#UpF|P_+OZ0u|1J#>+Z7Qq^7xAD3OmsWI`M;WpSZ+^?9tqu7|Z$<;JkU z_!mn{`oyvZ?hIz-Eu#$%_=Yhxwt*r5$WMN=hLA1A>b^NjmS=Q!)QT8~Q1qc(`7r;b zkfNxK&%%1n@?2^qBo4_zgbLiQ%)UvGsmN7QSgh?%FM;R2EjjA>4Q=-cu<+!*uDvsK zOol4S7eQ)IJ|b*ng?C7b0Ofk3|3C|+P@r>A@#~JYlyhau_pEDDz(9g`3qHP#2wwrH zTIg9J4BfC4o_Jo=60Riq3xs|jZ1D@Mlkb#eW0)qMhVP_}$sCs*w<0TkdL_hH!OKiQ z^XVn8Ffju^A1?XXgq5ZM%HEd}4p&o5aL%v2)iWDFPo%HM(USX|*=- z5hJ0BP`{u>i6kXo1Z)Oprx4)}r1(@j>h58)`IXk=rOcBvRzugesIc35ajn_{|3#Vr zeyLBl&7A#KvXwl{-+TH3UQshd6L7UleCUSY?_Ig{v&QaFN1mKO;aPR?dP(#lxiRA4 zwaEmT!v2?&tNI=9n)+^KKL8Jl{7K9uan0;q_jkuRRg^vIgP3zgcbxhgO4{u&=PYw= zOj`_I<5S(cj7l8GO4wgGRKEI=wlFhO&OQC}thdCOzcvDe%J}lu6J_SWnRdmcmJBG{ zI|Yu;BUO1^aqiK9oVag0{$%QL4Tv^3<`Tuijl`|#K()Qcp26DJZgB`<8D zTJr@$JtdFd+3M`m6s!O^RBXdCR+rYRQ-j!}I{qPTY*7*f*g;VA71*`I_AOK|svC+NHB-FilJAS1pD0a5~=} zkmvS9CLYAbrA_Kd4`9gZZ4z4xVuG^y4J8aGGavvws`>^smCR|4nlU7c&jhK2cv(i* zx~xa1nSa0QrP1LN;TUVTFQ-zTwX=em`6LdsevN-)N*2zbw?faM@xeL=C#Mk$g1y{3 zvnj#Ag9mk_RgFrSN&|sD6X2?@D!1wq$j4xCVJF{iDnD$?^h@S<$=Na4F87PXYtb*c z8Jk5;UbVpKWqbxD<5)hwy(WLZs}FK$tvt_u$xJFLk7Mjw$X3OrG~8U$UbY2BAypQvD@4IU*!U(cuDu z9=y8mH^hNtAdmrHX2Zk7B$i~0zB0lrDxZ3>%fCf_2-VK5tYxyJFTwyiTcXeX(2T@R zQH(3-qZ?8ZGURF7cXUSsqStuszefna6m4;1PmM*CQ&wMPx~22C>jOyoYahU z4i<5a26kHFgj0H#g~AuVujt(90EU!Cvg!)P2BumfER*gBZ!&D_te*;bRQys1)lPnr zq0&mk47bhBY*0jTh-r|7P^d{Q?K5+D=JYvh%JbXiXR%L~FbqVg5EouGk(l3-sk@Ia zlrnE;l&20Pl1?USdy7YfpGTrmu2FRDWJ!|OB;P*JjD19VXreBnR?gky&JtYg{F$We z?$H+K&&^W)OdU77k60tmp0tQial&l51MlWSou*7jp(i^}HGlmW_z3k` zJ8`UjR6kOzZy__)yJ;oR+fleUiTfVT+jhW=Z(pjhy@l+d(Gv(YVZ=KYz!$ZEc6VvM zoZ{_(F*KjGS5vJl2Q&GnBSkQ{P9`j^RFug26REl|0x_hvd)`KhCJ0KZ!Sb$Dfs|i0 zq;{(!S$O(Wal=}}oJ&VN_-V2~H5w?Hi4{AVP1w_xmA%>W(xhf52=3fp5zXKgv2r&* zR^Ivz`t3SMUcY<%^ub_<%(*AFkdS%bI{xX}R}X)f)HXzHvnO&&rU1*vABUV$FM`y} zTECH$-*B4pS1fBpU$z5*AQQXavmD-LOa0IogkselM96fI`#g?R4rk{x% z;5TWXyIO0fL0U|jrirpsk7JZVp{{;=51`F5RwxI}m`@qu>Ys??aUdsW{I5~Arz5Zl zaj`ZkavXbfgyl5_yV<;qM$%e9GCm{#&ut9_IkXi2F|sRyl@h4hiwpA-bH4oM@34TR zaQ6i6ucolOD{pcK$FK~A57cd#02*l8`88YurpIsxnYeXxO#B$K5|2N|dWW`H0`mwbDWOcYnYaR;$OB(Wt_iqaty%O*pmeSgh|`{Z{7c7;>C~HvBcqxT z7EE2SOT(ghtMmgtvDxXxex@ra+nvJ~pY)5JS(-Ls6oh(tD?72t5yRk->mZxR$UxVH zMgOrUS$-Rzcw3kPQOK;NrNM=kMZ>8dQe}yc`aosU$&Ie-Nw3wM3y2tIa?tJwJ=KR& z4C9sFkLT^D=j}A?g<_w-tTdu2R?TGmg4u>?lr)%eSoD1K;nLDqHR}?5|B=Kz3PSvH zmsXUL&dk@>cjRHn^uD^qsL`DrNRxTtz3er6?{|ja4%$xEHQ{f&%sD_JB}Pz~TBTYg zx5%D!VcDI!Jg`7~(|LP)I|v3&aNtJ*BWi-!NqNLNNua4nw}~?F7BuLgx_+P*yBYGnQMdxP%hM-}K|Vg*rObmCX0A=wS@yfTTNqSy4a_$Tnq-s5wr zdl2F>@PAX$O9kDp-)r8!xU&%d0M2?uPP-NBb-bS6mAk*SCpdcBQBUl`B*y2tW_T{W z%&^=Q6`;A(EJg*lAIy%Dii3|$xTLv!bZHh^nG4&w_1|0VGLSG(ciw(avA8lJU7+Zb z03|VJ#_~nDEQEE2eW)jLlA2##XR=;-s2^Ff^icer5OaNFMgf1Y?y#uNT}|0*Zx`BJ z@pp+`%&qYPc=|Mfk<5@FP`RN?+I0Ei=>%^Zz0hUbA!UQY_4Uz5kwD22YbX4uH0jywR9H>Qt^`Gk zOT~lS-CpO5`=Hxj%fE=xA*9Jlu2Hm!_IP)GY25ZoVa=CDBk3i889R_K>EvTIoCP4c zo~MZV5wZn zil;-!h1Ns<)P0DdDun55Cs>zKA@Bg&8m4qbi!~#dU>s}7f?~7MUnJ5-z=3mzal_sP zFh!H-sQNZ|vFXoK45cP0B$R6>ycES3EyLu>BUb}B0vJ|Qg788JjE=fPw$Vbf7)r`eXjW82EqTM_m8R`7dw$f3FfE#)y^P*r)iPlWo^W z{~uZc|ER71`^HMKz=MwlfNO0i>={vBTzQYJ&5T9f z1It%W7srr_TW_vyWjt&k;^6pLF6~bJK7+-(8s1OU^8d0phsP(<#J@4~Uc%L4hgIbf z#Uc})r6wM1V&xXofshekcEko2ph(1q1Wq97$pc|S6)aDHGB)60e9~JYb8TB9S7rmy z=r!vPth)62l&oLn=BR^Jb(h!{GlR^=Zp^j$30oh}+WR}8PneC#Ku20JFy_+ZDjC`J z_x}GCT4dWSo~UWt_;>k^>A&5AT6XmO-uHUf>VKP3*IeJ|!x#MXsg+prOOd#+jAKy; zUnNHBOPs#Sy5p2;vaUCycbi4mBcTm5Hj23>SbHUA^Cw*HaSgIqwPnVtH@~G$My&Ik zu_YT#XE=J;~g{%^`|9EE?+?K@q$=CkfrZXM=%Upl`2`(ouQcKJuLPRFs# zABp=G&KLKezlC{?6~}8Hd)@M2e(T81iwtxOcc?AWi3#`WQ5Cipj6SZi=E%Mcf6B|Z z{5|65lUeZgV$>h~`L|;qMC(uMc-iM;W)ODjsg^~K)af4^Q{2>&-u=7uSZu?ct^ZQl zH?~w+3VuDcj&WOe>vU^&{cBs!u6RD#Kv-pSs*d%}E&-i6Cl@U9oT1^^wY{hH@X?lp zhyN5y=dDkAIc=lLzu)fMFghwe_@_$^4Ze@jM+* zf9;c$?DqI7pYYd*ZNsBLPM_E~Q3i*N1qxRDe;Bs)yYg+_wNb=?eHz>FIX~G zN2s4zc2{#+Mti^-3BRQer@x+k@X#wBG1ZNWBG{HKvQ0|NjXAVN=UQKF81v>cej5#v zUuB%p_`b}g z!u~5<`+5K6TG7hKKQ7EI-LwDjcKL)i5C2^M5*(3Uzr25blfCH1b9KJb|E0z1Yo(0D zk`2RHl3(U+y!G$fw(ntQHzsV4U~@V&GrZO2_sorPHAQ-V45zWoe#UCIfcb{rhey9w zrmkryyipPx&LDB@6Q6F+#yI`tH6K!VdPL`0sWqsw$357)QtQ{Ousx+eb{mQ%|E=jc z8j-s{>}bTp>9?7afg&H7{x6la+Q7ij*2oZ%(#sQYvwr_2PC2ep^Ft>meNCUH6S*nn ylwd*1aCaNTfQ19iUz(vH_=^bEQ)xlqpoBMES@6Y6A-k_bRuQ(hMM2r2aArl zbc$5)kfwd1LJqp^NLkEankDkQQrq6@%Zb)#H04)(_>jF%^(E}6%vD5G<~5|=q%s08 zOD+tAA4<$&jCesWh}S_tM4?cLM?^vMN2U?{OTHfd$p4d)fQ)h6ls#SVF7Zt%;|xMK zH8MsHW4useGR9yK{@-$C&OcuApQbsC|1!BA{&?_D<$sj_UjN7Nh30LCa#x)VO@8G| z{0^%(EYA+c4Ih;?96H)>Sf{hQ24ri8fcDmrMXcY#c&V#r zHxC3OZ$Pzro7qlIKfb7ybT%OFOI@2u9c0N7_D*B|GZ~|GcsC!;cITDVQq#6fLJ+F;fFttbf;ILX zUrKs8Upf~$KvHN-(iSw%pVV#j5tuCbY}C6vFBASqIX~7%e|n%$@jkBt_-#1>v4ij( zewSoUH^DCPi+2xVsFN3y7L&%4vU*ythHu!;58UgT9O+a!4T>X7LCVlSNC}i)8@#&I z^%rb4xHN~(wcA8SeI{HIJ7=ymZgUxXWzptC20Nr7_s$LdePf;&WS|mt)J4YIsgn8v zx)*()3yYmXQD_mjgsR(rRoT<2YJdDvlW@IyGB`tk7mptn0=t=$eJ}dy&l@tYtV9$S z7l>SHVyTLL)6kYGMbjimHnIU0Iz(nm)h(M8?3)hPQZkbFH?p;1dcvNFcVpc7!)3$M zl@4r9EBW$}-Ysd2swAVWaF%UkFOv3C5G&Q!008HHN&tp%dPz@{Q0t_$e~Db==YcPE zfbQ{vnt8pR`GXXTUVUReP$ZDtr7N5&KlR?s5&%*BaCMCjrlsVK_sSc&T{6q-Z_nn? z#gvd2{ zYIZ@}a)l|t1-HoPc;Luv&7->PJn!(@rV8{_^O1Rr;f1YbQ&JSA8d(tFSJ?H?}yVWFB zD>BKM(3?`oCmjD6;P~S}>ymuekVQ>~I1U&1 z`s+#SSUKISP$HEQqCk?YD46z-=UnA=ch=99a#`%7X&zr)%AUen1UT)S*e32;oDjHu z^=&o&^i9oKfgz|O1on<3{SNU{xp()A-wRj~QZyQ?kJ_2;(>>6BSInKgh-X(jsAvx= z0g84*zid67F5G`Rcz!$1+9>$NaS5GQMym#@DB_U(78f5Zq>iPDl_B}E{!-kbTo?{n z90+1V6k@qGCC82eVBSoPDmVas@2BTlN{a-}*Xvw{ z=ywm1j6Pyy;j1OQYQT7kGC{3 z(uk8eH%30ptRIG5(d90^9VU1+KD{fQKS867E_{a>YzXsb4qUvwGhzd!vs^;S_=1xv z!(Y;<*}u8ohG>VApW=@~Dje_jw4a>R`wBia4Uge19nj@k&F$))lOZm$UzsA8%WY%i z{^j330H)X$SV8zh+g-^%576iYOdZ|x9P-3M&km@{C~1z7c=98+jjTtx^BLpl91}-D ztF)KgwXB@tY+SwIfNjcI_h5VuU{8fi9gP`CPF(kS3(XpKY)=n%yvcnh;(C)gQ**D#vSielu+$K!}(Pb=A0G?GRwON0AfTOdj{iOQSeYX3+eD zrBHJOHyPOksw(vSWrrgX`p7d5S79^N%@+YSm3Mhky*m{ergbY87ptKx=VrF_+zP!TV5=}H%ZavGmlODu z>yDq|E48PUqf_{4Z~1_9rN1o(SH8Y>cx%?lY;ClevLP4$W%?q{TKhoz7^4_UK15vo z#3VR*-0 z6<5<6nHiS3w9|EpDrfe1_Kt$M@^A6q3QpAz;Ou)PrklXeekJHwxcXLeMA)?8$`}Gs zm*be39-0V{bxvFp*&^|II_decE%}*A0dqNRxXgzVPfjwEKMb3bY%<&B##tAV zgDJ*6kN_iOmH;0Vd4!p$&vYK|XB}!(Ado~cK43Wzo^fd&@;G>;h#SCp!F>pz?Fn=d z$uiq)`#gzb2m)XeaLQ83J0yV40>0+y=TPU>@ciKn#}#{AZ10@P%TM=h>4;V`4{XjJ z)oCH;^>%MHGi2%L(2pB9Sc%B|!p}H)(Mbcv744ulHLp+f-b9xnO2C&$tWInpoRyu~ z@m-*@?=bw;QnuWRn15}j#zjoCL5gwq?w>+>oH z5%yC>4e7itN&BTMi2$>dbJ2vg9C%-xdWoLuK`E3S^Lmlcf81p5V0N z9|!Z2(Im6m71j6>yXxC3pL1>D@ynRmS9-)%sqiQ|@vDtwFSB`6u_};1eRinbSjSD7 zIQV4I`hA&1)K=h!jze8F9>2UdCSm@^XuI|8_3j>0OJqDU)S&(H@ZsrU)x76}$!#pF z<-w8w*r@S%z|m=eAnD_|Z$eIwKiO|tv^~Ys)(el>VYOk_2uCJsyB|GGrgnd=H#^5+=g8X4#`SA7!VbV zEJx?*ZXLg7Sp}I;2~K>UMk3}Bs{oSCaoYS_lC*&-}$#DEtoBJ|$GC_vNsW_%y^|r4q;=^gz zvohK5XCJ5ptp~MA41O=dsqMv9?P+g!>@sntAi8=A0BLzRMNjx?SN*AYGwbIElPS|Q zoTFCb!*JP$`|Z{xRXBs1cAo3J_Pmt|lDMHg$z}ni2@MUYJ7uS@zf@o4*CqVoPN4O= zN;S8p!Jc7yrs2fgvd-=Genu+gMIWLNS9WQ4hUs#QwUO@)>=HgjuH5d4iMr@#_Kd#6 zIYuID8FxxZ8=XPgh%FqD^fF4oHmP8oa0Y&q;32QeKx+Zz8s)}CI43j{XKzL> zw5N8?B3}HQdbzNEzvW4zxZ#dCX>`3bN!xZ`0%YKcW5;$T8DIofFJHvimBZ?1CM(5y;jPYcn}*@-RysNKg`$ubU+caE?YDfFR(pBe)U+nLa zu_f<%U!4^?sr2cL8!-%AL}<;E^<}TR;zL1*O|E`(EeW8ql>%a1XrXW&_=Jh!O)hcf zi%&tv+shbN__MP6Gqw#3F>jTUZHNZ68)>ZcF)!D3Zt#=O#zdAy@p8LY&1=txV)uWx zrQ3yE8o}K9a%H5~Xy*L^i5GKRGutgg=I5-2HO@8PUM|(H{j{hJxd>(x$$wmF01^!x zziEcqD)%c`8BMq7l^?pfDX0ncV`(HeujZoBJMyJv?xnQZ#l)`=tGlpO<*TBgi49{d zi>sfcO5rEwYlq+L<@I9BDYKdmIP~rqmwN1Ev(;(U)R(*FOZlcTJ}N-Z3T{OHkO((4 ztB=QOvVsPWFgw(PH*29H*bpt%KK?z86W(F#hPy1q;j<^$>;j0frj`VNxW|s!NSQfM z?+w6LyfU=&tq7(DGjVBTAHE}AA<-Og5I}_H2~6EeHL#0=s$G|OdTY)UA5N_g0Al_{ zkSd@?$SA^TH?8fhoYg6_BK;QqGN+XAl)RQbh~L?}rpOX$T|^fFyX0kqZ6f_(FPB zx;X2{#m{tHjVA3{ZzpZ&59JN$)M94 zNr29LRqK_ z?;6TO-lWeqx0cM$W?olAREy8g?=3#r%QhR^oawghG4qUjPqpy6y z$XFp=#4*}O2I*mWZq!r1D=L=mzxr)3I@OiBZHwVqNU82m`F!Wrp~Uo06>mzyNYWid zCg+-T_*hG?rcMbZOJ{E}k=pgpMa(R)zV)?KHWtG;b3V+SIRcl4=X*-`e$qwgdG-yk^?mK_hJjAvUD%Q5 z>jr0=cl(9Ar9Ie6YycWO>G=-a)t%~F?Cw^3-=40BXJtHZT8Gz84Bg!>kx5i`I>lCN z#V-$irV=7ukb$(Cn8sb8_6FTiIa&mjo5&(O)3gJxGxj(<4i5>1P@E@yL#XA;3#M|Q66>=wM?KPy`4FnVzBSZrQQT+|5_6{WaNxe>B8Qap?{ ziH>@Ieh7i)!-r|zA|TC8Uo67Lo(RJJv~JgB62GDILoUu-Qk}ZE_aEnhd*nUm(9EG!c>Tb7l^0FiI8v3>m`n4BOyVq%`vC@ zd0mbnA}lQ|ei`&IdK|)pBi?_PK&xcLJZehMY0}v#baMPCYhJ9*!nH@luh#eQS6ZO} z(U8nR3w>bZ_pa|H9v>n;>y=b(m7d2xvUQ8l4Z;+<$JN|g$dztM zVA`s7LkrR$8exTKB!SY|Ixzj9*CMVg)^HLfPqIquM!LLqp%7T+wx*%kAhY!)KDLL% z1wwDbzGicIziyugm6d`3C9%%f>%tcl53x)@km z@c^|}&I|6oz;ZcgOX)vT;o058d<>{g!eL)u4N&%T{H|Hcdl&J;WPV@YQFrv^?}E|m zp8!)M^4r<5a%k*YRT8~=qq|^7x+8Gr$TKHnt>n)oiMJOXiDandcO%W!7Abi+!AMrQBNC>$7t!sZBiqY+IHy*Tr z&P13H{yPWvuY}ZpN4)(9vhAA1`cJGJ*^m4G1?w+X?O$>KN#gzQSpQ%M|6ck3M5*jT zafqV+g`Kpc`oFkQ$@hnP#EKOq0$)%l1X28;?ZU6EYQ+u?{-gp*El8z2ZZ5y3V(~Oo LbyVO=pwNEtcm+EjE|M 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-y-list.png b/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-y-list.png new file mode 100644 index 0000000000000000000000000000000000000000..141de3407cc2f54af0c3fe819d32e12baa01f050 GIT binary patch literal 1490 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`k=6XFV_8yXrK8ykTP{6JY* znU9aJzP=u)UQ<)k(9qD|-`@%hBqSu5nL#GIxVS(J0V;;G@f!<~UFdeD63Egm3GxeO zNQgfmpinR&;r@aR59V*UK4GTxBu_(sK8=A z0|U!hPZ!6Kid%2*v{v2r5^#9vyTxdE!OooSw>Q7n?~C>qx|sD?*Zi7gD#zcZe3oe& z)w|9}sf)}s_7m$7EHaUqTW7-ortG)~7O{wgMpiMb^xb<6SJ|NQU`0d|y02$U zOPK4evh2zB156;RqD&8$b#2aWTYG?OeJ1DP!={NKOL3dGbot|r>t2^1|E?MF?Bt!f zCAC%jVLKiv9KOaH(fI9AIZO5?>zS`6vz~r`;g`znWszxX#UkR)E)L0h=WSjT&v&W3%(i*z4tJaDT)Gm8nIPeP8f3O=oMode_xX zvw3NH&%LatFPE{b%-Fj=s^#+T<_?Xp_${;cIBB0d!+Kh0$?9t^!D|-2Nc^NbJsL`5w}h(2Jze%HF?8vi=-Ym& zzcg&b170IPC%_4cPXekRRayJhN1|EJH>dX|1Z{NzeN zWyq}ApPN^3S7rzwVLx5HvcLCu(%GoELrmId=cg1L3b+;O9i3MnyykZN<=5fc58HXH zpT0dV-?h5>cWe-|mZ^X}mi5SvPvldR|wZMFR>TiAzB#n0{sGKIY`%6=NVge^N|a_iRv zQvSSCUwYX{ZrHNB^Yr3>D9*5=eNn+O@4VG ztI2$==;EJ@YrJke>Ul zLSD@}uRABTCn7_f998A1E4axBc5gM^zcH*Gd s#ESxR{Z@Ndm+GTkJ##kd8EyK{?D|r1=Yzm2>Y%dG)78&qol`;+0JUj$mjD0& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/underline.png b/crates/resvg/tests-hinted/tests/text/text-decoration/underline.png new file mode 100644 index 0000000000000000000000000000000000000000..b010c0ebf36dd997b4ad369d79cfefeb678d559c GIT binary patch literal 2125 zcmb_ec|4Ts9)IRklcr1~+0s}VT+3vwM4iaxAj^#1gfUYycCwX7Gwk-=}s@UJBS&9-Rysfi^DE-e;0)PYn1b`R-C;(0a;0^#D0CfOl z0q_S%2nnJA&;?sI3;-Gcq1*Nn0Db^m-&WeO03hfHa1(e!o;V062}x=|8n76cEF>%H z@?v;lAPg)32B*Pc(Xd_6E;NM3Gw^T-E((kxV-Z=JA-$Wvo5&y{AcP*Iw>1?5fEXYm zixkWubI}fF1aB2Z&^9X4+!|>orGE>;zXdyxsQzz`h-vi=-B#G@jRU}RtH@w5AP9=u zyMO_r*AnSy?*vSRCPHD0aA&Rmx-Q(<;0r&j35BT5E1~1smD{%E{8 z`!th3C8!y@+mBmYZc9q`zcO&!yLPJ6; zummoJXZF9`*JCz2P^PL4i__)H+w$8j|8Fq3hc{w(o}0#bxchI0BH6&p)7U2-)HvN| zN%4}o-P3b(*P0aE#3q|oghFO*7Fu0Zs^%|2MfVFQ>v$19V^k{x0_v_>55M+O*3mOg zOT_MVCi$3x)J6)>i*x2m+>lg8KWx3U3J$iYt#&gfL z`=oFz;l%DjLgA(7>|7u8QSCzpxcU2NiF&6DGRT$oJZkMyR4oycO*)Ko9q0=2vT+E1 zc~9j{D6%jGSti%fh8V1#O4IqyHAh*qfJ1WT*B^)pKHSMQuOd72$v!llIzZLDA$B@d zQ>luHSV>@ell*OF5%7l`FvpF&ia}1yW64-6R!tlSl~{j5>NA;FgrSe3SFtv>V^%u+ zCAGIXaFgt2YX6gBd-l_e0c{pmSXv>m97X=6oGhEBSmMMw@=N9nX^5pN!$>x&8m?%P z%QIhh>$O3s24YukCl%s#$u^Z?15^U9@!3n61BM<6AvK%F6F9)2u{A9=R)rPa^o9kj^DH`t-iXTCQwX_sHD^N9$+Te5Bw!k2NEPqC1C zIEvsn;nR}S-Oxn5I)*tP8$9Z%RXwSo#{IBfoYlhnIn|JD#*MKPl*JE@M=NKjmi^TA zZpqs&WR!)slAeDtY(>!%AO1m^cggk~uCUi3vqBkfEj>MV0Y@?V%fnk?pD=G_H|!ywp~y@Sb>b-edp>wCnbsFRv^7IFSyJWj z;Hb!GE1f1C$#^!KPhSnw6JuhSznvh@lP0S z{W#9_j*LkTE1?L^hkC;HOeWldtJU{3}@!=={I?aT83sLI@rmUrMp|;%BXhXni+FUoNV~#hK7cN=UgJ z=s){(Z=Kapc_=rmaNm1gAjJe7A-{YweR+v$>OpImO`P0I--O8$CuYpQ4{wG)U)$V! zadpE`w*9fX0TyP}&`vt+~0*zr9#1Sl@gkvgP0{UXSpN&PG0ItqJ)?rxkzEHFUH4 zN!0xMr27qm+ECJRZhd*}zESwk`gJFjM*v~1Gk<_cCq#VBaj4GM={jW`6fq?HJm9bo zC>_{insmH#b^5UFLJMyGSizrixBgjowCeALqIuGH1Mj#8+#Z-2}+d Wpyjqb-lCrc0IV(S&1=j^asLFh{ILZ9 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/with-textLength-on-a-single-character.png b/crates/resvg/tests-hinted/tests/text/text-decoration/with-textLength-on-a-single-character.png new file mode 100644 index 0000000000000000000000000000000000000000..545ea2502ed90525eb4dff758ad95a24aff900ac GIT binary patch literal 1109 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAQcke6XFV_L7)LfA~WD@pkyOh z4N!z2VqoCeG)oYuMXDsoFW7-WKtRF3-XS0%zo4MLVZwq9`wyJIaR0&k4~mB^R2UeT zr+Kt>9i)%xBvU=-e~shJzvjmz216KkpFef=LdHD&fF2nrsc(1=7x_F zUFY4sJ9p#yMBg=7up8xbL)ajwwBV*Y-=QUn_S;;?AY(pFZt&;l+@4_`gk>wfnNkny*g;KUn>FEO+f~*Ovc@Yaa8et_eMn&8$6dTKu)c zzk=HDNJYe+$Yp;mvuXD9zO5WT*LolC(!S)pE8E6*dT;1)(M-0Ch^f6(BPOcpUCq52 zar{VENzHDVS4kT`#aoppuFw|Ku0I~vzA*V@MC~(!F6FvFy|CHUv$G#{=!<99|4wy_ zRNlAV`)JqW+PV7`a)1n`&o$R;7e;*KsXg&ye>+FC+O_ESO1E|x=n7}Q;*I!q)HPn^ z+U)oK+Y?u43cfyT{<+&=i?-nFIo~IUS|1gRm%H}r?%_i5wrfulk4lE@w|;!?XyVoP z{R>X)*5X~w>wNaN_`7W;Ym$E{zK-8%&>Qhzopr07yyM)&Kwi literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/geometricPrecision.png b/crates/resvg/tests-hinted/tests/text/text-rendering/geometricPrecision.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ad2b4413db630b045cf61777b8daefed303b3e GIT binary patch literal 2030 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/optimizeSpeed.png b/crates/resvg/tests-hinted/tests/text/text-rendering/optimizeSpeed.png new file mode 100644 index 0000000000000000000000000000000000000000..0f9e551163bdb33cb20d28210db52fc3592b854e GIT binary patch literal 1696 zcmb`HX;70_6ox}F?1X(0Mv*N<6A=eN2?`2{NmzqOAV7vK5ztr`*%W91MFh$gAjrO0 ztC9~00Yt>I$RYtWKqYJ<2uPL}2?+^c(b?G@<0QO$Kd>ICV$;iln?I7?Ek(ihWj-oH~RYAx! z;+&H!n5r~IQ$El{PyON@!vC&F*YO3%Bzkoig^Vmd0Zm+Ots9ze%EvfyvxmfXw}d{C}qG6h=^;uSn(^-!^vm!5hxWmgbLG+okN+`6BgB2Whm%y05te7d zJ{nxQ$|VR^RC9s5O1G(p9Z&E)%dRn-PKIIyOQ9jhrJ_DR#5xOrGvQOm8YQJGZg1&5 zLm;Qqhg|3bShAI>*LA+M8@s<(yBvtnI91z-!pdWLGaK1E_cLZ7M$}X(^^g^JQqgP* z!cd%iTDOsCM9o*y)EnkiX{IH}9YWZI<4LKk&C$6gsfy~ z)#!HaLaQ-`Eu|8?kJde`n^47+-5-vC0c|HaX(k|;?2wp4pA^)WDsR4qnTF$8KSn$Y zn45YIPqER&t{YRBZVzP~sQyjGjfJAKX*E%n1=L@nluFW}O7o*WeacoX2KF{eM;hAH zW&PCZ^tpBj1CdhHufd;ebt9GF4_vts0X*K>fw`!2J;c0)JXC3G^96IqO4^bmm%L_| z$-CBN;$4?_XP)vHE{p89%YAdNjUbqHZFa8Z*}1c@P*o)hBYOaaya6}B4Gj6rz00Jz zZ#Dr0R-7$Pmy(-b2WKbgbt<$jP!Tl+d1|&f$;9r3xp^2X*HFLoY|}g<(w@}EU!*~& z`?>MWZ|9Ij^u6TDcfy8Aw8K^MtKR|xEVHcpANe3dK5~~{X5ZRwJ^X<(ho`ytONNt3 zqh9=g!?rFNZlu(k%$!K--J3-Xfe*4qa{8;}5=?dvjHb+z?pq-N}CXsD_0XIdO< z)!>#MpMotrTAOt{WbMG;cU25Y+Vwo5=HQ21_E=+vvfY_8NxX!DA8?7cteENzBz80ekFO?n#~ zw_!O`vcw+?(28%D$OQ<3_Fi|(=*AHfxt_2S>0_}4^`99hu!^M3F_rMjm@iu&v^;;( z8IL4bdT@L@liuP?K!sj95INJDD zKGe?*)x)5?rl+}Ojd_Bsz*|S5*=;_}L$r+p=yJ%5hU{&Rh7RhwvF@P{*dV>O@Z*~7*)&8li2(p2 zRIM$UtwTas!3(hhjlpZ}#J07d=;^lHW}zRr9$9tN*OmNNW52s{s4VNNs-wP5{x*Mm o_l@b9#-S}0`}FDF`Ja3C3$YXH9aYjn4!d7I0qcaRwed~*6Dx!C1^@s6 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/with-underline.png b/crates/resvg/tests-hinted/tests/text/text-rendering/with-underline.png new file mode 100644 index 0000000000000000000000000000000000000000..5f3d9f55d4fe950360472be7c784619084377ad1 GIT binary patch literal 830 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&7G|JGckpC4Af*`K6XFV_;h?dxv7w;>!UZzw z>+6B+Bch9z04c7LAirP-1_Ar{g#3cpbH3j&?O|YGI^^l%7*cU7DZoswSc_EiNI zZiyXS3`r6t4YDtE+zvXjvoO55)z~IyDB|!iorC+6O}EwtjjiXe+8tQR{amxV^yHnn zZ~sJ1UNVQd?TP&Svl5-Mk(*LZPEz%rrW3iT%mYNG*zW!F97Mx}iDHy?*hap8d-PF2 z&dF6~kz4mEYrn4EBqfj=e64!+#wfMdCXt(dy?+8o zleX#D?&3pLy034YT;Q9$RVPya0Hf91tK8a?M2~mYT4~#DvT~VqdJpRwyA3BQgCn1& zMn&*i^chZfb?aF(@A$iIQ>OCjOxh&4no&06_r``5_K{~_F>IN+rY?nd-=VIfYt~F& zvu$3ew^**K_PK~!e=&xQ(yQ+ut@^iT{Ri#!Ctokrx1U#;|A+HDf9b(r-zwLCFpCL3 zzW;v>>%A41kgD#7rCZu^_opx<{R`1)z?JrpFFiN zEOF|u-Zj}VIiDgU?T_mw$3C96X-C!|`l8RCT5*(ZO^$B%*ViR~%a@ZF z<0#1^%om(=*7}1fu+*CS-ez(o2Y6nr32he8NeD=gXldYNn6xoYDODm(5R~jaUHx3v IIVCg!0B4(N?EnA( literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/bidi-reordering.png b/crates/resvg/tests-hinted/tests/text/text/bidi-reordering.png new file mode 100644 index 0000000000000000000000000000000000000000..22424bfc4c2efe080cb43edaa761bec44083e78f GIT binary patch literal 2107 zcmd6oSx}Q{7KZ<@7(v4l8e|uw1hTM=MrGd;1F~<)j|L$SkhMS(x}i}L)`%c92$2Q> z8xcVQgk3-h%Ye!v5s+2clommd#k4I5Ol+&>YG!IK=3-9OSLdzwoI3Aw_oX^J;$h;7 z;s5}^Y;CZv002RMdk2LDj^o`pyr5M&+q>fgoxxzl$HxoAe<&|6FL`-+C=@E#F)}g= z3k!30c9xKkFfcGsQBe^V7It!S!eX&9GBP9*N#F>yV5Fg;Ay}r<>4J#R&`=~2i9jF( z=0AhP#lI2$mle=!Y$jMWq`5k}0Y2VR44)3?h&c|AOYL6q&I-CZUeLmiyEaH`W!~mw z-!2HgS61Vc89rZAJWF5y<>SyDHGT7ai&sBRpa1}Rz!q!i9zFGeX9=+YqyT+@cYw6- ztJb+2CQTT{!=t1x!8a(dtd4bmT$aUGlpPE0Sw~U-H;w%u=lJ*0v+V!9K;ixh{}-np z`1^}BIsL{o2Ge(`5|9V*?SBV@Knvv9J#sAJs$mv!FcD&@;` zhj>{?VEqluwmauh3Rje^Z!ooF1gnU@stHyrS%gC>FMpD0n(4buIQKv;if0u>SsM+1xS@wi=&Tf$P#~tvqtJ!4w(^#e&^E^ISocNERDIhL#1?gkc>$m zqsn3{MmwpjvX^j{*T4#RZ0fDcO-(}BAF1lLb#ZdKTqFHgO00b3*N$cBls#Y}XpE>Uy2OA?GFW39W;)HiTW{>s<5xkVk-%7=tuVrVI5hl&Ahp9fmp zqf)>aQ6JB4NKr&>%C89JMzQI>pM~v#l78->ZXGenV}c^2{!WIsR&}~JF}d4vMP3fV zuDJ=?7iXR9T>6D{Bc zcNaYO#i+TH*eWO9qvFMoND}`DXgMNF0H66$aBnttI0wz%6*g+obnDj~x-YH?%}-_Z zkV_%F#!q%iUju&MMlhs*V`DcdQvRCS!65nWDV~BH>ewN%bZcUR198ABB>>FzQ0Z;H zSp;kup8HZEy;zW=wSE|7vv1xVxh90V9@wO4_we3w#&96(VrQ!?A*yJG7|eN(2uaHq zeS}vU$jRhG8^;(r#!^_Pe81_YsMvkfj=`RF_K9#BGdEJyL18IXH3FUIQe6m5oDIlV zol`4ppjV9!ZI4SY=%wKfR^(p0fo70cR}znL@_)U(fb`~P+}dn9E1~(**{|i>Jp>FB z9q=r0i4%Z&i^^@CU43AG<>}aFx%(!ckSk)~sZJdJQf_hDWhA$?MRwWHu8njOt&UH4 zSPABjtp)0C>gZ^ex$O+i5o<4++hnGgmAnW|i4JO@&sW9$euFFDzIDo^d``wt^*J(S z!kX~Ynb?JdWUdyPGJtbPzIK_%luaAfV^(J($9kTW#VQ7Dw6;(<)YYS&rTQ7ncU4Nd zrCsm0^L!EP$Mb~fWvwNfNfCT>RHARD9xExn-|sq(9Hm{e<&ZS0XR8dibxW6XoWP$+ zY?U9~B9snI*mbJ%2jINgsO?C`n?rSfP5K!Y5g&IHjza{niS zeM$f%_MHa)o$2^@M7zI0S3=lm*+p{2itiv{QaKpkiw#Dq?SA`#ZE=p+YAc_Fe*hg$ Bjr{-s literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/complex-grapheme-split-by-tspan.png b/crates/resvg/tests-hinted/tests/text/text/complex-grapheme-split-by-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..6c704ceb3e4e93c877da060b2b1a4a8fb56d1981 GIT binary patch literal 1382 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-instead-of-x-and-y.png b/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-instead-of-x-and-y.png new file mode 100644 index 0000000000000000000000000000000000000000..ef9f341314c43cc5056aed5c5c5cb43af640990b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=$(C&U#<13^PWLt|qjgpHL{ zR#xWY<6~!MXJ%%Ojg6I+m9?_60tx~(=H%q$=H>!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-less-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-less-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..989d203b86af1cd378e665330cfcba72816ab9af GIT binary patch literal 1674 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 F698qc!BPMK literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/escaped-text-1.png b/crates/resvg/tests-hinted/tests/text/text/escaped-text-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c77ef22f7611c0ad0b367138aa1422ff1452695f GIT binary patch literal 1621 zcmd6nSy0ng6vl4~M4AY)hD9g^LAD5phB#=HvXejtQQ!|QBnTq1FBL>dNQN~~2f;)^ zP(}?j5-|YlH}`%|x4@t1rG_v> z007i{yxju;fT6#Zs*++tyh-s=2*cm^u!lnbIlBOe17HgPM*&C!;1mF!0E7b&s;-Vv zQZjrZEUi#vJ_;d zmzUzgcmPf)o(2F1fDr&z03-u&4geaBroaLL;6fe!3fe9;fOrVFY#f+Pl;7Q#C#~pT zS{v4oC)`V6N~)(S-pi9G*jE#C>JqMYjeU^?n}m^`l}9@l0ifdRe z2H@Gkj|*qt5B=aLm^Rnasx=6`DE9a4Bf@2unF5#g5(@&0ON}%ou+Sm(5&shIhf50J z>#FT5`JYUmY~#uBU6vY+NJ%>+NkMBemJVz zLDZMeCy6xL>&mmFr6^-)ov&28S9>#e20hQ4kL$S}^5?nLtI&Q#OS?e0%x$U{gf8M} z2Y#WLe+bk3bn76ttzYD5=)}h|n0(1x>F?)I@=pB}53VrPDl#Bf-E_Tle02q5m!Ro_ zV)37gP9{rUwjKzH_=5zp$&$q4X7Rj?r=h*-dJsA#u5p4+JKMOUg||k?2W_|BUd=yZ zHmw=X(M8TxsW$j>V}~#9nSN({BASPfK<Fnk z%lEN9)7^DGa|}+{@x`jl4Buh{W%u@WV8VNnZ(i@hZx3R#`^+2Nko@|$25#xM1KUJG znl7PrIG;V(sDVR~H5r%`rdw{18H7(ze|7Jgm~3%ocQK*a5)zkeGrkj*1YKJ!z8>jJ zXIIM*qtUpImU5qupDJJJ5OT&KzwwcI9%b((HuOw zqr6=#v~&`)9U(tyw#Svx@UyX*7nn_u4Xof$GM|SzZMP>6yBC5oAqkytw77}Cq7B&_ z)Vfk9e_(}{nN<0}QN)q5@o}0sxPC_~q*Uwve1yVHlHf-%Jl9OahCB@BT45?zuFJV_ zwr^2uf%`EEGJG>&reByaEp&}}+#Vx<1jL z@b;rO>iyO}@bNsnLt1&G*J~)Jq+eu)^JSY9#t&7~S4nyUO#bG5S{eKaSzM8H0O_>K<>9cX$qaLPpptP2~n~}y=)SvUPg|TQ}S|NbeSx^<~!t$_?21=mj6$ z+H4C-2T`dcY6*eV@Dd((K*+~zjqoiY>+hTb`h9b5{4$dBNbotl{Y?2(A*We+ XPFcq~aXxHT@goBt52AaWD~bLWT;J4} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/escaped-text-2.png b/crates/resvg/tests-hinted/tests/text/text/escaped-text-2.png new file mode 100644 index 0000000000000000000000000000000000000000..7d7279ae73c137db83b39a6a9376b2b57d1021b4 GIT binary patch literal 1517 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`k=6XFV_8yXrK8ykTP{6IoN z!qCvr#l=NfSeTiaIW{&Hs6ID0x4ym}XaZ1*ot<4%QxhnttgIXp6NBG0G}(Pw=bC{+ zx+Ot=!3+uU2@L`t4BlUu5OBW!@a&GWUyJ)Q=ggk-dYS)*lJ)r;3Lfl_zrSGq0R{X2 z4)c?jb~7-ryzq2!45_&F=E6qa1_J?>4GkiO?zf(Qo8RBTxo`0Sxr51KzQs?LXjhpgxfu{V$8)jOmb8dUp(l$yNB63dzO)5QsUmixI+h= z9_1w$1v^IUs^8Oe`Y}GxVj~8^Zt~x02spx3^kMd`cr*kT_L?5=-uMbd+UGktyuG`9O z<)VN!_WdDqmxWK}+>vzbP)LHcCzsFrm{kSqIyP?0@jjifN-jAxVi8mLk%(Q-mih!n zG=|9O3F}_l!(O%J%HbK`<_7;4NDNsaQ=!!)cj!O_{68@XOX;pUc}Qa!&l#?LN@t`$>1 zmzQ;g$ncyBA%p^i%jy z?B3Nio$uKG6}K-jEiz2Xm1sZHH|r~cmvvza09lKNfeTDywaPCLlV7Os7`_32S3rRPh< zxbMZx%2@RJNYk}BRovV&^WMJnQ&m~`W24Zgtht&J+{T9KYG`$z>@G4(^l1 ztZPKrV+E5J*8GjrHs015pcA4O9{l`&sPNZ-TV7T3{+#i5eEly!b?&E-wH&g>ZWneX z2Oiq?&+*cXKVMB`RDXUtE1UiHpx@aQMlP~j-bGv}dZjXPb?Na%Mx`rEuGMG6a$c){ zpYxwFK;Hh1z3uO|=VkH#w&hP}<8ftVVDA1m)9B@)f3K&$NnduF|lPvMpM2 kTV6Z8>g=`kb29%j-WK%SSsL@Z6jXkCy85}Sb4q9e00t?3mH+?% literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/escaped-text-3.png b/crates/resvg/tests-hinted/tests/text/text/escaped-text-3.png new file mode 100644 index 0000000000000000000000000000000000000000..77a0fb19a51a453c238d6039f89ad308c38eae32 GIT binary patch literal 2093 zcmcJQX*?Tf9><>`Bt%LaE2>pzi@53t)>&7H20&-eFv{?GC5`DVJ|9mPfEMF9ZfPN(e% z06;Kb2Tbr_1z(=%cz{Yb7f<^G8UVmxFp`s#F9Q$&Kmq^`09XKU0e}bqe2_>ZLBTjp zO$LP$kHtzrAOX_ShaeDZDDHY-!2o*tG4a$f0J5?vkq1 z`i9|+UGM#<$5vmgb(Y+$01yFAb~c_@=2l1bWf;~7DBChB##W|lQ&;?`C|B>CveMLy z#5oT7SxL*uuAN2#!ma>AZVc+5%l-?uQvVIZw%>N#Qp5ef!e=b`Q2TdfhdbcEM7u}d zudJaniQW@)^9y_a_j4TESysuj_mz#$(#yk45sOa;^=wB6P)S|fW8)cITnun2?K31r zlW~$gc{DOh3|I2ZuCKh3)u%vu%mGce`Q{`|rR2C>JiB6f@Nm}m$hx9Xt+rzJ;`vTO z;ap(_3xboXb!*HcLwzz=x9gg*bk0a)OP2fDyHAct?Ftr7eWH%7FHwI?7~71`dRb22 z4%zCzb6IR%M=>Zu-90>`iOQqD$`KXOHWHr>H>utbdeYZw4-d`!kxC|1w5q$L@ElT{ z1A>ERES=icJxMYDFzijc6*_cH#vuh&d(y0ckB`yBJe`D@rxpw0ZU`GmJh^_od5}3( z@<*#~EUGSCuiA|E_GGfV3j<1o<^SQ|9dDpKd7DWOWXD}CZ28c>Hf6qm;OU%J4p`gK z;hL7Lnv*1Lah`1h>^L~aCvN918JX)-g=<+)iPh`r=`!c4w>zxyc!s2!!=9$|Cz&*s z0MkEFVAUycRr|uv4s6wWt@zbovMyGfsEAwkupt2j-i%d|Q8%_rHEU1@M51h z?vkSB_Cm?cA{AP9?L=s-ve8&ssQ3eg{&#W(_;A8lIxU66g5&(Isljt6JSWSX3Nbw@ z69$6X!se2e_td|5-2EgR{XD_uOe!rb%!qXpR_k3HQ){-SPXt$v3Pv)a`b387_lr`Z zeo;*nNWN`-FCpDasng+%*m3j-KQI8%N;eUgeEh_B*^BZ#mxkVg-0ADiq1xjov0=%Q z&$PP7eLcD&Tt59|g;`l&d|4Fgd{Kl{G5gkwqM>KnxAF#YtSLs0mP1L74zI3)WjAkm zQOFq+U2AheO-t8j(1N7jdP4|%j~P6rECFNgREq>-6^?nDxI6tj7OB-CT4z=;&-wIA zH5E2sz=NNOO?!a7NT-ohCBs}P(Y%lnnH+&vAB@J2T$Pl)2k0aMCWrCuWi~0c|9pg~y-u~^o_??_Cp$@gnEkZ*k$hD{ zsC?Z%Eup8HBPdogC?Q*&(o?Z3L|j1D$?rYX7vE2$OG`zU3J+W|KE6Pk4iQomW=EOh zIvOheo;Bi{K_~xNg1fvFa!xiq!3;7z9j%IluTyQ5C(@x+QtNw#CaG#v5!+a&8YwOA z@|T+q+GSJuN|+y*Gz-!OxZQAW>nlVVCi!{{@x2Wn@{4u`tVz|y8c3@Bq{Zts<_fwIZ!)n2pHk@*bt@IlmQbBK z(P5qry*en$-uF2&e$(QTXLOs6#3vj7z+cs<(XyE0*>YkCYHmtSmRlh|eL9$v_c}Ks zsH#nNZQ8N`UZIv9w8L81jGq&S`@!Cb>GX`VI)c`7-VI$eVH`HKK5HM?|sibx_x9Ok)uM7Oh;k>gL({HD*OSixtmKg>-Ladb1?bpga6%c|Nf_M vO8M{faq63U{v&pr4~i}D$suLK+H^O?l`ZvxfP(shuVQtw$J^DPqFnnIq&b`4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/escaped-text-4.png b/crates/resvg/tests-hinted/tests/text/text/escaped-text-4.png new file mode 100644 index 0000000000000000000000000000000000000000..64da98e1ca9525454c0f8d4fc80a709ba8cb2189 GIT binary patch literal 1257 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAe9r~6XFV_A)uOpp&ZOAVqj=& zY;0&~0P=FdBDL=B84L`SW@bRa`uh4L28I|0hI~cEPzHufNy#J;5kCfoC_X+n28JMR zZXmK{U@&H2FlA=eU|^5|B1T4jusKQoldFIX<&q%3UPc^mui_=Nm|g4XtFv**lN zzj^)@A|M|CcRRaeD0}H38i(^Q|tv46k866aPST}tC?%?*f`iRqe z6`@Ig7iIc)EmJXdI=n(N~N46myx|GpM6cP zQ=rIkPBz`dyvsXpZO<&(_x``^b=~##k3N0jS}d~TIm4AnOdpix-tWG|?;~;iW0maj z%^S|lN%m6LF|PHQ*_xWxnZL3%bxEHJ$LSLSo;oe5*Q_&Jx6alRTK%Zi^!V>7hm2m& zWl4Oia%aM_*KeN(abz32?pa#zC*Hfk?6TV8U%|U(0JZ#H`D^OBbBAtu%xq~3{%Rci z4aiK8SZlZZv}?pq5$^ACU$?vo+p|H6?R)r|1G+Q2H>g#;5?$S6Evm0mamqfzM$$Sl z^-{6;zoU=B6W^}!xGjCHvN};~P1~ehiGhiZ5&V*se^hn8a3$uh^_XqGCMg>zH*exx z^Gk_~fsVW!kZ^To>&gw+3=-Bdwz{_MW)+LLGplt&(bs!TU;STlcW>$8{2tL0HF<;4 zSGzd}qWD)GQWEbo%hqvQ8yBHskkUByuS3L4eSrv5pmSc$RpizQ6Pz-0gPB}a!q?Yb z;$bHzeC;@zK6gWyu3Wdf&c4#k8^ZDr9MWudogdp$YG27GTUq%sNMo&nPS}z%uEfG9 zv&&rF4-cGC(K+U4y|j9bnw(!jzv+>~kzCIsuKYHc^hLiU<&nu-nboKH*{%ljm3(PS zUE^`^)V)>d*CXDner2m8$Fw(l%>lzo{_c-Sg&@h#5w`IT$0Kx8xAeOnD@`Z z==e8K$7)?+`_*7a_l*x^?pU{RjJw&k~fw3TDSfxjH)2hNwgn|HG6@^TR|ornzy2b);A2ODD= y)KyToL0!lKaVMwP8pSnHy&>|eXDS)Z(v)Xgax~|SfwDHJF!6Ntb6Mw<&;$U3(+q?F literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/fill-rule=evenodd.png b/crates/resvg/tests-hinted/tests/text/text/fill-rule=evenodd.png new file mode 100644 index 0000000000000000000000000000000000000000..44d6f118ef32847ea6d0305421952271892012dd GIT binary patch literal 1702 zcmchYdpOg39LIlJ!`W=Pw54fsnmI@27An&-mAOQ;M*Iw!+o=pwmeYuhlR~-1%1N!H zuzqD*L@sGAEgY9ah{~lnr$gaXt|e#c@AEu8=a2J!p3mp~`h1@E_xt&N|N5rT+#FE| z90C9U)E*})9RQR_E1?Qgblk4TJ1QiNw%5a6p?p3+At6Bl-@X)EcsyQMSQr9<@bmM- z58OfAXzm-H%~c7%2B@=H*L??QAd{L9aF;fnugC zk@zLUT~-*56nx28l7d;aiW>XX^dEus>sAY>Y=OqSkz4f;@vJw7kBJtQ*S8GxxmZBO zcJfeh!MGk4T4gkj_8bhCS0!N%kb74diH<`AC~`PfEM=m~I1madmVa^%z<^xiIy$HW z!eqGDCjKWtBviBIG<-spHH@d=kywQOe9Uzgd02R5vOhbrnoqZ&tnKFty&LmwKdTd!S*QBYD3H7>I8Im;k zri{lnf%Y?XE&5_j%XOwX?xgr}#}N-PX~5^U|5O5IMB4TgEEswfrovgrzSm{!nLJT% zE?F!!g6$NwEr*c9F)q>7eNmzF2R?`VZYka!gt>gzz`m5e?e27bK7c)MXONxm@g6n^KLerOIFfjEm{RWF)HuPGq0}Odo2nm zDcEJ~Rg9r1dltSXm&+ug3pwq(xpDUi#;E3Y*b}3}VURi--pWb`ip+{y8;>2l&|)zX z(-UwBIM?$U#1>`W-m$wjVv{enzq_wuLVxFNsd{_gU4ceKs~v9RS?7FYw!X4^roKjH zYUhG;N#Gg@*ZzYl2p{xj7|yY#-xPPL^=t>RaW9L6EK*jaZ8N2_^^xU#>MGYU3;R)B zR@x=>_vUG5h|Yteqo>EGO}2T5oFp{u{g5S@Pq}FIwgWv&shDcuKO<5$VEZ?emlals zqz_Ro; zacOcvSVW0in*H#qb~yGUPdM142bsS5FyqrL@Q;r>^7L51j9lnH*e{RSS0aO0OWP|( z3;qf!x$1%c7;PutAxJo48`TWwLbC}(*aoAuTqr#OGjwN53ny; zSEsnpYQc+u7Yr^bC7&1!86;b|2uvhfg4+&(7*`z^AXzXe4m|a|e>K2#&}w+O=Cy=# zim24X(I*{#2`bAITTs1f-0qTCkwH2!(u9+EoFAcGd!sNVsOiuxy0t9znvO&1jg+AE z`B9cArM8TNcJA_eYgae%YIX5-ukKMv;UfvXN+tzXTg13nTa#{@9WrP(gU;ohvRG6F z3%3A<)(s-O*DXHpU970@^rocashFn&A#NoUHLT&po?@z#4D1 z=7!efwjfNUp;zM{5>kX_Yd%p#D4(99OWYb literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/filter-bbox.png b/crates/resvg/tests-hinted/tests/text/text/filter-bbox.png new file mode 100644 index 0000000000000000000000000000000000000000..90a08c413d43e7c4cbd9c3ea5fe6d60e038edc3e GIT binary patch literal 1456 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAmtt46XFV_;h?dxv7w;>$_3ID z3=9Pf3>gdz2@DJo3=9Db3?2*&4h#$y3=9Sg3>pj!3JeSq3=9Gc3>*wV;B?sUG?3yb z3GxeeU=Xm6PslI0&XNxlV&(C4aSW-r_2$A=M;AsOh7I#}+rRwRy=Z=fJm2)52@?Jq zQtm3Qf)l$JBz&A8s?6myO($|wN^H2;rj(PDRJ}2&S?7QfUz5SIV6`A+AjY)%tEFi$ z4yH7Q$n3NoXSb&17VlUKvhifqye{y*Ook zPxpsudV*u8k>z6cO*z+(o;0%4WuLVD74OB(29avh>O6bh?mn6>>}L4vsfW#KueT`YJU^i4sp`8i)nRoBIa@NYEVUBVvfl=5<^@uk1( zo;n!k?5^BQ(X|I#n9yM#z^Vx!z1P?q263wPC?%Y(+N zN=+=`-gsX?<#g8iNv)ILw28(2ySHJL?t>pU9~OkJThkf8C{q2PK%IY4>d~z!%oUos z--@PMZrt?dT2V!LTmD6Rj;XCY_qW-`Hq8|5*c=gg`I^O-^4rgwRvufLvVBv`{V@JQ z#nYRevo^Kg*{IWcX7k$8`SKy%Ms`v+*RMIS{h&<6%3l)?noM|FrsI9RP%?Udt+axf z?D@jadZ`bi7sMyMSgjcQz23II@^$C_&HTJ~?rsGJ2{r}^vv2Qzq&zsYvV|jK>%A|U zt*qQ)IuRQZ4mROn$RDxVAN2U=!KTtWJgR6X1$7q-#F?BB#|i5)r{ED%a&Fj?TDU*Q3CIf?~tDnm{r-UW|B1CdG literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/glyph-splitting.png b/crates/resvg/tests-hinted/tests/text/text/glyph-splitting.png new file mode 100644 index 0000000000000000000000000000000000000000..f30a932fac11071efcd849dfb42a57d3dca3162f GIT binary patch literal 1323 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAk`S)6XFV_Nd*A`0nE(I{{H^C zxw%|iTsb*8R#sNZ%F2d@h7Ao3_4V~GE-rk0d_ZG?f_MyXY-|LozdPmrDWD?lk|4ie z28aLl4f_K=7%aF@fB(UT_5HP9>oOl^P1-Pf_MGe1iJ>_u32$ zEP9?Ujv*Dd-dr#gY;X`@*$`du=`8;bagOGux1K5~-#jz@`-CbthjFdZ*LGIilyY*C zs`s`1CxGNMok$Go^{!Nq0-zK`C2bhCZ|<}gEjAEw2rP6i_kMqrRbcl2|NBK2C5CIC z4y$UqKljnMJLh=T9q3CAT`jdDT+!cYgTdJ?3At;Jgk&GQ6*kBB@ebA*oM91xY)hI% z!{!}~*ud1?7_#BeC1H;`rD^x7Pg!oSvNHZ}rn8k{m3)UN4gbT9X{{gIB9!H@#H;<33F_={@5B(Q~OpgfivvQ6{g(!RU7<{3M=%zKlgYa zPlxT}vKc4SH1t2D>21r?4y)Bo*ndFW;hp66&GJ|Ml63bzE^A6<6MGoZbd_sbLajxZ zRm)L>pZh<$C*6E}`fS9{xa<7Kihd`oG4V{B81!{nKi|(fr~3jMzG!TeYEN9sV4`Ud z`1<(PiBbaBB$f-T(Tpwrz5VO$`eUmt!jL7PGa9 zR&Ko18xiO})lN22ELZ*Bwv9VCr5dZ~Z2ge9lIO#o1G5kA3=6w>VB?wW(v57|Uz5J7 zXX#%{nGvC-J2OlCv_aLz63#U>5y1-g=e}=y#xjxJ`{~TJsfnfz8A0Uh zbZO>On;IQ!aqp!Py5iotjT^<*$a$N(ojz!EcxzbG(~Fxnlw@vUIelr>*6!4}ORu~( z|GMp7Yw3U6*tom5Wo0YV{m;L%U$<~=!|c`TGZ`Xu9rnhre9IYj z#`|QM-odN`CPC3cYi#OP9r+caA0fTED?#_5(d@>fS}F&FDqpx2Hv!!+mCJKO2-g)Y zje|kln?hPuBX+HLV(MMi^zjCttS}?PAqR%V?fvV%zMo(%@`ou{37VCN$RMwkX_}dU s`IQ@D0WK;o?JM5}b8VNkD+P)fQnK!fb?@CN2P&03UHx3vIVCg!0Hhu`KL7v# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-1.png b/crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-1.png new file mode 100644 index 0000000000000000000000000000000000000000..9be04f99234be4e946924f48d4f5a834c330bef9 GIT binary patch literal 1592 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT>F_C&U# z3dKhiKxxC0AirRSg!uge3I_QX?gy+te?4n`Nk{wH*%Rl?e*Lg^=hvmh{{8U<9~NwQ zFu(r&goFbP_WvDvru$VfFt93nx;TbZ+Jm!_v?C~QhOIZ4&~+Wr$ja+*#g29+(93Q_=+f~u5;&~O22Gql;Q%NEVv z#n)1JXVTj>dz>5Jbk5y>|Nl!plPnXZB+D<)E)@LAWXxo9uH#B}UdQ<5p4R0FZm(v4 zY^e6vnf-aHqio|l@z+s4r(_n(IDF|YeSB&~_50Jif>tpZXeZA!^Dq6}%a|SgUr2{L z;GE6O9p|=gc*MuBCD8v!&)T+Esu7Y6qTD|hM~bgrsIgg*vFzE-t&QP#B0n8U2|FMZ zcJZen;}_xkEccmt^bcw={ukfa7cV}`cJI_L4i%i!e(#Q0rW_cYr4a1@h>*&BB(L ze!jN)>3Xr>8{Z!|7wxCh?s}QAENjI65VU^>wf9g7$4;ZnZ zowiYH*~8sT({>&Bm9cBltuJSoRy?uNPHdeVGBdY2O}Fl6$?Aku%`a)MneAe(@MtG= z2JTN?dpL&cSDxK^j6ai3|FKRLLaT4vS48a%jtWEoRWO2-9M_8Pt#?%v@G{4 zp9e6ef+xQ?wJvdIcfDoO4Cz15He6}&NV>8(!cXtn(`en@Mh!JGk4;uKl-=nT&*Svw zH4R>N_wL=pM#;OGZ^$28|KIK9E&kP4B%U)^$(@h=$hW}K#cSmx&3h3HUOx|sZv3a* zrn63=tx@9Fqv9F8x-0&_yS5~C*`LX6jxo!bF36lYHd~apqDsm=(1=e|LHl*nLg)FX zx1`!>sU_;HY+1~6d0Dey*BVYuEgt4;FLx9Ol>dAYdDKkDI5c*`w*;0_gFe&H>sxoO zvaVS9ZbSBUJ{^XJM2!wH#oHm@=C3Ph;%B+n`+;Fj^vzqm++sQr8xjsSu?{wdH^f!b vpl*Y@5bDk?Ev(#O@vL8u2i=$>)q0hgf94+r`x{;DprY8*)z4*}Q$iB}x1XFK literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-2.png b/crates/resvg/tests-hinted/tests/text/text/ligatures-handling-in-mixed-fonts-2.png new file mode 100644 index 0000000000000000000000000000000000000000..93c8be5b7e93096245c6504ebc39f93fcd2a4851 GIT binary patch literal 1610 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=kzC&U#{Vd31|Tth>{*w|QRW@b%IO$iAJptzNlm6(_q(9HV!dRbZ7 zfPeshe}8s%_L!I$Of&I|9JMbK1gbD83GxeONQf6uxc)w1zCrzj`2MW*{_ES%X3j4D zy6kYrq-V3|?5wSOU6Oy{{DuejKNKuT*ngnG{=b8Br+Wnh1FNQ|i(^Q|tv46U85tBs zSPi;lmOcJ?z0CLEeNUAoXS)~O+|=!HI&NXY-^fhXCu?*fH>I4M)QXF8o383T4I)Vo z#_PoEHdlm?Uu9U;*`mE=W8@rQIe9 zynT~8llv&=k@XAm!X;%oT+Zt|D8H?BEAETDq?lVegL&SMN~7Y=w@>Sq`)zNXvr$L# zd-~hw4ytuh+jIAA{Gq-;Q2CkGYPI+0cd;aW)LzmqUjKbrN@#%0?zU$I$JrOuYHvzm zQ|o9Em=|^Jk?zS=3q;tSc27Pv>9lmintKXXf9x(^R@J_^aNiZ#)d@DcqpC{V#dY+Z z!i=nbOgzs#kW2dow zaoH4d`y*$@E#BWL51CzjZ@3)zc5*30=Hw}7)mrVg>y+zcUt+MI#M-i|{5C^MnME(x zSJRoyGi^4nDf6BdQ$I26#EqPyovWIkYP@4RxYlOk8ZQYihIol3x9mc`M5b;nWjpe< zO(NUzwZ5E*(+)|7nX;8%c^Nj^bgpsXS#if@t)XDR+~8^FB`zj5){@!mLHDC4}QcUCM@>%D-dhowrQpEZatZw<;zviAw)Te|m0a_Z7UN-VPu ze^lDJV8&90ZA~tjaVC7#8VuL#Y%A8RDatmzKkaHvP(wdMb@<5}NlZIsw!D0ty7m5) zt$bmn{$-h)X30jb&D|LOgm0--f%?>?Hte%cPgQLw^VeRRGyC}IOYEtkd}pGkC00d> z+GcK6oV!s+)Z+4~PmCE_nX8^@dFv%#N{NbGTDfA*R-K)D6t%8gnZD3irFW0yDK3TU z>jgI7sC+7XJ|K+a$7S{(g|eR~FFi9!efrkVvu^Fqh|F5AbA5`R-fG6YmW7WNrM}#| z>C5WB>8%X&-dJCqaNd7fipO1srzM+G_#WJ0ag=4=xr-rEHQ;8yMb>%l%!_=CDvWay z_I{gVz@A?Dde&{(Cz+|7;@x+|U(QVZxm}z6L{oHp$Ja~DEB3Eh8t__ydCt{((N+0Z zHG`fVP%L-7{eP?Vyr5|X!91NJN|nBm;mKkWV&UODcjE6xiiWM;z3%*D<_|^RZ>a9R z@~Cq6;~Dn9>e{LqCQE+Z`8wUi=5IaYe6jlfm#=S>;4hl7IHgwNbEQXY^vu_<^|C`F zX8!x0zrSAh*N&ITJRm literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/mm-coordinates.png b/crates/resvg/tests-hinted/tests/text/text/mm-coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..05ca508a3c9bf0eed147b10e74d686f842acf5d4 GIT binary patch literal 1707 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/percent-value-on-dx-and-dy.png b/crates/resvg/tests-hinted/tests/text/text/percent-value-on-dx-and-dy.png new file mode 100644 index 0000000000000000000000000000000000000000..64aaa83ae0d21051d9de464525114b67e5c98b36 GIT binary patch literal 1196 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*SX?$>3Jk2S93afKP}kkZx#bXl!f*GH?N9 zWn~u^7d}2dSy@?TW@dkXe+dZ*D=RCYU`$L5PVsO(Wh}Zn~}}QaZdrE>Rm;yunDj5z6ou(m4o0lVDP< z5Qa&uHt&9wgS&1YjQ0cT(LMcPelqXpU5g)D<{fK`ZwVDT>p7SA>)V}Qv^R)MOgL)B z6=oBrA8|3lqe-+klrzlcnxXTW#K<=JgHqpSCayd@&*!P*`VDO-O%9mZ*z@qS8@*MZ z?Ir#CvCHaNrxFk5xT)PZW@j4A`f|y}Ciy?d5*@SIj(uqG)BUteQCr6*_(F@Aw`f`+ z-)r$H&n&r&j%1w(`SR65uKLkAG45jtibn4^B$LjjtP=F8Pz_Gq*ub8aFZk_)z|$hL zkhCqE59eu3&Dgl%LFo3#mZKAt!-V_fDrXu_o9%TrO)zYNq8R_R4S5MN?W|j`78He_ z5a^cWV&PbRt-8HcSKnnjhxHkuZ25D-zt5CgzdvwI;XulL6=$8NWsDDBoSs{MYE9x6 zJTp3;xp8{3+4T2G0rUVglKEBAl?Pm4s?Y~U4(>D=wK zF2dJFtZWa5Ve}d$Id9=`$7`oITs5!Wcks}p9YULrEt(-MmcGe%XOe94#tL((IJ2p~ znH@{t{TKT7=a0=sxBOKs5%*eU?#(uvp(=LomQ`znak0f+D|emUS7qiMdlbHHb+D6Y zlI-Q?wyKgP;Ke~UepMT<9bM|dockI6$)34Q$c)3kX>)58r z>%WJ+dy#x`j?J{cZ%gE^1ZeCZC`gf;rV;{TRIzd z1iRPm{nyo6-QRlo-&giG|3%mAj=x;|>(*y?xj%RI#Y$W7xG;+BiEVXHTgJxn*F62% zku#rzGBZELYd)R*kL|F8^jQh*pKJc_xc~pr_8luPpPfE6>fs9~& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/percent-value-on-x-and-y.png b/crates/resvg/tests-hinted/tests/text/text/percent-value-on-x-and-y.png new file mode 100644 index 0000000000000000000000000000000000000000..64aaa83ae0d21051d9de464525114b67e5c98b36 GIT binary patch literal 1196 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*SX?$>3Jk2S93afKP}kkZx#bXl!f*GH?N9 zWn~u^7d}2dSy@?TW@dkXe+dZ*D=RCYU`$L5PVsO(Wh}Zn~}}QaZdrE>Rm;yunDj5z6ou(m4o0lVDP< z5Qa&uHt&9wgS&1YjQ0cT(LMcPelqXpU5g)D<{fK`ZwVDT>p7SA>)V}Qv^R)MOgL)B z6=oBrA8|3lqe-+klrzlcnxXTW#K<=JgHqpSCayd@&*!P*`VDO-O%9mZ*z@qS8@*MZ z?Ir#CvCHaNrxFk5xT)PZW@j4A`f|y}Ciy?d5*@SIj(uqG)BUteQCr6*_(F@Aw`f`+ z-)r$H&n&r&j%1w(`SR65uKLkAG45jtibn4^B$LjjtP=F8Pz_Gq*ub8aFZk_)z|$hL zkhCqE59eu3&Dgl%LFo3#mZKAt!-V_fDrXu_o9%TrO)zYNq8R_R4S5MN?W|j`78He_ z5a^cWV&PbRt-8HcSKnnjhxHkuZ25D-zt5CgzdvwI;XulL6=$8NWsDDBoSs{MYE9x6 zJTp3;xp8{3+4T2G0rUVglKEBAl?Pm4s?Y~U4(>D=wK zF2dJFtZWa5Ve}d$Id9=`$7`oITs5!Wcks}p9YULrEt(-MmcGe%XOe94#tL((IJ2p~ znH@{t{TKT7=a0=sxBOKs5%*eU?#(uvp(=LomQ`znak0f+D|emUS7qiMdlbHHb+D6Y zlI-Q?wyKgP;Ke~UepMT<9bM|dockI6$)34Q$c)3kX>)58r z>%WJ+dy#x`j?J{cZ%gE^1ZeCZC`gf;rV;{TRIzd z1iRPm{nyo6-QRlo-&giG|3%mAj=x;|>(*y?xj%RI#Y$W7xG;+BiEVXHTgJxn*F62% zku#rzGBZELYd)R*kL|F8^jQh*pKJc_xc~pr_8luPpPfE6>fs9~& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/real-text-height.png b/crates/resvg/tests-hinted/tests/text/text/real-text-height.png new file mode 100644 index 0000000000000000000000000000000000000000..411fb38283145ef38917de0e028d8c9494dae98b GIT binary patch literal 1826 zcmcJQdo+}37{EVdFfpc@K{0N#(yXcEP??m=x>PQ!DfQ8)VO&;bBD9U`d>gQ<~y|s1aYU9d3w*AP9zG07B>=wh9DjBz=j20U#9s z5D5dSNHzp5m`itsT-6|e1d%u#4ic}K1gOqQ-FN`^BS3>_hzpZ2%SLekF?v>-M*~cV zX#g3pU={%)_`<$O5h6sSKonqZA;v&B5J5FaO#{-vKp4b3-z{dYtYIu*7WJjExi29(P7lD&>m9L{N{pE7(qi$x*`5{cr< zkr&ZLx%(bO)Fx*N@}i^e#9}8E-BncrrBd1OjGikp#X2gTxcX)x0HA(mi>vbvwtTEz zhYlDK>c1Iu!#HAnp7suRCcR=qu6BV3lTOmg)y5%r z(nP-Y3ze~_iv5ZeSdHjv0TSw$PaA`4cW-W9)$4M&tuf|3OOOtp%1{1up}I#X>lg!@ zw5k~v;Rwg}3T4}0gH06?lC76?*x}x`mU~yZLd<#1;!8aHe9X?lN`sv7>iv&gh&aRaG>v4&9Q^!Q?`TQ z^qSuO9t%EY!ia<7C67suuO@B%OziTXWPtW!Qd%&X>HSbuad!Acws58tWY0LdOPj&gg{Kbe&M`i~pxDhrC{vX(R+lFOIcs1FZI%T*9}lMp=O6*Qmnm zL`hre$ALYS3!2kCm+{idrUT53bwcD6J&BZ-VNMgCnjT>LY-(M7rAqWW(N5W3tPJr4 zuX15KUhZ|FU3z71E;lPc@qDdBul$iz^#OXLZ3ips9m)+BZzi6*61JbAu8TE{We{-@ zTK3Yb)^IPK#b93WyjcFYbe%^VNxk|z4Lv|)jRiLNJwg|L9wD8128;SNE&n!y{?q9B s--8#<55li0-t|$`D*j+d%oYlzUTA33UA5bV13&;pgWU9v%*X zKu9FgR=K4c{*CWnOD2;k6pD?z>Vd79gVFA;CqUMlR)l?XePjX4?H%vz=u%SRJz9NK z==7Np-VG)$C;6WLtEhonRmrRF@TVC7!@|MAs zy-oJ}9H(aVB1;{*{&@VGM$qpTokp>zP^`^b4bo=zkDXp%=levN|2vdVWfi*HQq3XQ8 zv#&rm5*-rO6Nw#Uk>Tfb%cJTqK7gR9me|CHV=Weh`WB?8S@CdOM!aBX_;nD?D}F0; zFPZLPar;`K!1}(k=KH1juf`-2sAy&svFd zZ=}GCWI0k*KF3DP$xE}KJzhr!@Xg7Z^O3An_cNQn+z_%8$QwT#>N6sSB1{S!Czrx9 znc~9Hh5i!DSUEt9YvUD7^%N`=A76PTTe=qUg`dZ5i(6(Me~QZJ@6={z<1?3D=}<@U zY0K`fb=RrYmPyXZV8P&Q!lY@#;=<^nzU9)>jvrRAz^qkSa^Dilf34TY;=VFJX=;8w z>&8fMp}*yjqLbGvjH!8>*9AQ-~5xh~p4I^NhvV4oeguD9qvfR4dglIjKwY==nV0`aX7o#v1Z6<{AueDAy>7z`)*^Z;hiudgH|r58e^66^6H0@WPX&8 zEg5)y>PU`@l`!uLA=|v)$&V@7lxxY{{L+7lP`9=wtk`4WBf|)^mJVNn6=?Bw#_z{* z06L;VR5u_%*zwdC$37s6Nd?b8Ro75h^Q*27{rP=TcnQRN#^?(M@lHL#!NWB0*5{4_ z)fRTj`VP}eO*GQb>4Sh0j#MR)Xv;FW1_$!82)Hooy2p`4e!=!k!tUR zQ6k4`qQtWY;^dNKT_#|qBY3szut=9CnKfBX(C!PGK>vq7#?4~WN}gyd4v$kdl$hE@ za*Xye{0>I_n4(IyS~11k=Fk&%^uoDI3tOq9;;mkTR;hlwHnOHxKK*nIAj8(vSy=XY@4@!kFpiP7 z^lVf+Zxp;UqAmihNbK8~Sw+ZRZ+QE$DrKfA1TvsZ%tIRdC@(+es33_RfVF3Ou1>j} zjLzW()5V1b*W2bi4!9`s4rUd#=5!k?3jC&yy2}i<(yUs$+lS| T-PV$(Za*3atSjcOEg|JECjKKe literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-an-invalid-angle.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-an-invalid-angle.png new file mode 100644 index 0000000000000000000000000000000000000000..aaaff76ff38601aa053d92c516c08da25872a980 GIT binary patch literal 1694 zcmbtUYc$kp9G(d=<62|gRY)x(j7u%nj%J53#$_6pMsD+$OUA8fUE9pKtV^*Zb_^v& zE-}NOB1RcA%H_1gS_&IWv_e8cL_|b{ zgh(Xn>gp;fDWOm(Pft%Q78@EGYHn_>qoadBAmH%ruZ6J;2E)n8NnKrC`1Hx-e-~}1 z0d1kfG=k*l3~8nK$QfSlee(Ml82)q)q^{J&m9|}rNDaDD);*qe^%}h?+sBDfbfbns zJp201fp{Kz%j(gC>BA6+SS%iU+$Cmsey|>BwUWmkM-2kI`&PyZ%#7pm0dH}OzJP&B ziYv2$Vt0%@g-_^t4U!aWXBYrKQA|=nZwJYLb22C@RLCF&CPaTIa_=_(X!ty`Qpa24 z`Id$z@z5)`qLvtZ3Wdsrn0ZvW0fTOja_J~bGbZkw4y6%&)C*Lb-F5lG$x`j zE&4pA-oO(ge-|yaKk`|i4}!_b<)3RlcfY2)r;txg!S@)t_B#!y&GtGRUP#GbHUXMm z#8j8$AgfrIB#q^MgF$AY@+obY2UULa_nA@$o2F%?<5WmYU5f)q2$z9A~?b|aU*5vKqK`##hoMN2Mf zX^{2n%)8|3`onj@QNFM=bD(gNZOe`FGnJXBX=K@ukN+_uYNx;JQL^dFVi<=+E|2AP zXEbI{E&vbjVEU8_!TFz5t|RsrDA?pOhEz(yVdRU!jIw!7TB8iz4JJ80D(B#Z!K)9u zv*ezc3MNX4lO_bhx27J&O?_}=+O_+gj57V%@xDdzL7`oaDMvm7J4nci+f|L@=T5q6E8^IQ*yNC zNpVe9VJ9Y`-0U%W{hM)34KMPcIb20mRP^GDq_G9rj^(fYM>3~q{Y0nKJ?4vdWEEpJ z?%GQ$oT0`3!hK7xJQ%H+tD=WVZ>7%s>CQ5rQpBq;X;pKe-<)?&>J5K`gEErTp^3e# z++2>uG2cLc5w;kUc70;jr^QN(9{0hscT+Zhr5ZoU=aTxCRqP-ePdCZXETv=_Z>)dON}ahuR4&f+l;qeIsy- zKG}i);J10H=?s~(&x>O-GZp=AJ!G-7GcN0{MdN^EXKhk nu*Cv*>osbS7L@kI`%L>K2qK>|AQGT2y4~}5Ye#G~hLZRfBWccF literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-less-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-less-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..c29af579b2306f15013a8bb2a4042803ea86bfd2 GIT binary patch literal 2226 zcmc(hdpHwpAIImM6*13>W%7{5wonR@Q#pi~H;1g1LpG;jB!_HvqR>dAjU1AC6eG>b zLk{7Qm_vrvddiuSLyt%zr*}QQ|Gob_?_ckIUH9+%z3%Jx``w@Gy6@|{?=&}82L&Jm z2mk;S98cPw1^^_GKjtjH0$eZYbIf&cl5^R=14=4BP5l+#Qa3&0Y<&T8Nhk&+hB$|iif8YHh zX6bDIFM&SzJ0VNQ`Df<;XlAAU?u)>9eF~gEB?7n648!86)OhyrHy4~dfA!+l84>yj`mN*cJ?F#8=T5xr?d_sO zL+WIGm0;!RkAB76yf62iqFvs)J2Z;7LlPeAGegnBH=lW8icV?e<_w&ijT}$i9)E?Z ztjUnxB^$*%CRw72hCcIeqk{=x7RXQ*WRaoLaCHoQ!(DK_dJz;JQsOUbu$7z z)37l_r)Pk*8H8BX!69K#Y+M|_-#_s+OTqQcd;tY#3F-*EDWRvXtX=+7 z254WodBEerf(USX$6^qy8fss_eG1k_Y|T}*;7^@tpgWANgKqVQJ=}&iCMJ-s$QXw@ zvd2y!>{CpM^1P18Oq=roOxFV)c`xOB77lgJ*A)g0SyhHjPbrx3`SXOf=*7D+d%;w=p9gq@H^_Q_GXn96#J0 z8he<#bkIWU&eMjMnlYs9its%7q?2g1Y^y@`7s7Le5y5xM6kL|$X%}$(POBaDlj8`}F&+5>^+mAy zv&!m?*{0~}z;>-w<=(;+@-t*y?!f~!W`}SkFv^iK=mdAST4r%cr40j9DP+PB7OU>L z(TS~{i`|q=iy^v{ioDS2eg*ciJGDRTm^K4JoWevd4MOy>oldAtcma2$?uy^?Efo&D zu4vEM;?!)`?RA<`ra|xgdySjS;dDZbG~Y?%DkM3c#A>L3Bv(6E_#bfhN?0_}#vos`?HJZ_2|#mLKtbad=Z*$8P`HtWJNpO}>rr82 z^r{Z}+vCfW75}*hmg?b+W0uR4dVwUG=9fP1xFH%Vm4hdD6BR``g7LuKO3L&NhfBvC{^ z;b@FGg3G)uYm}A2B(sIXi{hgLY&rPQ?l;zfer1dw()SvG`PIw>VTJ3pua@srh_7%E zpk!$HO*9UirkBpK*2Q*R5NNxGG>seKo=)y@R(YBR(r2`IrW(Pu7{#be|7#l91O#SR zl5aEtkL!R0Bl2=Rb}!f-ck4IALRxL%c zlY%#_a_kn|!xQpeALU)U4ScpvP%}OLrM9V~^WhtKb7JVcqLcWM)=dTO!4c?TTd{Qc z%^?$I9~zD2Mf5}So9Qy!cOkvGel7n`vnbwP=O={oPZah~po*sdV11V^+v}AZC`>NX Y4>8sg_=IKz{`eL++PT_R9`~dF8`6>P)c^nh literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-more-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-more-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..4b89b642d594c22458f792a7ea56e2ef844e012b GIT binary patch literal 2198 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-underline-and-pattern.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-underline-and-pattern.png new file mode 100644 index 0000000000000000000000000000000000000000..3d645baa55eae8fe26e049bba75e9eb083e27035 GIT binary patch literal 2766 zcmbtW2~^VA8plvD6f;Z0ZLBE<7ji2{r4%zslgV8k<*u2UX)aV~At0fqqhtnVYFSQW z3MsginJAN@hNf2H(toacjwJEU99X;4kVqlj=(V0V+~F^ zlRrj!p9v2k^pCjsrX$}9HFcTOIV}UkTbSbo>4k2QCovT3N`naJCMmqKr~5i-mf)^@ zak!Y*{LUVHP&C~ zQ@zt3Vz50530xFEf^U_v5I8pKaMi`X7$k9zF0G}GcKpvk()Ef=F3Z>(2dD(Qf6hm? z6;L7*9w(lBocrPXjS&}RvQx~TcQPauG2aZLm&r%!qJ}1_ozylD2LRb`wYkK&iFgps zvM%hfcvpT}F^t{^{UKX;)xYaD*%S(k!H3&x(_2rn_t}8NbuQw@*;~SRCVl&B#54ll zSbtZxz*3n|4ajB`q!kE+Xy)YIC@6$e&>qw}T6d5OrE6}O+TDF1xY3-zuW_HOS!~=J z9ZRSXW*{7jKD9r@w1n`MC}Bx)+pc|P>(|nYqj@HY{?R;0u`Znj9*3iJE{F1}RtZo} zE{cLiK4$F&i7g3Jze3qbDJmh2Nvw6^>l)l7Bd)}hKG8q&Je!lQIn&@ptIb=-sqQ$_ z@X1yS_DGN_ZtYhv_7)xg<$}&9MHsB#6kDqqL9NwO6eea)$ew%zO$w7;d!&WFrF^^1 z`pt}ls$WMEW-H#td7@R04wTPd3uWaHlu)jDeu<=?D-u1ylbS7V;LxIlTV+k~5&>$%ejZ2!8gTays)6&Ghu-gQ_8iDm#ua>ZL35#B zekMiV>xo&jt>)RO8+!=9a9W34gBak@w)f*_`DrB$TZQFM3DyvF_lbJ7E3aSSm?Fr_%LEd92%UOkI&CPpvF+PTp3SA#9lEuSwpWUh z)D^$xnx0)QOfMLs^j^0aNwGc!2?4yKE7k32DXuo%LiXv;N1ZpqEuO4+!_od=dYFr22IDWzk5@e6Qq9{;*)% z$5#-T{x`C^`nVjQ$josjoQ!OV_iFU$Q{8)iJ_y3IKYt2j$a}ob4gbJ4n6OWqdvyU^ zgnjRWEk;Tfew(=iINAkni_i*E* zkQi4K-b9J*gKstJez#nBvkPFAzYdRe;-1jv`e3ehWdPC+GRTjsUB4@UzOy_ONn#Z2^@ctftip`T)s5xC?H zZ#_(zWmQPbiu!3U{m!K}ubJFfqIGw>hlSNSkQ87PQ%%Y3Q;I{o>2wGjy3$Bj$F!Ed zGB58RcP*ahY#13aPwdRN%I_czC?fPt3*lVl*C$jnqzj5LQp+B%9c;`-LTT19c-@os z7`rW@3inR+s`VqaReoMD^xX^|E2HCxqHi{3rXyP+&M5bvhUSQ^X!LvOvSP-d^}s;t z$kLoi-Qf`byxRqCO)^wMctFNDW&XKE^HO;JF!?4pA!S#1TLy#QO?k(rc^;c((cBVy zHFj$V-o|vE(zyh5-3T#yBzovynoewiyQn!S4 zcN!l0c!+!5P{AsckQ{0k-TZo7`XUIQH}o1 z$0ni!zrMqs|Hbj1?6-utTVoSXQa(kG<8kv3L^saxpSKrbqKI*Ho#>*t)>kt@TE2qR z@ON3;xay#|O;)c*ZsE?jEc;_oE$e~3#+nUD0W1c*YndsV?TuST_O{iqN&ugw6d3*Ll}!*sY=K@C8W%W z`6A`0W!XUYXQG|CP?~?kq;tWc^7E#m@3z3=rqT&l{F+Fqh!wJ(+k?SfWWonyhBaP| z?^uP?x|ZVx3%_QB>U0R}$-Qs-u!?&L=)$jl%3uT!VwaFwcq{R7f~3TES!UH~6rfWw zJrylVIk8QXP3G{agV6%IiuzXS3)0@MHi literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values.png new file mode 100644 index 0000000000000000000000000000000000000000..4b89b642d594c22458f792a7ea56e2ef844e012b GIT binary patch literal 2198 zcmbtVYc!M#7aomiFu7H(aiS4}N$zsVbzH_}W+-YnjGTE-5ztuBi-B zFX2#;QpON*B)6o{MMYC4(?Msx&cAPc-#TlZv)9_|dDh@&D}?G4XCZ(j_k)f?OifKqOG^`yzYP+J6doQ9hr=Z#B*MbNghB%Y z10s=V@gwMTx}BY!j*gC^q9PiN#^G?nu9TD%5{dlV&Hpt(n~<6kmJH*(2nS$+6dC=% zr56>XL3(*4F*#&q_E<@2NeGMHU|a9QM2$Tqrj9>Z2cYSl$pTe@}Gjw?x>JrjKc^DB4JsUgk4w|F;s;~vc zfVf{LwhFr~A}c}Ck=#wM$bpQxzExP4L5PV#4MSKZKwx(NLSfLeQ5nE)J6Cxp9^5_) zAR@9hAn@ZCD`0j&%IQ*FXJV{%Qr|ExH$@$C0_Tg=xDL+lC#|$?$hceW^nG587f>JS z;%u!t985j-^!oU_cPR&PHCy&@=}qYIMPG$CS<+8z6#)rJT@V7M~F;kBsX5w&bK*%2C7xl2bU8 zaM~{+0lMY}Gs{H{dutCX6-Px&>vBVz4h%(%Vl-1Ow~^#+w}c)tToqj^Sj#Ttm)AV= zLH_&;nP11!?v9M7F*~c9cHrAgO_T{;Idcj~)_ne2NED80=WuniY4TGaE&DzmaYLDO zr00~Lks1oWaL=q6Te_w+x?coUK|f43++ARtkoGk=YxmDI@vYY8KPg0>dR?aOv5DJV zqKaSER$jTE*gBW3GmVN=o*-owWfpXnUf|`zGKm6ikasJHnp6p^l+rIcgES`WEcnaPH3iihNbIKvCVLvoudEiry> zJy7qJ9FBw=dTzQ&F&obyK~X&C&^Fq*ug*8c)9eSdyKhV_yTLPw+nnShvJfAR6gDC_ zK_#@w41fLDn>)nbhVSo%bJ95!E>Tgl>JHE3TOad;_sLFKWz;$DnwovDVS!EXfoy6k z?URW~CCJ{xjtLjHuV=Vy_$?U8Ui)=+F3-J$y)$gSu4@d*onU+MHyu?K^z@rxPhs1} z^FyVffnb&>$G2#u7Vz%KjdCP7-Y^$FJ;A&!C%~Q9-jKU_WY?74D{7*RTtxb5PI=1- z?r}kSs}v_1GNVC^AN7!izG7tri5Ad3&@stS_`8`xkjzk>0$Q| zW+dg<3V$E7q(%#3=C84@NH%TWAu&Y0-`hPP6G?5Ok?CdDLEf5MXNZzoC@s3O$EuUS z*KDOVw+87F)qd}$E1cWSDTi6)@>Y^ZVV02os}afDNm6=?JR^GXl7B}zT|jAwIDj}8 ztUBN$>m~29vHVi^QwZSfV{&UsdpWg#w{Zpb{MzisWg1XBVag6Y_($`&m;-kcXD8Oz z*@k?wT4ynH*1mczW5*E^xlJj(#B#y`jNmU2=jE(2#1>`&|D?~koij;~3Z8!|u;w+r zpISS)zG8WOmA`Va(l4d6g|`7WSZdh&Dga7Z&Z1Aozi!%4Ygyr}G?&b@ubYE-@qGLw0yUc2$9mV!8ZU~GU!+s_0kO@y<64YRJ@u@>XnvlaFQ^ zkhXqKRzCZv9^(moyth%0S=9EZV1Aq%)Es_Xj>YkvLY8SKK83neZ}c~Hp}h+C|=inME6LQ29M?tjmo8#H7(~TOO$N)P48MI_sPerknhE0vLFBFel9OYBd%_ zgiAKkfM~?nPaSOc+c9Jm*psoOK}i~Tx2~C?fgb)u%!ylQt<=t`8^bc*YJrGsr~wyB zsPUAyeeB{>2&h%pudp_*%vqaB_8{Qdqo=XuWOc|OnU^L%d4=XpMVywlw%P6((L6a)ex zNc$b#K_D>xn{R-uWhf;HPHV_=bEXm3_^(VwMFj$ZSXfx->+3uIZDCY;{(i7p=eYT} XH4$37kI&;SA{ogg_9Xr~6>_gI1< z_G%y?rMjvF{`JL`O|QSEpZl!@9p@-jLo-d37;-@d*qw)G)*N~~$o(5R=l=%iv!Oyv_FfyhwJfYbaN1l*^}|TUp_M<_HCw zIt9ahN7Waz6|kV$PpbD4&c~!gt=u&9^5;7~SoQX=7awS6N*@Y%m>zcb#`byXtmp};uD0% z_se9MwseoOM)$$NY_FDeyxhhc%k^z<-rTTe!K-uW@H@i(xSK>E=w)4HLvt@HMONuH zFoLa}cxk2o(I+c_(M6eLe;h)5;9fryTtRz1R2-SPxzT7CpSU^5TcZwf#J~DP`%Z|s zRU1D2_C!R!peu8SQL5$4<&NK7T3R5|NhqwwtP&Woy2hA&Br6z934itG<0U^3%t%8@ zG{FB5q+vW9wnDW%lmj#^%MKa~xceA=t~&`+VXU;hlH}$)Ot!C>qKh}oD}w7g6th%J zLVe>(5Ij|?Ap-^K|Ktt2lLzC97hLX}F))$I=TQAC5zh`0L z)xhm|w@ZeY`?3!L8(5#hoDIT`u3*;Ta#ztTvQ**D)q^+;@hXsQ08drle8;G*9=G2@ za6NxZdml&abg~ByqV1Hs_=>-lLzNO{)1xA zFPW!*^GEcS!|M=JY(!q$k7UpX5ZguN(vqrTMVE8#Rmyx@m}w2dAwpTCu=RF!`Jd75 z?>0+t1TU|}9buJBegRPx8TsYdVC({*Ny3(Q3x{n(2^;Tb!akx#!TcU8> z!Q5OnK84q5eM-Kqi8|kaEPZ0>WX2V;<{CDZ1a760Gz`L1DBm77zNF0AJ`@!iurb>)nEIP_&N;376wW#wM zdKWPO{ELGzK2+PjGZ~v-P1vU3K}C)jTFvELtq)+NT}BGi%kcZ^iY_g?s&17W>sqY` z67ow_Kb6Y#&c1P4x!GM!=5QiP;y#c4+5euKQ1EN}Zf*obxIx;F{t}hY^Vv`D?6~2| z&9ryKU*)=~Q@wOv{IjjS{Wg*>3o&<5BCnq0NAVf9r~8y>_KhjB8G4!YT?Vs3(Nx|A zs!bFR;<_CbH(B$USE3j;#)tCfCQyHXu_L`Z5gmC-7|uZ2^ks2Q9k?uW91$GL*xNKIz9zzLflJ069 z9?8`7mG)uakSY2?S2N2zR_U3xjF#;L=tfT>kD#+EX6-c^Fk`==swkP{! z8lvRc!|NWJnu1v#2C2!TIJ{}2}0AQH;L8vhJlZsSB$I#q=lJtXLd(BuLEs>fHQvZY?8L@ z{pdCWb51|k{vQa=cTM|u3O0>p)?|Gj`TtnlM)r(Qh_Bu7;=0}rr6&M1P|i8%@J;JU LM2h2G2X^vbP+-e} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/simple-case.png b/crates/resvg/tests-hinted/tests/text/text/simple-case.png new file mode 100644 index 0000000000000000000000000000000000000000..8de5c7465dbe6b2b262e4d674c8e89b528b348fd GIT binary patch literal 1704 zcmd6oX*AS(7{{kvkzs5#Mj8^j4TCJ9iLAxQGS>dw!CaDT*`iF$4B1C^Znk7gH#7YI zl%zrQPSNA#RcfQ~AJkR+)pLf4Rf|aR|zySdm3?_s( zGqHuic45ChejaYes+3~Nl@fx5{b{b!Xtb!PD6aWQArJ_0aq*o6H8nL93MC*Q;OFNj zCntx&V2DH_w@Dxna5$W`wKX@8mzS68sZ^?>q9P9u4;qbjadGkY_va??@$voS(2t{~ zrsH4Xv@Y9P*}+I|ts=+L`o?=FZWj%|bW6=|oAd$iTrP;rpyaQm7nCnIhIm`g2arH& zb>Jt$p~c5EeU5=iz=bs!jF*ZxF|@xr@}UnBq8$=}8E7^n7ppC8R^M@!`Z6$fBe47y zen70StfAI9t&hbxDj$P&syW}4aa`h?D8PRZCVgi^;cU)-Hk5-?b>6ib4Qby(#^1Bk zvV)-j8S|941}K`t>=CP`g6dbiH3rB<&P55L#WhN^HTz3}R`o>t1VT)qO(L&jqEbiD2jX0{q==H3fM^n^iG!r|eyuxaG`!@d zP4heei8S(uP~;D&hLcEU_ca(PmSS*WpsJp=JLkmSShHrG*)ev$Eovh1X*^JQ20PkQ zI*@Qzm~NW>!a&`e54Zz|i*mGN3xNTT$2Tx*{*#hHZrgEj?biRIU^Fi=vypf54 zSC)JE>$XNv;4RJss}U@l_bEWEbYEqr7Y{3r%nv5RUGbRVT1Tu3I^)V2)j4Bq=EQ!* z4)Rb!_MUP%;b1|iB#bP7{jjbi6Ii*lf47l@dv2WDRtrB~*)jghh1^VNqFGM7^iOlF zbo6oC1(K-5+l1|#R*d)=Ss0J|=V#N?WhlA~`q@OR6x6T*=4HDtQ`FRv+Dip*E_N(Q zMFUr(4T<_PfNXRVuPgG0Khpba5tl3lO|T=*4v!C$p|z5!IuEBe z6qQCQfqr^xD)8hGtlP_{k=mCKD?G{sR2t$3gE+U5m6LOjsM6CJjZ3yl?KNYOua98O z+bYqQY`cMe3RETWuG13u{9@%x!l&Is4IT^|*FD`peP_K5=*rq)$sl!$Q-|DRJL?1B zP&&t^M$f~k*SRp=2nqTWPbDn0UW*%3MzT;<7uln_D~R4K^U+?bTl#yAU#UP>Q3dQc zI)!Y}yt)XLxUwiYsgc?`*H@EbH=T?_Z~6QkQ6*iWg$C7i;$qTMBY&e>ZU?tSv|2l8 zEeO(k+sq6ZU}&eN`vbkT#t(>YLXEU95jBf{FLSg%%JVLfzU=f6G^k5hhU{Xde{IWVY84EZH~!J#l6zAIY;k&{acb9zM0O6`xBSY9|13xK32(f>E2utRlrhb`wj v;djnxUSDfq&@al~|99n^Nrx~<3q1N<=U8i82bKE|!C?5)Rwh+Or09PE*J$A| literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/transform.png b/crates/resvg/tests-hinted/tests/text/text/transform.png new file mode 100644 index 0000000000000000000000000000000000000000..efd4d7db80e0c987a0d44ed321d83febb6209528 GIT binary patch literal 2062 zcmd5-c{tnI8V*V-DzQ}THG|q3OIrJFF}4mVi9KjY?7OO^)=I21HCok*X;6%&7%D$Y z(Q0ZerJY(z38fgd#9nJ^xsy!X>3{d1d+%TOJkL4r_ni0r&Uw#yzUTRV#MoaJhR8rb zAds-l_m++z5D(&bp5){1*jL=V%!Oji6=y3h{#OGEg>v;$Qc_AvN_>2L5D3K5(lRV8 z42eWyFc@QFV+{?B)YMcjFE1jI2nK_%UcHLL;kc~0xOjMYI5+D*xsF64ans$liXymb z-55uECy*J(v>m^x^V`fd%pXAHoiXn&U~l$^km8hlYH?lBYD{!de=rT5N-KRgm{<1A zXAz<|{{87e5fDgV-Ny1e=lF@WcSup9naByibIGe8w*N&SJ#F1a*^gxtjJ_?F(CDgG zt9{Pm+XlZk`Dam#_Sf8%jBx)qSbgq)EZ|aqEB}{ZFE8?CTlJjT=|YR2khA2;snLzz zKb59j}F*3hSBkSH8)=`RrqtE904GEt^1ilW3&L z0g@PTMzw0NwvKkKN|!TmvM2OhB`u=>YP#pwZJg|Bzq(H?*o(6bRh>4DEP*$ zbK*t#eX?EfutAkJDf5hTScf7MF(vC7Kcn_a2Vn@z(edAXE}i!gfzQ*Z3md|#!*q42 zEPk;5v?N^1Gg2BZ_jCINLTRu z)-~*tc}~VcRH?rdd2KNed;Rs)d zJQ7;h8#-TGrqcJ~-i}QEa;^{{Fdf>QMJWHkeAEHaY)@3qesW98pj9$#C5uqa;%P2! zO=>7Q(z~@mP6{bzh6%ylZSCu!1ZmCqAEYAidP#QYg-|UpE7I}7| zATAN06Y}$>yBvq6qeIIgmTt7pDWO7LRO9x``bWEx9!U`?PvATVxgS}SAUN5i%-Yu% zV2?XAl1(D6sx|$xOYxB)KhyyuE|5FsFWnj>_BIH&@-{o zk8@nG7YPh+E5}1yxQ|3xfCM?+4tWZt{!q^v;&jNSf9~xu&&VcP_NOP-0J|B_Vs;h+ zU(cO9){-APW)axF%*dOZbJRTqn!AaxRO@VBi-sYy=zGoEF9Kwe2A#HDnHzP4tTVGWV5VC_s3ei7c5t{9wImt#a62X4R7cT zXdqI|a&2~kjcT!b9^LxBK@39EsT|e5V#Y;m=~`RZ$`DKeGnx4cJW|X+U}Tu3pJ50Iy)Z9vaw7h$?#e zu&)UAyGtV^2Ub;|yeVOXh-iE)&FTznAJ9Vlsft-T!X+;PucO0c^9_25|ou62w zJE4b#!Pvoi)JQ;oGTwm5m{#PLN>3K=D}~gl?-t?(aDwBGuYU?%l zG#XvA$)?p5b|I%X`huss$Rwt50%x1GvT~qHAyHNP)K1#n{bxw_y}_>9ddK<`Im&(W z1pm7A?m{xFEDTMtp(5h&{T#vjY3JUqe@_`z-x0a4!lx|DEr$gCx}DtqM3=&wamf^6 zeiX3CNt-C)_*F5ibc5*bzT4Eh#Y#Xrtu%vkrXG05FCL8@EvLV|8D{6Z&&26-o85I`eeYq pdKHFw-_2rTX;+St`q}54qIp$EG+VU92PnsF*2c=-vd$cz_7@|&oL>L{ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy-lists.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy-lists.png new file mode 100644 index 0000000000000000000000000000000000000000..03d211b24185463696c03cbbdb7dd97532db3e21 GIT binary patch literal 1649 zcma)6c~BB~6vhKJ5OYe2S}~8zOspu6(lIa60P_Gf$((do6z_AR!w4xsSIa~okIWsB z-BC$_Qad!w8a6>Qb7ei!!qzTmwbc;sRhwzrc4q6%{J!sd?|tvR|9-gvem)S;CJ+Ds zfS?beZ~%Y?V&&;+Em!=w6rW|H1o#FWSY|4fnw6EcEWQW>1A{LrpHf|2T__ZqkdOd} z!$Ba>GFq+%YBfIDzAEll7s{7S+cR)}ctFH4!&b9P&jf#TSJWq;J?3Aaco}y~e!E_f z!+8Gq=ZNuuiCrnwHn%1B8Gt?>005pqqdbC63@QgSbTk8D**(=Uo}@Lwo4V$vTkmvnx z-)zfocH!TQVHlHXY%<;0i5!}mta{|NuMnP7*&-vsMqf4;XL%so#ym3-xme}s6 zu$Cx$gWp-l?{C#3jdfqfKebYHL2~$$*w)Fhc|BvbWG+)ZrSo2k6F6V-!`_hvU2{zH zmWEgSH%SE7aTxl91cXCU7Uo$z;ROV#GnU{_0FMYUVI2KH?#rR+_j;!nLC6QzwWh9z zk3zZw}`$l9Jbak2}N8P`k7`*H6qi-3)>oKOxprs;ay!yE<+5lwIfmp~+UQhwBjeAFYd|Tp0ul&Le%|q9nqD`sx>M?oROJW*Oo zW?1oaVloB=9eA^wV0U)}ZCI#>7w^E5gmu-9B02dkR@s~1BVBiNF|WWz=R4Riw%sU& zViqQ-tbI{rHRa_X)GHC+>p6!^bU>e+&fIYORhVjF!~k9f0JOUUjBqgq9gAQPZGr4a zw!DHMh@v`}R#?ve3)642eaosS^N+{=L;UWK!L0s;agBqUs1T?6y6sY?6?2#aA)#8B?bo80#6smkcwMxE^K6Ua1dZHVA##D{eQuN_VxCX zimsdgxdb2iCR~{2dyxO~T+yTaEjp2#Qcg~qDh{SpxiP4#Qz0r;y{G9!<^z?286Z6* zFnGN;+1*}KF9lreN z3u!KGTeZWVqyO}YPQABR^{4rUnoScX#Y~Ipw(m^6yT9pZ`PZpW*86)cm({kr*(WOd zwrtG{5$mv;S3v%8S#7K4+Zz{6K7Dx8*~fn-9{%k4-%IB*_u)-%FV>!4criTU=bx$5 z-ly3ezf|w)J@;F&z;0h1``xQ$q>pU6V)k+J`Snj~&Wr4K)j7+fu{oek*m0Kh>z}Va z@6D-to|5=;adOd?4`;p3>wYd0Y-%p|lL&hl7Ss}v7NdKFM^1y6d#!EYTVz4 zJYRMAwUh6&{g@(s;8IA3)V-}SoJWl;oXVzIGG0qns{iqZ^Hrom7~|5z{6?-ip=|Zm zhv&p7i19`gdcIuT8nNqFSckBUyHXgN@w-sJLx=Y9PX~H6Mki{crXFX4?l#_#mN30( zjn_<8nT zKfAZI{%m&9k=oFI{Lnmi=I8xE8&~Y?IeuvJ8_sXr*j7e#T{~zc#=ZQVX|ac{!0H}3 zmSQE_tY;IXoVH0H+f-0)B6M0OR^9Vw`os6{u5Bo2nb~*z(CgbfPRblOte$&1;@;fL z$C4j@&DA*)_xXQtTW-?9@YAwe9wjmBoQ~yOTls@U(Y&2i`tZ$9%3p(@acJN8;C*8s z+tIvdDzlF^*{-~qyt;PQ++xPC*Eb$NpPGGNdEY_lBZoe(*_Z1#zu9p4vzdLo)88HJ z4|9BQ%Y2%(r``NB$C>Bds>+Tq;j?RL4KD9lw}V}3`;?Fy_U?>pDr@J=v)!-JlCUzd z=jg0FS^MX2&c|u8c)zsbJN@WN?NWj09Ix$tt{-i}&0iXal~wnq|9t!>^N)1I|D(^g z&fUFXtpwWv1C5)4?F)TQF_nIoUw7uqjQ7$93Yh?!^YN%go0;Ev6H(A>rU)V+cW9r3!JIH^hb0pzb`_v{iA<$FeRHyJX+#avL}8)(rl};4v?? UJo$lg6{u|YboFyt=akR{0Mr`Rng9R* literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-less-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-less-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0bebcb7619a4953c1b2fd8915cf645704066d0 GIT binary patch literal 1688 zcmb_cX;hMF7^Msqaw`>$qEaU>C}YalBVLCWM$c= zb_PnmO3fA$6{tLxl3+Pylj|`o#|_gm2CLJb@yGm__nh~+_uTin_x^iN`gjrb;Yc_H z0?{YA6MP|%MVR@ktEExAt}uxjIOF5t@1{W(i^XQMHRRuiKp^}OH*DD8?d@$~U|?ls z1&709V`D=?LTqhqjg5^p38|^6=H}-1_Vy?g>YGbTODi}ySVu=klc2Hu$oY?C{c_~* zn$;}~UoSrhb$_GLre{<^VfJ4&sa4D_!CQJ_W!t&(=JJNDf+>d5yJmk}#hdnvK7YrL zu6@XIRd2^hEo2Y~^cab-!#|~aL{ZCL>|+8E8JAnf*Q;ko^^WLwA0NLn#FsWLjT zP!&T74Y}5{+otxN;OQw;<*k9ug8WuPS!O~2kk$6$o?!?vbS=EOgc{hb>Osp>3`f<6 zg0lP#2|2~4p)T@`^>a<(mMdS!70RzmaMh-{j*9%|r<-fK-vsXq<1ukupsOnkeSppb zE>HN-?ETV9Ga2Go2ZgIMup&n}@jwow0*sxwBGv#>S)k3o>{qp93jx`h2JQD_iwQ_H zH0H6CwT^(~aqTeN^dd>LcpC!U2dfplj_iteB`Og-ib8Ai4lP5kNX9Hx%^|=| z9{>}UxT|1q9-gA7dL4|XxTt{JOM*i16#Oh;ij$YpGR==;;O#Tk(&*uYVN?qolmp{n zg=?Cf8OIfYC8*ji+zuvw8fBGBkD~*r*|xYvpR5OB^)v8K zip0Hv4}Lcbb7$6R=MH3DtCJvpPqiqee ze7B#S)I{5M*fF!v9n)sHrU^H)YB=i7L!I@yezOn3!C$9TZN&1UUq*&=PfuuhuTDRH zVa+jZ)fi0O7BzWx`p$aANcZZ4`|yOJv1Z~q@kqTHwm`iSXBe5~a$hItpgMZ2OZ(t0 zr%lSkJNW8ImlDGxq}+B6WBr4j82INswt_qd1$U!p=V)KbB}upOCqyrtZ^;>O^-sXD zpjW{Rsj{ih4G83{o15$yv&C? z)bSNqj@V;~bwzUrfDsFOKLfZZIrk@IYo}9ZA%S+iv46tQgSMASE}5!t2kLsDf{4-2 z7ePw_Lv0&G#~A8x_3`{mVE2{!XLY9rbvO~i^oG7OXc<5hvY|5TTBBA^EM*ZT@R@ZI z4?J2Bm$>6Fa}!n6ALjVw{m}g=rqKs=@+z{E@U=bpH>Pf#MYSo~Bv}}k-Bqxw`uuiG zD8pvvMZJ%?5+>el5$Af&L$9HQGC5iwlj*8JCs%+O9dje=kj+Cv+L^oRAqKVf(yp1w zuiIlPw`MV0R(b_4FSSW>G`}&y(5FIh9_-pdR)AY%*6!U4F4a9VtRp` qN8bt-1gxf%x0Njn$cU61{h@{J=R9u`qF>E__#`(k!i}BOw0{6;n&VIa literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-more-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-more-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..23e8df100e2b260f1567b3ec2c920844aec0a947 GIT binary patch literal 1679 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 Kw)c+vUik}062h4P literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-tspan.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..059541219ba19c22e61e0cf592e0eb032e315737 GIT binary patch literal 1914 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 S`PQ(79q#WNgdPEP)F_*Vgg!4wr0F&K=M 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/150-on-parent.png b/crates/resvg/tests-hinted/tests/text/textLength/150-on-parent.png new file mode 100644 index 0000000000000000000000000000000000000000..461c20732eb4b6ab7e49f9ef6b8b572a4a25362e GIT binary patch literal 1482 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 HN@xNAu~2lk literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/75percent.png b/crates/resvg/tests-hinted/tests/text/textLength/75percent.png new file mode 100644 index 0000000000000000000000000000000000000000..711de47ecb0084a062d27bfb3bcb5ac76cc2dc20 GIT binary patch literal 1474 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAT=|< zGEj<-kIw}R3=IvftgM8Eg@KIR++1d6=A4|I*w|QqfB%@67+G0ac6N54nf3McKwUtU zT3TATOvWRAC|Pm|P};a8$S;^7Azr}XL%{tB2^Z#XcyPVFW6q?rvopVD71x#Qd_8-P z|HP&J_3`=V7p&iKK;eDC{s#O14%1pak1#N>EcJA845_&F=7Krn(EyR78?Hb2Q}wgh z+qvMG%RJkaXX9t2t*)Q(>OfWagnQy)rmUhm5gQT?R*6kZIM~F>Ev5q@Bf#v44J_PZ zYc3{2#enLd!c<|bnVr1W|4LJ-Y#`9yH3kvZ)!!CMujXqhtSLEO@>KNQ%4m&kKR^BB zFF*38$!U+qW>ukxKOvXT%KPa2elzFywurU!tsUq5iP=3dLYKit-uq?jN0qe})9xm} zyjrbe`)1>nOSaSE_8q@;`ddVn?l#fY|9>wpTKB8?#rw{y@dm6r_A9jRmvqr*S#K`( z|E0l6zBPSM70-F+D?Zs3()fMru}56<|6Dt^NJuGG!p}3_(>TF-qfh&RiBmV;VrlNn zY}4lya*og3urwmGUBGH_x9icfoim&xy0pU@10$>7zg{W!Iw{b$jFUY$IA-H5J|)kW zr_==eB)jkH72Ylo+En%7c7&Bh$E?glsx4QKF8Z$UPEu*@7v8Zbr$(=%z&HD_(zMqOvJ9r|XW#fla5h;aFUuswD zoKi6AG8EfyHtqP--XAAFt+%{u*ztSr)IA1b=`&<3Z!JCiQgx$N%>;Mp*FU-gqnM?sDa9snrT&4YaA_j_OFdyD=z6M&pWB^3sDJ zi|f8`bxzsyD&leJ!#|d1?;D3~JQnJFsJs0N7w?hxrNSM;mn~+tCNF1Nq4$FYYB+eNDA$qp7uW0{>GEvNq@hupIhx#qQJ#$V5Kqt zti?+9-}j?)WQMP6%YnGA9Hb{%eG$WJD$VG0+ zIw=KEyeob5J4R3HEV zY{uH7-2gxgT#tCT(Bw`{WB2rURMLg($5Q@e!igj~73|OyOMQY$u z+O7uFJnxg6HkkP>YP8UW(ppXSA9=-ZVltRxUoKWZO9~|=|Ne*(;vX{yc7o^)wTzCehN$;k`r1A5gEUD*>8x(3?C3HY z>`VX7+JrJ5V^e}|RYkZk4b*!Eiysz1{g&{ZvRB$rV-1${A}Q^}Ng}_IX24v+Ta2}( zf3l>rqLJ8sf+bzPNqbd6e~fq~Z$`ZG3Wa+P!(+}AQMgdExIAQl)i_c5l|nmw5n<_R zT=NK#1ln#n!C|!mT2o-D_yO614Raz}gL~Ky2 z@Y&rRIt*aq79J(oreoXe3m(Hye9msP~?0eo@iDnl{(9D91g&H`Y|2ZpI%F9$~7K+pgrr z*%QN9o2n25p;;=_`PJ~<9qQ&9UiBmiwzu9)u=eoNSb`q}02F8j#V z`w8UJrzyR{mB_+mAHMKM(>#ko5b_fEDh+4m`8}Ts-``7|CDl@ZZ^`dOJM7)%wtB@_ zL9Fm>>7U_e%nQn=knB49@!UFj+vS;q`?M|8$lNWr9rFFZ^vsGVGf}iS= z!PVC~8FGwOXOomy_YUcJC#LdHIp!gzlh&njB27UdQ?D+@wAmxgGv*pKZ8q5nEMQzm z*VW+V%{bJ~QE9mDLZJEvVmC3>`L3wTjs@O_M*pt|Z@`z7=S~sy{q#Z4?3=Oi<$dV` z$J?a1Pm;N2)%}Vw#pgMMm9k1*j0-xkVcKt)^G3{G_N#zD7KrDjh7$wwQk@)qONyPeHPzpH9dAiv7+)n z7riZL`^FyGK=WCBpa~soI@}mt-7LUgAX)TxsVw^Mk9Cp+HcE(P!3)0l?>eo!bUp)Z z^K;FwqWZtPsm$LF{BPoSoUh%tHxpN>XF~#>gui=II_KlRe&DbNozYb`0cn2$c>pr~ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/arabic.png b/crates/resvg/tests-hinted/tests/text/textLength/arabic.png new file mode 100644 index 0000000000000000000000000000000000000000..f931ab8cbf43083a979e22120d3847cf916fab91 GIT binary patch literal 1656 zcmb`He>~H99LHyq9}~hB({_c{Ih>H6<07UpJN95VUkNiOC1Ub3WT;FcJZ@95b=AW~ zhK>AM51FhVEas8SkFHjnlS4y|J42`Izw7St=#M^+$NTeozh95%`~Byukm!%oh8jab zAdt4N4>k}4QnC6_8jwxL|Hf(Drj!y1B=1fA%%`KH6CWRsLZOI6qPn^|6bdynGlM`N zMn*;$3??ir%)r3F*4CCzr|0D4#KpyJlAn3`BbJ++ySZDifrD?(HpzkhK_HL!?sOsL zWuok7-ooI>v5xH7SB;9EvXlK)l~u8VixB~hISG=hU8QoO&8}?`l>O5~7!YVnj4$>8 zDSdoy&=yX&fvNIxcuxu4U9Rco?QE>)k*hx~|7Kq1bi7))+GGba^xkB<0*!GZ2oeni5ZKuAIK0vk+;t=n2^)TRDJ%MdOZW3@5DL}Y~+(g`n_5FKE{;$ z(HRChTC@~!V0xvfm@(ya6sjt}d} z(ehJScLN}Yw&xG8Qfo7K(8rTPW8>7?XWjjSl5@-_eK&;082URW3c5McVP6*I)_$br z)FqlrJL2(SK#i;FV1Ez^kG5gWIFkjuB$}fk8LCgtPof2?MlmlS)TIm4JeZMYuZMi& zkzFpJ_6Ric99eUp&C&GpvNmZMf<%PJMRV!9x7D2?ag*-q1mWGeS$ntxYH!xrm)CBe zc${9I$jy5`Q|94*)Z5|>-si}@i96{dX@o!+a$J@)W@U8TIpo>aQoqaE6cPK1X5E(2 zki|bjAwxh_Y-_#`*m0|+3;WIty`Q|NsS@RZJ`MB`5*9q#Xh~xU%95y-UyI(R9`?17 zW~|@efuATupQI>|v&%AT*Lp`;+8VbiD~~g>VazI5{(yWkQNZlaLnG20l=HFZ811@Y z-J9S6aje-&kV6bQ7idkT9@9Z{fMGYlWyRvk&J+R*ZO5){uYMf)SocZ^RQB!eI$EdFb62nFTP>X^1d$s zACFVMey@CS8(}E8MRLdYmoPn-F7Y1_8ZE;1v1WGGCa@1h2_6w=mP;d^P#v zF6tQAW+F&54yj&~@XpC)p8SJ#}H+=iXbNN^~A*ER@KD5(rt8T(_}8jjt~phC~HB5HaHnNOhE!v`cR7#e931=0tEH2G^#;4QE6T_NEle=*nQ%WP&P41EO-_E3!b^_1zodf?pffb2Eef z9W+z_;eASdDaYhv%>9o@Pm?3S>&+U&mrd<;i@3jEkM7(U`w-v0-u~DIPfFh34kX&H literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/inherit.png b/crates/resvg/tests-hinted/tests/text/textLength/inherit.png new file mode 100644 index 0000000000000000000000000000000000000000..461c20732eb4b6ab7e49f9ef6b8b572a4a25362e GIT binary patch literal 1482 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 Z7qi*Av+LI7DBJ}VOP;QNF6*2UngE*HCaVAd literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/on-text-and-tspan.png b/crates/resvg/tests-hinted/tests/text/textLength/on-text-and-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..e816ee471fe18ddaf5151c22e31bd292c1abaa8f GIT binary patch literal 2100 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 E1J%|6g8%>k literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/dy-with-tiny-coordinates.png b/crates/resvg/tests-hinted/tests/text/textPath/dy-with-tiny-coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..c720d53eacefb38fb535ec777c9cbc868de4ce9d GIT binary patch literal 3457 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 Fe*tnoy`}&F literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/m-A-path.png b/crates/resvg/tests-hinted/tests/text/textPath/m-A-path.png new file mode 100644 index 0000000000000000000000000000000000000000..d7241a66c8d73c5445f47efcdf7171147b35acd5 GIT binary patch literal 3822 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/method=stretch.png b/crates/resvg/tests-hinted/tests/text/textPath/method=stretch.png new file mode 100644 index 0000000000000000000000000000000000000000..d84bbeb00e1ff6160d25ffc78b02f37217e3d869 GIT binary patch literal 3475 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/mixed-children-2.png b/crates/resvg/tests-hinted/tests/text/textPath/mixed-children-2.png new file mode 100644 index 0000000000000000000000000000000000000000..a5e96e06be53ee83f884b67a2099d001001c30b0 GIT binary patch literal 3748 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/nested.png b/crates/resvg/tests-hinted/tests/text/textPath/nested.png new file mode 100644 index 0000000000000000000000000000000000000000..d64b6261a42cf0fbb3a9fa5c546eade5ae310e0e GIT binary patch literal 3923 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 F{sW_nB~}0c literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/no-link.png b/crates/resvg/tests-hinted/tests/text/textPath/no-link.png new file mode 100644 index 0000000000000000000000000000000000000000..746d45cd7241a6e950316859716452a033cc8d6d GIT binary patch literal 1796 zcmc(gZ8Xz+9Kc6hvNMWE9&Zw9a2t6}B z7z~C8*tH`R2Gej{e7af-qzmsq4}*Ot2-x8pp7BoBFT)H)nV$Xq+GWEHjruopZ!MF- zJpP~{K%I9Q__LOvPKO4b7qj(;whTFhioN=ik1}okIX=&}uh38PdIE9FmWw6mvV=lu zyeW$MdX31d)YLyHZXPbOEgVhOr11;^O}JzBdX|<6pcx1*cVuZTvIQCl1}uED*Dua! z{{#F>Wl4gy=otw1nlCvnYO!n=O*<{gbHr%Jf}M3Q?I?cq)8_ethywyS(F(0kn}6eg zWzX79t&}I#HOuRxxib@LQY}!_%gsmxY{%uWgFhr z6D9iOYi zSZ40WiO|q0c_m5gtJWRt3gtdW>tba(vbFut1<|&)T`J>JkM%hiPo|%A|8b+~EGoe| zKhFvYJgJ^ZlskOhMs=f7^AfXB(O62S=8;#>ChBYt%!!rP%5aGSg)c{YDC=h_iP`5c z>mKtMr*=*Dr2itcuf*Z((^wm=FHa8acUH#iNv`88$MSPsaKn_5-3_*iI_NuSw~mc- zIb4}ce#49+(DfS`c+)MZDecV4~Z_3KT zdQa22v5liXPEeHISRvNl*&7rd0-l@!Hex}-4HK;8S)q3nNu4MgXsYRWNBGbV1s%%A zpuw2=jROyW$E4s@WOstt8IeP{S5%=gI2QG_BE?NSyRP3@x(brc4HZsK`XS}Dd{?KQ zELBdqFK>56Gu55{hyc-23k>AP#vLK41Tl)s(m!