From a24de9dd75f0c4788a719b8a59752a8e8ec2ae57 Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Sat, 10 Jan 2026 15:27:32 +0100 Subject: [PATCH 1/8] Port to harfrust/skrifa with hinting and variable font support Co-Authored-By: Claude Opus 4.5 --- .gitignore | 1 + .typos.toml | 1 + Cargo.lock | 202 ++-- crates/resvg/Cargo.toml | 6 +- .../examples/generate_hinting_comparison.rs | 90 ++ crates/resvg/src/lib.rs | 79 ++ crates/resvg/src/main.rs | 27 +- .../text/alignment-baseline/after-edge.png | Bin 0 -> 1314 bytes .../text/alignment-baseline/alphabetic.png | Bin 0 -> 1281 bytes .../tests/text/alignment-baseline/auto.png | Bin 0 -> 1281 bytes .../text/alignment-baseline/baseline.png | Bin 0 -> 1281 bytes .../text/alignment-baseline/before-edge.png | Bin 0 -> 1315 bytes .../tests/text/alignment-baseline/central.png | Bin 0 -> 1312 bytes ...ging-and-baseline-shift-eq-20-on-tspan.png | Bin 0 -> 2116 bytes .../alignment-baseline/hanging-on-tspan.png | Bin 0 -> 2095 bytes .../hanging-on-vertical.png | Bin 0 -> 1635 bytes .../hanging-with-underline.png | Bin 0 -> 2145 bytes .../tests/text/alignment-baseline/hanging.png | Bin 0 -> 1315 bytes .../text/alignment-baseline/ideographic.png | Bin 0 -> 1314 bytes .../tests/text/alignment-baseline/inherit.png | Bin 0 -> 1315 bytes .../text/alignment-baseline/mathematical.png | Bin 0 -> 1351 bytes .../alignment-baseline/middle-on-textPath.png | Bin 0 -> 3399 bytes .../tests/text/alignment-baseline/middle.png | Bin 0 -> 1330 bytes .../alignment-baseline/text-after-edge.png | Bin 0 -> 1314 bytes .../alignment-baseline/text-before-edge.png | Bin 0 -> 1315 bytes .../two-textPath-with-middle-on-first.png | Bin 0 -> 5661 bytes .../tests/text/baseline-shift/-10.png | Bin 0 -> 2123 bytes .../tests/text/baseline-shift/-50percent.png | Bin 0 -> 2086 bytes .../tests/text/baseline-shift/0.png | Bin 0 -> 2092 bytes .../tests/text/baseline-shift/10.png | Bin 0 -> 2061 bytes .../tests/text/baseline-shift/2mm.png | Bin 0 -> 2094 bytes .../tests/text/baseline-shift/50percent.png | Bin 0 -> 2050 bytes .../tests/text/baseline-shift/baseline.png | Bin 0 -> 2092 bytes .../baseline-shift/deeply-nested-super.png | Bin 0 -> 1565 bytes .../text/baseline-shift/inheritance-1.png | Bin 0 -> 1651 bytes .../text/baseline-shift/inheritance-2.png | Bin 0 -> 1588 bytes .../text/baseline-shift/inheritance-3.png | Bin 0 -> 1588 bytes .../text/baseline-shift/inheritance-4.png | Bin 0 -> 1588 bytes .../text/baseline-shift/inheritance-5.png | Bin 0 -> 1588 bytes .../text/baseline-shift/invalid-value.png | Bin 0 -> 2092 bytes .../text/baseline-shift/mixed-nested.png | Bin 0 -> 1801 bytes .../text/baseline-shift/nested-length.png | Bin 0 -> 2033 bytes .../text/baseline-shift/nested-super.png | Bin 0 -> 2071 bytes .../baseline-shift/nested-with-baseline-1.png | Bin 0 -> 1591 bytes .../baseline-shift/nested-with-baseline-2.png | Bin 0 -> 1591 bytes .../tests/text/baseline-shift/sub.png | Bin 0 -> 2087 bytes .../tests/text/baseline-shift/super.png | Bin 0 -> 2084 bytes .../tests/text/baseline-shift/with-rotate.png | Bin 0 -> 2290 bytes .../tests/text/color-font/cbdt.png | Bin 0 -> 10675 bytes .../tests/text/color-font/colrv0.png | Bin 0 -> 1561 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 -> 790 bytes .../tests/text/color-font/mixed-text.png | Bin 0 -> 1752 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 -> 978 bytes .../tests-hinted/tests/text/direction/rtl.png | Bin 0 -> 955 bytes ...-baseline-and-baseline-shift-on-tspans.png | Bin 0 -> 1798 bytes .../alignment-baseline=baseline-on-tspan.png | Bin 0 -> 1467 bytes .../text/dominant-baseline/alphabetic.png | Bin 0 -> 1169 bytes .../tests/text/dominant-baseline/auto.png | Bin 0 -> 1169 bytes .../tests/text/dominant-baseline/central.png | Bin 0 -> 1173 bytes .../tests/text/dominant-baseline/complex.png | Bin 0 -> 1496 bytes .../different-alignment-baseline-on-tspan.png | Bin 0 -> 1823 bytes .../text/dominant-baseline/dummy-tspan.png | Bin 0 -> 1467 bytes .../equal-alignment-baseline-on-tspan.png | Bin 0 -> 1771 bytes .../tests/text/dominant-baseline/hanging.png | Bin 0 -> 864 bytes .../text/dominant-baseline/ideographic.png | Bin 0 -> 1167 bytes .../tests/text/dominant-baseline/inherit.png | Bin 0 -> 1208 bytes .../text/dominant-baseline/mathematical.png | Bin 0 -> 1211 bytes .../tests/text/dominant-baseline/middle.png | Bin 0 -> 1208 bytes .../tests/text/dominant-baseline/nested.png | Bin 0 -> 1850 bytes .../text/dominant-baseline/no-change.png | Bin 0 -> 1926 bytes .../text/dominant-baseline/reset-size.png | Bin 0 -> 1169 bytes .../text/dominant-baseline/sequential.png | Bin 0 -> 1793 bytes .../dominant-baseline/text-after-edge.png | Bin 0 -> 1167 bytes .../dominant-baseline/text-before-edge.png | Bin 0 -> 1182 bytes .../text/dominant-baseline/use-script.png | Bin 0 -> 883 bytes .../text/font-family/bold-sans-serif.png | Bin 0 -> 1156 bytes .../tests/text/font-family/cursive.png | Bin 0 -> 1385 bytes .../tests/text/font-family/double-quoted.png | Bin 0 -> 1189 bytes .../tests/text/font-family/fallback-1.png | Bin 0 -> 1257 bytes .../tests/text/font-family/fallback-2.png | Bin 0 -> 1189 bytes .../tests/text/font-family/fantasy.png | Bin 0 -> 1474 bytes .../tests/text/font-family/font-list.png | Bin 0 -> 1126 bytes .../tests/text/font-family/monospace.png | Bin 0 -> 1179 bytes .../tests/text/font-family/noto-sans.png | Bin 0 -> 1189 bytes .../tests/text/font-family/sans-serif.png | Bin 0 -> 1189 bytes .../tests/text/font-family/serif.png | Bin 0 -> 1247 bytes .../text/font-family/source-sans-pro.png | Bin 0 -> 1126 bytes .../tests/text/font-kerning/arabic-script.png | Bin 0 -> 1664 bytes .../tests/text/font-kerning/as-property.png | Bin 0 -> 1551 bytes .../tests/text/font-kerning/none.png | Bin 0 -> 2181 bytes .../text/font-size-adjust/simple-case.png | Bin 0 -> 1454 bytes .../text/font-size/em-nested-and-mixed.png | Bin 0 -> 1115 bytes .../text/font-size/em-on-the-root-element.png | Bin 0 -> 1115 bytes .../tests-hinted/tests/text/font-size/em.png | Bin 0 -> 1115 bytes .../text/font-size/ex-nested-and-mixed.png | Bin 0 -> 1032 bytes .../text/font-size/ex-on-the-root-element.png | Bin 0 -> 1051 bytes .../tests-hinted/tests/text/font-size/ex.png | Bin 0 -> 1051 bytes .../tests/text/font-size/inheritance.png | Bin 0 -> 1189 bytes .../tests/text/font-size/mixed-values.png | Bin 0 -> 1135 bytes .../named-value-without-a-parent.png | Bin 0 -> 943 bytes .../tests/text/font-size/named-value.png | Bin 0 -> 1866 bytes .../tests/text/font-size/negative-size.png | Bin 0 -> 642 bytes .../font-size/nested-percent-values-1.png | Bin 0 -> 1142 bytes .../font-size/nested-percent-values-2.png | Bin 0 -> 1142 bytes .../percent-value-without-a-parent.png | Bin 0 -> 1102 bytes .../tests/text/font-size/percent-value.png | Bin 0 -> 1142 bytes .../tests/text/font-size/simple-case.png | Bin 0 -> 1189 bytes .../text/font-size/zero-size-on-parent-1.png | Bin 0 -> 1189 bytes .../text/font-size/zero-size-on-parent-2.png | Bin 0 -> 1189 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 -> 1189 bytes .../tests/text/font-stretch/inherit.png | Bin 0 -> 1189 bytes .../tests/text/font-stretch/narrower.png | Bin 0 -> 1189 bytes .../tests/text/font-style/inherit.png | Bin 0 -> 1366 bytes .../tests/text/font-style/italic.png | Bin 0 -> 1366 bytes .../tests/text/font-style/oblique.png | Bin 0 -> 1366 bytes .../tests/text/font-variant/inherit.png | Bin 0 -> 1113 bytes .../tests/text/font-variant/small-caps.png | Bin 0 -> 1113 bytes .../all-axes-combined.png | Bin 0 -> 1259 bytes .../auto-font-stretch-condensed.png | Bin 0 -> 1593 bytes .../auto-font-style-oblique.png | Bin 0 -> 1533 bytes .../auto-font-weight-700.png | Bin 0 -> 1208 bytes .../explicit-overrides-auto.png | Bin 0 -> 811 bytes .../font-variation-settings/grad-negative.png | Bin 0 -> 1520 bytes .../font-variation-settings/multiple-axes.png | Bin 0 -> 1163 bytes .../text/font-variation-settings/opsz-144.png | Bin 0 -> 1598 bytes .../font-variation-settings/slnt-negative.png | Bin 0 -> 1533 bytes .../text/font-variation-settings/wdth-151.png | Bin 0 -> 1611 bytes .../text/font-variation-settings/wdth-25.png | Bin 0 -> 1431 bytes .../text/font-variation-settings/wght-100.png | Bin 0 -> 811 bytes .../text/font-variation-settings/wght-700.png | Bin 0 -> 1208 bytes .../font-variation-settings/xtra-extreme.png | Bin 0 -> 1652 bytes .../tests/text/font-weight/650.png | Bin 0 -> 1231 bytes .../tests/text/font-weight/700.png | Bin 0 -> 1156 bytes .../tests/text/font-weight/bold.png | Bin 0 -> 1204 bytes .../text/font-weight/bolder-with-clamping.png | Bin 0 -> 1245 bytes .../font-weight/bolder-without-parent.png | Bin 0 -> 1204 bytes .../tests/text/font-weight/bolder.png | Bin 0 -> 1204 bytes .../tests/text/font-weight/inherit.png | Bin 0 -> 1231 bytes .../text/font-weight/invalid-number-1.png | Bin 0 -> 1231 bytes .../font-weight/lighter-with-clamping.png | Bin 0 -> 1157 bytes .../font-weight/lighter-without-parent.png | Bin 0 -> 1157 bytes .../tests/text/font-weight/lighter.png | Bin 0 -> 1204 bytes .../tests/text/font-weight/normal.png | Bin 0 -> 1231 bytes .../tests/text/font/font-shorthand.png | Bin 0 -> 1724 bytes .../tests/text/font/simple-case.png | Bin 0 -> 940 bytes .../simple-case.png | Bin 0 -> 1214 bytes .../simple-case.png | Bin 0 -> 1301 bytes .../all-options-comparison.png | Bin 0 -> 3867 bytes .../text/hinting-options/css-style-syntax.png | Bin 0 -> 2861 bytes .../hinting-options/eink-mono-clarity.png | Bin 0 -> 950 bytes .../text/hinting-options/eink-mono-engine.png | Bin 0 -> 1620 bytes .../text/hinting-options/eink-mono-target.png | Bin 0 -> 2535 bytes .../text/hinting-options/engine-auto.png | Bin 0 -> 2792 bytes .../text/hinting-options/engine-native.png | Bin 0 -> 2942 bytes .../tests/text/hinting-options/mode-lcd.png | Bin 0 -> 2446 bytes .../tests/text/hinting-options/mode-light.png | Bin 0 -> 2830 bytes .../hinting-options/mode-vertical-lcd.png | Bin 0 -> 2898 bytes .../mono-hinted-vs-unhinted.png | Bin 0 -> 1772 bytes .../preserve-linear-metrics.png | Bin 0 -> 2338 bytes .../text/hinting-options/symmetric-false.png | Bin 0 -> 2899 bytes .../text/hinting-options/target-mono-1x.png | Bin 0 -> 3241 bytes .../text/hinting-options/target-mono.png | Bin 0 -> 2476 bytes .../hinting-options/terminus-mono-clarity.png | Bin 0 -> 1619 bytes .../hinting-options/terminus-mono-target.png | Bin 0 -> 1351 bytes .../tests-hinted/tests/text/kerning/0.png | Bin 0 -> 2315 bytes .../tests/text/kerning/10percent.png | Bin 0 -> 1459 bytes .../text/lengthAdjust/spacingAndGlyphs.png | Bin 0 -> 1541 bytes .../tests/text/lengthAdjust/text-on-path.png | Bin 0 -> 3339 bytes .../tests/text/lengthAdjust/vertical.png | Bin 0 -> 1689 bytes .../text/lengthAdjust/with-underline.png | Bin 0 -> 1555 bytes .../tests/text/letter-spacing/-3.png | Bin 0 -> 1631 bytes .../tests/text/letter-spacing/0.png | Bin 0 -> 1631 bytes .../tests/text/letter-spacing/1mm.png | Bin 0 -> 1677 bytes .../tests/text/letter-spacing/3.png | Bin 0 -> 1675 bytes .../tests/text/letter-spacing/5percent.png | Bin 0 -> 1661 bytes .../tests/text/letter-spacing/filter-bbox.png | Bin 0 -> 1032 bytes .../text/letter-spacing/large-negative.png | Bin 0 -> 742 bytes .../text/letter-spacing/mixed-scripts.png | Bin 0 -> 1544 bytes .../text/letter-spacing/mixed-spacing.png | Bin 0 -> 1421 bytes .../letter-spacing/non-ASCII-character.png | Bin 0 -> 924 bytes .../tests/text/letter-spacing/normal.png | Bin 0 -> 1631 bytes .../tests/text/letter-spacing/on-Arabic.png | Bin 0 -> 1705 bytes .../text/text-anchor/coordinates-list.png | Bin 0 -> 1026 bytes .../tests/text/text-anchor/end-on-text.png | Bin 0 -> 1421 bytes .../text-anchor/end-with-letter-spacing.png | Bin 0 -> 1240 bytes .../tests/text/text-anchor/inheritance-1.png | Bin 0 -> 2387 bytes .../tests/text/text-anchor/inheritance-2.png | Bin 0 -> 1295 bytes .../tests/text/text-anchor/inheritance-3.png | Bin 0 -> 1596 bytes .../text-anchor/invalid-value-on-text.png | Bin 0 -> 1431 bytes .../tests/text/text-anchor/middle-on-text.png | Bin 0 -> 1459 bytes .../text/text-anchor/on-the-first-tspan.png | Bin 0 -> 1377 bytes .../text/text-anchor/on-tspan-with-arabic.png | Bin 0 -> 2436 bytes .../tests/text/text-anchor/on-tspan.png | Bin 0 -> 2555 bytes .../tests/text/text-anchor/start-on-text.png | Bin 0 -> 1431 bytes .../text-anchor-not-on-text-chunk.png | Bin 0 -> 2030 bytes .../all-types-inline-comma-separated.png | Bin 0 -> 2070 bytes .../all-types-inline-no-spaces.png | Bin 0 -> 2070 bytes .../text/text-decoration/all-types-inline.png | Bin 0 -> 2225 bytes .../text/text-decoration/all-types-nested.png | Bin 0 -> 2225 bytes .../indirect-with-multiple-colors.png | Bin 0 -> 2700 bytes .../tests/text/text-decoration/indirect.png | Bin 0 -> 1481 bytes .../text/text-decoration/line-through.png | Bin 0 -> 2153 bytes .../outside-the-text-element.png | Bin 0 -> 1481 bytes .../tests/text/text-decoration/overline.png | Bin 0 -> 2108 bytes .../text-decoration/style-resolving-1.png | Bin 0 -> 2313 bytes .../text-decoration/style-resolving-2.png | Bin 0 -> 2313 bytes .../text-decoration/style-resolving-3.png | Bin 0 -> 2253 bytes .../text-decoration/style-resolving-4.png | Bin 0 -> 2112 bytes .../text/text-decoration/tspan-decoration.png | Bin 0 -> 6465 bytes .../underline-with-dy-list-1.png | Bin 0 -> 1532 bytes .../underline-with-dy-list-2.png | Bin 0 -> 5668 bytes .../underline-with-rotate-list-3.png | Bin 0 -> 2130 bytes .../underline-with-rotate-list-4.png | Bin 0 -> 7987 bytes .../text-decoration/underline-with-y-list.png | Bin 0 -> 1548 bytes .../tests/text/text-decoration/underline.png | Bin 0 -> 2120 bytes .../with-textLength-on-a-single-character.png | Bin 0 -> 1129 bytes .../text-rendering/geometricPrecision.png | Bin 0 -> 2082 bytes .../text-rendering/hinting-comparison.png | Bin 0 -> 5931 bytes .../tests/text/text-rendering/on-tspan.png | Bin 0 -> 1459 bytes .../text-rendering/optimizeLegibility.png | Bin 0 -> 1557 bytes .../text/text-rendering/optimizeSpeed.png | Bin 0 -> 1707 bytes .../text/text-rendering/with-underline.png | Bin 0 -> 852 bytes .../tests/text/text/bidi-reordering.png | Bin 0 -> 2111 bytes .../text/complex-grapheme-split-by-tspan.png | Bin 0 -> 1372 bytes ...complex-graphemes-and-coordinates-list.png | Bin 0 -> 994 bytes .../tests/text/text/complex-graphemes.png | Bin 0 -> 1033 bytes .../text/dx-and-dy-instead-of-x-and-y.png | Bin 0 -> 1680 bytes ...nd-dy-with-less-values-than-characters.png | Bin 0 -> 1678 bytes ...nd-dy-with-more-values-than-characters.png | Bin 0 -> 1703 bytes .../text/dx-and-dy-with-multiple-values.png | Bin 0 -> 1703 bytes .../tests/text/text/em-and-ex-coordinates.png | Bin 0 -> 1676 bytes .../tests/text/text/escaped-text-1.png | Bin 0 -> 1621 bytes .../tests/text/text/escaped-text-2.png | Bin 0 -> 1562 bytes .../tests/text/text/escaped-text-3.png | Bin 0 -> 2101 bytes .../tests/text/text/escaped-text-4.png | Bin 0 -> 1284 bytes .../tests/text/text/fill-rule=evenodd.png | Bin 0 -> 1732 bytes .../tests/text/text/filter-bbox.png | Bin 0 -> 1418 bytes .../tests/text/text/glyph-splitting.png | Bin 0 -> 1362 bytes .../ligatures-handling-in-mixed-fonts-1.png | Bin 0 -> 1621 bytes .../ligatures-handling-in-mixed-fonts-2.png | Bin 0 -> 1646 bytes .../tests/text/text/mm-coordinates.png | Bin 0 -> 1725 bytes .../tests-hinted/tests/text/text/nested.png | Bin 0 -> 699 bytes .../tests/text/text/no-coordinates.png | Bin 0 -> 1690 bytes .../text/text/percent-value-on-dx-and-dy.png | Bin 0 -> 1220 bytes .../text/text/percent-value-on-x-and-y.png | Bin 0 -> 1220 bytes .../tests/text/text/real-text-height.png | Bin 0 -> 1824 bytes .../tests/text/text/rotate-on-Arabic.png | Bin 0 -> 1798 bytes .../text/rotate-with-an-invalid-angle.png | Bin 0 -> 1663 bytes ...otate-with-less-values-than-characters.png | Bin 0 -> 2220 bytes ...otate-with-more-values-than-characters.png | Bin 0 -> 2206 bytes ...-with-multiple-values-and-complex-text.png | Bin 0 -> 2462 bytes ...-multiple-values-underline-and-pattern.png | Bin 0 -> 2781 bytes .../text/text/rotate-with-multiple-values.png | Bin 0 -> 2206 bytes .../tests-hinted/tests/text/text/rotate.png | Bin 0 -> 2217 bytes .../tests/text/text/simple-case.png | Bin 0 -> 1690 bytes .../tests/text/text/transform.png | Bin 0 -> 2072 bytes .../text/x-and-y-with-dx-and-dy-lists.png | Bin 0 -> 1660 bytes .../text/text/x-and-y-with-dx-and-dy.png | Bin 0 -> 1680 bytes ...and-y-with-less-values-than-characters.png | Bin 0 -> 1697 bytes ...and-y-with-more-values-than-characters.png | Bin 0 -> 1674 bytes ...y-with-multiple-values-and-arabic-text.png | Bin 0 -> 2643 bytes ...x-and-y-with-multiple-values-and-tspan.png | Bin 0 -> 1866 bytes .../text/x-and-y-with-multiple-values.png | Bin 0 -> 1674 bytes .../tests/text/text/xml-lang=ja.png | Bin 0 -> 2252 bytes .../tests/text/text/xml-space.png | Bin 0 -> 1475 bytes .../tests-hinted/tests/text/text/zalgo.png | Bin 0 -> 3110 bytes .../tests/text/textLength/150-on-parent.png | Bin 0 -> 1465 bytes .../tests/text/textLength/150-on-tspan.png | Bin 0 -> 1459 bytes .../tests/text/textLength/150.png | Bin 0 -> 1459 bytes .../tests/text/textLength/40mm.png | Bin 0 -> 1472 bytes .../tests/text/textLength/75percent.png | Bin 0 -> 1459 bytes .../textLength/arabic-with-lengthAdjust.png | Bin 0 -> 1870 bytes .../tests/text/textLength/arabic.png | Bin 0 -> 1693 bytes .../tests/text/textLength/inherit.png | Bin 0 -> 1465 bytes .../tests/text/textLength/negative.png | Bin 0 -> 1465 bytes .../text/textLength/on-a-single-tspan.png | Bin 0 -> 1393 bytes .../text/textLength/on-text-and-tspan.png | Bin 0 -> 2089 bytes .../tests/text/textLength/zero.png | Bin 0 -> 1130 bytes .../tests/text/textPath/closed-path.png | Bin 0 -> 5916 bytes .../tests/text/textPath/complex.png | Bin 0 -> 4903 bytes .../textPath/dy-with-tiny-coordinates.png | Bin 0 -> 4187 bytes .../tests/text/textPath/invalid-link.png | Bin 0 -> 642 bytes .../invalid-textPath-in-the-middle.png | Bin 0 -> 1430 bytes .../tests/text/textPath/link-to-rect.png | Bin 0 -> 2061 bytes .../tests/text/textPath/m-A-path.png | Bin 0 -> 3813 bytes .../tests/text/textPath/m-L-Z-path.png | Bin 0 -> 2420 bytes .../tests/text/textPath/method=stretch.png | Bin 0 -> 3485 bytes .../tests/text/textPath/mixed-children-1.png | Bin 0 -> 4291 bytes .../tests/text/textPath/mixed-children-2.png | Bin 0 -> 3775 bytes .../tests/text/textPath/nested.png | Bin 0 -> 3883 bytes .../tests/text/textPath/no-link.png | Bin 0 -> 1796 bytes .../text/textPath/path-with-ClosePath.png | Bin 0 -> 4825 bytes .../path-with-subpaths-and-startOffset.png | Bin 0 -> 1677 bytes .../text/textPath/path-with-subpaths.png | Bin 0 -> 3331 bytes .../tests/text/textPath/side=right.png | Bin 0 -> 3485 bytes .../tests/text/textPath/simple-case.png | Bin 0 -> 3485 bytes .../tests/text/textPath/spacing=auto.png | Bin 0 -> 3485 bytes .../tests/text/textPath/startOffset=-100.png | Bin 0 -> 2354 bytes .../text/textPath/startOffset=10percent.png | Bin 0 -> 3380 bytes .../tests/text/textPath/startOffset=30.png | Bin 0 -> 3493 bytes .../tests/text/textPath/startOffset=5mm.png | Bin 0 -> 3414 bytes .../tests/text/textPath/startOffset=9999.png | Bin 0 -> 1796 bytes .../textPath/tspan-with-absolute-position.png | Bin 0 -> 4427 bytes .../textPath/tspan-with-relative-position.png | Bin 0 -> 3775 bytes .../tests/text/textPath/two-paths.png | Bin 0 -> 3573 bytes .../tests/text/textPath/very-long-text.png | Bin 0 -> 2808 bytes .../with-baseline-shift-and-rotate.png | Bin 0 -> 4507 bytes .../text/textPath/with-baseline-shift.png | Bin 0 -> 4341 bytes .../text/textPath/with-big-letter-spacing.png | Bin 0 -> 2099 bytes .../textPath/with-coordinates-on-text.png | Bin 0 -> 3338 bytes .../textPath/with-coordinates-on-textPath.png | Bin 0 -> 3435 bytes .../tests/text/textPath/with-filter.png | Bin 0 -> 3573 bytes .../with-invalid-path-and-xlink-href.png | Bin 0 -> 1602 bytes .../text/textPath/with-letter-spacing.png | Bin 0 -> 3015 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 -> 3115 bytes .../tests/text/textPath/with-text-anchor.png | Bin 0 -> 2512 bytes .../with-transform-on-a-referenced-path.png | Bin 0 -> 3312 bytes ...th-transform-outside-a-referenced-path.png | Bin 0 -> 3281 bytes .../tests/text/textPath/with-underline.png | Bin 0 -> 4008 bytes .../tests/text/textPath/writing-mode=tb.png | Bin 0 -> 3841 bytes .../text/tref/link-to-a-complex-text.png | Bin 0 -> 1957 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 -> 1706 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 -> 2014 bytes .../tests/text/tref/with-text.png | Bin 0 -> 2014 bytes .../tests/text/tref/xml-space.png | Bin 0 -> 1497 bytes .../tests/text/tspan/bidi-reordering.png | Bin 0 -> 3873 bytes .../tests/text/tspan/mixed-font-size.png | Bin 0 -> 1846 bytes .../tests/text/tspan/mixed-xml-space-1.png | Bin 0 -> 1858 bytes .../tests/text/tspan/mixed-xml-space-2.png | Bin 0 -> 1825 bytes .../tests/text/tspan/mixed-xml-space-3.png | Bin 0 -> 1362 bytes .../tests-hinted/tests/text/tspan/mixed.png | Bin 0 -> 1887 bytes .../tests/text/tspan/multiple-coordinates.png | Bin 0 -> 1632 bytes .../tests/text/tspan/nested-rotate.png | Bin 0 -> 4161 bytes .../tests/text/tspan/nested-whitespaces.png | Bin 0 -> 1690 bytes .../tests-hinted/tests/text/tspan/nested.png | Bin 0 -> 1687 bytes .../tests/text/tspan/only-with-y.png | Bin 0 -> 1680 bytes .../tests/text/tspan/outside-the-text.png | Bin 0 -> 699 bytes .../tests/text/tspan/pseudo-multi-line.png | Bin 0 -> 1953 bytes .../text/tspan/rotate-and-display-none.png | Bin 0 -> 1392 bytes .../tests/text/tspan/rotate-on-child.png | Bin 0 -> 2054 bytes .../tests/text/tspan/sequential.png | Bin 0 -> 1887 bytes .../tests/text/tspan/style-override.png | Bin 0 -> 1706 bytes .../text-shaping-across-multiple-tspan-1.png | Bin 0 -> 1626 bytes .../text-shaping-across-multiple-tspan-2.png | Bin 0 -> 2783 bytes .../tests/text/tspan/transform.png | Bin 0 -> 1680 bytes .../tests/text/tspan/tspan-bbox-1.png | Bin 0 -> 3790 bytes .../tests/text/tspan/tspan-bbox-2.png | Bin 0 -> 1692 bytes .../tspan/tspan-span-and-BIDI-reordering.png | Bin 0 -> 3849 bytes .../tests/text/tspan/with-clip-path.png | Bin 0 -> 1680 bytes .../tests-hinted/tests/text/tspan/with-dy.png | Bin 0 -> 1625 bytes .../tests/text/tspan/with-filter.png | Bin 0 -> 1680 bytes .../tests/text/tspan/with-mask.png | Bin 0 -> 1680 bytes .../tests/text/tspan/with-opacity.png | Bin 0 -> 1852 bytes .../tests/text/tspan/with-x-and-y.png | Bin 0 -> 1680 bytes .../tests/text/tspan/without-attributes.png | Bin 0 -> 1680 bytes .../tests/text/tspan/xml-space-1.png | Bin 0 -> 1585 bytes .../tests/text/tspan/xml-space-2.png | Bin 0 -> 1585 bytes .../tests/text/unicode-bidi/bidi-override.png | Bin 0 -> 1793 bytes .../tests/text/word-spacing/-5.png | Bin 0 -> 1704 bytes .../tests/text/word-spacing/0.png | Bin 0 -> 1723 bytes .../tests/text/word-spacing/10.png | Bin 0 -> 1720 bytes .../tests/text/word-spacing/2mm.png | Bin 0 -> 1714 bytes .../tests/text/word-spacing/5percent.png | Bin 0 -> 1720 bytes .../text/word-spacing/large-negative.png | Bin 0 -> 699 bytes .../tests/text/word-spacing/normal.png | Bin 0 -> 1723 bytes .../text/writing-mode/arabic-with-rl.png | Bin 0 -> 1696 bytes .../tests/text/writing-mode/horizontal-tb.png | Bin 0 -> 1651 bytes .../tests/text/writing-mode/inheritance.png | Bin 0 -> 1714 bytes .../tests/text/writing-mode/invalid-value.png | Bin 0 -> 1651 bytes .../text/writing-mode/japanese-with-tb.png | Bin 0 -> 1322 bytes .../tests/text/writing-mode/lr-tb.png | Bin 0 -> 1651 bytes .../tests/text/writing-mode/lr.png | Bin 0 -> 1651 bytes .../mixed-languages-with-tb-and-underline.png | Bin 0 -> 1594 bytes .../writing-mode/mixed-languages-with-tb.png | Bin 0 -> 1864 bytes .../tests/text/writing-mode/on-tspan.png | Bin 0 -> 1651 bytes .../tests/text/writing-mode/rl-tb.png | Bin 0 -> 1651 bytes .../tests/text/writing-mode/rl.png | Bin 0 -> 1651 bytes .../text/writing-mode/tb-and-punctuation.png | Bin 0 -> 1690 bytes .../tests/text/writing-mode/tb-rl.png | Bin 0 -> 1714 bytes .../text/writing-mode/tb-with-alignment.png | Bin 0 -> 1727 bytes .../tb-with-dx-on-second-tspan.png | Bin 0 -> 2159 bytes .../text/writing-mode/tb-with-dx-on-tspan.png | Bin 0 -> 1460 bytes .../tb-with-dy-on-second-tspan.png | Bin 0 -> 2146 bytes .../tb-with-rotate-and-underline.png | Bin 0 -> 2549 bytes .../text/writing-mode/tb-with-rotate.png | Bin 0 -> 2227 bytes .../tests/text/writing-mode/tb.png | Bin 0 -> 1714 bytes .../tests/text/writing-mode/vertical-lr.png | Bin 0 -> 1714 bytes .../tests/text/writing-mode/vertical-rl.png | Bin 0 -> 1714 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 .../resvg/tests/fonts/Inter-LICENSE-OFL.txt | 92 ++ crates/resvg/tests/fonts/Inter-Regular.ttf | Bin 0 -> 407056 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 .../tests/fonts/TerminusTTF-LICENSE-OFL.txt | 97 ++ .../resvg/tests/fonts/TerminusTTF-Regular.ttf | Bin 0 -> 500668 bytes crates/resvg/tests/gen-tests.py | 110 +- crates/resvg/tests/integration/hinting.rs | 293 ++++++ crates/resvg/tests/integration/main.rs | 76 +- crates/resvg/tests/integration/render.rs | 32 + .../resvg/tests/integration/render_hinted.rs | 405 ++++++++ .../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 + .../all-options-comparison.png | Bin 0 -> 3807 bytes .../all-options-comparison.svg | 26 + .../text/hinting-options/css-style-syntax.png | Bin 0 -> 2952 bytes .../text/hinting-options/css-style-syntax.svg | 17 + .../hinting-options/eink-mono-clarity.png | Bin 0 -> 948 bytes .../hinting-options/eink-mono-clarity.svg | 9 + .../text/hinting-options/eink-mono-engine.png | Bin 0 -> 1668 bytes .../text/hinting-options/eink-mono-engine.svg | 10 + .../text/hinting-options/eink-mono-target.png | Bin 0 -> 2614 bytes .../text/hinting-options/eink-mono-target.svg | 10 + .../text/hinting-options/engine-auto.png | Bin 0 -> 2934 bytes .../text/hinting-options/engine-auto.svg | 17 + .../text/hinting-options/engine-native.png | Bin 0 -> 3044 bytes .../text/hinting-options/engine-native.svg | 17 + .../tests/text/hinting-options/mode-lcd.png | Bin 0 -> 2545 bytes .../tests/text/hinting-options/mode-lcd.svg | 17 + .../tests/text/hinting-options/mode-light.png | Bin 0 -> 2858 bytes .../tests/text/hinting-options/mode-light.svg | 17 + .../hinting-options/mode-vertical-lcd.png | Bin 0 -> 2973 bytes .../hinting-options/mode-vertical-lcd.svg | 17 + .../mono-hinted-vs-unhinted.png | Bin 0 -> 1783 bytes .../mono-hinted-vs-unhinted.svg | 6 + .../preserve-linear-metrics.png | Bin 0 -> 2106 bytes .../preserve-linear-metrics.svg | 17 + .../text/hinting-options/symmetric-false.png | Bin 0 -> 3003 bytes .../text/hinting-options/symmetric-false.svg | 17 + .../text/hinting-options/target-mono-1x.png | Bin 0 -> 3337 bytes .../text/hinting-options/target-mono-1x.svg | 6 + .../text/hinting-options/target-mono.png | Bin 0 -> 2531 bytes .../text/hinting-options/target-mono.svg | 17 + .../hinting-options/terminus-mono-clarity.png | Bin 0 -> 1618 bytes .../hinting-options/terminus-mono-clarity.svg | 18 + .../hinting-options/terminus-mono-target.png | Bin 0 -> 1354 bytes .../hinting-options/terminus-mono-target.svg | 17 + .../text-rendering/hinting-comparison.png | Bin 0 -> 4223 bytes .../text-rendering/hinting-comparison.svg | 39 + crates/resvg/tests/tests/text/text/zalgo.png | Bin 3123 -> 3104 bytes crates/usvg/Cargo.toml | 12 +- crates/usvg/codegen/attributes.txt | 7 + crates/usvg/codegen/main.rs | 28 +- crates/usvg/src/lib.rs | 36 + crates/usvg/src/main.rs | 1 + crates/usvg/src/parser/converter.rs | 25 +- crates/usvg/src/parser/mod.rs | 4 + crates/usvg/src/parser/options.rs | 49 + crates/usvg/src/parser/svgtree/mod.rs | 8 + crates/usvg/src/parser/svgtree/names.rs | 472 +++++---- crates/usvg/src/parser/svgtree/parse.rs | 13 +- crates/usvg/src/parser/text.rs | 187 +++- crates/usvg/src/text/colr.rs | 343 ------ crates/usvg/src/text/flatten.rs | 973 +++++++++++++++--- crates/usvg/src/text/layout.rs | 396 +++++-- crates/usvg/src/text/mod.rs | 14 +- crates/usvg/src/text/skrifa_colr.rs | 422 ++++++++ crates/usvg/src/text/skrifa_metrics.rs | 104 ++ crates/usvg/src/tree/text.rs | 257 +++++ crates/usvg/src/writer.rs | 32 + .../clip-path-with-complex-text-expected.svg | 2 +- .../files/clip-path-with-text-expected.svg | 2 +- .../preserve-text-simple-case-expected.svg | 2 +- .../tests/files/text-simple-case-expected.svg | 2 +- ...text-with-generated-gradients-expected.svg | 6 +- 518 files changed, 4510 insertions(+), 929 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/hinting-options/all-options-comparison.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/css-style-syntax.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-clarity.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-engine.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-target.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/engine-auto.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/engine-native.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/mode-lcd.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/mode-light.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/mode-vertical-lcd.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/mono-hinted-vs-unhinted.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/preserve-linear-metrics.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/symmetric-false.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/target-mono-1x.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/target-mono.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/terminus-mono-clarity.png create mode 100644 crates/resvg/tests-hinted/tests/text/hinting-options/terminus-mono-target.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/hinting-comparison.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/Inter-LICENSE-OFL.txt create mode 100644 crates/resvg/tests/fonts/Inter-Regular.ttf 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/fonts/TerminusTTF-LICENSE-OFL.txt create mode 100644 crates/resvg/tests/fonts/TerminusTTF-Regular.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 create mode 100644 crates/resvg/tests/tests/text/hinting-options/all-options-comparison.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/all-options-comparison.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/css-style-syntax.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/css-style-syntax.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-clarity.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-clarity.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-engine.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-engine.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-target.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/eink-mono-target.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/engine-auto.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/engine-auto.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/engine-native.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/engine-native.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-lcd.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-lcd.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-light.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-light.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/preserve-linear-metrics.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/preserve-linear-metrics.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/symmetric-false.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/symmetric-false.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/target-mono-1x.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/target-mono-1x.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/target-mono.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/target-mono.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.svg create mode 100644 crates/resvg/tests/tests/text/hinting-options/terminus-mono-target.png create mode 100644 crates/resvg/tests/tests/text/hinting-options/terminus-mono-target.svg create mode 100644 crates/resvg/tests/tests/text/text-rendering/hinting-comparison.png create mode 100644 crates/resvg/tests/tests/text/text-rendering/hinting-comparison.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/.gitignore b/.gitignore index 97e0980f0..c23714a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ target .vscode tools/build-* **/diffs +**/diffs-hinted 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 5e4fd69b8..f10cb52ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "adler2" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "arrayref" @@ -26,14 +26,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.5.0", + "autocfg 1.4.0", ] [[package]] name = "autocfg" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -58,6 +58,20 @@ name = "bytemuck" version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" 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" @@ -67,9 +81,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cloudabi" @@ -105,24 +119,24 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.5.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "data-url" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" [[package]] name = "either" -version = "1.15.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" [[package]] name = "euclid" @@ -144,9 +158,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", @@ -158,11 +172,20 @@ 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.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" dependencies = [ "roxmltree 0.20.0", ] @@ -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.4" @@ -235,21 +271,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.180" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "log" -version = "0.4.29" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" @@ -259,18 +295,18 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", "simd-adler32", @@ -282,7 +318,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.5.0", + "autocfg 1.4.0", ] [[package]] @@ -352,12 +388,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" @@ -473,6 +527,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.46.0" @@ -500,9 +565,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.52" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] @@ -522,29 +587,11 @@ dependencies = [ "memchr", ] -[[package]] -name = "rustybuzz" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" -dependencies = [ - "bitflags 2.10.0", - "bytemuck", - "core_maths", - "log", - "smallvec", - "ttf-parser", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simplecss" @@ -567,11 +614,21 @@ 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.1.1" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" dependencies = [ "version_check", ] @@ -601,6 +658,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" @@ -629,9 +697,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -658,28 +726,16 @@ 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.4" +name = "unicode-ident" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-script" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" [[package]] name = "unicode-vo" @@ -695,15 +751,17 @@ dependencies = [ "data-url", "flate2", "fontdb", + "harfrust", "imagesize", "kurbo", "log", "once_cell", "pico-args", + "png 0.18.0", "roxmltree 0.21.1", - "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 36d149f87..9defadf5a 100644 --- a/crates/resvg/Cargo.toml +++ b/crates/resvg/Cargo.toml @@ -14,11 +14,16 @@ workspace = "../.." name = "resvg" required-features = ["text", "system-fonts", "memmap-fonts"] +[[example]] +name = "generate_hinting_comparison" +required-features = ["text"] + [dependencies] gif = { version = "0.14.1", optional = true } image-webp = { version = "0.2.4", optional = true } log = "0.4" pico-args = { version = "0.5", features = ["eq-separator"] } +png = "0.18" rgb = "0.8" svgtypes = "0.16.1" tiny-skia = "0.11.4" @@ -27,7 +32,6 @@ zune-jpeg = { version = "0.5.8", optional = true } [dev-dependencies] once_cell = "1.21" -png = "0.18.0" [features] default = ["text", "system-fonts", "memmap-fonts", "raster-images"] diff --git a/crates/resvg/examples/generate_hinting_comparison.rs b/crates/resvg/examples/generate_hinting_comparison.rs new file mode 100644 index 000000000..191bb4233 --- /dev/null +++ b/crates/resvg/examples/generate_hinting_comparison.rs @@ -0,0 +1,90 @@ +// Copyright 2026 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Generates comparison images showing the effect of font hinting. +//! +//! This example renders the same SVG text twice: once with hinting enabled +//! and once without. The resulting images can be compared to see how hinting +//! affects text rendering, especially at small font sizes. +//! +//! Hinting improves text clarity by aligning glyph outlines to the pixel grid, +//! which is most noticeable at sizes below 20px. +//! +//! Run with: `cargo run --example generate_hinting_comparison --features text` + +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/lib.rs b/crates/resvg/src/lib.rs index 45a4d9d6c..6ed57159a 100644 --- a/crates/resvg/src/lib.rs +++ b/crates/resvg/src/lib.rs @@ -3,6 +3,17 @@ /*! [resvg](https://github.com/linebender/resvg) is an SVG rendering library. + +## Main functions + +- [`render`] - Renders an SVG tree onto a pixmap +- [`render_node`] - Renders a single node onto a pixmap +- [`encode_png_with_dpi`] - Encodes a pixmap as PNG with DPI metadata +- [`save_png_with_dpi`] - Saves a pixmap as PNG with DPI metadata + +## Re-exports + +This crate re-exports [`tiny_skia`] for pixmap handling and [`usvg`] for SVG parsing. */ #![forbid(unsafe_code)] @@ -83,6 +94,74 @@ pub fn render_node( Some(()) } +/// Encodes a pixmap as PNG with DPI metadata in the pHYs chunk. +/// +/// This is useful when you need the output PNG to have specific resolution metadata, +/// for example when targeting print or e-ink displays. +/// +/// The DPI value is converted to pixels per meter for the PNG pHYs chunk. +/// +/// # Example +/// +/// ```no_run +/// let svg_data = r#""#; +/// let tree = usvg::Tree::from_str(&svg_data, &usvg::Options::default()).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::default(), &mut pixmap.as_mut()); +/// let png_data = resvg::encode_png_with_dpi(&pixmap, 96).unwrap(); +/// ``` +pub fn encode_png_with_dpi( + pixmap: &tiny_skia::Pixmap, + dpi: u32, +) -> Result, png::EncodingError> { + // Convert DPI to pixels per meter for PNG pHYs chunk + // 1 inch = 0.0254 meters, so pixels_per_meter = dpi / 0.0254 + let pixels_per_meter = (dpi as f64 / 0.0254).round() as u32; + + // Demultiply alpha (same as tiny-skia's encode_png) + let mut tmp_data: Vec = pixmap.data().to_vec(); + for chunk in tmp_data.chunks_exact_mut(4) { + let a = chunk[3]; + if a != 0 && a != 255 { + let a_f = a as f32 / 255.0; + chunk[0] = (chunk[0] as f32 / a_f).min(255.0) as u8; + chunk[1] = (chunk[1] as f32 / a_f).min(255.0) as u8; + chunk[2] = (chunk[2] as f32 / a_f).min(255.0) as u8; + } + } + + let mut data = Vec::new(); + { + let mut encoder = png::Encoder::new(&mut data, pixmap.width(), pixmap.height()); + encoder.set_color(png::ColorType::Rgba); + encoder.set_depth(png::BitDepth::Eight); + // Set physical pixel dimensions (pHYs chunk) with unit = meters + encoder.set_pixel_dims(Some(png::PixelDimensions { + xppu: pixels_per_meter, + yppu: pixels_per_meter, + unit: png::Unit::Meter, + })); + let mut writer = encoder.write_header()?; + writer.write_image_data(&tmp_data)?; + } + + Ok(data) +} + +/// Saves a pixmap as a PNG file with DPI metadata. +/// +/// This is a convenience wrapper around [`encode_png_with_dpi`] that writes directly to a file. +pub fn save_png_with_dpi( + pixmap: &tiny_skia::Pixmap, + path: &std::path::Path, + dpi: u32, +) -> Result<(), png::EncodingError> { + let data = encode_png_with_dpi(pixmap, dpi)?; + std::fs::write(path, data)?; + Ok(()) +} + pub(crate) trait OptionLog { fn log_none(self, f: F) -> Self; } diff --git a/crates/resvg/src/main.rs b/crates/resvg/src/main.rs index 9abac77fc..1412c7b9b 100644 --- a/crates/resvg/src/main.rs +++ b/crates/resvg/src/main.rs @@ -47,9 +47,9 @@ fn process() -> Result<(), String> { } } - let mut svg_data = timed(args.perf, "Reading", || -> Result, &str> { + let mut svg_data = timed(args.perf, "Reading", || -> Result, String> { if let InputFrom::File(ref file) = args.in_svg { - std::fs::read(file).map_err(|_| "failed to open the provided file") + std::fs::read(file).map_err(|e| format!("failed to open '{}': {}", file.display(), e)) } else { use std::io::Read; let mut buf = Vec::new(); @@ -57,7 +57,7 @@ fn process() -> Result<(), String> { let mut handle = stdin.lock(); handle .read_to_end(&mut buf) - .map_err(|_| "failed to read stdin")?; + .map_err(|e| format!("failed to read stdin: {}", e))?; Ok(buf) } })?; @@ -102,15 +102,16 @@ fn process() -> Result<(), String> { // Render. let img = render_svg(&args, &tree)?; + let dpi = args.raw_args.dpi; match args.out_png.unwrap() { OutputTo::Stdout => { use std::io::Write; - let buf = img.encode_png().map_err(|e| e.to_string())?; + let buf = resvg::encode_png_with_dpi(&img, dpi).map_err(|e| e.to_string())?; std::io::stdout().write_all(&buf).unwrap(); } OutputTo::File(ref file) => { timed(args.perf, "Saving", || { - img.save_png(file).map_err(|e| e.to_string()) + resvg::save_png_with_dpi(&img, file, dpi).map_err(|e| e.to_string()) })?; } }; @@ -267,7 +268,7 @@ fn collect_args() -> Result { std::process::exit(0); } - Ok(CliArgs { + let result = CliArgs { width: input.opt_value_from_fn(["-w", "--width"], parse_length)?, height: input.opt_value_from_fn(["-h", "--height"], parse_length)?, zoom: input.opt_value_from_fn(["-z", "--zoom"], parse_zoom)?, @@ -316,7 +317,17 @@ fn collect_args() -> Result { input: input.opt_free_from_str()?, output: input.opt_free_from_str()?, - }) + }; + + // Check for any remaining/unknown arguments + let remaining = input.finish(); + if !remaining.is_empty() { + let args: Vec<_> = remaining.iter().map(|s| s.to_string_lossy()).collect(); + eprintln!("Error: unknown arguments: {}", args.join(", ")); + std::process::exit(1); + } + + Ok(result) } fn parse_dpi(s: &str) -> Result { @@ -577,6 +588,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..7d8c9c0e667bdf5b33effc355991cdf39c7d0108 GIT binary patch literal 1314 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBN z1AIbUfpmR+eM3V7kbw*E@$o^_xVX4DJ3DJ?YFb%Y0ZC?N=9rimAt50{Lqj$;HeA~A zi_2P05CE#sE(!7rW=Mz^P$+o+Az?$ng6nf;w|6X?xb$nu**UM{{p-)?ufH(=!G!w; z2lhAE|99Z@Sk=kEz#`!3;uunKD=Fa`!?T%k zFv&d)$o~3;6C%aR4N=)d0VCcHVaA%rKPOJx;G}AQ>FNJNO<$i~)s7I}xNFX5^R}x~ zXQzo~1n0f_&w1@r^x>|lyZ_Jn$9OHvN^H%~6rG6IHj>=ewneU)zJA;D&$q+#cS)~# z`qMc-pRsn&EEoL;)=wVi`p(VI(L*9zy^=UOH$ zO}U+M_g<~=vgc+GrUzVqAXj;W87 z)*V;KEApt?(e5;uR_7YLVa^@Rh!+pe(~A0ulbs_n>wDG zY~hT*qZDTUCZXK;g;?n&)`>TdudkgRb!^sE&mEq-T0G<5KKuK1m)z~6T>Ta`=d`ls z9sjy#$+V5TtSoxP3q`~YbrO>!5;yoSlo2@Q%Hw@Q=N0XUZL|Zslbp}xM}+1Xh}M#kUY z-_Or4Ha3`uT4`Wv2j1M_`P7srr_TW>D7GByM-ux@ytI^o~j z4J_}^i6y4KSNs+vz3^AcTB(HE$gM0Z{-2tp>OD;-@&pd*wMFVlh}5PO8Z*|+mi-;D zPNroc!>Z+_#* zq|@H9U+Oh$!S}{{9igdfrYDz5zCIcuXMC-D z0?VKNKQNb1VtGLG)4mU8xrZYH+CHkfXdaqa{IA_>P24;c^`57%40`J9rH^e*b?=Sf zo^eD#O#I^+=Ho4etWg^ySk|wa*&Z2sDWP-2jVDoSbQ*(S?LP3k(V?a$^bqsBp6(Zi zPTk5pw#$QW;x(myDZND+3&V8WWm)*<`}DQTicj=jA-Vd|ypzGJo3?b!^Ijpbn%Di^ zdQC@>jdQPWWj`C?cOu|VOnb3s^@%miMWx9^DOSx>O>xDimxt74&1BvKKZ23rSI$;r}IbnMu<75 zX-=D?CK#`7!TLU=ne};y{`7>-exa#<1T;42g(g~BCAPJ`m=J%r!`ADkqCsW)mRTEq z{Jb+q?)HV*f!mnJy2dP6pWlHNj%q+)BGI-zSn4n`i-^yWYJMpsYIe{yuUxAx<2=Sos) zd6%#0Q<`m&T3P!c>c)U7< zWq+!r^NzdLGudRsHY6NuV&xXoi5PSY7Kp1jA#M|bxKI`1PH%4@{WUb8UZ?fy%%B@K XwTrITL`6E}feH>!S3j3^P6slbp}xM}+1Xh}M#kUY z-_Or4Ha3`uT4`Wv2j1M_`P7srr_TW>D7GByM-ux@ytI^o~j z4J_}^i6y4KSNs+vz3^AcTB(HE$gM0Z{-2tp>OD;-@&pd*wMFVlh}5PO8Z*|+mi-;D zPNroc!>Z+_#* zq|@H9U+Oh$!S}{{9igdfrYDz5zCIcuXMC-D z0?VKNKQNb1VtGLG)4mU8xrZYH+CHkfXdaqa{IA_>P24;c^`57%40`J9rH^e*b?=Sf zo^eD#O#I^+=Ho4etWg^ySk|wa*&Z2sDWP-2jVDoSbQ*(S?LP3k(V?a$^bqsBp6(Zi zPTk5pw#$QW;x(myDZND+3&V8WWm)*<`}DQTicj=jA-Vd|ypzGJo3?b!^Ijpbn%Di^ zdQC@>jdQPWWj`C?cOu|VOnb3s^@%miMWx9^DOSx>O>xDimxt74&1BvKKZ23rSI$;r}IbnMu<75 zX-=D?CK#`7!TLU=ne};y{`7>-exa#<1T;42g(g~BCAPJ`m=J%r!`ADkqCsW)mRTEq z{Jb+q?)HV*f!mnJy2dP6pWlHNj%q+)BGI-zSn4n`i-^yWYJMpsYIe{yuUxAx<2=Sos) zd6%#0Q<`m&T3P!c>c)U7< zWq+!r^NzdLGudRsHY6NuV&xXoi5PSY7Kp1jA#M|bxKI`1PH%4@{WUb8UZ?fy%%B@K XwTrITL`6E}feH>!S3j3^P6slbp}xM}+1Xh}M#kUY z-_Or4Ha3`uT4`Wv2j1M_`P7srr_TW>D7GByM-ux@ytI^o~j z4J_}^i6y4KSNs+vz3^AcTB(HE$gM0Z{-2tp>OD;-@&pd*wMFVlh}5PO8Z*|+mi-;D zPNroc!>Z+_#* zq|@H9U+Oh$!S}{{9igdfrYDz5zCIcuXMC-D z0?VKNKQNb1VtGLG)4mU8xrZYH+CHkfXdaqa{IA_>P24;c^`57%40`J9rH^e*b?=Sf zo^eD#O#I^+=Ho4etWg^ySk|wa*&Z2sDWP-2jVDoSbQ*(S?LP3k(V?a$^bqsBp6(Zi zPTk5pw#$QW;x(myDZND+3&V8WWm)*<`}DQTicj=jA-Vd|ypzGJo3?b!^Ijpbn%Di^ zdQC@>jdQPWWj`C?cOu|VOnb3s^@%miMWx9^DOSx>O>xDimxt74&1BvKKZ23rSI$;r}IbnMu<75 zX-=D?CK#`7!TLU=ne};y{`7>-exa#<1T;42g(g~BCAPJ`m=J%r!`ADkqCsW)mRTEq z{Jb+q?)HV*f!mnJy2dP6pWlHNj%q+)BGI-zSn4n`i-^yWYJMpsYIe{yuUxAx<2=Sos) zd6%#0Q<`m&T3P!c>c)U7< zWq+!r^NzdLGudRsHY6NuV&xXoi5PSY7Kp1jA#M|bxKI`1PH%4@{WUb8UZ?fy%%B@K XwTrITL`6E}feH>!S3j3^P6PZiiL!PfP%5Hv21K?nwpx1hK6u8L^Aw1Yu^Bs zYLo=|1v4bX8we;|c(DKc`s?xa^Rwp6KI>ondfDv$`~@2VJ|x_KUofHJfc<}m*N6DE z85me(JzX3_DsH{K-R*bVL!#m0!ZMC2mvX;z?Q~2^fA;r&!F6T*b4OxDI78RW`1~^K zwA-tR^~UqMF36Q8=6ZZQG{vdw_Y&?~>1#wv967~wA~qx(T%`>nn^?WUB=PZOi#XhXqQB`U}9{~ z*42`)D`G?<&VHOfD`3lvb4wGsk~i*J%kuj4^BL8<@{O-;d8V=D*7Ju~(sn%56f3=& zAo~APd)X1L_J<$L=1lSAS8OTmnVMAF>$<&LaCPjw*nKBYZ+Uq0wf51h{3N}&|Jon^ z{0==~`ZFVtFYy$A?EUYzA7(_|4Qnht;jmh5|NiekAG~{&a#J$@(2XpaLmT()yWjTn z<;}dfbtlfBo}Z{wFaOp*FK(M@@>A9W&vL$gap&0Vm^1&F;u>-7{hNOmTq=q(5NWQ^ zXxrem#%IF}-805sh8;hzy$&$FW)OY*)2vUC(K(+Lo^dA!n}*e?uXPTLJL%v4+ot1g z&rZ8FHIH6z)Zm-Dc#3m``Zc?A(i^)R&zMe4E?u82x+u26G{5bGOnX$s&&40s?A~4X z&vD9h;SJx`zn`+qVw%?RTcYY|5tq}?l|}e(nZ~!Vo;Ul?nUnfI&zC0ao)XPy41H&s zGRt>r#M9;Rvy$iL|LC1>n|n2)a!=m#h|RIzFU;kCq-A`qWow7?ZppBnukCJg)LgtB z(ipmD|9o@RYx++Grb#!lUh@r&cw2hr^Hsm}eSfOL`4U$K+fDgyn%J5q-99g0POks> z{dfEC9g}chbJwJ0v*Vfe$oKy$YHBR5G>Xnj)u}odHHRm0ou;{b(41G=2f5zKkfYwzCRUsw(hk2glYQUYi!m$+yDQwMd{sD@2}sr>-BCg zvyGWk_ksDB@PTF4U;eK0{+IFKEhOhqF@sFSnlC{~ycCp2fi~I7l{)rIdW%nUnq89k Z_Wpb4+gYym$!3+-n?HdkkFqn{V{=xMH7xL@l z*FQX5x50mD)}+}xi(mI=er@lVzkdJyfDi8l3KZfK{9CjaGcYj!@^ow-_Zg<(7%hu|8X|xa!z+*5vjg6N8{OrBeq)*w?I@ zz__w6!c{^*GvQzpD|c921QWNIPQ-=;P7rahNfkt}a!)(Z#QHjuA0h=30IMOJ@w&d1 z5+k~Pcpcl2@Rxg|-TJT%Y)MxQkNyA1xX*&|mvY3_0-cD<2O~C|vXJ1umS!Nf=9l-n zh_Ab^8Xdd)%6sC5RTU@J@!VZAJMyZ{!{Rrob9lop{(Sa&xA+=^%xm#Z>W|ZmGV4!> zWD8dR{L>VgH~XoYZNarQ+e;tM(7u-Y$93BK?=J=J=|0+|n|LfDG^c2hJC6?0bF+B>(yF zPxGmf+@~+gpYbQY{r{w6Lk{KiM`lhC`pxmwb@RQW65CVnMRfnrw%mSo7iVR1FMEQitB-2SSF5m{ z+4)eFa_HZKk!wP0&S~u^>A3tkBKG{rKQ5;BYa)#! z_O+Q>$0c5Ud-a-5_L`F0HFDayKSVoCqt{g4O1JNxYWC;Z+}ib96b(=3b*qV~N2u?9 zw{VX~zfYg5Uc^eD)4ycGv=Xa6?Rt|Oo7z0JtgqZ$ap}H#8_mR995z3fp5f5Wd1QF{ z_U?-ZGfTeb$v#ef{_ys$_q$%smwEJ7qvfJ`x6Fof?`^h3Jhhr?u=CxiV*fcQO`>Vn zpKpAo&UN|U&d*xTYXZW=V^_U>9KKxDCi+OBUxeo7k0nI{vwhYbbFH{FUprANiD}L1 zmnz3zdxrkDuJ~`lKw+w;R68h>fy}^~1Fzi|24={+Jt+=(eGx_mt{U8uGd`(T3tT_I TxH=tFx-odV`njxgN@xNAR3#ay 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..315961b2e7b1697faff8799c34519f34a02418e2 GIT binary patch literal 2116 zcmchYc{tnY7RM7Bii#N(xwX}s&w0M*d(J=SeV#YR-p)!`P(ly{ z0tut7%^g7?F!F00=RH#F9wu8IK_JQ+9|HnGJH7^(tOk`l5{vC^oh^RQ+`z4u|9AD(cA6$Ij!K%0N(96!GFS{DqG6N6~p6#scoFB?ibdOH!gjeHe#~oM&Y7&z6VT` z-~)|Llvq6;3Ax%a^)Q~k1;hOiU|bq_dlj!BW)gpX$=^zAg$xNejLTuZ zYicwbt>NEZoLL{58}hycpH9vp#-<~$^D*wweHd|*RSw^BuDKPljeKRh^rW0k zEgrkw@6a^?(`yOsPrHli+t~#7(;6C4?_>n$zLLRDKHpLRPx49-Y&prD}$+ff<0+H?;U zA+f4AL#0)+!NRD-;L$VBk^oTVsjP4T0>obAd|S0IxzezAMk>#$n*m-y`6&2r7X%5X z6H2IdLpR?bmI{>`b<}-}{)%0K2h`XDLsD{>CJ^Qv!$MPQHz@qMtz+@3(E#vtp13@j z5xr<2W;vZCujci#U5qe$ka$@2toS3L;5}oix2!2Me5|tm#5ndOcd>JFq`!K2bFR~E z(%8#qpH)ftNH}<8bhUV+A7^anWu3@uKF~^R7$~(QGWRc_pSs}&wnjQ1R^(>wQwKlH zyD~mW)+;s*u(8@D$_VI-h3%D6?x(7_L)(K#yu`ooh`alxLjK$Zy9vA1rQpunOKRg; zjQda1$7Ul>pLhJe)m!^%cak_~OD0YaGNg(3)t_?um*^aLHtf}iYbk$gUCrFR@gK`| z^{NV|=99nBPp9+Rr&`r$<| zL(Q#wj(&3wo&>cf>%L{?kt=?-hzc9TJuH-UA=ii9W;jT?LF%P zW7pM~+2^K6%#eJeJGnr7*?+fXe=5=)a;Y=NnOG1s>PDL1;-P40+zN8NS8Iwq&F8ep zW+p;E14zo3)%a^|5O?5ItcUmW0u8T~`yJmm*ig-)E`HGr zFa_652hua+3Ps&{C(vqiAB2_3TN{>Ni{rzjeUm=g+{EQ$FGxfO8vfW~(@X6HtR~$@ z<1rO$L!JMozfD5s&+q#8--NI*lHMjyZ{rdA4L$(=UD!*g0Doo+vcAp8mk V2-Ssn%dfvK+QQEK@kPHI{{$oUv-|)6 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..08f21c5083035e4e29e22ea1ff242b1d41f70c70 GIT binary patch literal 2095 zcmchYSx}Q{7KVRFvm`bV*&Af-umuoML_s70*&;$9Lf}^**d%QutL)Itu4J%vKoXXS zA_!rT2>7$LEQX~uL=;*f2qLnJ?8{6F5CR>`o2i+p>Z_Tr>eO@UJ*VDt^Hsf>Zmy0} z2xSBS08%(7I|2ZR7=9^9m{4&oO>z_h9_|E20s!*&FC~&|fK(BRG`Dje_Ch8nC#R&O z2%EorNF-8AOG{s0-`CeSBqRiZK*-3*n3|d@Dk_SLi(6P&SXx>Nr(X^6csvXSv$M1N zOWS{2NJ=H)g_3C$!Sy`gPm(s#a9his_@lq}e%9MsW@O;xtHSQZoZIDh3lsTNJSnU$ zyf}HBz3ShQg4xH;?$56RfP@&%&c-9|-O?W?L;y`WF_Rk#L(|(QVqH4Naj3Fa)qfj- zes${gEAbbAfpT_vhTvriH|M$`2$BCA9P+iDg*#t{|KDb)yD#3P`9`FO#}3ND>cY+~>I_}Z^!DvCaTi9dno9J%4)`10i zbFf@}VtW%0DqSu5B?NjX2DLnctjMJG;Ngxm zvJd)zliyvfSP9j82K7%KcO;2mV~r}7IxBr)*y)VwEY4V{b$!g+&!SKbBijdV1kkzOHwm3F zYn8$2(s@=Hyf*XsldrY4ex0#gxOaHqMs<$tt?dmc4&AFcSYaJIz!^$Y=NskoV4)uo zJv%5=A`&G7+J3bCbiO!4us%Hdn&RwKFKwG=Tgv{8C9Rff;!oZ9eu8Qp|D;N^W^gc1 zEj>z-XSO3D7=faYK8%sNdH%2uw!%KhvgjEwG4svOuNkAJbLV@Gm~=>BtF~-txQL}j zT&GLOMv1Z7gr}3pJL<_%4W2F|V)S&6C%OaALEbTyGa=w&1Htc>O69^UZZ5D0j~a|} zw1-7gR-QX#@;D!rZ&R2u-&sh7%gju#qkO!Hvc6FM)3~1`C{O&380f46;m7W+(lw{L z&ME2_EzjVltXJ%jD-d+;B|ShQ5+~rV zgT)vZjs#`ISh!u8Pt8s%?0rzcU9ct+F*JFpy6XvwU|J1u;#Q`6B0MV+d`ZJf+Sn^p z^BQ}FJ$CO=)!znuTlF5ljE6jsx1LrS%3r3P5q~v;*Eq8qSpn)8&`%vxwT^Q8iGhi^ zQY?Nny4+CKh)~eda*cKPtg4Hf&n<01zh`!1M%CuMT)&}SvPc6=wFfWi3(!O06Z|I- z9p-OY$iBvMEI#EIW;|AIq2R3XJ3C^U+E9?zCHy3m>B%5eqQ^ooh@O$$aqc0=e;c>` zP){j-i>yg*Q=}d7?T4~{zTZV^#=KA7)Snt{9c6FrRkVgNKO#f%oa8Ld_Z{PeEq=wt ziMi2M45po{&QAWky1NBi69}qCH=8lAW{e=Nt#I`zRUNgargVz$OTsQJLn3>HS(91g z>}{o{cBH|W62yH&?Y=~d))5&dhd>ICx$lH92Mbv)d8Y^8dc|U{RGEY<(h2*6US9lk zPgCj`-&2r9c+t3wpv(?RuK!oR^++ zY_^U=6+2la7#I2W@xcpKWmttm!!s;T%eYTOz3Q~Czr%jXK5eO)#3|~1_k)4+7&<+d zo0E?%HRPSqZH#YV)G(GKJ+=`Perc|IUR&w6>lXu#WvL#hrZrOi$odBbyUc0B7!8(N zo^D=lD(1KfyyzLSK>mejS`Q%+Vo~e%ac*SsQ&ysCS9s$n!U*ZUtUsZpN~B$0I@>l+@(4rwyWUoE|gx#oLs&&9ilh zvzxK(VZ}SsX)d4JYwr^8YX*%fJvaf*$(n<6(;Z<@UsCOtfJ+)Fa8+jV{N4cE zH5_A;b4cr7B7$}Bf0z~7Uo+@GFck3hC~*}?thasn5biE<3B9XdLGIi560kUXSGyWp H|Fk~=HQ%&V literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-vertical.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging-on-vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..1f9c332da0d3368951c4054d23fd79e6506345f0 GIT binary patch literal 1635 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging.png b/crates/resvg/tests-hinted/tests/text/alignment-baseline/hanging.png new file mode 100644 index 0000000000000000000000000000000000000000..26a51e43e4b7db89c2195dd50c3ebb104f20e7bd GIT binary patch literal 1315 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 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..62f85992f41a4133d1741a3293aed1a0367151bc GIT binary patch literal 1330 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 Z_Wpb4+gYy(fwYBx-%a{N9 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 E3vz5ey8r+H 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..5f87dc61026ab92706587cc452aeccbc20b96e2f GIT binary patch literal 2123 zcmc&#doS6iYQfDbxTn+Q9%;hR47VFYm-rQkRL56bK0V%Rg^N- zrpXZ3PA|JIk?xQpgD9av8Eep?jMms`O!?O6}lA@(Q((;IJcdlf`0z zASfq*99W<3$K*da_(|Epow9$ST>PZNLHG{Af>=3$fDk%JR{>Sz9K}MRK$N_Zyq!FC zW4Y;oIzSG90WtCv2EuGuHW(HrnU(Agy6c1bIyyQ40H~;_V6j*T1Y&G#jK||K7z~|G zr%)(1Ha2oseo!dX4*85Z01O6`ZvltH|4sj2Ng{DGR$fE;G89Jus8QP6onVnzyJ)J> zacX*HH3aFELhWc2zZk4xS8pUPo#i)HR7REb<11J*^_8?@K|g+pz40ikB9VEwrn-@J zHj3{#!+#M%?O2^oS#cahc7mSUUird5;pHpk9mRTwrAwE^7(LK&w-R4#W*|BzE_QW+&yfMl`uOwznkjzl8zcvK`AJ=>JN1Y?Br-;{>}aC2cmC zU>F}M6J@f?gJw={yq}uuYg@N+v#PR}92B#nV-FBEzP1Rm8B!Wmint0J*_QERY{j~u z9;I~;lK0^VOM@?MLhO1}V3L{t=eWWS4<3Uzr(LX@lm+J%ou7S9#%{i^zAH7LdcSvg z4&CJuK-%SjCB0@tx$ltCslkH60r$fa_Z!8A=bv_ooKU!BqM1cuf9GN~<`O?Ujx*CH z1N>gr#8O74!w1#STwH0nCSXQI$=reg}iL}MiqmI3o&W2$VKGbn6s8> z@Qd|JzW}EB%dO)R+E2J>JBEh~GvNXz=b0x5D zKDxA^d%LE{-%Ic$Wk^F1a7wy*{ zngyy_)0wEZ+zY;zLVoLY(jo#l-u-IC%gTlEY8B*Go$&tIX}d3)qvHAko{e^@($1jIZT=*tQ z5n-%Gi0o^oEoS>2R3Wag!^sNy4{7noE{zwSq|E(f+c0Ft2f+beC2`?gSU3Tnwp9it zt%^Dfztg2iplP^v6JJ5ZQqXk))kVcW{)}G$oomw`;nGVs8yyLE|NE0<&Z0I6FiH+n-lFzg?{VXq(JIZ|6a&#!{QhNIjIIb+u{2QN)7@o zYP|l4rgd3h9n~AL4&v5{#jqY6e90BuXb!-BdAs6(d-DDa#=VSeBs+P<QM9d6?WN5-t#Bi$MeWPU=WjCBBeEwwt%l0$JoXO@ zul*8a{8~is_f2H!@$^q2%rkC`vDDrKR_r<4SK1+&_TSH9z0qy_P@Y`MfA(tdbf?p| znFcaw6Qi!REw!cCPim?9N{6O)@lLb{n$-Ti`XSrJ^OI-Tvn0L# zx~${cw!^83R$KoTz9s+X!mk9jvb1B=AJyif&0ucyV?+ku5_(w6ZtwEzK4a-^DDT86 z2q}Sy2wWeRMk{hr+B7mr^tk`gFdct%+-OiAv9?K5=I<`gBUinPLpCf_5uP$V2_tFl1*befMu0uyGf`|(~)JL+r0uullauGTxE5{A51>a@OcuYoq3@0se(Q`Sr5O literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/-50percent.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/-50percent.png new file mode 100644 index 0000000000000000000000000000000000000000..3ce37d105a79d9e34601a7a74d351d9c1c0d8752 GIT binary patch literal 2086 zcmcgtX;hPE7XD<35F|*Z6on{=0wS~~Wh-0Rf`DL>0wP~37$spz3Q`0VG33)I0c{ak z0wpX#KoA090@#9BGG&n@L@`)4k) z^VWtNzyScz_VvLA0KgWjP0>(QBDnHYZ>7Q zKoArI#lRpKj)B8su>eDf0s!=0|JDBwqAXDI#rIn2004%8F@a1l5XOPwpbRY_3j~DN ztWh!pKq8SA78aqQp(Z9K2m}Iy!NkPGpin3{9Inj5U@%oxRX7AkL8$-wfbt;#FkzS| zwLYYegpgPWyE*j#BD|6y{GVHgsR@0`I5;5y7YL9}M9WiISwaQmhGvlBmW;U%OHaF= z;B$-kob1xd!S?Y!Y2_LIASb$IazeiHs-F~rrz*lY$R=Bu^sMgb8{nGH$ZN1>S%1* ztBAxMvj;70-QI|^P5szbV9)LxI_Nv+yQ$2Rk0lk+hLxd|ocwB= z{hU*4dz1FRx@#YZ;58>ButV{p-&M?Jp$FFS4(1dxG9!{z)Ho#BW z_fUJcP4s@ff#n&Tp@Yp1)&TR{&r7+Tj7X_U+nUOY6^d#1!GX)dBVzdIP2P+hWtEfr z(=)bSSgX&Id+N52RNsy0eiOjTR?qPs_)X>xqIiYp)VrI@4_l^C!6lG9eCbM{W7+a( z?ZrV~Fbr%BH{1OXv#TlRdz(_&E3v@T%@!aOF>1KE9k9r%^2hF!&#J9^WV%8J;CyoU zZbvNod3h5t^Nkschd6NB6}e;XQ*qAL?sZ$qp*ZRC-JDE=9j1+Wp;`QhmHrt#WwK~8 zc`Th6Va?~Mqz$Jf3VK<|d*28@e_?EyeKnaB>+>TLmUki;Xu5#%2`_2gJ_)`smTQE} z?d)WgguQ~s+=F$P%ON7CgSQbyPd$URpSgNyQUaLyd2BFP)9bKa8IF3hmy`s~{A`*8 zVDS+k54^9T=d*5j!?dL)&Ph=5CAykU)}B}|w29aJfT{z2h)zAyxN(a+?#ph8;%=Sz zeo)*>;sWXC?ZN7g64bV0=J(N3s$p4+^)5J1-UwGsAC>ThAXO2=tdffiI$6epMaQ&% z3nlNW+>?&2>rUk36%z}oOqN_!6S#NJU{UH*8ux*z-_ht=)6VRz3E5rEWS6n=cllP* z0a^C7nu`Nwpc%(XCs#DED!PNNkPkWj(#hAcUd-GGDN(Fl=D8jeBh}l65^GkxY=a0D z_T|z&e(_zN1s*8)bnhbzQfouA5wlKkPqOw*OMPQ*gFzmK?^oOjy!@Ta%6gVp^!Uhu z)qe65lwe+n9aL#ho9!1*6*M95_UK5?x9#)m)00F&zE`a3s@P`??bJsdieo((UAa#O#}$fi>uh{&(SrIproSizH@e(M{8vix1Fbr1ifwDL z_}cT=XM;JxDH-Gp=lWadYI2Z~I3Vn*4&^ET>iR;LJcY=BcvpOToQ%dSi%>?pd|&=N zyX46}d?A@D)sZ=fr{2v+M^n@1F4(5 zQa0A7=^xqKG%eWXQI$m*sjt?uwBKuXhRDkcWFz-BjTA2o%n;$A#ml=6cRoJi0@I<@ zKE>U=Ajl;aJ56&|S~=lR4=pj5z?MbT)N^X4Z;YSnu`Vb2nOkOtzvhw;ebv_T)fde& zeydM^;b(Yc`12o%;@T&xl4iL8prHX2#Onjg*Hw_C652I1_;>Hv_pATULp_wIKpFql mwEz1G)S35%1tS|f{Y~s>&FK{y1WMQDmGkw&Ve36emwpGj_mqJE 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..8c1320ce9d041a4b92e9616fefabf0511f3ddb84 GIT binary patch literal 2092 zcmd5-YfzI{8vYDBoxC9yn6%#NZghB!$e2@l$g~gDD0O2MU^Klc! zT2Z-`$ZZj*8X(-%h(ds(1qDPzpt3?#WC#e93REej!R-Fn+1Z)>wXM2sj)Lfk05Z z>P3g>csyRi|AA=$3WdU8F#jU{7tO_3-+k(_fOtQj!vHr_e?tM~KGL7aU1TlTO-$0b z?Uwa1vhqg*BlWYqGNH0cCQ4<>L&aT^UoK1fn6t~0RCzW}R8?MtzbV?2?&6>P)7+yyT7Z=i+%CuY#>;nwao!yho`1g5cm4EO zBZ2WCq=LI1#Dl+*l7bq;doE`Er{Z2{?Ny*L|Hnj{jcW>t{sLK<{JNL-JzBKOp{xA? z*8T+Z`NomD@SvKXzH_{8G~QpDMJ%X(_j+0{;q#9^Rh_yr``iF6++x#hkcyC9EPU3Q zKD?G1A1K58MQ;`0OH8yUB?i%3H9Q<7wfN4glLZ(N&` z>J8V)fd1$=mfO~5vFkix*w`aI2UdULxfdYFg94bg2@&+Xl78CO@sJ1OU zca=HNUWmJWsW_IB-|D==s}U7!)e=jntMb7~#uy0;AD)t0>Yc2HAH$WJq+x#+>{X~d z%xdu+*B3u2nx_ZSgaM+=7DO=|tsLr;xLG2A-7QGSIJjqj#RHt~m*q3TX!hI-YpIpP z39ozOAks>!1adow-;I0^3*}g3GWo-uM-@8rpY?pws~6Ecr1jKeuL&F3(v)j+`$=B( zG+;Bi@1kMW-T12|K9$2=QNYhgV)gy$%l0Y7x>EVu@|(c}W$hf!FW`@~%Y#E-aJv=n zVa7x;zBpGXivxKx`p?28lUvT(YPnh1ax6?Kk)SL>a$#<4$9^-gnO}CROJ$MKjd*}- zj@CKL%diTjNOw#|ethQs(G^a#%&1hiw*I95#`$Dv{WIS{&{f&Zyse-DuJk3Q_W~X;6Do0({XhpX=@migYm8|O8le6X^Z)`hkG|8Dp z37@6KKJ@&Wn-q|KGi>Z!Dkp(`I1=<;DtCN+=gcwjRH_M;m5Ck3j1S9R#DOc^gP^%+ z$MKs9Q>e2U=WM@q(n_L8-6OXD_8djY$r~LqnjPA{|6t!K3i00M;|Eq`*6fmWV`ULP zmgT)X+I58uCz+$x*w*JaVbM4VLbawb-iomCz^M?>haVeRX>jGY|I(@ zb|&g+fP{Dra%=4zkvsLwQb5sM>^Cs>S~;sg5oMb%T(|d?rA(Yl(8h@#%6s)haup%Z zT9)}k+OO0Ll0~9VAMP#OX1Rb6+WwU=0!}-5HQKk(YRf zkIrdrcS`c!ph-gr(qa!6CBf?gC1mbEX9`l*_G=j!MN7x#R5VS4>=x(u@{RoWetiGG z>aU>;OJO1B@p(d5JCYzTgVSzd)#Yp4iA3C=b eb~Px~H_F7+@{-5|nk6bWzd%nnA9|fDH~kM9Uu+iu 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..6ce01fb822ad483c1913a83454333121ece3c4d6 GIT binary patch literal 2061 zcmd5-dpO%?8~#NqB_v2SEny>bSR!2;r=nDFR z^Z9%b1T_TE0RR17Km1NM6b*vESN|Y?h<{N)00zP|elnT-+vO?m+d%*eVzGQI5hNl( zBn$?FgK!iIrFqKC%nS;J5{X0_jmG72$sier!!emmO-Zw`SnLMbKsX!@qyR`H^3US` z!`T_~(;6QwJ}4j&>&Ks@r=sSV%bh zKZ(P9Z_t$9J7;G%^164U_3t9;w%g4QoD8hHcozD>c2MUz(NKWg%=RfIeyZpVza(F@ z99n1Z_lS@ml7sDg`8O*lu z;H0p^#_vips!;OgWFVN`3y*Oe?$s|$|D;qIYtb0~%lA!_)|<-p>6x3+VVfHodv~OT zY>WD`V`Ao|&UulWN792qcjuqIPhtn{8N4B6EA*5bNiUMI-#Jei7R5^9I0 zQ-~{@WT~?Qc!m~j-^?3Nc!ar`v@gNYh|xHESW9-G0%i12?@^xz(;NO_%CN8u(U%eU z5t>fCY%l21FDQlfea+5u73!?5Him>Ds9OL+l3wD7BwQM&o=bPNEdN5+uG}ZeMtKQOh5VPyn?Hm(kJnplWd0MnuiLR6=2n3Eru{PQO!S zE^m!BVwgKk{dE69e*SCq71{A^W@(B`0Kt51+s#mg4kjtk& zrcNI_G~%PH^diy33l^Q-hH7KJa{_BuJs+)N8RrG?&*1jwVQ9*auS$W(xvgTS{MXa}J9ap~N`T-rh z+Us=3>$V$Dcjs9S=tSP7D;^uaYv4a_%d&pOHwW~_Pkok&;~NDX6(1PN47FNZyLh2( zFeWC8LNzI*IjWAdkiE0JyD)y{^yc_WP6IYq4TP10o@Rb38##utz(Hw{f@!Y2rnDE# zvB@q|SLP35&|A)71G3|3DfeZCJz-u7%Zl+?#AA@C{+4{^-LMq`!GiQtoI{HqBl(~#>pWzd`0w0r!BD^J z7t5YWtF;e4V_*IkijXsLL?1RBnC(Gn#VJyuZPnI0=ve!Y9&eBEH$@w&w1wx=***zQ z(4@g=wjwq11=pf~EP+(xTAC1OaI#8F61x++d7}1vY0rOL9-lyr=og$%ySy{fnF>Wa zu z8!eT3U`K@RuI)3U!m_t-{9Mk)_4waTtX{j659QVJt>!-MSZPn%Qv=zq1F>MF=F(vw znEuk&^2B)Iv4dUIDrQg8>A5FA65Tpdwe`>hhK%)(BdCq3tT$$(ZcJFHnX}1wqY}Di gG2CTZoqQt`XRul}J?$)LQm+4ezTN@kIxkl0uVCR=5dZ)H 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..cec1b5774495b98f4c942dc335102ba2b13c1ce0 GIT binary patch literal 2094 zcmd6oeK^$V8pnTQX2i&Zn8;L2S*&p~TZ+^m!+2+lX(*Z5yyX3TYqZRd6wy)Strb(2 zG|k{=jIF%H80>1&*fR{W$gV|R%1V^h*pWTgwdb5a_OHFJb6?MM-=F7u-`9P8|9h@@ zx|3B=+fe`js5&{4jsXA+zkZeAa>f0dWU{;{M?3n&0RXyv{lfB1(7JMQ-qY2~US63@ zCJ2IZ_>W)$04VPPK+4A~hmEr#{@3%*;s%2N8br%C;FvfPNLpVdXAl(Q^pt)TUqO=8vN002}_m8GM}lJ0WqvTx>wjF+lY0Kt4Bt@r`MBTuN_cP4p6M+7rdl; zTa|oiX>9gj1zKq~dN~?dELd;k|moJWFrI?3rbJk(}l2ECPzdP65gkZIW zj_wwmOE^O{qzbokPnGb^WYo6lxO{x!p+N~-Dyef_E!@m`GkhwzVdZpA(98Prg}fii zIYIF5h0|u-v0H@AvFX!JH@$o;i?k{h5n)9m?oFpJ{OXcOFz_Aj_hn7~xH2B-9&$L_TNN*rm0Aiqzex-H*$kg#$bCgR?zs~#orr0BzG}toFzTO+8hlNxlrbtBR5z{1X~U=4lxt)F{(!4s0>O+2Aeoi7UA2r8D?#i@H=cjL9funcA;>uZwap zCHw4>8rAPp5c!t%Zen`|PMib2+7pmYS5JB4OPzZ<`A`(9BpNL9Zg-r|&#O!H;e&Xx^lj?4Du*|&ZT01DgZ5&makNS(qsYfCen1A4blUU?L zEX7ftf3~>F>ctj$QWxolI{sS~#CoX*301<&_F`)BL-%mlSogeUz=>!sa zF2tMGahZmU73LBQ%e_;yic%|lH9~QB+mE=#L?{(pY`8dPYksGeoLj9-4Y$Gb7fixb z-{r?#bu))$sl6yMpb*+_&xRK8_VHX>zi2EI2V}1@l&dYXwT<9IiL5(^iFgiDPbR@_ zC3ZM5QmZ@i6L%Z4&_kcWL<_dht8>`<^)$soX9)M)!GehYh41;;)Ejrj^|vkzml~B* z1lm)eQ?j#FdE(^LUzo#Oe3VI16`Eb=YgZeSE?7L(Q)&eoraqy5_q9T*jN{WG>t6Qj zOk957-T-jND;KT&lcz00j!s!^5e5?We@IMNIY3?9Jywx?z_roj##(N07oYv1WX9u2 zW#L$)#jB~=_=jiuPK<66kL-#$hL#-N*E`vk*?;5kNr`}{`i>4$!QiP7O^}NGe*>34 zOr>l%Lu~le*f8rNO+%_kyM>6HV)ZbdHc}j`lsk*?@p>dN=yA6 DpD2J< literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/50percent.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/50percent.png new file mode 100644 index 0000000000000000000000000000000000000000..47ba520d5ea260739be26a27a01b8566813472fa GIT binary patch literal 2050 zcmd6odong8aTdC&Vi&-Z+u?|aVozxOJ| z*XON1G#brdFnoM`5D0|KAUj4zMw?=@!(cEt9RAB$$#vA;Fi@oAeY6Q@5$ z9D3Vh%Z|aR;X3cUerFhqZyH!&Jy+^V_*j^)k9>N-HRzUJrOSP4sOF;Gpp=gAbm-Vs z*c&Y0IENY%WV}}rLf5cs(V{i;H2+wRM{3bz%-G1ti$0B)nnRC9`)4t1|1iC)&>JEa6W<_z#Z(XC6E5M9SGk{e8nk?JEBu(+$2R*?+sH z^_kYHrjY5CcsZxA5yddQTA}KigI$Cs^fTT-Xcor|Dyy6g+cXLg3U?clIr*oQTmsJu z<_Z~&~ma9^qxa# zCRJXsOpr76_vTozhe;@efQUhDM6-4vqu;j_T|^N%c$XBVk-p0db7#eKq(FaL{m;_S z`?%3KP4|x)7EG^Z_oY#XOP6ltBTElSRj3f8j&ygSA{P&JvYcx1X80VB4xn{P0nhc^ z_1%TcmQl7z<`}ogz6rF5(oO^lN{{1CSCx)Wb<@545J3+QEBOtihupCI0Y2G1VPE97 zHARg40F`WOYNh22Nlo;4*l)U~vQfPDLnKoKtxd6$6;N&z*0q*tWjJxP*71W};drgL z(RWvtK1qc3d*eeN>6~Ov#;j3>hRN`WYg6PqpV5UgA+dPa79}Qus$0s@!2Pmj?EaWieB$D@6?{Wj-RQS9&R{4N0e^9u0Z2nn7 zhSxWt>;1w9wJoPAE2@;gj*o#nkUUY-N}HDBBonQBJaEOrxPP~L1;Jx)ztSDk$8QlL zW`U(FVo~6l*8@H3g;Y&p_wfeM1CRazAzu((bw`2j{eos67l3Il;A4AmkOa=_HyZUq z+FayXs%99vQlf}{d8#qCET${sH2>+vX;pvaw>MSj;Wp;vcPh5M`1JbtRQYrc#Nt!e zJ-tejC0M4IVCVR*d6F12nxI?|>$<10so*OQ{OPA)H%>~L$<@-)e)7_&ZpLqwG?TMk z2UA2pM_qB>ag2NPAF9_Ve%e8~<|C~FS8v-(=jjLr#k60r-%$TZknyy~g@(8Q!1{Y` zZ3g@N9@!iDuWqim_-*u7%>xx7UsH{PTQJSJP6yd#pSdu~Kv@kVzsn}MjmXUZ7wEx> zH_lu}yM5}MMOhfzv?jac!9Df2rX`T}z0R`KE$bi@3@huE;eNcE(TKHYrBWLDH+5AqD4`Sk3gC&}to=lTO6P*ACZ+WE_<}r-kN1b#08l~A8TOgN zLB&;U+rE{9vy49Ol>-3s17f57RyM{tLv6i1FN~(z_WXF(a~1K1L&U>um6!9}@#=A! zIin?NYROGB9Zz;IMlkjyuw}ow!Ff_v?a7k~Tsz_spLC^2-rz Loe7VQ(Ahr$moRcH literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/baseline.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/baseline.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1320ce9d041a4b92e9616fefabf0511f3ddb84 GIT binary patch literal 2092 zcmd5-YfzI{8vYDBoxC9yn6%#NZghB!$e2@l$g~gDD0O2MU^Klc! zT2Z-`$ZZj*8X(-%h(ds(1qDPzpt3?#WC#e93REej!R-Fn+1Z)>wXM2sj)Lfk05Z z>P3g>csyRi|AA=$3WdU8F#jU{7tO_3-+k(_fOtQj!vHr_e?tM~KGL7aU1TlTO-$0b z?Uwa1vhqg*BlWYqGNH0cCQ4<>L&aT^UoK1fn6t~0RCzW}R8?MtzbV?2?&6>P)7+yyT7Z=i+%CuY#>;nwao!yho`1g5cm4EO zBZ2WCq=LI1#Dl+*l7bq;doE`Er{Z2{?Ny*L|Hnj{jcW>t{sLK<{JNL-JzBKOp{xA? z*8T+Z`NomD@SvKXzH_{8G~QpDMJ%X(_j+0{;q#9^Rh_yr``iF6++x#hkcyC9EPU3Q zKD?G1A1K58MQ;`0OH8yUB?i%3H9Q<7wfN4glLZ(N&` z>J8V)fd1$=mfO~5vFkix*w`aI2UdULxfdYFg94bg2@&+Xl78CO@sJ1OU zca=HNUWmJWsW_IB-|D==s}U7!)e=jntMb7~#uy0;AD)t0>Yc2HAH$WJq+x#+>{X~d z%xdu+*B3u2nx_ZSgaM+=7DO=|tsLr;xLG2A-7QGSIJjqj#RHt~m*q3TX!hI-YpIpP z39ozOAks>!1adow-;I0^3*}g3GWo-uM-@8rpY?pws~6Ecr1jKeuL&F3(v)j+`$=B( zG+;Bi@1kMW-T12|K9$2=QNYhgV)gy$%l0Y7x>EVu@|(c}W$hf!FW`@~%Y#E-aJv=n zVa7x;zBpGXivxKx`p?28lUvT(YPnh1ax6?Kk)SL>a$#<4$9^-gnO}CROJ$MKjd*}- zj@CKL%diTjNOw#|ethQs(G^a#%&1hiw*I95#`$Dv{WIS{&{f&Zyse-DuJk3Q_W~X;6Do0({XhpX=@migYm8|O8le6X^Z)`hkG|8Dp z37@6KKJ@&Wn-q|KGi>Z!Dkp(`I1=<;DtCN+=gcwjRH_M;m5Ck3j1S9R#DOc^gP^%+ z$MKs9Q>e2U=WM@q(n_L8-6OXD_8djY$r~LqnjPA{|6t!K3i00M;|Eq`*6fmWV`ULP zmgT)X+I58uCz+$x*w*JaVbM4VLbawb-iomCz^M?>haVeRX>jGY|I(@ zb|&g+fP{Dra%=4zkvsLwQb5sM>^Cs>S~;sg5oMb%T(|d?rA(Yl(8h@#%6s)haup%Z zT9)}k+OO0Ll0~9VAMP#OX1Rb6+WwU=0!}-5HQKk(YRf zkIrdrcS`c!ph-gr(qa!6CBf?gC1mbEX9`l*_G=j!MN7x#R5VS4>=x(u@{RoWetiGG z>aU>;OJO1B@p(d5JCYzTgVSzd)#Yp4iA3C=b eb~Px~H_F7+@{-5|nk6bWzd%nnA9|fDH~kM9Uu+iu 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..c75e1e8d120598d3a5d66e9bdf9cc71233b3f4c3 GIT binary patch literal 1565 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDf z1^9%x0%;Ja#~>SFB0vUMwxOYcp@E^kz8HXtFU6S08>OeS!G*a-)PfTUkKhy{^e4N(N+LdDnoo6x*9K(=^8 z!rJ!G_@=L{rw<$knK{21tbFCJ%r*a}y-uuM*R%5z+iSb>#;qNxn}x1zJ@YnEH(4~F zgF7r6Y?5|p;=y0M*P7>Azw(u4d&F?hI8SP;W3U7BbRVuMX)~=P1Xl)r`n&%|4Xd|= zOkwTQcmG4y*!?Z}X}w9XGWI&p2CMn?p{DhU2-gqo1bC#CXv_^wlEj#ZY573XQ-xRR#&aqP(lZ%%} zoOCar$Gdm)k3?T0AG@zUeduZ1L%T=}9OMdY@=?AvJh;Ye0(_~iGzYcC!U;g&bF3JaFb`L_Fr*Q#K# z&p*Arjwk)x&39h>`@8cYItRP9#(W@V5HBCLf?8GA_UhfTEFETj81aJQg5&pSvYC@vz%*OBC+c)b8>&%_@_CRDo z-u@lSGFM&xa(vON9Z9S=p9uI~Dsg0B$)0$?A!MJW`P1&LD-D<5e#X)L6#CLF|)Y^m%I-;?00bpFnbwY{vTpYHz=(715vQZ;!i19ncPTf3RL z8xl3T7R_&PVrBIBCcn9)$^Ue7vAYHLo%-9)&wb&{PP>(!R&=i9TnpCx3C_yU{Ee1% z=_aKLDMY*>MaDF!GoZyv6RUR1)^%=C`eDYQy;;jXGU&Zu&i(YalQ*dF^mO%eS?83{ F1ONtEdrtrW 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..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..dd4089f7230ddbeb1da51fa95f16a079668f7650 GIT binary patch literal 1588 zcmd5+X*Ane9DNa6gjgc6cZP~0DN1QMw9yJOmWGlAQ^}C&O4QQUs9KWHYO9vgj-^#g zdyL>;&U8q75T!l36Qn}5orA_wX=^D{WzucF&4>9m@4Vl;_uYHn@4Zj&6eZ9{OT$7Z)8EEG;c9Jv}|a#wJ3MF*0JI(Z{{L&0sJE zKjz|cA~G@viBz~OeSK>srEMxIX-sAq3grxk2LNCSKs*5M0K@=b4L}M2idKq-x!1xT zDK2nK3=Z54h-=&B?W^v?*^Q-ToGcxVY&EWEwXC$JLG+Nn(ovl7;_8ECdAwxd(FfW@ z+~RkUOe5)GPXJU@$zGlz$D}iZBo>^a4@A4zvHm=ojj#kd#Pq-xGewyyNG##YO8?C1kTMc0nAH3n`D#F4bBaU%K@r`XJ^Lju z;HK=aWAcBouWMLt4jVeM{MfiNhsNZah;k%c3`Y|`;+KJ$MN@B?3ywX8ursBSreOz7 zFIU5Y%CUmc;pVR5wYApyXrD8SC6l@h??XRoLOjowaK^kSN6kPG@Tfen9W%)4Rh=$V z*1Mi9XLWOYuK77<`T|??rVqT(@(a{at(fS5=eb&A-hplVYKb+-K^c2D3Mw&?A}1{0 z&YjKp0Uf9qtR$4U5sZI|2cqF>#xzUS7omM)U^*`*iTWm}8JDjj5= zog2JICR!j;`w_@ULp$YB|I@q?tC!K|JKZdx8==1IN}gU^(+%ZP>9yC5R`c`Mk>j>N zV)gst8Yt=Y;pxGx(fLJTEYfj{Aj@$g+P^SeNTs8j2`5EiL;YJ~YYy=FyWV8wd~h+{ zYIK)#1^vt$~`1^9AzBA+zn5F8P~ z>RoVnj-oH_Roj_Kl*RnW>W$2$2r*Ex9ew24fZ ztDq%8#ju@~cka;ga+6S`0&DD0!JrE9~m4(<8@a zy`@#J&MQf;aE$@cP@PFof4WkK^Avqt+>Z+>CNP?!dkS!V|2KmD@~nS@jqHb74%_iw ccv*{AQDObYaB*ul*F8z91&(*OVf 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..dd4089f7230ddbeb1da51fa95f16a079668f7650 GIT binary patch literal 1588 zcmd5+X*Ane9DNa6gjgc6cZP~0DN1QMw9yJOmWGlAQ^}C&O4QQUs9KWHYO9vgj-^#g zdyL>;&U8q75T!l36Qn}5orA_wX=^D{WzucF&4>9m@4Vl;_uYHn@4Zj&6eZ9{OT$7Z)8EEG;c9Jv}|a#wJ3MF*0JI(Z{{L&0sJE zKjz|cA~G@viBz~OeSK>srEMxIX-sAq3grxk2LNCSKs*5M0K@=b4L}M2idKq-x!1xT zDK2nK3=Z54h-=&B?W^v?*^Q-ToGcxVY&EWEwXC$JLG+Nn(ovl7;_8ECdAwxd(FfW@ z+~RkUOe5)GPXJU@$zGlz$D}iZBo>^a4@A4zvHm=ojj#kd#Pq-xGewyyNG##YO8?C1kTMc0nAH3n`D#F4bBaU%K@r`XJ^Lju z;HK=aWAcBouWMLt4jVeM{MfiNhsNZah;k%c3`Y|`;+KJ$MN@B?3ywX8ursBSreOz7 zFIU5Y%CUmc;pVR5wYApyXrD8SC6l@h??XRoLOjowaK^kSN6kPG@Tfen9W%)4Rh=$V z*1Mi9XLWOYuK77<`T|??rVqT(@(a{at(fS5=eb&A-hplVYKb+-K^c2D3Mw&?A}1{0 z&YjKp0Uf9qtR$4U5sZI|2cqF>#xzUS7omM)U^*`*iTWm}8JDjj5= zog2JICR!j;`w_@ULp$YB|I@q?tC!K|JKZdx8==1IN}gU^(+%ZP>9yC5R`c`Mk>j>N zV)gst8Yt=Y;pxGx(fLJTEYfj{Aj@$g+P^SeNTs8j2`5EiL;YJ~YYy=FyWV8wd~h+{ zYIK)#1^vt$~`1^9AzBA+zn5F8P~ z>RoVnj-oH_Roj_Kl*RnW>W$2$2r*Ex9ew24fZ ztDq%8#ju@~cka;ga+6S`0&DD0!JrE9~m4(<8@a zy`@#J&MQf;aE$@cP@PFof4WkK^Avqt+>Z+>CNP?!dkS!V|2KmD@~nS@jqHb74%_iw ccv*{AQDObYaB*ul*F8z91&(*OVf 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..dd4089f7230ddbeb1da51fa95f16a079668f7650 GIT binary patch literal 1588 zcmd5+X*Ane9DNa6gjgc6cZP~0DN1QMw9yJOmWGlAQ^}C&O4QQUs9KWHYO9vgj-^#g zdyL>;&U8q75T!l36Qn}5orA_wX=^D{WzucF&4>9m@4Vl;_uYHn@4Zj&6eZ9{OT$7Z)8EEG;c9Jv}|a#wJ3MF*0JI(Z{{L&0sJE zKjz|cA~G@viBz~OeSK>srEMxIX-sAq3grxk2LNCSKs*5M0K@=b4L}M2idKq-x!1xT zDK2nK3=Z54h-=&B?W^v?*^Q-ToGcxVY&EWEwXC$JLG+Nn(ovl7;_8ECdAwxd(FfW@ z+~RkUOe5)GPXJU@$zGlz$D}iZBo>^a4@A4zvHm=ojj#kd#Pq-xGewyyNG##YO8?C1kTMc0nAH3n`D#F4bBaU%K@r`XJ^Lju z;HK=aWAcBouWMLt4jVeM{MfiNhsNZah;k%c3`Y|`;+KJ$MN@B?3ywX8ursBSreOz7 zFIU5Y%CUmc;pVR5wYApyXrD8SC6l@h??XRoLOjowaK^kSN6kPG@Tfen9W%)4Rh=$V z*1Mi9XLWOYuK77<`T|??rVqT(@(a{at(fS5=eb&A-hplVYKb+-K^c2D3Mw&?A}1{0 z&YjKp0Uf9qtR$4U5sZI|2cqF>#xzUS7omM)U^*`*iTWm}8JDjj5= zog2JICR!j;`w_@ULp$YB|I@q?tC!K|JKZdx8==1IN}gU^(+%ZP>9yC5R`c`Mk>j>N zV)gst8Yt=Y;pxGx(fLJTEYfj{Aj@$g+P^SeNTs8j2`5EiL;YJ~YYy=FyWV8wd~h+{ zYIK)#1^vt$~`1^9AzBA+zn5F8P~ z>RoVnj-oH_Roj_Kl*RnW>W$2$2r*Ex9ew24fZ ztDq%8#ju@~cka;ga+6S`0&DD0!JrE9~m4(<8@a zy`@#J&MQf;aE$@cP@PFof4WkK^Avqt+>Z+>CNP?!dkS!V|2KmD@~nS@jqHb74%_iw ccv*{AQDObYaB*ul*F8z91&(*OVf 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..dd4089f7230ddbeb1da51fa95f16a079668f7650 GIT binary patch literal 1588 zcmd5+X*Ane9DNa6gjgc6cZP~0DN1QMw9yJOmWGlAQ^}C&O4QQUs9KWHYO9vgj-^#g zdyL>;&U8q75T!l36Qn}5orA_wX=^D{WzucF&4>9m@4Vl;_uYHn@4Zj&6eZ9{OT$7Z)8EEG;c9Jv}|a#wJ3MF*0JI(Z{{L&0sJE zKjz|cA~G@viBz~OeSK>srEMxIX-sAq3grxk2LNCSKs*5M0K@=b4L}M2idKq-x!1xT zDK2nK3=Z54h-=&B?W^v?*^Q-ToGcxVY&EWEwXC$JLG+Nn(ovl7;_8ECdAwxd(FfW@ z+~RkUOe5)GPXJU@$zGlz$D}iZBo>^a4@A4zvHm=ojj#kd#Pq-xGewyyNG##YO8?C1kTMc0nAH3n`D#F4bBaU%K@r`XJ^Lju z;HK=aWAcBouWMLt4jVeM{MfiNhsNZah;k%c3`Y|`;+KJ$MN@B?3ywX8ursBSreOz7 zFIU5Y%CUmc;pVR5wYApyXrD8SC6l@h??XRoLOjowaK^kSN6kPG@Tfen9W%)4Rh=$V z*1Mi9XLWOYuK77<`T|??rVqT(@(a{at(fS5=eb&A-hplVYKb+-K^c2D3Mw&?A}1{0 z&YjKp0Uf9qtR$4U5sZI|2cqF>#xzUS7omM)U^*`*iTWm}8JDjj5= zog2JICR!j;`w_@ULp$YB|I@q?tC!K|JKZdx8==1IN}gU^(+%ZP>9yC5R`c`Mk>j>N zV)gst8Yt=Y;pxGx(fLJTEYfj{Aj@$g+P^SeNTs8j2`5EiL;YJ~YYy=FyWV8wd~h+{ zYIK)#1^vt$~`1^9AzBA+zn5F8P~ z>RoVnj-oH_Roj_Kl*RnW>W$2$2r*Ex9ew24fZ ztDq%8#ju@~cka;ga+6S`0&DD0!JrE9~m4(<8@a zy`@#J&MQf;aE$@cP@PFof4WkK^Avqt+>Z+>CNP?!dkS!V|2KmD@~nS@jqHb74%_iw ccv*{AQDObYaB*ul*F8z91&(*OVf 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..8c1320ce9d041a4b92e9616fefabf0511f3ddb84 GIT binary patch literal 2092 zcmd5-YfzI{8vYDBoxC9yn6%#NZghB!$e2@l$g~gDD0O2MU^Klc! zT2Z-`$ZZj*8X(-%h(ds(1qDPzpt3?#WC#e93REej!R-Fn+1Z)>wXM2sj)Lfk05Z z>P3g>csyRi|AA=$3WdU8F#jU{7tO_3-+k(_fOtQj!vHr_e?tM~KGL7aU1TlTO-$0b z?Uwa1vhqg*BlWYqGNH0cCQ4<>L&aT^UoK1fn6t~0RCzW}R8?MtzbV?2?&6>P)7+yyT7Z=i+%CuY#>;nwao!yho`1g5cm4EO zBZ2WCq=LI1#Dl+*l7bq;doE`Er{Z2{?Ny*L|Hnj{jcW>t{sLK<{JNL-JzBKOp{xA? z*8T+Z`NomD@SvKXzH_{8G~QpDMJ%X(_j+0{;q#9^Rh_yr``iF6++x#hkcyC9EPU3Q zKD?G1A1K58MQ;`0OH8yUB?i%3H9Q<7wfN4glLZ(N&` z>J8V)fd1$=mfO~5vFkix*w`aI2UdULxfdYFg94bg2@&+Xl78CO@sJ1OU zca=HNUWmJWsW_IB-|D==s}U7!)e=jntMb7~#uy0;AD)t0>Yc2HAH$WJq+x#+>{X~d z%xdu+*B3u2nx_ZSgaM+=7DO=|tsLr;xLG2A-7QGSIJjqj#RHt~m*q3TX!hI-YpIpP z39ozOAks>!1adow-;I0^3*}g3GWo-uM-@8rpY?pws~6Ecr1jKeuL&F3(v)j+`$=B( zG+;Bi@1kMW-T12|K9$2=QNYhgV)gy$%l0Y7x>EVu@|(c}W$hf!FW`@~%Y#E-aJv=n zVa7x;zBpGXivxKx`p?28lUvT(YPnh1ax6?Kk)SL>a$#<4$9^-gnO}CROJ$MKjd*}- zj@CKL%diTjNOw#|ethQs(G^a#%&1hiw*I95#`$Dv{WIS{&{f&Zyse-DuJk3Q_W~X;6Do0({XhpX=@migYm8|O8le6X^Z)`hkG|8Dp z37@6KKJ@&Wn-q|KGi>Z!Dkp(`I1=<;DtCN+=gcwjRH_M;m5Ck3j1S9R#DOc^gP^%+ z$MKs9Q>e2U=WM@q(n_L8-6OXD_8djY$r~LqnjPA{|6t!K3i00M;|Eq`*6fmWV`ULP zmgT)X+I58uCz+$x*w*JaVbM4VLbawb-iomCz^M?>haVeRX>jGY|I(@ zb|&g+fP{Dra%=4zkvsLwQb5sM>^Cs>S~;sg5oMb%T(|d?rA(Yl(8h@#%6s)haup%Z zT9)}k+OO0Ll0~9VAMP#OX1Rb6+WwU=0!}-5HQKk(YRf zkIrdrcS`c!ph-gr(qa!6CBf?gC1mbEX9`l*_G=j!MN7x#R5VS4>=x(u@{RoWetiGG z>aU>;OJO1B@p(d5JCYzTgVSzd)#Yp4iA3C=b eb~Px~H_F7+@{-5|nk6bWzd%nnA9|fDH~kM9Uu+iu 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..879aa172953b188655de1c8766316db65fc3c0aa GIT binary patch literal 1801 zcmd5-dpOez82&9ywlzAgxg3|4kRMYiQORXuU0i4Rv7y?Egf+U5+CsTR;nHLLghd?gV~yO(9WtxG7H>s%1}8-)eXe;DRg z^UnWL^zk?44Q2# zLykOxd78v`QPq5;0`-byMEO4L6>4ic?ma?u!5awm9;@0ugvwl}xDwAW@Ka=Z_2KpYjx5bi{8 zYX^O<6!oG1!BEC&QtnpOdOz~8meoyM+iM2w*b9U&&E_UG5eshEH%5|VwFR|T`J1dQ z{h9t(16HR`%0@(Dw@TBtl=MuUPnUgxEj<)Pdl#-mtufGJef5P7UpmJMq#ndpiJeF7 zy|}<~neb&z8Giv2Phz8&UP7jQae~Do;;ptOOtsnKa(Yh1hG;w)xmx}`4)^_;Ifsdt z^j@=Q$N+0QOAK(=B2hS% zX$lTf<5H!2@Es9rAnjot=(4kL3h*DiyK!h;2FI~}iedI@*XdTcOY!zc_?ZM=>|oO_ z3PBMLl0Ti%71@pJ=Lio6(-^&Cn4e{Qz2L^NzR?T6YZl&KarQb+f$^=O_s~W2k(b_; z`-*nH5AcZImM47Pg)=_PSWQ;* zO4%c=XQwHULD$`i-9`1=xfA#G2G3!bWufi#@J2;MpoLeXr*Z~m`G}JG-ngc8Q0VRN z9n@k|kAR>mk7SevS@A7~_VMxflXiCAW=ppR#}i;ZPm9P`9ig1M63aldYpHgd?9Gd_?2lQTa#(Wwd%;xgTUzX*q z@Eq-%lB!ibM!DuVUyktMK1rK$?*93k`sfaIQej$_jRWo zvd7n|@!D1c3AI#6%rQF|8(Fw@z30Qt-2+GNprJz_TJXXa&Xq;(veUHC^3mJpyCNbk zQd5PSbgG@mbyYUm*f&_wvos_GiecNu%?4WfFuJjzEi1K%YdDpmVW8Ly)AFvgpAG8$ z$}Ogqrtqgo*V)hS!!=P5k`cYkyo!RU{w2H}+$OyVN&v}c!;yC9hOt%f`F#Ol?*q8y z+NHNDf!)rTHfF&A^4cIsJes53a&lwekhN;(bBBI?I%*wJJLU^(`mkQetHKV_uYWul MqKiAB!YMfZ50^Cw-v9sr literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/nested-length.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/nested-length.png new file mode 100644 index 0000000000000000000000000000000000000000..19aafd4529bd28a765aaa4fa87413a6e6dab93e5 GIT binary patch literal 2033 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/baseline-shift/nested-with-baseline-1.png b/crates/resvg/tests-hinted/tests/text/baseline-shift/nested-with-baseline-1.png new file mode 100644 index 0000000000000000000000000000000000000000..91ba9361870c379fc34d4ed13dc1a1a557f9375d GIT binary patch literal 1591 zcmcgsX;hO(6dj;Z7Fk4yg$O8?JsM>RvM(p>5+FeOv8Z1NAWH>Y2%xfvA_^QMN`e?m zj-sLx4Z#K)Rue!)K+Do_Ko%`aK@^H01VU*;@bsU5JLkOj?%cWaX8yc;*&pwrtf;LB z08sYw#1R0HL9d6roP@!bWq3%6LXv05NdQz@))tpC;(|#Y$_Hj5kvqW(MWPQ0AT;s6jO>$ zVXMa0Wo^?1TYjFIrXo}c^Rp4tRoMt7BpRyxPMTqbbqw>>C0SROBoS=TIu=qs-D-9* zf>V`-k=~7W@f(F{r`wLds8?yYl`KjYIjRvGh_7u|i>gVqI$vmfnDo0iCz!2TF_Snb3QE%|rSmeVv6 zR)0x}+@x82z)%>4S!z3cJwfDcEGn$OFul2)5J~bK#5if0NAIzI`H+V*7MEMxtk7WD zY~P#qg!9*B&X5B8Re(0#?6FAOX9O-L8ZCGmBDn((i8=S8PvIK385(SBM@F7xf`Oa@ z=1oN(MD?S^;jU#WPRnPrGHss;jvW(ME9e%7s6JMlQLDe?W>Wf+UUUOBs>l)t>XA!_hc`R-m$VVl1*=|TZw|OXx8qJJiM8@(zsZz zo%dX@vMY8#;ktUB6=@~TkA~t4R!9bZ(YrO2l7IVPANDt>oRsI14q-IS90rm?oC#!; zz|M3FqB4PFIifV>IcALf(6lzJz=c>P_(l8j&BDS9U75{#tr5vV=Uzyf+gY0Pp!e?l zO__OCe_%i)TXNew0V3 z>Hey2r);kHg-xsZ;Qp&H>w#@gsq&|773Va)X)FWsr-QLZ!f;P)8#G6)tgI>MMDroD z`O@y(oIs@pG9w5rbPdH>BOO#NQfbKis42LIieTCo{_K1k%KIs)S}?=ML>l>{kvb(} zj%;kvrWpb!yg{yqYPCJ${2T_$S@;#QO~LM2#GQ65*%1a&!qGwc3^wd$TiUZboidy( zN4_0vFqG?-*spJq@#;+-2}bwU-SwKAs%3KL^tCgi!qFYe3s}@0OxM!TYWvxvZ}+dM z7DS!kMKSPqUH9G-gxbv(nWHoqx|;c=YpvGj)#sb2F|Il_wD&i(`_9gfzgwB@EXd&6 zwNgJKWQY~)F5OqmfQeDP%Bn_7XO4bI?R=jA{0xWnJ{`x))4RirgwxG& zhSlR~GLVR{vpC)1;^$&L)!Fv%*OcSh&Xac;js-r1=Q@_Id|4ATxlH+cc8pvYPx{!m zweER%X9(XnIBJB-{=3?gCyJjCSG66}YP#q~T|1IE5Z}S3%mBG8HTmYrOTn^t#mwXo zK;Na6IwB(|lUePf_h&F`0^@o$H^zN^%vnDFP5U=N!+q`RvM(p>5+FeOv8Z1NAWH>Y2%xfvA_^QMN`e?m zj-sLx4Z#K)Rue!)K+Do_Ko%`aK@^H01VU*;@bsU5JLkOj?%cWaX8yc;*&pwrtf;LB z08sYw#1R0HL9d6roP@!bWq3%6LXv05NdQz@))tpC;(|#Y$_Hj5kvqW(MWPQ0AT;s6jO>$ zVXMa0Wo^?1TYjFIrXo}c^Rp4tRoMt7BpRyxPMTqbbqw>>C0SROBoS=TIu=qs-D-9* zf>V`-k=~7W@f(F{r`wLds8?yYl`KjYIjRvGh_7u|i>gVqI$vmfnDo0iCz!2TF_Snb3QE%|rSmeVv6 zR)0x}+@x82z)%>4S!z3cJwfDcEGn$OFul2)5J~bK#5if0NAIzI`H+V*7MEMxtk7WD zY~P#qg!9*B&X5B8Re(0#?6FAOX9O-L8ZCGmBDn((i8=S8PvIK385(SBM@F7xf`Oa@ z=1oN(MD?S^;jU#WPRnPrGHss;jvW(ME9e%7s6JMlQLDe?W>Wf+UUUOBs>l)t>XA!_hc`R-m$VVl1*=|TZw|OXx8qJJiM8@(zsZz zo%dX@vMY8#;ktUB6=@~TkA~t4R!9bZ(YrO2l7IVPANDt>oRsI14q-IS90rm?oC#!; zz|M3FqB4PFIifV>IcALf(6lzJz=c>P_(l8j&BDS9U75{#tr5vV=Uzyf+gY0Pp!e?l zO__OCe_%i)TXNew0V3 z>Hey2r);kHg-xsZ;Qp&H>w#@gsq&|773Va)X)FWsr-QLZ!f;P)8#G6)tgI>MMDroD z`O@y(oIs@pG9w5rbPdH>BOO#NQfbKis42LIieTCo{_K1k%KIs)S}?=ML>l>{kvb(} zj%;kvrWpb!yg{yqYPCJ${2T_$S@;#QO~LM2#GQ65*%1a&!qGwc3^wd$TiUZboidy( zN4_0vFqG?-*spJq@#;+-2}bwU-SwKAs%3KL^tCgi!qFYe3s}@0OxM!TYWvxvZ}+dM z7DS!kMKSPqUH9G-gxbv(nWHoqx|;c=YpvGj)#sb2F|Il_wD&i(`_9gfzgwB@EXd&6 zwNgJKWQY~)F5OqmfQeDP%Bn_7XO4bI?R=jA{0xWnJ{`x))4RirgwxG& zhSlR~GLVR{vpC)1;^$&L)!Fv%*OcSh&Xac;js-r1=Q@_Id|4ATxlH+cc8pvYPx{!m zweER%X9(XnIBJB-{=3?gCyJjCSG66}YP#q~T|1IE5Z}S3%mBG8HTmYrOTn^t#mwXo zK;Na6IwB(|lUePf_h&F`0^@o$H^zN^%vnDFP5U=N!+q`8YQbi>ye~H!mUT7X%QRLl3%?aRga~% zm`kh55=}1E;bN1}jqR#OUG<7Z)-BsAb?ea^vUOv2c4qG%J9B65%zoya?>Y1Np4VUJ z6a@Hr>%dH4008I^eDIe5Km~K4S`a1U*O1|@G|+e-3L606PY+b3(i(nDNh$&^1bHd# zZ@~gt5D;>Xdkz2rrJz6*z&&sd-rtIn`TyXr1n7?ivC86jB|tov%LPI3pqCQA^a245 zPy+&iXlQ7_K{yqphH=ASAnd;;`8D!@1OX%$i3E`-E=pMgiA2I+Fa!c&Wo1RBQc)-r z91h1~u`Cu#*+|*WugE=985fjv$uAIa-#>euv7Nub<%9d8QoY3hem$S&KWe)XP%6?} z1nJxbq1n6mvGnwslDxdyn!39BvC-A-)hTw8%+`H_E{K0;Cj5K1K+r84Ze;VPY8W)S zX7RX}$=Kw#~hk?yfb(FyA0Uz&VAtp8qXkL2A#Yu<2G0WV#)x zbw(Oj8FdEU9&DWTvrO8!s$Af#gRiQK{*;`?KRV!6of=i$lZO1FtLD)-n#=^gu1?&P zf7L`WyQH^M%mfXL%2UVaXuXX`iF0lNhwM3Qzvkomx2n3{t?Gb~`xxq7ik5teczRe+jJ{!8$K)c8yFT0W@v5uHdH=Ij?U4Kd&UA9NGn}@YoY-m z?eGY_PmMenr3#)st?!+usp%wNUmQ($!|$zK5AQ9p)(qUMn%`O4!)gnYLeJO5r|ikH zmX>1t>mDzBC7)Xhy}PYO5+Xa~uc0Pg$t{DxMvA0$feX+0sbo*?>%!hLBvKUSv>$)! zndiheuW5^&yCY>)AJGjZ)pvaS( zv8(sWiJA_ThD<58GSXsfxTdk2KTcQdM#St@%DCmlFR8UOenCk?1|KW(s)e{Gol;Guu Jf8lBe?Vm-dwG&eDkFy{E2jM%n5NSjmPzSgO;6c0-&B*{X z&;&IxASQ|yrLL|H0Dyvmg1fuBj*bol0>R_)W@cv5(a}LcK^P21>PnY^fx!;hsVXWe za5((W%KzrhP3CdZ4v$zbqBlSeMxafH7J3}E1g)Uy6~sKche}@Xcs@j{8RXNia)Ko# z#i@<ily7XustUD_OCWz97{V zf6V7X-%L;KE?Ip9;IL%aCezGEs{gdv{KCxC;2yo#B;@IPw-KZFM1%YO=IYE=p3%N^ zod0b~XCD^24Y~XO8-fn~%OEhe8#kmaJM8~JEasp=VlOVVLBpROR#?!jRTrHnvY%m% zF-AW}Wc+k8KC85-aBbc+9hUTA^X#2mY&C0+q3xc3-DaQjkE2g+Jh0NJDc{5PnSQ2A z*1eA=;pDlAbh$ydGq7o-cnIlxOT4)`wHZvK`B^3hcCg~kgpG&7FHZ?buNBGQWLa(Q3xT$S4tmIv8bRy=3>$@x_o@tuoF zgoOuJzu;wR?$XIBaZW~^)8YI#pSp%6p4aZtVLTw;)n4p85^HKJEvp6BxWqL zPr6Q{56tGi9{Q-ag%m4m^zhePrf-f_!ynXth$SOU!`G;!IEdkg@LP4EqIo8H%ye?E zV9}0P^GzHH!hOdJcosl5u|FsQPP1y{&^N`Kx?L>8Bkd#0Z%|X80=Eu^NZgH-VEl0_ zj4WadYn9-U8OpYTIt=$aOz=|8=_t`n z>5Cpv7B6n7K0eL~>P!7WG23&}X0Aio80kxHH1t_FLOw}wu>%jK^Yl;&O0Y~}u%N;9OTt|7#=y8Q?Sjm4@skfksJF?c<6pK74nHaxyIU_> zx#z^U4r^8~>5mqw7j;P5V!Y8z21ha3RD!MV9W&w=-a&n}KnOrNN$iQnv5mesI9n81h3JbtVe%RdF5H3pYfa za)>=|K@s*fkXTRj<@FELK_0n%*1kAd?c&|{STu!Bo`?d(OtvdFR4;YSqb>fQYB{34 zOB!CSRi_7K=vH5%;eMo5^{S)hJo$lLoyerlic|T=XWLnjUK;PjtQ<^b<*qg9oX)B$ zXJe(Ammv~H(>JSk`6_((uyQvO%E~|6W6f)c&%Rv#cLZtrSGv9e>7G$yt!7N|LO8iL zsB|@)e6DW@Q3uD$rj4XgN+#|8}A~IFH+w1fx`F-4&i*ub3wq1{DZZCdCJvR z4Xpmzo46L+TMZ+fN%y*=eAgI)8cEy(^)0`%dpc|ESN+Nc%vkQ@haB6sOP#8X@+68p zc8C_h-CfJ^BSi~h`gO_@ye?5%m_dSd+Q<03G&Dkyn!jY!^!+Cko(e|{Y*}{W_c>ni z92(#7-8%KKvw>qz{%Zcx*&i*TDVmOfE$O%1>__`mYr2i+(kE=McQC9!`uI}@#gC3O z6c>c35Ul5HuiL*maxU;l$FkwN^-)yQ;jQ#I>+82apCn5>`v)${Ls2*qpWK%AS0np( zrXuXj#`t~0-{(w|pGNc6nhd+ucqy3Bu?9A#6*AfMarJhD#_IMz=;}{%PYkm90+u2%6!4zNs z07zj^V(z@6-wL604fsz2g|OXe2P;97LZMKpQ~?1f zTd-x@M1a&kT|j2n3?5t4k)6U0q#KD3m}WFeDPW zO|}sRgTdkOA1i-_&w4Y)1Ujc+yzN4FD!Z?U_@THIRVph5{ zFn4b_Ovr#(rCmsI1`_IO<&=J#>bO<7?Xs3Qc3%OP z&ZCQz=i}20?dMX!chS{)p?3ogL$A{uwY!(H7UPl)rvn$kg^Y71PevY~E~c+nh{&bx zVSIv`{-Wx+xbT&UxW(`}p9if6pH_|UDn5ZP3%&+6;JfmN{#hAk4o55a%#2iQ3>?!Z z(C&@>$3Y+#YOFV5rM#f1VM}9sb$czFk=Y9S63@hefoJ^@KH%CRYdZZD z`YqSaV#cJnE;vVRF#l3A%Q59U6l5Ps+@Q%J5{b1f;RoK8GtA2pP;HkQI{V`tLkiZ} zCXL3qzzFg}2mj0STJ@_H60*dcBE!b`@kFWPrMomecJmBAShX;NQgEka1I*1g*8OD4 z4>BAP>2xS%h3Wa*YmWlrUFe4h2^^(kst!1W zQz_7$O*ppnmJ*SXiP!hEJIpY{G7N8zFx8f%d{+$I7d1hJNA0(nZjsk^D}Rk*wbb`$&XIRU&UP5V{y& zMpF6*;wJAy6X)0EByoe9wU||}l+v}>*1+OJ13yI~20W)WlwDgcdJqY~j!R!HN)RSr z#J}Ai@^ND`?Z7r!@Mm`0Xs^*}w@1d&oG^TT2Rkshi+S$Q$Q_k(Z*1l3gA)TTk8srw z3G$EI5!jZG-_GGBybKTeR%d&JM{1z`%1$=3E|7JmKM(LT?j}7R45_Nsww06+Z@NAu zhLr5_ukCDUnH)Uj(DS&{0QlIhK)K<*V^uhVrPZ!AdKC~ zqGP-Evz0_5X08(SeraHw6=z*mSaiPNq0+$& zeM>epG;B~gV3ZUhl~>VGBuXfxav5^(hp^cJop9gi!${-K&|7$$#{*IBl{*)Xn;-RP z{H?~im`G|X;busHiMrPh)B?7i90Jb3eEuNu_t>A zo$BF)4Ng)*VqW&JPC(L7S9Fmc8%p=B5yy$jO*zvKpu3;!EmdBoMYJO8%|}am;tRBS zIh-hRK1L!Yc4OsJoDP}Z+zso#0ss%bbmk$gYWJg<-F9HDyp=!_T5lVWg)@I`iHAH{p$XJt+mTYp4nx6*+&^%6$A8 zAIB<4?Lu`}=MwSOqEfWQ#7D6ws?Jcc&fK&qXJ_}2WL`GfD2`UVa+;r6&9`rDILM54D;UBHt9>x&oDYx8 z;+Bs~W|aI(P82$PGxeAb4@pv`^3*h&1Al8Yoi>WI!>w^mTcgsOgOf`ANBI?A**<6Q z2{aXp;YzljBN^aqVd_OAkh@d2>jfupWJTfo%e+dcz(pN)1>l>GP7m&JMr-qOu&->^R)Ps$Iz$<8;-;Xu4j%_ab%g zy3tb3>UZ_02b3f%vp3ldZyz!AT^Ec)wWV64L?qJP*$;ywTX 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 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 E0D>@@KmY&$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/colrv1.png b/crates/resvg/tests-hinted/tests/text/color-font/colrv1.png new file mode 100644 index 0000000000000000000000000000000000000000..23bb63a05b00f896290c1a5baaf584cead684658 GIT binary patch literal 6295 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 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..bf0d5e0651e0c19c8b6d3570bbebadda3b6a584c GIT binary patch literal 790 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBF z0(?STfi%@YLqkJ77yudPn%*b@El?;4@(X5g_-`+uaNnSyVZ-@&AOHIG4?cW;KBXo< zC1JsZ*>e)&`x!aUFfcF~c)B=-RNQ)dqc!n~frx|S%h_*LPW$`~uROCP`P3dEw>2T* z@iSjdd8{4mXZh=o=*s%Wsgw6D`me7Izopr00FfQ Apa1{> literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/color-font/mixed-text.png b/crates/resvg/tests-hinted/tests/text/color-font/mixed-text.png new file mode 100644 index 0000000000000000000000000000000000000000..e0e4509720ac9402ff79e99ed39d2c9021120ab9 GIT binary patch literal 1752 zcmcIkc{G%J82%79VytDkoMaoz5ZxSdWXU*ohGvGb6GplWMQAY-uGCN%OWDS?bgh}b zlx$;)WDE_-(r(Gnj6$KbnERpAU-$N3-#NeMeV+IIp7&eM@AqCnx!OsHDTx69AmLz- z^Z)<>#Kzh#1Z7++lI)-$8f}j|0RXV>jU|w$2m5{F4wN(67Aiv5I@|3B@;CX0WNjw< zH;_akLCEiSArgrYiHwZQAt&(rUAK}Dy1BV+$#s?sB#}rYgb+6~GlK|ZH!?EX@~&^X z)YR1Y{mxKHSy>rs3laXNQC?pD?LD-NjLeqYLKqD8LoWBYi-~P~?5AFoh=>TEwbA5z z2R?s(Zer^BAS741?0Id-DbRAf*6e0EiCu1d|Egh4L3DLKp*#d*l_4!$XE~8!&ZQl zl&Y$sp{11@3Kb9#7#MgofWLX^l>JIzMP6K|;xGqp1^v_5__4Tv`xFPA>X8Z?L|j z+tI)=5!4dq4D?}D`F%N>PWcF2@BajzX()561cv+qva*K2{k(DO6XPBFo^jgZHbXHc zY17vg<8|I1gipV-_`1M{nPk1l;l}B7HES??I(I%n&>qk^2WHnAQ%-8tiLeeE4BueL zUVFx6g63|gK`=}z_wPMbC2&YKToX5%HTIS( z=Gtt6hArRUam~ly#P3EkMFfYqRJeb8d}DkfMxQz?Z~e(5e?>x?ToQ_rQ^;}AIuk)I zvlxdvG%&kuh=)szLl0;Nr#-~Q#yXJLRrq`MPD~H?&|5LgQdCpJV~t1* zc(JvT(h~$)B#F!wCxMqK%QNU+B~CXk;o2y-ue^3%54^Ibh0FbXW&ZfSS%!%kBUqPH zAM-LJCI?f3caPhqtKkG!K$nv0CpqAmiIjkz+Uyy4rS+~3`6%UgQSVb5UUW$)r458) zG=)dNN0hsDvR{vC-|3*!P3d>&^h~Amopx9%g3J0W9lo0cw^T)(?^R=dT_a=d_P zV@)t%3DAvmjRimHP^yRpEhE$H0GT9mY|@Gr;%?(RjB(rnvU7y zhmsyE)AmhM2kPuNR973^Stgk}Sq)aNUz+#AHrbJED{h6(h|M_gB8YfAp0A6jT6D_w zF}U3pg>OI3nDG*zQ^NvL@2no#KDyj{nKq=WI&;Z8GG|+|Iyn)4XOj>9U+hZAAb_px(Lt zjVIfoy;$Z!@H*>{)(Ir!+{@&CYg6>1ETl?Sa)V5w_DZ7XS3XBB5WD#E>UDk-M$g~{ zCV03Hcq0VA8^;TN_&y@+1hk1QTIAc4?%GMSLF3Wfyw^@oYf$7 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..e24d936ad364c322f5c7d1c8433853bb7bf93b8f GIT binary patch literal 978 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCo z0(?STfizao(9i%BudlDiDhm+=s==>-kB<*id*t zDftD}^$q!j=FX}iiy~eaIlHh z8%%Of1F^ZqbRc8|kRA3KA|s{)Q3#YAER6lUVr#-KZ`wAiZ9|ps>08-FZI7YurlFJV z%9Wj7thVyc z!`I)pm)=T}m6`WJ_5H?YCzO+B6usTJ;~1BJ^_l|~YqYN(7rNOXvh`EMAs&z5_Zx2{ zF5F(bWZJ6;-LyALAN;&+qdiMn&Hd>{E+47S_Z6MR_?s`vo__rB)cJLGyArRg>?=L; zqONDoi5x?vvm32?HvO2FAQ&Th-01RpYq{=fmNn*Ktq(Ts3K4ADd@n-o(YcEehnym| zZZu*EJ;WB}z>}3M$TV4?TTo){My(FJ%-Hve8P*&9erne`U-@~6^U%{`zDLIQ8zvv| s+M=9PwN}1^Kgz<{Vpg_-)Gd~OtZ$mWiI|@ZRt4n~Pgg&ebxsLQ0M^A}t^fc4 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..490e5b4c3d7da22c650f4cc11c3805d1f952d830 GIT binary patch literal 955 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDz z0(?STfpmR+eM3V7kbxig`}?D*w6e0|YCrBi)QbPO7FAgSDk*dH&y=H-nQ;lnp+wYou5It=_dS>;I;GHMZ|kpDpkI zxFIhs(9OkCd)4-hQTvy_UVTmfb@A&EzbM`NZR^e699>!S_FnzPM$wD!kFQjUTXm+~ zvTdt!lx+Eqs+$W>{9Di_dhz_#lInl|oW(vCRWHil`Sbn8Rh4p5d;flZzx(?dzloM| zQ~yo*wU%d)MFuPPG-!f=CJRJLT613toVuE}-Zb-=%^Y?(#68s9=PEz*EYB@*%U9Qf OlE0^`pUXO@geCwZ)?)|& 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..84acbeda0cbd2b953eea6065fbd2be2b9df009a3 GIT binary patch literal 1798 zcmc&#`B#!z7^a~Zm&66rN+}maP|PLCpqW%e^bXH&e?pt;{0jDx|D^2JU2QI9y9hOU*4TEId3ss8p(&Ad$%LF;`m^ z#Md{eOYP(RnE|kHJu`=~{iz-O*REF{-&Z>t9-HEOTH-3XKRIyvdS33e?z=^uRj>TU z*}tbPxUmNs&9}o~%Txf>J@8=P`_6l69}UdP#ryspW-%S^j&w1BqYzpB zFK}q8J(F}|jb>FL4W%iGb7quO%q^t8L|-wn7UHY z^}72Tac;rQ{``7(aNS`>JJ>I-?$nb|7Z)J#_(-)j0cjWzoXv;b0xdhK}*cce?l1#9FIIsr+S} z@6~?n{H`SHI056aM~c_2aK?YIYr&HwbHdT9M?WPqGe-*8ox-k8<-!T8UW3|(D#8K1@c5CT>IO*%B8eu0tGZ$;B!65#`)r#6eBllbq(DZHd-o z{$*(8m#2aQ5_~4bsC$h_+8{APhpOMZ2NmJpEj@-A{dnFp4M#Wh(zma*QDVW^;cw@& zFRW-D8j31wJ$eQ(YWNC0M}q_DQVcf<)rT3CJ2{)_MrxLYfPgrg_j09c3DN12G#xWK zWg_JeyQ&Gkd#0dzK->yhw!hg^-ql)7Snprzn!>WffU%dOJ08tZ#2h;}Zp9tKm{r6b z-E!PL-_M0+KDe;kq#57c!h^&Txe!9oNR%dyjWRHvpGB?0htE%g>!bKtS?H~OW)FcL z#lqZdL13*191x$7E4BkW$^vtQ7tC!-+zqV7)eq?w3Li)$y?|9pZ7#ad;JI0d2`ox@ zhUmPZLP&=w$aNJv{6Lfp$*+sF-5oNKp+3D#6w^xs<7pT!(Uu-;8DWY6XB(d2;FqD< znLL2;ARx;UU`aP^B@0&1_P*db39z7r2=%7(MZyJ0@cv^w7G!(kYoxvC-KsJ5?oFm^ zT1P&r2@SDTFbxMQUZX*P>= z`%+Mp(5Fx#1R@T4mkSh4z$nP+dPmLA{X9(-O;!rtx-I?^?4rAqq{bB#XmQwTgZ~l! a9pJEWlyVTA-7CLlx~Kr2OzKq%JL4}OApgDq 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..0c2f2dd47ff7b514281529da0fd6e69157dcff43 GIT binary patch literal 1467 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfixy)XlMWm*4Nhq$()=Vh=SPISU*2M2;0TQ#o5^z!Uigas04DAl$7A43>ZMv zh>MF02?;^ie0+Qm1{)h2gu%=Va%zuA13Qq?EeY}qW)M&?aPSX^k55R*$}cFct8ZxU z=$|lq&in=I*KgRcbJzX@htHnBaQ*&+*Y7`kl@sK2WME*K=jq}YQgQ3e1x7{&0R{#I zhJW&A%vV~N+?gP@Ff`c7o|vTSJ#EcxFr|}n62zk;wRGbRW9EC?auvAbJ+Ga;ktsTN z#neYt!r?cAmhSog|NAl-|E!d2#a#@Y4L=wK3ZGS{e`G#+$amgzd6T^^de`4GU6Wm; zRn^G!rn(_CL1Rtn)d_n!*YJqzepqeUJRw!#9TiE0$?T`itiz=dN3J@2^C#|2D6i%nXOlFYC&0 zbNhB>K`!^S*pr55=1t*qc+nsm{=&A+fMHvQ{O^+{EDOvz*Sslw#;B3JN3*e@Va?sI zca~^Acpkyv#Bo%FwaRyiRoM!$z8HxMy<*PU0jyJgvCNfxRK;Mi?MqDhfyI|UEzj!z z#WL+o&7Rm}xiTUBuQqNs5N9l$vaE4-R9aYqd~|hGcL+nkt%xftmW78uZivvb)VN|e z>F=MFmW`o@KhJ%7;qrNlqidgBJo)gK=$Z`~Q47?%9oKS9J5kDz758J$Kfb=xyy477 zkrN+(jad1IQ^&zr=aq$pq;bpgZ+fk&6OM@TCv~6wb8^;`Cv2A(Ha_7^*YW>&<7CK! zh(nJg+f0v&`bV{0JIXr-Y7|(wadD{8raF+|GcE^#^uNexwZd9b>)v{=`%)QE;!tm%cB+oEyS?z)dwGcvu5PY`H?jPm z!zSvVDK5XXC9%DWz3{N1v-Sk%kfo{ZybK${zu0d$(xTVs%BnK&(4>^RF4X;OlRvLGGCq-Y!>;EW zcHN6S6_vmK`_-@KzyIIrd>owToBym;-?&)-oXaC2d7dKb8nCp8+%y4HXb?+@LCYQn X0rS{}eu~atJ3s=Su6{1-oD!MSSLo9plI&&9>%=jRt28w(Vdk&$tBcDAyz zs;{qaXlM`@7uVF(#BVrU7N{PmtI~H;3Q$PDB*-tA;eUg}fr9tv_diIuzP|oz`+Wb` znY9n=itTrHOq?_O@Y4SL3-{MAn6M$>gMorTd_q0k!_hV(>_n+9JS*JFsLv-Umr!|$Ku4~pG+0^l4e|_r7^HC2zuRq=ualPZ~ z)d)W2YvIXvm4L*~$zeL%?L%3oT|KuYVyAqJh1oiu{|$3RilRfCQlJ0m_$0PL;q%wx z@`Ojxd8C8lfoIpQ{wMZ(ehfj?h8Jc~%~u z`8kpgajA)$88r*c+{b!Pl;zQ`)k6C?=H7MLQupL;)-kJ2wM$YPH($BfsdA+&Rg>NM z?MK6#@20ZpD{*d35_G&}E%!u07$n)@y8O()89nh?rJ9P`@8#I4t%!>K&2Ee2Hk#T*k&dbULu6EaZQ;%?N=}*<<S#vPP1K5=h5B1zyBp1@tc)(sEK*$bkT@6flAN$ z8+l%@;W~YZJ@}2aZ{F^gRVjZI1MW!nvguUXtyklI{5j81Q_%gceQo4VffHuzb0ipk zXRTo7E)o&k5M$2is&s01&@vY8GY=j|OrOW3`sih#t@aV7@`o|A%}sXrI?e0Y?r!>X z_J&vUWsGx@{#=}QeeuODFKg_i&cFJ)ds*t%BWl}BySLvsQWDx;VJW9OyY1qS$iK!+ z_qv4^m>W2Rr8VftJ)6zO@b*F@DA6`3)W2qR(`cEX>OD;-a?`+4KXib3hZUBWSSt7I U?#iu8iUJ9Ey85}Sb4q9e021lPy8r+H literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/auto.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/auto.png new file mode 100644 index 0000000000000000000000000000000000000000..030f0789969d33ebca18408a24a91d727ccf81c2 GIT binary patch literal 1169 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCY z1AIbUfi!-=$H%9nqy$vM%*^cK;sR03#>SSLo9plI&&9>%=jRt28w(Vdk&$tBcDAyz zs;{qaXlM`@7uVF(#BVrU7N{PmtI~H;3Q$PDB*-tA;eUg}fr9tv_diIuzP|oz`+Wb` znY9n=itTrHOq?_O@Y4SL3-{MAn6M$>gMorTd_q0k!_hV(>_n+9JS*JFsLv-Umr!|$Ku4~pG+0^l4e|_r7^HC2zuRq=ualPZ~ z)d)W2YvIXvm4L*~$zeL%?L%3oT|KuYVyAqJh1oiu{|$3RilRfCQlJ0m_$0PL;q%wx z@`Ojxd8C8lfoIpQ{wMZ(ehfj?h8Jc~%~u z`8kpgajA)$88r*c+{b!Pl;zQ`)k6C?=H7MLQupL;)-kJ2wM$YPH($BfsdA+&Rg>NM z?MK6#@20ZpD{*d35_G&}E%!u07$n)@y8O()89nh?rJ9P`@8#I4t%!>K&2Ee2Hk#T*k&dbULu6EaZQ;%?N=}*<<S#vPP1K5=h5B1zyBp1@tc)(sEK*$bkT@6flAN$ z8+l%@;W~YZJ@}2aZ{F^gRVjZI1MW!nvguUXtyklI{5j81Q_%gceQo4VffHuzb0ipk zXRTo7E)o&k5M$2is&s01&@vY8GY=j|OrOW3`sih#t@aV7@`o|A%}sXrI?e0Y?r!>X z_J&vUWsGx@{#=}QeeuODFKg_i&cFJ)ds*t%BWl}BySLvsQWDx;VJW9OyY1qS$iK!+ z_qv4^m>W2Rr8VftJ)6zO@b*F@DA6`3)W2qR(`cEX>OD;-a?`+4KXib3hZUBWSSt7I U?#iu8iUJ9Ey85}Sb4q9e021lPy8r+H literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/central.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/central.png new file mode 100644 index 0000000000000000000000000000000000000000..9c2cb70ea771c78153b41e732bcf3a255ffe1e9a GIT binary patch literal 1173 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z1o(uw0_pntdLW4l@bU3Mq@10dU0ht4nVEBQbGf*<#Kpzg*w|!bWDE@r{rvnaEiGeX zV{>wHl$4Z!>NPbrA-W)3T!y2GH#9Uv=O+9FiW-yz`2{m1{BJl=u;D{M!h`DzE_Aei z&3t(H_0HLKlZvx8_%F@xUmss@KY#!F`{ySZycbY#huV7$c&i8b245_&F<^m%x z0|N_#0n4I#Ytu9TIQl2UtZVRO-;}cV)TCCO$W19H=}4_vmwH`ii}LkEgEfH(J8Iq+ zu^%q`^^bqk`^^)rBX7Q*vh!2uB5aZ0rLXqb{&FQA#-#rHdIn$+c@L%pVJkI%C4n!5F9y@tPg4d?de zh;ND_+S-mumbr|tGP{n{t8^QjZWTY2om44aaW`OX(N$T-2*(`$xwRZmPo3I%WZStp z=_{QWCng>jVL83Zm+kGT9xbUi3SsrS%Rbbl#@ZSmzp-(fcJ?Zn+f)Cq{IoiLZk&wN zzPSpIPOiLaalCJJI_tbcFJ@XE>XR>f+9UGAwz$0VV{OWnnyu2lsbALYc`uRmoh^Mq z(8<%MSPD-mid3I{#MHcw#dL9Lb4Rjj^fi(EgbY1f#+#cKMW+@DShj3G&9y1S*q~lw znrMn@hDXzyzL#$g+uvQV@ZzCVRlmfDur_uhj()xwe5W_n9us{pqP=>VQ|0V6w`>w$ zzFxjIYMoA9?zhxR=Ka&Qc1=xvH1+qUKaKH6i}kY=0=uOzCcHlRY1z94X?IS_MQd)d z@LBpT^`_#Jv#mv`x<^htI$2oE*%LRvTJeeFf^rSklTDmbr{1QqFDRcK+Gw%;*6~|k ztqSw`cD&v8w$3m0#3yzBy*i-<9DnP3cScY2i#_sZ(`F&tA^wPr3n`r}Wx z{Go#iZj(|BOQ#$&K4KB)vUaERFU2Pcn;hmYF??j?XHpY#==pFVdQ&MBb@06cfx0RR91 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..cfeddc29040cf68d102779073792e6c26892d444 GIT binary patch literal 1496 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z1o(uw0%_ubi;Ii1volb=pPwHa8=JVexS^pTGc&WMrY2CZzP`Spp&>RlmWzu^NJvOV zMn*|V2`COBF>T@F<3kpNXjfkOS|2ECP!i-9%<%t!LxaGF2LTfbHk@A{-`!jlSu#MYj+$rZ}6VX+A`_M zv7>9Pd!m|Jrn(%h2o+^c@U(S%HZMihQ*&j^5!2N#Pd0HRvwu=4*mBtO^hCM2VprF^ z_q{g7WL2R`^dG;->(4)bV4eSN|K#L9Gv|N5A6#*?{qgzpn=}f)9*)V6n;&gD^@ro7 z^e4ApuY3{tK(A&uWB&>D_Wa}@^W?#b-5;Ot-}EW#$zlHBy_L0fH$#%5cc%JYwH=BzEs|rr(36Wy5Ozh#IQSI)7YMQ%D!xvR(t0rANRq6&38Aa zJ>0PT>4r%s{>O;zEBdkN|NN^3>5)MNyLmS+nR{j9N2RbQb>4j33I>}#3%qJliSC|% z+N(R_Ub9a8q>$sDmo?pYb(nf)=`h94Twp5{W`0X4=}g9zA0LlggEy6BjylVI(^Xu(P4^v*@z!3$RXHm)H^Tcomy7|g?gnA&#?&g$lbeq8 ziAQQg$nxq+X+;J(Ys^e#oaHiQYMYoC`<4^0R`eg|hzzrw+^QUTW>a0=re~YFxK9T~ zh*+yg{b{zWPjX1h`k>l8N5_BH&y!w@t8X;^lsa~?(e}ivqo;kQ^|2+M(9u4peC@XX z{QDa}6i04KyHQtlM?7_!>ZY92%%>i+Z+g?G!oB?8`%RZ(nD!Z-pMR!J>>f*kl)Or$ zWafwE{)x|QBBzy{m@~mtD{7<5vne`dx8JTlF1^X=*_1VtoCGIWYI5&0Qsez$Jb6vE z%IQ@Ukn``9c5)@ zDwV3JsAz9*4}n1B3We(F=~-G@Iy*aq!C*~I&0pLsZ@cpHJx30U zC~u4pKsu^z(USXStj8gT#yrZwc7LSI=S>!uyo%>Ev=yhl9ViuY>9}j3NpnVtt+Ksk zTaY^dKxxs4`#&eH73=)Gg1f%v*pqxyG~_oUdS*E7Zt;Cc zXZY*$)3Fg}(6yHPlO5({48`EHb;vyxZ^Ap{LcSibc}nw2>B*=kR}pxAY~9d~SOnYJ zy3V|RRl>_*9o#|r5%8FQZ^z4z371DxQc=6jisB5&*~GHctsTAou!^hPX`}G{PeRxq zJ`i|O3PC;tG#R)v8}H&&(ig3Kj^YYN5i4MxrMl+Hku>onP2-jcWP?*JRB{makN<FdVQvJLuC@9-8)$ryAh(_ z_n-0Ynq@nl`fb(9HM>X`De9=On2Wp3A$wTV;3~ilP7nvK9v`%~DY1P7Z7c@n0EXWX?WP?47Y)7$~Wj&6M%DA{Lm!k(pAx02yD3zlV3gzcgDcA?y|ASwx&=GZbS;8#qD{<8ch50~fF9{JK8nIx zvv;1b-L|#CZk%O}+b2R<;`zrKB;0JU|iV=MaO8E@%SN7=q1})6ifFclo#j*=G{@479DF;-fYK zS$#UE%SQRxHhN*#Nek<9>se9huls#2oOPFaM{R{$)f;R|%jT4+p(yL%i#6b>fH;jo z9?`uqskZh)nO(Li9lag)kEh7&#IGT#O~a?RxdvSTlaYJqQSgY$^z>fL_RXJ6CYD<3Sx_ z34uR;JK>)9RfQ53-@Elq!6Kh67~oBy-qh@7p@<`(=A^iA_}@nWyv52Ij3k;3&XADP z1zG8B_+g!!b6f++`1em$N8nItivZ<%0tK3<~81k89Q*{#h+PiMJ1YnvcKpxj(>Q zxsWoBeQ_(|#O270^6lhmJH396Lc3>WbGGRdwZ)Q5q7J%`XB+7olpOxTJtd4Z`<-2g zUJ{XMMExnh)2gY6-eFAqP%ASNP5`6HG)`S;T|#}dXVZ#UDu1MVj1Tx#izVf@%)=NE o$1b_WvfzZ@iP+j)xsCtyb#3yJ?Z{Hj_l{M;Z9m4j+L4s}KY?8=<^TWy 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..0c2f2dd47ff7b514281529da0fd6e69157dcff43 GIT binary patch literal 1467 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 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..aa3bc1b63ec600dd53897d38b33e2133c24640bb GIT binary patch literal 1167 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBN z1AIbUfpmR+J&+_7I6FJLxVUI)YBDo3$Hc@42?-e*8nUsm0Y$8=tbk@VG&Jz>@!>ZX zs75NI?*vehc1e(5FhhdF|Azes-rt|_AYlIb`h0);_>T6aUrWx;dA)4noY~jUFSxKF z;e$bef3ngm$3N<>w7kD)J;}Yc zuJx@-cR^8W&ZMuqQ*@sd*T_y@qoDMo*Wyo6TfceE)(=fw_6MSwC!VRhmbK$2v+?Ws zPfhnt%S_v9bau`9XJTv4t$DiV^yiy3f_Z7z%>JL@aVfuX^4?09hj-VqMkWTH^tky` zMSG3^JKKz&rrgBi2?7trAnOPCHbxSSQ7*s+HMT_PT*a zch;t8-gCUA%BTJYidl5zaw%T0e*UO8@5t;4qFQT3>tu3EzC2Jo;J8FUE3@oo6mPcf z+P-7`3zjH6>sa&Rpjhh983!Af6PHhQaBDl9e0_sX_64roNk*$GO2dDNT)($U=iiZ< z`MkH!9Ir^*prf6!(4omo#D#C6Ze+*`#}1|f0m~M%)U8n~iWb>SGWc-p^13xXdIfi$ zEY9%TB%!fo_KlyO*I0i93Ywq1)MWkWUhHvkmx)?Fn^qL8TN`uQBRxj!twW^P-KCvr zQ9hfxK5traeZ&1+*2|j?Oh2pBEmhb2Z|==$TOVln9MczxcEZ8t&_S%+)@&E3%jKja=gswY41{u zd|~cnQ&}T*s5t$~LIb64PUnjrOK$S~tuw80RrEReSo>Ak=KT9PQGd!?R<|ElyepE* zx}3!zy=!lCYRI+aWp8J2HAt{5dZ5U{@*w^}=Yks|#zLR!wmmv$D1FK)Qo}n^gFE%3 zLFz`y%dxproXP z)j&+~hK7d4U-)JNRqK=l`2{m1H2im{Kk%VoL&E+24;Ebi+FyJ)v!nfW)~@{cv+MmY z*w0^oe!>QW_W=q5@j3hE-DO~4UgYWG7*cWT&4q(NLpT^VK00|{zqdMvW3~#+2@kF{ z>O^k(m2z^Ds`oSFdbtZR(;z)|+nKmdZ{GmyXQk z^WQvm&z@I&3dbTR9^KBNp*?ZyxyZAQ>74$KE|NW`9tjDSDsRf*IWL=A@F687A}o5b z^7%QZpS`dYikx$J@)5~Jyg(km^(?}Uq&Rq{24);>5dPD`UU1$-Ecg9&-qNyFFS!M{>A*y1m^u-P{4ow z-`+=$oT{$rT-+?v>QVV+;h!dnUCYgvvbG%hG56|$%~f90{+yl3ykd1?iNm)kIyX(f z^e)YfltQ^_ zTXb&jTJ4(f3iwM6o2=f&f)U;PWnu&ZpUS# zCmp>W5qxjy%Xc|k=Z$tuHG29rEOT9YW>t7v*gf9k7j%|J=iarfTbx&%W1!%zQFP?Z z_pD`!9M!Xa+>U&@EroNkp;^k&dmilp7xJ&{Ir0BpcggP~j|(UH%$cnsdh*4Ab&HpF zyiK}PviyXW((8EZ5(QAoS2%IMY6AB{)5uN06yFNW01#?5h@}Y32ehYP`A;Euddb@* RcRedW0-mmZF6*2UngFYH;qU+e 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..2a967a431947e0b65916ee19259ecfbe2778b61e GIT binary patch literal 1211 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z1o(uw0_lc^1|W$C@bU4%WyQtCfox}IXBQWj+}vCsTSi94%F4>$-(OQx6T*#&iLtb_ zTmYy=q3_NCptMOzkY6xE{DJ=t z_67kT9=yMQ{lfYAhwD4qGy8W&*p5UIqpZ<^{7){=2*8VOfU*%<6{eY0Wy3n^I0rY8?=2)p@U# z$>;U1+-*xV;931oSpBJ-#N|Yun|uFP&)($Dy7P5n*}cM@_ZKbj&JQTvIEBUhgS<(Y z_~{GPW-Kp~H>RcXTr=1Hnmla{*8z8V&;KFOhd;gBxGUn>IUvDT-gours>OXzOLS%% zd3$Z$wRRWNe}-{ z`C{^!`8V`#ynJ?6Sx0vM`RDEKpRcLj$k_MH_{lU$k;;qi)$GX?Y)@~Uv^xDXq4dL- zJ15%$K2BV-d6~e@KbAMA|9`}j^T1<=Vuafo!(&ep+^!TJ`IIqp$s;Mx#%n%Ffy`xV z3>dtO^wWolswdt9P6pQ_4}7-TSvA+rH7AtQxEd2ec2qk zge{Oaam_{*w@n+91 zgbKJwH1jfiiM_MYD`(*}yNLmJHvT!g@k+DQtE9Uk-aON)qhr@>4GfTf(zA>Wq z^UNUbMCJa_)4b+KXF2$+xLw+?({LKQvE1FdX{^%sL{2w7746+^TVa{APjT9u> zi%HZJZAnR=Ud7?M_;rNG$%v$rxj7bhJtv#^mM>#YSkfNQ(rn?D{cG<0GO^Q3H|V%K zB<*bMQ*Mr!cw$46Qm50R$lEe#@O1#8?J9P!s<=(gII@jKrFI_v$=rUVR?)r$*1mM3u|pGNWjz8&t;ucLK6TCT=tOw literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/middle.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/middle.png new file mode 100644 index 0000000000000000000000000000000000000000..9d5c0afcb4041f3e590498f1ad30e66ac3b44fb6 GIT binary patch literal 1208 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfpmR+J&+^@@bU36GlPtcjg1u-7thVjb#``kadBZ|W6R0Ok&%&s7-C>xproXP z)j&+~hK7d4U-)JNRqK=l`2{m1H2im{Kk%VoL&E+24;Ebi+FyJ)v!nfW)~@{cv+MmY z*w0^oe!>QW_W=q5@j3hE-DO~4UgYWG7*cWT&4q(NLpT^VK00|{zqdMvW3~#+2@kF{ z>O^k(m2z^Ds`oSFdbtZR(;z)|+nKmdZ{GmyXQk z^WQvm&z@I&3dbTR9^KBNp*?ZyxyZAQ>74$KE|NW`9tjDSDsRf*IWL=A@F687A}o5b z^7%QZpS`dYikx$J@)5~Jyg(km^(?}Uq&Rq{24);>5dPD`UU1$-Ecg9&-qNyFFS!M{>A*y1m^u-P{4ow z-`+=$oT{$rT-+?v>QVV+;h!dnUCYgvvbG%hG56|$%~f90{+yl3ykd1?iNm)kIyX(f z^e)YfltQ^_ zTXb&jTJ4(f3iwM6o2=f&f)U;PWnu&ZpUS# zCmp>W5qxjy%Xc|k=Z$tuHG29rEOT9YW>t7v*gf9k7j%|J=iarfTbx&%W1!%zQFP?Z z_pD`!9M!Xa+>U&@EroNkp;^k&dmilp7xJ&{Ir0BpcggP~j|(UH%$cnsdh*4Ab&HpF zyiK}PviyXW((8EZ5(QAoS2%IMY6AB{)5uN06yFNW01#?5h@}Y32ehYP`A;Euddb@* RcRedW0-mmZF6*2UngFYH;qU+e 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..7e13795d065b8f03b67be07b674ba5f25d05894f GIT binary patch literal 1850 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 d%HG|7Lri=B9IrMKQQe|<3^ykXqM>Axe#NAdsw 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..030f0789969d33ebca18408a24a91d727ccf81c2 GIT binary patch literal 1169 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCY z1AIbUfi!-=$H%9nqy$vM%*^cK;sR03#>SSLo9plI&&9>%=jRt28w(Vdk&$tBcDAyz zs;{qaXlM`@7uVF(#BVrU7N{PmtI~H;3Q$PDB*-tA;eUg}fr9tv_diIuzP|oz`+Wb` znY9n=itTrHOq?_O@Y4SL3-{MAn6M$>gMorTd_q0k!_hV(>_n+9JS*JFsLv-Umr!|$Ku4~pG+0^l4e|_r7^HC2zuRq=ualPZ~ z)d)W2YvIXvm4L*~$zeL%?L%3oT|KuYVyAqJh1oiu{|$3RilRfCQlJ0m_$0PL;q%wx z@`Ojxd8C8lfoIpQ{wMZ(ehfj?h8Jc~%~u z`8kpgajA)$88r*c+{b!Pl;zQ`)k6C?=H7MLQupL;)-kJ2wM$YPH($BfsdA+&Rg>NM z?MK6#@20ZpD{*d35_G&}E%!u07$n)@y8O()89nh?rJ9P`@8#I4t%!>K&2Ee2Hk#T*k&dbULu6EaZQ;%?N=}*<<S#vPP1K5=h5B1zyBp1@tc)(sEK*$bkT@6flAN$ z8+l%@;W~YZJ@}2aZ{F^gRVjZI1MW!nvguUXtyklI{5j81Q_%gceQo4VffHuzb0ipk zXRTo7E)o&k5M$2is&s01&@vY8GY=j|OrOW3`sih#t@aV7@`o|A%}sXrI?e0Y?r!>X z_J&vUWsGx@{#=}QeeuODFKg_i&cFJ)ds*t%BWl}BySLvsQWDx;VJW9OyY1qS$iK!+ z_qv4^m>W2Rr8VftJ)6zO@b*F@DA6`3)W2qR(`cEX>OD;-a?`+4KXib3hZUBWSSt7I U?#iu8iUJ9Ey85}Sb4q9e021lPy8r+H literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/dominant-baseline/sequential.png b/crates/resvg/tests-hinted/tests/text/dominant-baseline/sequential.png new file mode 100644 index 0000000000000000000000000000000000000000..d94ef3eae27d07d9d5394c7ba674bdf27bbf1839 GIT binary patch literal 1793 zcmb_ceKgYx7~a}lBE%|;MM*W8$}-*LV=-UJDBAt4Xv{~-ND;X{wu&@2#I>b}5S3S{qLoF;axP;^wmHhkcOKp zZZ`-7Mt#E~$h?CuNphJd)ks%j6bPi*{0(4+nWn+KdBJO^kJCI;sZ<(`HZOisnwpw8 z91ej%sHv$zAP`+$T}MYp7z`F39&T-IZE9-j=jVsV<9&U7Ei5d41TI{-(Ae1c-`F4G zCs+Qvx;PNeoS!#G@5XzB{7Eadyv8m^zC71i*^^q|KOsERaWJbiDk(ZIKhORh=dfpG zW+ADO(?yki@ZWS7J4fqT0Ong%_>Am2Ccsx&! zSQMQs%ABNf!xl6nGJ-tyFRf)S3)S{fI@4}^4TpHdRm#1IkHLGO(T!5G8w3R%cL{}n z5;E)V^fWFbBxiYEfd};i<)ovXZT9ri<6xHDf3Xtyki)(9?97X9qY1!p$s|m{X3J*0 zSbpub>@awVaJAJ$1NV84vt(<>06c`qBJbZL&aL=p@#Gqm^GXyoYHL6%n>zx;C$zR3 zv{IaJ5SW|-h?{IFAp~iJ4HQQY8c)G!9(u`<-o=b9N|H02vSbWJEu@u720taaMAW)o|`Tt#`UY z7^Ar>244y@5(Oc)>j@v`thf9)P_@^3OIg9%;_x%_U{1o#^i>ySNoQ4Kz-D8>#b>2O z%5i{GA)*`*fl!7`0QUwES&}L4i>0F6^R4LSh!$lT zwm>+Hlp|-=-JkPjPQAd8%#l>Hz5(>k05?{eYltbwG(9N*)wsPin!QH7lRTvN(UN)S z>V@P67eyVjUbu$dTa%r_vDv*NZmOjh`(9^80Z6GCw}gFhgZAsCmkU~8?gr@|PAY)* z)9I9hO+B{KN=jY9WA5w-i^}(r@J=P z=Q>ZD_~O?!q)yiHx!lc$Ts1~})&8l^cOAJ|b%&?rb%T{*T*HmiUnZfE<70z!>{dwN z2Cn|Ph{N1C+e;f{*)_qC%(=vu#y+ze-7DrIV`2vJamtYVJKL1+vkH+f_s^yr)|W@Z z)!sfu+jJumyOGQhJ+rbX;31-2@&;EGG$tD#-d7xmaxXEeiq_@`By{ri+%k5ZdHmMa zNAS@%{Y4c()$_}z$1npH%+M{wp}$4dgajW6R4tGf*_149+)u~O9b{o5PW7yG0lxAn zy+_w=fE3qiye25w@3KQ~B=^fX*43+7{1fWPTOzcUsOxt5VmapBj4=N53w#HD~$F8t-cj8MuNHX$%zp=M$#s(e@Z%o ztpEz!x+ue$JaZGpbrzs%N2mk}GpwY0OQf+W6~wApndXXn-`=LWqK+^6W05#}jXM(+ n^vmd7ehP|MJ)ie~`u?nGpsc0|W;xn~^v!W|!sFNu{wMzdxlt@r 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..aa3bc1b63ec600dd53897d38b33e2133c24640bb GIT binary patch literal 1167 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBN z1AIbUfpmR+J&+_7I6FJLxVUI)YBDo3$Hc@42?-e*8nUsm0Y$8=tbk@VG&Jz>@!>ZX zs75NI?*vehc1e(5FhhdF|Azes-rt|_AYlIb`h0);_>T6aUrWx;dA)4noY~jUFSxKF z;e$bef3ngm$3N<>w7kD)J;}Yc zuJx@-cR^8W&ZMuqQ*@sd*T_y@qoDMo*Wyo6TfceE)(=fw_6MSwC!VRhmbK$2v+?Ws zPfhnt%S_v9bau`9XJTv4t$DiV^yiy3f_Z7z%>JL@aVfuX^4?09hj-VqMkWTH^tky` zMSG3^JKKz&rrgBi2?7trAnOPCHbxSSQ7*s+HMT_PT*a zch;t8-gCUA%BTJYidl5zaw%T0e*UO8@5t;4qFQT3>tu3EzC2Jo;J8FUE3@oo6mPcf z+P-7`3zjH6>sa&Rpjhh983!Af6PHhQaBDl9e0_sX_64roNk*$GO2dDNT)($U=iiZ< z`MkH!9Ir^*prf6!(4omo#D#C6Ze+*`#}1|f0m~M%)U8n~iWb>SGWc-p^13xXdIfi$ zEY9%TB%!fo_KlyO*I0i93Ywq1)MWkWUhHvkmx)?Fn^qL8TN`uQBRxj!twW^P-KCvr zQ9hfxK5traeZ&1+*2|j?Oh2pBEmhb2Z|==$TOVln9MczxcEZ8t&_S%+)@&E3%jKja=gswY41{u zd|~cnQ&}T*s5t$~LIb64PUnjrOK$S~tuw80RrEReSo>Ak=KT9PQGd!?R<|ElyepE* zx}3!zy=!lCYRI+aWp8J2HAt{5dZ5U{@*w^}=Yks|#zLR!wmmv$D1FK)Qo}n^gFE%3 zLFz`y%dJPD7;Sy*uVaIe0_g@)@=W?#mipLnLU5OhVvipKPb2`p~2z*frR^g z>^uw%%riV)978H@y}7{2*xX`{MouzJFEGEvzt$K6qI+>O^izIXS6yK&h=Z zAV=&9vs}UoE;^%e?X$4h-J{+*KaE0k>ls!*@`c8&qMbLI{<A@(zSjwU7ldQjtc zTU^OUtef|@`cgrqG`ZIr+}0aw*sn3Y*pn+e;ak$l>~jp?rj)MM>JnwV{9Jtr=%`_cQ;)yxh_vey;w z@GYu2@-j$dy?(IV#uHxy@-})&9+F&oOlcd0(wdUVyl z*S$9uv=buVRzo05wIs+d zm?3_>fPz87`TOzq``6FU@Beys_MF47uRmDuenY^84+RYe>i;_=_!?;jGB7Yzdb&7< zRNQ)d>uS?22Z@G@2g6_M`W>?W{qOvZgNgyuw|Yy zOOb3DcVES~yR>8$UpWwE8uR3(Mp)6@EuMi_S?pK2`im2%Zw9{aZ=KWU}-($#CjzUxUv{7u%my7AS&U(cSM zt#uJz-PK{aBzA7(oG(9FR@>Dsy}0V}g_>J-$6lG(Pm4NJ780sHHz73e)zZgTVndeJ zn60&m>#e?Y^vZ!%J!N%LtA&?Vs=rj<5VXB4`L9lxrvIcmrq_{ItLEGjU!%X)UE{AO zfB)t7e*XT+woCivDGGaxNRwkECdx3hfszPFBO>_#)6o}EjnWDG3hG~61Eq0KS3j3^ HP6;vKx@(b!4`X|g^uzth-1LrT?fAIc8@L{1; z1_tK!o-U3d6}R48U}R%Tlwduuef0zJMI874zMuJ)p|W9avm35f~*UYuw|KH!Kaet0canEZ{@w^+cS=nB@>uMtJ3Eaqdx$)3HHL046 zNS+7$aRJM{rrF2*5{&qLd*PNNExlfAe&@s&y5A8l(>{IG*5S<7&7DnhB`RXlr*Ai> zwaG;u?XV7W?(T@Mn_oL+KVwyjskVi?+#>(}kjfTqk&{`9mo^CezVfEWrR2*_sg#L4 zZbzNg{J6g>WvAeTnYl?P-+h#mo_kg8bx&`FnSM)aYlacCt?P_=b%{yL>+dgKBigBb z`@fssmD_GId)P80ytIqHc4`add6zmaD%W;h;Vahp@ym?l>~^OV!B-PqMfI);aqsq= z|8#HAbRB*{wbQOoO2X#rG_Nmw`rSd|X?n`&&#TlbyHJgJo8N?I7Wyyr7qh)l6W=1(8Mtsw-?>%$)DJD4 z;JimEaHU1*fuqlUcy(O3ux>|H=6as$X{q8lUs!Ely^>~=OPnry-D6YO_Vh@`BTpk{ zZPMXizWoiGSmKwPQ8`OlcU@aQzix4@$X4q|IX-8=+8eYRtkTQqyiiB13Z zC?s1}cTMR15w7SWUiRNVY!S!Z57#c4%(>mv%fftHR@Q!@9Urv9pc^4O-7x0)ODSGyQ#8j3I5v-fMQ^Bp-* OvEk|J=d#Wzp$PzHY2APT 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..92f6c221142b507296f88d0466993a752268915f GIT binary patch literal 1385 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N(PCV09yhE&{obHPxs!9jpw&o{ zH)HDpV&=3Pi=MLb>oz~@el33m=lve}NXE)SzmK+h3I;VPfs1X+Mdn4Z3;2JWxHW0x zrPWKm?%Q{3xAUo-AByMRevMhOhF!8yTi9sYL65o~Htkgjk-tlPJ{*=R82s%a6w1BMs_Oi(egUqZKFSJJDFJ~)!xxVX~V(JZxopO8RBDubt&#$<<)^-kG z^sybTZKggE&5NpaHyxY%YQoy%=1MW?Ob2KCtL;>7-+E$GW$B!%h6s&_H7?;=_vWX^ z_3KP^Eq^&7VX}v4%+Yd3LAwoIDXG300uedwQ>CBRC`I01$2Rdw%JJ0`U43Wl+|^n7 zRYoG7QPK8g=jGTdO4`{@rs_aPxHj!7!p1pV8l9?%5@O#a3myHYgBDtz9J^k`SjY_9ZpS8^X zibA&&)0caPe<`mLniZ3K$Kq2=qmJ3fy5*d$i+j8@`X6XbO|_Z+(#-VKq*TcRfx>C& z_tuz6GkYs}SFTX|x$fHq*3&@>CjJvemTrpQT{1=0_JA8h?3c{bQ&nr_mL|!boV#4= z@cm6MnwBhjabd}tn8+szM=t6tD}FS|YN^3OH3nv7=S!mh*zPOre!g@Q5C5FyzEh5$ zQu%R{{kUV8bN+e$z;$a3&91)-E!?$jt#YWzk$H)p=a&d^ZlARHaQ`|FPcB=Yvgq>S zZ_*_TH;ENZRW{qUOOG$#GcSkdgGjvhv{a{BgMHmgXU$yuB&+k}Wt~pxUly|;3Gc~~ zI#%yum@U2Rp7m~N^(EVUK6Gqr6D_!_IjR2bg+^8e0|Ax|pGE5aH+t_rz&oKwU;wfz nIYmSF{H@Cm>{}yra>4$loL1m+-tDnm{r-UW|6}d_< 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..95553622e5c500a16a0430013983e66b6df50ff9 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4&v?2xhE&{obAgeq!9j%ez;&Tb)h+e^i`^6w>|JJ99!if9oyy|9@K<|N-(|-AkIH`rUrW4KaLTI3I#o8^CRJALxaMn(notex z-CJ}oY?oiZCCNd-|Id$t=SLpCI;!l}xaPZ@|1p1=bRJvRD;y~ z^<&3@gm*=3N6Nfdyf_mld9QwX|AOlNd8=>mnR*-eia1@;)OKI6NYq=zeWSYLp4D@U zmu{M7HEU*=i0ABoYD=e`4DH=i^XK)_Ei$>yCl>E%Hi`@~ZBvSw zd_CWoGSHN7D=X&pz3%7+GP31*5sm`0SWcU218SI-| zHf-d0l9g&|bbO!qp_!Qz(zB<8s?04_{MxwPJ^ys(RM*dSi%WyAbZpB}UVUA0^{q0F zpeo5{cbY6dEqi-iQTuRQss+oY(y6iA7w3s?TCwY9QrCm;5pCYL*Q+d9%NJ>*@IZf$ zQR&wXv3j+>@GrLNv8FW}*dnK#-*K@%hUx8&yw*!EXXUC+jgVNMShW27zwe?i8KXBu zuI_J+a9gVR=l!M*?Ho_@GXX+JY_xoJH!($;CZA35-IVBdBX6x?FIOa!_`2869;_^G z?fmtk{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N(P1Uy|FLn>~)xv-JZ!GVEg1M^ksga5LdSYwuYxp_QWdt{Exl%n)r5sCb;WlR%Q zy|1lLIXOwydzubiDed3WU9TPOlhxhM$s8zgO;3qM_$UXDgvI;+b9CQWqy=V7;xl*r z6E3^L=&-raw2CJmLfiiB7JhvsYtQUghN}P9?cTfb-@2FgdrRk*b}VuG_~A_G1wU1W zI`c5)Fve+Dm5LggiHHOT%I|@_E(cu7;0_5^}@`B?e(n1$uq^ypHjcxDH`T9 zeR4@sZe*#R@v*N_r=QuXl*~+2GK*~AX=VJ&-~HpcRU0hC3dR5NdHiAIU`TcgiivPL zuPVowkWhPsX9JIGXDRy?zx@Y(b-Xn!Rh=~F#<7m6jK3ZV``pc(7&Xg=Vcw%7s~8h_ zGIeY>KYnw(KlEndoQOR&yS?=y+NUJ1n&f^UL(@;ESyMdeXTiUP6O4=fCMI?Ii0wNn z6?M!uB{#0s&`(F7<6%m+N2=k~XAZ|NCY`*xJ$31h3F{h6qPirqSD!zwyj(b2+B^U4 zM3Rvr0>M^GN*M zc>9sZMy{>R_jM#wR{Z(?$ws>FW6}Oq&Ph`umTY?+J=I~ko%L;tjWrvt@@O|02DTru zKHf0(qE=;v|E}v_gGyJw7YY5LeX#v-k@WSqSz1rI&oN3g*X9V;J+~APdzKY7z2{)r zgWS$jZ?hug=BzOG`S~~@R&i#p@%_J#+xF_F&&s`ijIa1`aJS)fStf1Icx?x%Q`4u| zUv?_>%$>FG?!3({m!}sUxKpjQIOkWN`%`bHN%b)sGOIl6OvRdJO})l3mw*5L6Q@ir zNPhk4W_0|R(!N!@+v+-8YkHZzADuC`H83kp?5t~1jSM%xTrvNDW;>q_LqnnhgPTUm z|3+{13X!OC<(T{DA8pl%+?1jS%qoMQs!u)3WuUI@5*prdZ_dmdK II;Vst06K*NUjP6A 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..95553622e5c500a16a0430013983e66b6df50ff9 GIT binary patch literal 1189 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4&v?2xhE&{obAgeq!9j%ez;&Tb)h+e^i`^6w>|JJ99!if9oyy|9@K<|N-(|-AkIH`rUrW4KaLTI3I#o8^CRJALxaMn(notex z-CJ}oY?oiZCCNd-|Id$t=SLpCI;!l}xaPZ@|1p1=bRJvRD;y~ z^<&3@gm*=3N6Nfdyf_mld9QwX|AOlNd8=>mnR*-eia1@;)OKI6NYq=zeWSYLp4D@U zmu{M7HEU*=i0ABoYD=e`4DH=i^XK)_Ei$>yCl>E%Hi`@~ZBvSw zd_CWoGSHN7D=X&pz3%7+GP31*5sm`0SWcU218SI-| zHf-d0l9g&|bbO!qp_!Qz(zB<8s?04_{MxwPJ^ys(RM*dSi%WyAbZpB}UVUA0^{q0F zpeo5{cbY6dEqi-iQTuRQss+oY(y6iA7w3s?TCwY9QrCm;5pCYL*Q+d9%NJ>*@IZf$ zQR&wXv3j+>@GrLNv8FW}*dnK#-*K@%hUx8&yw*!EXXUC+jgVNMShW27zwe?i8KXBu zuI_J+a9gVR=l!M*?Ho_@GXX+JY_xoJH!($;CZA35-IVBdBX6x?FIOa!_`2869;_^G z?fmtqZRe@KLlLpRh>9tR$8Xkb)m}5ei0V&VOfoT zrm1?1ZAv*giEdPBx&52joq4wnc-pkjZK`3*ta(}W|GA9K@}7jQ&uvoeGyhpgD;oWn zDpG&yZF0oY^EcjJ|L{R5@#pdM@PpouIjh|m8vIT-iN4#;RhH#<+Ae4` z%m0Ry+0~$gmHsDQ^|WV4Zm41J=?Y$SL&Wuf6pw+{`HUp)oFb-#R>6p{<#SF7YXADQ z!RGv`uiB>*Te5yOZuOdNyYR;pu9LsYPi<`V{r76ap?eX&yT1y{xG>Jv%lG=N@8&0N zsm0ZIS?Pj*o@mLBj~Xn~s;Axi)uDC$zH{Y-s8!4>zO4Hzc}LUJZ?oNlve<}!{vl7l zHSCex6uMEIn5C)r?mv;tO9sbbNK8MZD;a>6P4)EVes8Pi=7O zk*k;3tT^${id|d`G9MES-_9+4_uKJ;ujXqR<$$wGBEvG3pYZ;%KD6mbd!w(k;;X5f zmMTR2s!uq3<ZQsjdgKDk9ns z`dtayqpfowvwt${7XCkL-m)HC)t7Lw^~{eQGItJeH?qp;^dDST-%`T=r?LI>m)nO9 zU5o$d8_2lodC)dN7VnK4bc|mbtiLSwZo7iOw3oJ*&;AhqWvgQ3XrMF6{$u|2$j#|& zs@nvZ{j7@;Tp84~KHC&`-C8-p_(NLsab6kYw;nB`o6iK1W2OXo=SXXGvmSgi z`J(7rZuw1#NAFDO35_^6Z}+F!6GG$s6mCI2p4H#=mfDPBr>3r5Zo#F& z{rj%Mvu6hX>;Ap{UT$3yz{J4A%$SqPq_yB*E#I;S`&wO`n7{=9cjTa^ZaGcU0lDy% h^n&`Z4y$0rXN&^dJw1N=S*U>uT~Aj(mvv4FO#p$zaM1t& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/font-list.png b/crates/resvg/tests-hinted/tests/text/font-family/font-list.png new file mode 100644 index 0000000000000000000000000000000000000000..365870ead1e03fb933f0046f7e32892f5c0a93f3 GIT binary patch literal 1126 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4dp%toLn>~)xx~ok|E1qV*j9LZe)=nIQRDY&LE6+aXFcA^XnT--zkJv1+L$h9)!$+upteEt&+Y2j z-|No_KPq$i+5Jm2{Yp|&h+XAb3A;AV8_S+eOc8(iFIHP6Xi>tEZtZ(KqI)2Hf5{mArcbv4*|XpLyx>MxE_e|fqsy{vS83+sF{{nB%PgV0;^RV*34 z_vb%cRV3yVD*?%+%#xCC<>THF3rDnucxWr{-MT`s&md-)o<1>)TdvZ7WzK88UB9)iXY2 zCb6Zt_UjMWZTCO>Zl2`^Q?ux8_Zy4#{;zVs7XS7_BP)Y}0LzBYB6a^8z11x=CiDoT zoSdZUJxym&Q(q_RL~a7QaO?5|`_>4ZTyi8Pyen2rHh4}Qs9^AP^>bP0l+XkKT6)VW literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-family/monospace.png b/crates/resvg/tests-hinted/tests/text/font-family/monospace.png new file mode 100644 index 0000000000000000000000000000000000000000..ba5383f1adfb28c49235d9ee69132948a0c7eed5 GIT binary patch literal 1179 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-kerning/arabic-script.png b/crates/resvg/tests-hinted/tests/text/font-kerning/arabic-script.png new file mode 100644 index 0000000000000000000000000000000000000000..091994a38fa7cf6c3df12e47cf7c1d721d2b6d86 GIT binary patch literal 1664 zcmcJPe>l?#9LK+FZDq+hwKWop<{C?cP>o^v(K0`?uR1KlSuD&|ro;LnKk9Df+9W?} zG0rSDp~tU;JgZznOhy#fuPt?T@1z}&q^E`dpkSKamyVEt;CRrb2l@!9K# zy<11UHk90}$Q-Ob?b#WMqs<31U?e_1xH{s_w$q=Gll~95=VHm9GdcgUAiNsZiYswC=#2M0eC71uiy=Bm|0hob|R8vWku-jjK&in3wF9&W*lcE8yo@EE_GEw;_c zVvErqxb}H6*6LQ5hH}X}u$>{PA&Lf}`!H*xJyG&73O$U?fPQ@TZ*VY;Kj zP0>>F4txOLG%hXuW-p8*ySOcyjXxsdB9p{YPV88qQkt_s+mkFlXZ~>7lE82LI8P;q>wwqc@c4u&29vvM$kc|-Vq#-j*6h{f}E zR{=?76tHDUdrbJZJrjRbBOE>LZH5Xv_L^NsFc8LpC#F)-7ICP8Zi7{|dtIaGNSluE zvIu`JZgYAgFLYSne1PCpjMXKO0AaOMsUJSEeS4&Btz!Q)uERkhKJySvJ_W+c+NO$! zUd~9!`jtf|Bc1(_HiRHc#_5qq#@ybQNjsbrl=GJ9TgMe3)2<&c)joW(X8>I(5{~rp z?+`^LVU|Ht->2R1xiC_9wzOfa&jlW^OaZ6%zj$-1)}hQeH7fklLTJ}w8X*CemIl%1;rlINaxhO~^Ps#~_Ve`s7`3sJH9wZ;=R_N}Gt zvhk(Pj841U=rdJ%9zsST@EKUV;cR%TbYn%Bw1+nHfX^^ zzAiS>->3p$<>kl_u0(Ra459S1Fl8F4$ah&!>&*LqrbViV!{skRv+xVBOt|N3H;(H; zs0CnRKcLfgboO?lpqb)fi)ERDv9iPoR=%j zBui9=eFr?QSBKViPBv;BcL~41+}-JCN#5y_+%C7J|MpPwLGZd5`;DTJUkER8|0ZMF*X*CReC*di`5Lu4oP()~wH^ z%jMSuBe}%tfh|}y<|wl(v^1nZ~Us!I{*Lx literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-kerning/as-property.png b/crates/resvg/tests-hinted/tests/text/font-kerning/as-property.png new file mode 100644 index 0000000000000000000000000000000000000000..3fc891f941435aaade9f71c0fd7d1154c3b50837 GIT binary patch literal 1551 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBl z1AIbUfpmR+eM3V-E(1d~14B6jLlOf+5d(uS14AeSgE0exDKoPjD=Sbzjhh=kBO_3; z7Bh2(q-0%ue5IKgkO4FS0&Ex<(is>u7#N}%82A|&fJV!}q=580X}-5WO1UJ+FPI@A zzChk)PWZX~@4vpE-TH6N?}Not4;17JJZt~9{@?B2_WvCOejDa7FtEycx;TbZ+=nCS?spG3_)lL`u{6$P?o`KMtz>@Q-}9$tDHNxkoTTbKO(z8hwN-Bu zR4S6nj5Y1i#u3wmSr)xuaw(m;#$m#v|Mf zKL%~6I4HC5>74m*wRF~$v#n+2zPwp9=BCfb9kF&1zu7wi_{CnR&etxMnae2HeB6Jk zaH>cBQbQNK~04bJtFQzYle&Ewxt9joUghix8G(Ym&R=h4wc)H&}N!xDIA>F^f zFYQ$4m}j!)mhPRUdp56*ynM7OrT*@Nc}%DGt~y`r^XIvhPw(L!`*a}Bt=qis6zuqWhO29O z>(>4M-^Sm#&V5a2I~#lb|9zheK5b}=OZ##C?Xo}fpWXju^2b{$Ec{EKrS#&UM+yFn zky4hE+n=7^Kl9|>ggd44G#p#Ix5fSI1_oWsn#YkhZFOd<@n8GR^-#2ZYy5TTOydJ< z+s`y{Ul+03;V*ctWV2sWld=KNgu-x-1qy4P?z`92_5H2cUB~q?8y}|ac{DZAaAxyb z+58Cca|!Cse^L@R#vPldwXyTg_O~q8?yxCMY2JFVN_+q9DSV9PtIVIDeNmGd5hEuV z#`ctRy+gpd1RK+c4RHeIZfYM-o93Ko*kZKiQcqy6r0TS9x7G-jBrZ+sOW7u;pgnhm z;Uc{?8Hc;>RB=40{&Ar3_!6${toXL$;qyA!r1Ol9ui`p=fjio2zoE^A?0vP8p`u~p z+nNK9pQ=zkSKZjR*+N3wC6Hb0joiZ{a%PVv%D3IMp408(8zETs{)YatXX4ve$QZN* z8{0_6YE)QN8x7r%lh?xa9)LS1{R34jBae(pu?H31=_BwboN?h}+`h86) zRdCforoA7sPxq{C&pdqR?ScYpLAxMkfOWZRfjeR>VV7D@s6HB(w0%Gf&pJk%~U zjJUBm>FDCq8cuRiSJqURMoj&BX#UDV?qxTsw!5rgJ$R}g(s9CXSkwBo}9yX<}3L~cO!UTr(2N)uKwt8N>$otf%q3p#B z4hIDerW?C=Xea*dPGMv9cAe~TVx=Om$N&}y15T~^|Fo~gXw_LKuyamgr>;F;vs2^D eY*)>6=S=zV#&)CPh4apUidj!rKbLh*2~7Z`q@h6o literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-kerning/none.png b/crates/resvg/tests-hinted/tests/text/font-kerning/none.png new file mode 100644 index 0000000000000000000000000000000000000000..1e5d4d620a0c6c35f037b379a593481fe8492171 GIT binary patch literal 2181 zcmcIlcT`h(7XC#J3^fTb6UtDOqJm%|MWlpK1(qU&7Gc>0WT+wtE+CO4Gy{S#FtE&q zD!8D4Bq$jj=^$W1DH3o&s%MoRIz&qLW#z9u``4Z`_q=z%@4oxJdw$>h>v<}vcDVy0Q`mEh83KF{|G5UT%9~@p(d3|rO{|0 zE)L>?Ad>|-AOQIK3J4U3hk(x)WG)w!l^vBtB49E>f4`swT~kvaGV(|Ul~gLo$pIM5 zk+`i*&_W;p8V!ygKY9fYKOzzmkPL>!3Q8?4psNey<LvbziDbRa7W za5!-KG!PdD3&+K>f+#{&@&7!pZ>cwe93{8CZ^3u0n01Ole3>*wbO zl$C*yAOwER%z%XjOi2j@1w}+ed@~A=$Rh%QzWx!1x{!BO)uZy#r6U5J1d8Zr;Oq>7 zg9QU2gSLWCDhOz@r{^~cW#*@zK?ve+;9cASiD-7bTs5kgiE%y7FX!`-BtDWJAZUfw#4Uhg00?H(S)91Lw0 z?eX{5Lfazw?E^G!|7w&4e|n0~{dt?^{f_?maGZqPYs2v^M1?yj0EplmY%D$E$Cd^x zVHV(fVGOOgJrg0b-=y2g*eVZ+h{ori3U`5R6c*f0ewnA~_&1%)d^JIS9C+ftp{~B* zKZ3`Buf8e&05Y*uB>c-b0hxN{+_=#j{~+_ApeoFU-mi^@yuB}LHI9sG^Qt*c>`R4* zs8+^kX(+SIl#r;bwZ@jS*?t(>j(eTDK46+lhtSKJ|#>gyveWC=InX z6{1Ux2%{dB=d1|fjGAu0`4c?(_fd_vpBm@3Fcv8JtPw-b9i}SMI8Eh5_3Dk8F*oVO z9uEn(PCYVL(`1Oz7IhI$pV%l`iQJ}~Y*;ti9)0qG)G^t#_+s`{U|yNEo_G5sj^@^qFxT z>(FxQ-L&J)iluC27X)iYG{*+A&Ko2u)-9q8tDor6OM0$DR%i_-^;O2wJoxC9WX^<1 z+J`D~8cOX;6!qQ=iOcleN+fSS!ulv)6s}FCSmhY<(pPm@kFBOLx@w`kmbzXMw~nxX z71snKnr`jZ@!T(XUMMC%R(_t?r_vUNh_n?x^XifDBCxBVYnoGpw_5`^H+{(ixtw$o zw&z%h?r@P=!dz-f3qq+h-F_@psxl)Z+*pl}DEC$aLzck~ub-Lr_>*S3eej@D@G=!$ zsa{D-yMAv`>T1eGgkx8oOb>;%lj+qWA!I6(trOXbI!W#9uX=BpG3yfSlo=f9f+yjtWcVCIV0kLxq!UfcT?`ovqYOE$3D%f+?l zqcHzGNq9@=<~(ab%Z)Dhe9!WF`C?K%Nvne1!(7Ipe~O*FxSYkIB>!HZ;$=(qbXLTg z^+k?EpmL)P)oAScwwfPQupUoV6H8l<^{|n!x>9`ZlbbMKBB~WlCL5);)yK~J8*Ujj zx>VBBbb{-@rVk?zpNIW}&hdO7WEr-wHo7n_I>k+sp1-DtY=x7Ol;MS;xtZX+dA|TLA+`Ga<*w*1t61B7WTxFFM$7Ia z{%*R#T8#F##&w(z-iPqxwS>4ajY8y`KIgBf&Ic}dH@P?HLPf8_#vDhs4E6qySYj+( z-}tV*v%gwAJSjBPpO>ERvoDgVlD*V*+Cm+lPPmoff5M_FAuEE>>~Z0@I=E@rbO*7U zpnFaylKXLXQ73_xYf7eed;i{Dh#I+ajcd+`Y?$lth>=WtfxORMDMWddjhiBz{5DBp zvfk02L2D8}rEN7ZR90)vFmHdeDnU$XtOh*;Zoih~b$(61YS1_9usI!ErErZqJR44x z9eKyM^EMyMZQZeDF2?rC5kEUJXQbqCL2RR}?o6-dTfb1tpDtyq4&R9RGL_8!#2+lU z6t|BXqex6_?@2xNKNx~569DM4085O^>K-HLlIf)O3DHyEHs~L>E&t!iX@dR!D(`;+ m+XmYHe-#_k{8z#(Ouzth-1LrT?fAIdp-co@J z3=AwcJzX3_DsH{G(8zWuK!WW;{p^;)K=X(7|G(#O3Dj^l7t1}oQpLG3%yi+ZS9>|$ zyk8T=F-0eGQ_9InUwy?ul&Uv1snx&ARlTQyEcmj6`4owoF=;a)G6M`o$YIGT-%hSUv|#%V>WpVQ8oFt*cov#UaL6Z~)QUQ=>^XMkGZ+N-g` z(@tkD{rGTAz)?fNq^mqmi-MTB=LTxc^t-Qo^xq?w?&rL(o1R8FX&sGcb{E>MXy0ux z(I_HOZB5*j=s$8Z=Eiof3=fmnIn!nO`>k&fuN(J#Q_J2BEUWe0l6`uZZLfBDMen#& zAjq~_Xxi(}%ZjDv=PMg8gC*ow;!H*+!lJHmeiKi4AWZm`%W*3SNXzUtw_ zs|1=0cz-2S-rN`PXsOtbcFPk=CSjUum{i2F9hXk+I%IR#4@kLk7c7(EJ-~D0h+8h-T32=^Qc^}s>*6&V zuIt^jKXXT2|sfwhZo6*Z{PgP^ZJK2*14?N1+x-cgEuUxPhedwIn9#a zJCA91o4HOHQ}}mt9h;KpH>XuaT$~r;t^X?YaMAgb_bpvt9{m#CetEfo$B8|OiXT@r zihbPD@hbc9&3S<*L(kZ54C7gC`E7E9Pe#!m#k0z@IL--j>|p!+=*ja1VqpTsD}vW4 zp7LA}6j5d=GgZmeutfjM{S7OAh@9Wmrh20K@5y_GJ=a@Rm@FOsHr<#uCUT^;$Z7J0%@*hmAS3mx#bL!)3mY3VI zH4YrkS$uf<#Fc&O|5x0-^W9zZ8Ry5$y9e*BIMV%CW*ujDwcYB!0<7ih!w*kyXn)6N zKRY@nZNq*Mow#igx%2MlZ@;a4{&bkns+R1I>M)n24_~fCJeQyUJ>Xl(-scb4t%B|p z@E(4*w37eN`U^)BPI|R$Sd#tWcc#=wKcLZ~{fVB}C&-qDD`)C@CEUDlv2U5nE;gIx z8Vl+xv8yb=R;89=puDI4mPZKxR+?o&~&RbK@ry;N|B%bHXBE`L5uB$i; zC4Z0f?V0)U+x64S4eM^!rQMrk{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4n><|{Ln>~)xzN0onL&hg!|&c(RlnCq@?HowmQ<|#e@pni=i5$|s~puCIh#Kn zlMAZkul~)mDdprO)z??|rt?OEncQ@xvh>O_PVI8u#Ma!n#elV&CvDx{wr20z8^(uYSra9=`t$B}uHeXN*zmpn-0NpKHj};I z{jaLqc}wkyxBupns%c!_^XGCO+`0PLPgysQ#j3}0bat>#5MuWJ+W1st^3M8{<$DzW zPvCql;-LO-T}4#M(M^UME;>+XS$KH-RFj@!b zt>HbpA@+pPp~TXM{8K|V_^IjqmyfV=eRoy-nx4*wRg?I#9k^y2t+#YDN=!WP?%D;3 zO}F%Qcs3Mh8>$$2nXR#!c;o+$Eg!1yZSyeE(P|Uq7Oyj#{%uiWD6{)FpA)~?wWY#% ztIGuP?tcE)$Q2RAqEm6`<;9Mtm&M=7KlpaPqk)y#Mn_Ce(7NW=Ay)-6RnA7%@1OtG zbWF37S#PW_tE2aaCu-Wf8U4>1zq@lb95t4Cdf#V7*QdhGACy?aQm^MmynB4h&e7JF zDKT^xYfN@}(w0QwO+4?mu9(ckof`c<*q>K?D(523iyc1ezrJo>k^d#%x+HmdKI;Vst0L&e`%>V!Z 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..532facb74da010e1395e19c666f90060a80e9c9f GIT binary patch literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4n><|{Ln>~)xzN0onL&hg!|&c(RlnCq@?HowmQ<|#e@pni=i5$|s~puCIh#Kn zlMAZkul~)mDdprO)z??|rt?OEncQ@xvh>O_PVI8u#Ma!n#elV&CvDx{wr20z8^(uYSra9=`t$B}uHeXN*zmpn-0NpKHj};I z{jaLqc}wkyxBupns%c!_^XGCO+`0PLPgysQ#j3}0bat>#5MuWJ+W1st^3M8{<$DzW zPvCql;-LO-T}4#M(M^UME;>+XS$KH-RFj@!b zt>HbpA@+pPp~TXM{8K|V_^IjqmyfV=eRoy-nx4*wRg?I#9k^y2t+#YDN=!WP?%D;3 zO}F%Qcs3Mh8>$$2nXR#!c;o+$Eg!1yZSyeE(P|Uq7Oyj#{%uiWD6{)FpA)~?wWY#% ztIGuP?tcE)$Q2RAqEm6`<;9Mtm&M=7KlpaPqk)y#Mn_Ce(7NW=Ay)-6RnA7%@1OtG zbWF37S#PW_tE2aaCu-Wf8U4>1zq@lb95t4Cdf#V7*QdhGACy?aQm^MmynB4h&e7JF zDKT^xYfN@}(w0QwO+4?mu9(ckof`c<*q>K?D(523iyc1ezrJo>k^d#%x+HmdKI;Vst0L&e`%>V!Z 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..532facb74da010e1395e19c666f90060a80e9c9f GIT binary patch literal 1115 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4n><|{Ln>~)xzN0onL&hg!|&c(RlnCq@?HowmQ<|#e@pni=i5$|s~puCIh#Kn zlMAZkul~)mDdprO)z??|rt?OEncQ@xvh>O_PVI8u#Ma!n#elV&CvDx{wr20z8^(uYSra9=`t$B}uHeXN*zmpn-0NpKHj};I z{jaLqc}wkyxBupns%c!_^XGCO+`0PLPgysQ#j3}0bat>#5MuWJ+W1st^3M8{<$DzW zPvCql;-LO-T}4#M(M^UME;>+XS$KH-RFj@!b zt>HbpA@+pPp~TXM{8K|V_^IjqmyfV=eRoy-nx4*wRg?I#9k^y2t+#YDN=!WP?%D;3 zO}F%Qcs3Mh8>$$2nXR#!c;o+$Eg!1yZSyeE(P|Uq7Oyj#{%uiWD6{)FpA)~?wWY#% ztIGuP?tcE)$Q2RAqEm6`<;9Mtm&M=7KlpaPqk)y#Mn_Ce(7NW=Ay)-6RnA7%@1OtG zbWF37S#PW_tE2aaCu-Wf8U4>1zq@lb95t4Cdf#V7*QdhGACy?aQm^MmynB4h&e7JF zDKT^xYfN@}(w0QwO+4?mu9(ckof`c<*q>K?D(523iyc1ezrJo>k^d#%x+HmdKI;Vst0L&e`%>V!Z 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..94b459a5e4c305f928a8e2c8b59dbbf99bfc573d GIT binary patch literal 1032 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/named-value-without-a-parent.png b/crates/resvg/tests-hinted/tests/text/font-size/named-value-without-a-parent.png new file mode 100644 index 0000000000000000000000000000000000000000..13d787405d306de7ab49ee84ab8140769b4b4199 GIT binary patch literal 943 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB# z0(?STfi%^D$b;G)KtrWVg8YIV7z7jy?EM4c6Y>k{8z#(Ouzth-1LrT?fAIdp-co@J z3=B-SJY5_^DsH{K)|jQ_DbjXv)vGeu#cIb&On&YEU!8Y*BWI!bvc^WnBD(`xr??L} zKA5)c(xE8L$Qh?Pw(3S*C_AK8>Zr9L;b0Rh_qF+aVmcs(m`((Q+`s~2Z%E(-lLv)B z?1N3JV3O4vqH7vhFHJOlt6cGKU*6RO-J@1Z{`jm}=Oa5Qcjl`7?>{+jeD*E!-|wfl zb=F+H{4P9x`L^A6|Aw8;+b(B+fAaLZ5^JJ&d*{u){{8>O>bY6dV|G`alUcLzy2|p0 z$|s9utNp%x{(Zvy&OS@to$DgR)v_E%f*OS#hH^xrp5xu7D@M+`! zRjY$%tNi_+aL}uE&D_a*4*lXk;C|_qv;N5mISIB*GU-#-Upu*RUeU`$TZWuT#ec)f zPj0 z_UtQGsd-0UO%9&>YTeE)=X>i`9oV(i^4^}d!@r8NXPB>fyT^V_`;)3S|LkZOH3`&D r48N)){8zKS%sdn|!z(j2G3!55Cc{78>vOMs1LZJJS3j3^P6zu>&j^FHtQ{l4$}e81n%_xt(2S3KMtQA*lM zFc=JVz-b>523vuXPsLR-joZCMN7(|8a`KIV!IWF%b49kXvW`p{>2c88LAL&%^R>hE5)b5iVyO)0b#*s+(J8$#tqPl}NuWQeRzUB?z{1G6F4lXWE65gfmyFs;)08m>S~Ibh{2I%HFHdSrja@QH4KT8;vSD@3^4A zRrJ;3z~r+{h9GBk%>4o5!VN^%stqNTtcjywT*{*!Yt})wxJ>u!i|v_GTf~?NsnZxa zqZ%}NL9hM|qnQ$?nHr!n-npA??~7;~EoM&p0r70AmhoKBNegZpc~u1^Zf*Jf-p}a0 zFsy%V8_niE)Z-!L0&jNh`t&~bn>+xZ$VV}XvB16;iTFcW9sEE+6gvSu}qHrYOK~uae|f$5Z8fU zVz^!9)WBh9DIc0Q%kQU;>yrXv6vtYrL_A?v#+cZB=$nSXaKQ$h^{jZw__n(R zCaq)xP=Zz28<@}EbdKLTVtA#uGWN_!^tOtY_sp1OWRo;5gT{ls(+1@<{~r;3##Hx zoKxK*zYO>cntvqBa_iU0OL89f^PL`L%P26mfTR2MkwYT%T*ijzmoMsUqAUkTD4zZn zCky;s>{1lUb6s{2z~0C_5T&y7XuyrUO4gkYG zPDJe8x0$&sd&Qd))Dv$}dz`hc?r7u%TK*fpL$Q8gR*#+0V&>yaTmg*D?<~KhTETc6 z@3wIvJ=7d7#1p}JR?NW5RdilmE5ZbC>v;9`us-v)kJhxFK68B3QBNs?$%@Wny^?gl zL8=??h$pBjw}qPz6F`(1NeY@ziWwl!Pw5hPEr-%aIx&4^izV~X#}M8LIxmXftPp14 ziq@1RqoKaDLV1w?2d`0os(sl_EbjUeWK=Q+2XgiXIyLAD!N#rBzcM=x~w#O{gxXsjF(F(3%lTG+H2w(RErKl5gsm*LoYx zDcWDwbl3{y)IL9Pzr-KV_zjgBN9!96-Xsf;YB3~9t4rpPQu156u&JnULu9IZiS+_w zYJ6k1rS~xt@+X3tiI6*hLFzLfhO#9{`Um!0OIdgtTEh$TLKGZku%6!dB-xcP`=6>U z@RqYy-rI^yTD7;5*Ou!>w@XfYaXWaUyyz#T4gKpQ)adxDI|f|6y3cK;>H2SjJgeDF z!({HC+AR&%6!*={v%s}252|yJDNz*|h;XT|i%WhysO}RZ{dxHg5b&M^IcL_qjxfqB zVOI$~LitUV#hb$Njw}33l-sra%;;VlxP9)K+=mapRF)Rs>2`-~cW yz8}kRTn=D~07Pizl1N_o1sLg~nN;E(+aH?WnrkYBkXf7j^E=?+w(o&`P|`m!c{W4< 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 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4i=!umgR#`E;zcJd4t{BzQjes!R5jv%L`_ zl%Uhoy754S1b1@dMgy^9Ov#BlJ*>wL0R@2K24X<*L>-{`p$K{^987Kj2g4u<7etiw xs4|itN&ij5xDU>%JHG2mLU?M?i36K{G93%y4NOigHv*G|K|tQdK0LpmpsjuOoOSE>pS%6+{kPx$vaP<@F)%Q%^>lFz zskrs#f+M2?0|Uzj<_ix07bzV4n=3f2aG{Bs`cj)ncMX~NFgC8AwbOJWH>I3(qBEsr zzB_HfEeoFJ#3m<$>rb`RxBcD!fAT$>jjmzU-VAJuKd~DqziPBsiQfAA@}?gxir$UF z%i>Q@Fil~7R(fLB3BD!Qt$Bq%2)|zCd@VIkVw0Y5`_TiCur#mv74ZdsF?$I=-okHLlG$wJDC}n(X9Nc0V`!`K5YhOy5{& z9KC$&iT1mvPRT32yLo}*GGnU4iYMV>|NISP+X`m4tuc;#4v=ESLa?>6uAU900-(Zg-~=C54}>zq`#DLI?OSAUD% z&K@}_>ckcImusgBp8c2FZSr%1t7Pw~B|f>LcaO#^Mo(E5>a4=P>56oA-yM%lzw|yH zN>;nswl(L>o~IvP>0grcH^~3GZQ_pCS3>se(y7$iazp;ijmw1_SH5(ZCa{gm_u?((|- zz252;8WVa1Qcg}%^`53PsHv}$!5MDS*5wEGtr0r8G|K|tQdK0LpmpsjuOoOSE>pS%6+{kPx$vaP<@F)%Q%^>lFz zskrs#f+M2?0|Uzj<_ix07bzV4n=3f2aG{Bs`cj)ncMX~NFgC8AwbOJWH>I3(qBEsr zzB_HfEeoFJ#3m<$>rb`RxBcD!fAT$>jjmzU-VAJuKd~DqziPBsiQfAA@}?gxir$UF z%i>Q@Fil~7R(fLB3BD!Qt$Bq%2)|zCd@VIkVw0Y5`_TiCur#mv74ZdsF?$I=-okHLlG$wJDC}n(X9Nc0V`!`K5YhOy5{& z9KC$&iT1mvPRT32yLo}*GGnU4iYMV>|NISP+X`m4tuc;#4v=ESLa?>6uAU900-(Zg-~=C54}>zq`#DLI?OSAUD% z&K@}_>ckcImusgBp8c2FZSr%1t7Pw~B|f>LcaO#^Mo(E5>a4=P>56oA-yM%lzw|yH zN>;nswl(L>o~IvP>0grcH^~3GZQ_pCS3>se(y7$iazp;ijmw1_SH5(ZCa{gm_u?((|- zz252;8WVa1Qcg}%^`53PsHv}$!5MDS*5wEGtr0r8oHx{87*B zdq11Y3cZW|SH9pD^Yl=&4I%!9(~Qibr}JNz?#+%o%s+2~mW)dM#D_00o&KFUeg3V& zCtRzSwa;)oqT6Y)dygPbBBS7~**;xsHnNoe*wSpR8+9tXX?i=m()!IpFDIN_-Erz} zrPjF($J*7Hm8LnmOqrmq^Hi3{Q_AO6)slsLDo?miD;@|pFlboRA*AwzGrLgt{Pzf( zD>{zXy$afv3Q1bX>ubvYF`jo*rQ*;bHV!9_qVk>713tBdUYy;~?lh&zT<0^h&PBn6 zE#^8s&ug_$N?+sO;Pol+?uH3WY&<$vBE=DB`9+&0R|($P&Ug7bf83U`3WF3*@5g*1 z%2%a4PG9a^5qVf>cXr@?6_b}Y4ognEp8Z2@;cwH2n-@A3H?Yb*vVQQ?!(|?S0gv5D zhG`Ld zm=X&YgmEwY)WxoI@j^07gpucuAeUzU4GpSa{z-+2*Ee+}`>?ldXn7-WeZtY%%`FN^ zlEH`B#NuAADOCx}-sF(v%sIKEy=SLUnYz{5i{Jl0_@61j=wMxvz{tSE!uZDK===Qz zFIm`GCkZNnQsJf)#lcLinV)hJlwH=?vVKdQ>Y=9kj7f2a-|G9B>)(S408dvxmvv4F FO#qygsz3k$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-size/percent-value.png b/crates/resvg/tests-hinted/tests/text/font-size/percent-value.png new file mode 100644 index 0000000000000000000000000000000000000000..95999f1d2c83de840748adae74e9bf5c7671ee4b GIT binary patch literal 1142 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 a^%>Jo)~u`B9L4%U1)-;_pUXO@geCxf+d2;b 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..ca0f3b6d60bf24f5e4c619303f975aaa3b6464d4 GIT binary patch literal 1366 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N(PYCT;XLn>~)xxmQAuWw>Qhl7{D7o(=mW zcNz#pZb~^hN%i%6AmKetC-MZns3+}_{e5c=ZaC%3LM%& z?h#KpIyEj<{(o+BbTLow$Gq&nrhoalw`c8t^-|K{Rr-I|>zQ#InC7nd`EvfYoZSm| zF$jq4NaH?zVbRWg9!dlx1 zJzZ<4Z^3wU>p7pNa8P zuO*9RCHdK0^5dU2Cwtq5jL_)o0?x&g&(Ad5zG!tg??%B#DGzTR()t|xP}RDysVw;Ud&ac@URUA_aE9Q?{6y-^Z(jD&4=~Xj)P5yRvwU97=7jY zlqa7~bzOG0dOD@>xMXVdHIp>1dfw-yFMfwSpjtO4^4HAV!P>klfIs{SSM`rfR+1`ZI?l}(cSxQ zyv+BbrJrqZ%2ak={qFsiJU#uOS{qG{M^SAbCJWTKHT%5Qn{Zy~Tx!f^t*fc}GY$p0 zXXa&I{_tYgyLq2#@>>=+R0rkO4C_0~_%@V+s*;A#G`sr1ui0e6M( zWv2oy=KEdH-*L$6v#QtrjO%Zn#Le4ay=)5G8J@(s->Xvpa^>8~&-@ZMLA`yk+P>#= zlSDu8d|57QwSj?wt%;#*-l6yQ1ut3HStki9f%4*}6ve?zt(gxhIlQN>v1R?1I@Lo> a^%>Jo)~u`B9L4%U1)-;_pUXO@geCxf+d2;b 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..ca0f3b6d60bf24f5e4c619303f975aaa3b6464d4 GIT binary patch literal 1366 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N(PYCT;XLn>~)xxmQAuWw>Qhl7{D7o(=mW zcNz#pZb~^hN%i%6AmKetC-MZns3+}_{e5c=ZaC%3LM%& z?h#KpIyEj<{(o+BbTLow$Gq&nrhoalw`c8t^-|K{Rr-I|>zQ#InC7nd`EvfYoZSm| zF$jq4NaH?zVbRWg9!dlx1 zJzZ<4Z^3wU>p7pNa8P zuO*9RCHdK0^5dU2Cwtq5jL_)o0?x&g&(Ad5zG!tg??%B#DGzTR()t|xP}RDysVw;Ud&ac@URUA_aE9Q?{6y-^Z(jD&4=~Xj)P5yRvwU97=7jY zlqa7~bzOG0dOD@>xMXVdHIp>1dfw-yFMfwSpjtO4^4HAV!P>klfIs{SSM`rfR+1`ZI?l}(cSxQ zyv+BbrJrqZ%2ak={qFsiJU#uOS{qG{M^SAbCJWTKHT%5Qn{Zy~Tx!f^t*fc}GY$p0 zXXa&I{_tYgyLq2#@>>=+R0rkO4C_0~_%@V+s*;A#G`sr1ui0e6M( zWv2oy=KEdH-*L$6v#QtrjO%Zn#Le4ay=)5G8J@(s->Xvpa^>8~&-@ZMLA`yk+P>#= zlSDu8d|57QwSj?wt%;#*-l6yQ1ut3HStki9f%4*}6ve?zt(gxhIlQN>v1R?1I@Lo> a^%>Jo)~u`B9L4%U1)-;_pUXO@geCxf+d2;b 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..5afd7d670af1ad52576cb326f5c337d31890863e GIT binary patch literal 1113 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDF z1AIbUfi$(ivjnRWpjnb7L4Lsu4*%^B>@Rq4FyVZ{h5QBU?+0vn@IgSKzQH@;o+JYU zbHAsHV@SoVx3}6SEw&JG2z)4GeM9W<|Nk#iepTkS+}LA1CwirF$=p}Vg%qDYJu)SD z^Mxa`)zNd;DtXX`g)yR-f8;Zc#Z4M zA6IMM+UEx?bp9_q`~Jq)uj^dbSX_yg%DepkfaX~_?bu`eQ@8*9Ud|b|Pq%JM?q!Gd zf6u=cUbEXWx_|D=S&6mTSLOo6eG5vUzLw)xXycN!`zpy|l4tF0-~-^j)(&)x$sm*WEi4Wv@B+=5KrS z;qxJ_kefM2*FJIDkhD2eyg}4`UH-;|qf+rZ&ozpc-|apxnCSZ2b;~@(Yu@G|snJn4 z_uZayOyC-uV3^IXRs2e8c34)e=2co#v3tc%J0SPcZP)jUn>n-_*8P0v_JHl$4}oiO zh0R|-ZPfq$u_&-oAknmcdduod3WrYR_xJC+1!UZ^zd!wDl0c$p`-b->CLJ3--JWnd z?}e1$wSPZF_a9O?)TNliUH-&;!!N$2hfVo`MlX9CGVlCXpAF|uAG{TD{Pg+x#dp@s zWDMJxm%_35`)|jVtG)Zvt2-TAwyw6R&r23al+Aj7GcQTtdEeHR`&l-1InFT;+r4&w z`t4)IM=F!oF5km)>8QfLWRlYu*@=@fjj!YRAo<2h-*n;Uavk3_o;xod`6TX96LfX$ Sg|aQ6vcS{T&t;ucLK6TZ^xqx; 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..5afd7d670af1ad52576cb326f5c337d31890863e GIT binary patch literal 1113 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDF z1AIbUfi$(ivjnRWpjnb7L4Lsu4*%^B>@Rq4FyVZ{h5QBU?+0vn@IgSKzQH@;o+JYU zbHAsHV@SoVx3}6SEw&JG2z)4GeM9W<|Nk#iepTkS+}LA1CwirF$=p}Vg%qDYJu)SD z^Mxa`)zNd;DtXX`g)yR-f8;Zc#Z4M zA6IMM+UEx?bp9_q`~Jq)uj^dbSX_yg%DepkfaX~_?bu`eQ@8*9Ud|b|Pq%JM?q!Gd zf6u=cUbEXWx_|D=S&6mTSLOo6eG5vUzLw)xXycN!`zpy|l4tF0-~-^j)(&)x$sm*WEi4Wv@B+=5KrS z;qxJ_kefM2*FJIDkhD2eyg}4`UH-;|qf+rZ&ozpc-|apxnCSZ2b;~@(Yu@G|snJn4 z_uZayOyC-uV3^IXRs2e8c34)e=2co#v3tc%J0SPcZP)jUn>n-_*8P0v_JHl$4}oiO zh0R|-ZPfq$u_&-oAknmcdduod3WrYR_xJC+1!UZ^zd!wDl0c$p`-b->CLJ3--JWnd z?}e1$wSPZF_a9O?)TNliUH-&;!!N$2hfVo`MlX9CGVlCXpAF|uAG{TD{Pg+x#dp@s zWDMJxm%_35`)|jVtG)Zvt2-TAwyw6R&r23al+Aj7GcQTtdEeHR`&l-1InFT;+r4&w z`t4)IM=F!oF5km)>8QfLWRlYu*@=@fjj!YRAo<2h-*n;Uavk3_o;xod`6TX96LfX$ Sg|aQ6vcS{T&t;ucLK6TZ^xqx; 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..56da12fe6ea945520a6cc1926dd3cb5abe267bda GIT binary patch literal 1259 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-weight-700.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/auto-font-weight-700.png new file mode 100644 index 0000000000000000000000000000000000000000..9289cc9879277514ba3c5fb35303d5c63f1ae1d7 GIT binary patch literal 1208 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N)4?|Zs9hE&{obHSYPfB^%uL3!*#fqy2u1%C9iINsFvsy5P8ovAExZ2r`>4k;%m zsd`Ua^At?!M4kZg=uf!-?d0G6ZR<8Oo@Pdi6KtF2y!E;NKex<0bgusEmw~ONZQ9f0 z^QQ@T9QXR|MM~B@g9NywWpP89P_fzYmM9<=h5ks@bQH~_<=(c7yN1X`aX*B z^vc%}jH@{#B(ja{59|4KGl?D9v_E`>?cQuwoej@?4p<$oTA#X=@iouuhZmIk8n)hh z{JNpEOY~jj^^GrHWUiQZ{yDEsm7S+a*rvPA9(PeDRoPBV%J<(UnM0kd9$U_Red=Asb1K+Ki&5AZ={nrhB zz1-*hmMM?`K2SBog&S0UwmI5CN!oMr7y WV7@QN_qiEV)Ofo3xvX4*iEe75ZP&9HDWp-l|W?>asvy9y&-{< zdK%XXUF%Q!sS#1X^_2U;ssQHCHaZcdc8yf8DKx}Quu*4*7W&HmQ&HR9R7zuz~rlvcR* z>W8?~%J0GQ*Bn?(R-IkyjCMmU*A2Tldv}xKd& QbD-4i>FVdQ&MBb@02U}K$N&HU literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/grad-negative.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/grad-negative.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc27a1ef0e4e1f3d7cb925c2f7fce8f4e80e65a GIT binary patch literal 1520 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-151.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/wdth-151.png new file mode 100644 index 0000000000000000000000000000000000000000..9fc0ecd1bf3e71715401fa99a835ed78e5bec5f8 GIT binary patch literal 1611 zcmd6n`%}^h6ve-YVo{6tmTFnQA1Zon7rij>P!J=zfrj~-)3rp8Y+k6X? zCYY9pj3G*<^q??J)KPIUaZ4*vDj%>-TINJcvwy?R?wvXFnK^Us{o(v@u0)XbT0u8L z0RXTfga$t*%yYXzO?k|5cXqU-Ae}wIJLDUdm_y1KyKl&j-1`JV0KrP(y*XCe@0_gwwo5s z@|A)N?g(2FFl*LmA>JHd<~tYR-hg<~CzIy`J^qzbvSE75=UGoh5+uOA6`vL`oB271 zSxp?Zq=3Zu%Eow>eFZeZbPN&n4=Qh}M)eKM95-jXmM2;7l2I{?Hlhe-KLKrjVwSXb#Ba>`&>?xieR%hP_>^c`c%eN zJa$NmkM?)A<1aM7iJ!%J|HP+S$q&t>9fSOq!H~-9j@L(Z)N%Bdh?%5u5k%_h?xQ$v_TjJ= zR$v;{hXM+z#nmd-2;xL+YDXK|f_s@oJ?ulVvYCTQ6#`of!!6bxGxGNOUF@SIQ4(aM z3^ykR1t5^Um2sjKhBQf+rM#mViW;>|$^#dj6Ok~&f($tV*{$l&-Rz{Q@jyRbTl~$p z!lRntSBH;fPCQP!Ti{ku4+-E%z}NK*HJ~vq?*k%h2up&6We51qwkY9|XO5;Ur6&>` zsGcYzQIyp}RataghRUL$K5RFnI z7CPMPxOnT2nfWKbHVe^3)(2~t)Wj>@oyzeBbZ--$`!e~V%}%!33_ns@!W>=1wl)XR zp^K`z7#XiZjmlYI1hYYYSsc5|WC2x(a^jhL@u}*5W7f^;k1vsm5?FTS#Vgk9Es5dU zu*9XcXNqLIRAwhk)A^O?=*;bremVb0?^hnIGM%5*bozZR!YlOK<} z-5{lKR!R?Ur&t}$9or-+pZX=bW-_DfdBHNH&}Tkx|E_C0Dor6gRg@I#64_(-*C|=m z-BrFHW=Y$TWw6qMTaqV(KJ&?p_rXFUonsx~9CdQ}Veb-)_pRvk(z1Noplc8Z77l(@ z!{TfJ8!#5g;wxL%6#D 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..88b25ca5a421c241938064792487396c966ef456 GIT binary patch literal 1431 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhFg8YIR9RAxc_)w6r;lcg$`SaJu`}f!Hzo0N7;Jtysfd(dS zy+;fTEPFj&978H@y}8oJb~u5j_2RO{!K`i5>TCZ$k7*0M5yMbsr^i$ps{hJ=GntlZPUq?itf4U~Y88(1KUIKfH}3V}2nY*Gc2 ztlm`A7-qZc_gAfm`&Q5McE_o&k&n3BFg00rL(v-9u)eJay*BP*)IP2ip?K|<(*~zC z_k_bbO1~tuMr{2CB&vlEa&7E8f4S-FqjT@dW^Ye4=nJm*nD%zh+c1@FUrYaA->KMg z#*|s=%x%9VlWlx87X5JK$@*#=*7&7-&8OG!g z*e@Kp6|KXZaFY3x_Oxh5g}+8Rd0x2vy{Fk|}U1K~T z8D^yO?(g9fJKwo#uiW*V?T7I-#SKbl^drg@D&!k>Cm!6iJ$7Tmt(s|*8Vr83*Os@Y zRKJqEEf68SL|msqXA<)S-t71Lr3CKWd=%*7AE9McV`G2n!eh20iW^b_1rHbf_4rZD z$CzfQGdIRI!nG=Q^D-s&lI-P)K>I&RhrL-jSBv51h6tUiUP;li0~gJc1CJf(dcb>n z66;Z+!;3QK=x}Z5@;JC}kCs$<1y9q~gTHEdqO;%WPAk2zb%Cnm+tjVgzi@q4h}d)> z&1l=b8WDe;Z<#=&txZsy=B$db-TAo^x*!ar}zK=ng9AP z*ENw)( zA3yl1Kw_HDA8nnz*V+|?=KIKfE8L*;rY%(HgT<+(`W3u!pC)TEFFI_&bB)b>a;Jla zlK94wSA4d<4q^v-n^hT4X>MlT9do>E!jhMnRR;nYBssF#%1_NWV7i9K#yacqvjj=b z?51z?6FDD*y-=21*w-?3;XETwjp_2`CEwH{woKdVD9!23^m0n2#u@wC32}{+H{4gw zxA|-+a*gNSF@a4nI~PT+$*;F(n9zP`mICA3-#I_aBlu?MhV`;De3bE2xkMP7@eRfU-VAleCdpjb z8vU4abwq=a#59%zdjFpZWL;5y1e7p3>%GEPI?{E^Prgs}>+DT-UF5vLCo9azaL9pS z@$o3uuliH0+s^4LOcaRRlyY)XtInXKj;4K8y4*iEe75ZP&9HDWp-l|W?>asvy9y&-{< zdK%XXUF%Q!sS#1X^_2U;ssQHCHaZcdc8yf8DKx}Quu*4*7W&HmQ&HR9R7zuz~rlvcR* z>W8?~%J0GQ*Bn?(R-IkyjCMmU*A2Tldv}xKd& QbD-4i>FVdQ&MBb@02U}K$N&HU literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-700.png b/crates/resvg/tests-hinted/tests/text/font-variation-settings/wght-700.png new file mode 100644 index 0000000000000000000000000000000000000000..9289cc9879277514ba3c5fb35303d5c63f1ae1d7 GIT binary patch literal 1208 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 OvEk|J=d#Wzp$PzHY2APT 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..6e802955cd94bcce36499a72c0698b2b1b4c9771 GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB# z0(?STfi%^D$b;G)KtrWVg8YIV7z7jy>;vKx@(b!4`X|g^uzth-1LrT?fAIc8@L{1; z1_tK)o-U3d6}R48U}R%Tlwdt@UF%1y#-#WEzMo-ZtZbMzQ`u*mcc<=5A2Y#hI z4N+h}IZ4%9Y*WerP_JKG?YB)i`Rn_d())8$P3LXyUgP8z_Ev56cdNQ2Y)CD;K^fb+&l4vxCP>^l_X{TnhWN z`7gJxd1>wV^Jnt5sjoZV99R`TsnSF6Zs5uy&Tu1^)rzKD1qyBE_+H9A@ms3ls6mRB zVv?%;?WR`amkY&ZI#)K`d~4TW8j-7&pZif;kxQ_<=fDhajt_BLJKC*Is z?rF-VOk#Oc(iy5Za9Me)zc5}xo}M(u|Hbt{HnDNPfc|6d3v!}G~d=Y=#ZlH^^6T+dyLjN%z3_8=hUV>|8H!a z-O@7q^tq(PvKPL7yZ88_e|Ssl>E+Y5EWESPQSf5t)#)v)JLVpKbn`_~!%Y!Eap?^Q z<{y4_bk~B88xoDIb(W2xnwQtE=&+D%IGXON@5{f=9)Frk* z*yTvUPy0wqJD$t$E*Wj@71uqeBFB1h)~>1<+iIHw{^s20(_v^x)aY>2*!2IfXqD`bA2Kk(K1!1j)HQes1cECtp1IVoGx=SPU)zQPShL0Ye0; z1Ev7T4Q7}IG(sg}L&Cu(R&OxLJq^U>7Sn-{5ny)21{RC?Wl&Yizd=S3`gB&eA2boFyt=akR{0MxwSe*gdg literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/bolder-with-clamping.png b/crates/resvg/tests-hinted/tests/text/font-weight/bolder-with-clamping.png new file mode 100644 index 0000000000000000000000000000000000000000..22d105dc4aa42a88df87881d84d4a1c050af29ba GIT binary patch literal 1245 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDL z1AIbUfix`u-}K43KyzhEg8YIV7z7jy?EM4c6Y>k{8~P{AU$B0|{sZSP+<)-?!~BX{ zj~N(PSUg=ELn>~)xzNb!Y$(BYV7-5n2P0F;e@pKL4u7~>cMIzI>p$`=6ZHJ%!}vMn zsjFkk$w{i-)7H#CF{xE2aubk8FG@?|{cgqA*>88NzV44)EAM-)-L^P-l1K}q2Isd; zaT7k)o&I0{Jg-zgIjytr^Nk0UBA!#1J1P9It+0KkyLwM*Z2G>`*kc!TUmM*8;#v2i z!t!i+-+XuZiK$-S>}c*Z#aTDb4JN z!FmDHRu>KK=wJP2pOdSUmtC~yxn5)zB(&*_mtw2@)*}H~BNr7%Yk91lS0=Xa?J+&?i;6n~9=jimGul+J)H!YCvFGu^tD9R=EUgs9 z!(Q>Um6`c?Uh}bbUN@yk+FyF%vF9~joccyfuei+jc_klsGAL0_@ps0*Sw~oU9P<`G zns}8Xb4jbYwNRkv$)u-y*V_DcKFq>p;o&7VH`(7mSz1k1d$$g^c;;pwuW7qi>c(L>3rs*jsldLVKl%AGqEpFC%y)H7ENcvE4M0ji|o~zb1pSA$>iaFLv}gg z{W=ciTC2t1x#@O3j9IhEB1^H+mGx!P-uu3JE81C77@s-reR(E3MNI$hTSw>Eydx2F z`aH$Hr?x+wnRxj^gmQ%7x+kq|w|0b2S@`qvKH1w03{4CIDlXD@>f?pg7cBlz*Yf(m z&f?1sZtCy(bQVv(c=AO`iIJ7$+yu$FJ$`QLK#@#_(@-&}089x;vKx@(b!4`X|g^uzth-1LrT?fAIc8@L{1; z1_tK)o-U3d6}R48U}R%Tlwdt@UF%1y#-#WEzMo-ZtZbMzQ`u*mcc<=5A2Y#hI z4N+h}IZ4%9Y*WerP_JKG?YB)i`Rn_d())8$P3LXyUgP8z_Ev56cdNQ2Y)CD;K^fb+&l4vxCP>^l_X{TnhWN z`7gJxd1>wV^Jnt5sjoZV99R`TsnSF6Zs5uy&Tu1^)rzKD1qyBE_+H9A@ms3ls6mRB zVv?%;?WR`amkY&ZI#)K`d~4TW8j-7&pZif;kxQ_<=fDhajt_BLJKC*Is z?rF-VOk#Oc(iy5Za9Me)zc5}xo}M(u|Hbt{HnDNPfc|6d3v!}G~d=Y=#ZlH^^6T+dyLjN%z3_8=hUV>|8H!a z-O@7q^tq(PvKPL7yZ88_e|Ssl>E+Y5EWESPQSf5t)#)v)JLVpKbn`_~!%Y!Eap?^Q z<{y4_bk~B88xoDIb(W2xnwQtE=&+D%IGXON@5{f=9)Frk* z*yTvUPy0wqJD$t$E*Wj@71uqeBFB1h)~>1<+iIHw{^s20(_v^x)aY>2*!2IfXqD`bA2Kk(K1!1j)HQes1cECtp1IVoGx=SPU)zQPShL0Ye0; z1Ev7T4Q7}IG(sg}L&Cu(R&OxLJq^U>7Sn-{5ny)21{RC?Wl&Yizd=S3`gB&eA2boFyt=akR{0MxwSe*gdg literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/bolder.png b/crates/resvg/tests-hinted/tests/text/font-weight/bolder.png new file mode 100644 index 0000000000000000000000000000000000000000..6e802955cd94bcce36499a72c0698b2b1b4c9771 GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB# z0(?STfi%^D$b;G)KtrWVg8YIV7z7jy>;vKx@(b!4`X|g^uzth-1LrT?fAIc8@L{1; z1_tK)o-U3d6}R48U}R%Tlwdt@UF%1y#-#WEzMo-ZtZbMzQ`u*mcc<=5A2Y#hI z4N+h}IZ4%9Y*WerP_JKG?YB)i`Rn_d())8$P3LXyUgP8z_Ev56cdNQ2Y)CD;K^fb+&l4vxCP>^l_X{TnhWN z`7gJxd1>wV^Jnt5sjoZV99R`TsnSF6Zs5uy&Tu1^)rzKD1qyBE_+H9A@ms3ls6mRB zVv?%;?WR`amkY&ZI#)K`d~4TW8j-7&pZif;kxQ_<=fDhajt_BLJKC*Is z?rF-VOk#Oc(iy5Za9Me)zc5}xo}M(u|Hbt{HnDNPfc|6d3v!}G~d=Y=#ZlH^^6T+dyLjN%z3_8=hUV>|8H!a z-O@7q^tq(PvKPL7yZ88_e|Ssl>E+Y5EWESPQSf5t)#)v)JLVpKbn`_~!%Y!Eap?^Q z<{y4_bk~B88xoDIb(W2xnwQtE=&+D%IGXON@5{f=9)Frk* z*yTvUPy0wqJD$t$E*Wj@71uqeBFB1h)~>1<+iIHw{^s20(_v^x)aY>2*!2IfXqD`bA2Kk(K1!1j)HQes1cECtp1IVoGx=SPU)zQPShL0Ye0; z1Ev7T4Q7}IG(sg}L&Cu(R&OxLJq^U>7Sn-{5ny)21{RC?Wl&Yizd=S3`gB&eA2boFyt=akR{0MxwSe*gdg literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/inherit.png b/crates/resvg/tests-hinted/tests/text/font-weight/inherit.png new file mode 100644 index 0000000000000000000000000000000000000000..7b50a960c2c8165d689b3ab9f435c9441d580cb9 GIT binary patch literal 1231 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 Az5oCK 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..e6893b82d2b925c790e1baf506fbbfec641fa34c GIT binary patch literal 1157 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB# z0(?STfi%^D$b;G)Ktp9pg8YIR8a5={kFTHaUvR2w3o7eZKvFht~g3 z-!m{UulICu45_&F=0YP|gMo;{McyPYqXm2a|35FpamJbH`M(2Cr_^ah>Kjhd%v&So zbwzHChL^~Ogo912+}GrRq&I{;4J;z20}>b0iGYwBSU~Iz37lZ^pb&_Cut^n6lB=;R zHS9oD`0+Jd+57&i``R!yZ~cZ#xf?$5f(|a z>s!_;)ahC0>nzJHVyOB%DdLUj>k>JpO9hq}h2~z`kuR2_bV%(H`|B&prxu?yT4;as z+lJLyv!-;+y5DG0Y^5J@$N5x@0QZ##+jQ+eeyTb1NTgdbe}~Rt+up6JCEZ6elQzBV zVL$#=sqdxVyp6w3Z0So_V!7S)1jDzUs|#;Wm(o7IW!dNMrF-8*2VYA4m=vMEFnLY% z+yCVnrvt<$DQ?QvnW?4gY8K2rFERg#ndHbTXmZ^u4Hez*?4`Pq$tzoKUXgva-EALjQY2 z;0q6l+&BBLe~<|4_~o=Le+_eHK!;IR@ftJP=tKMcpIrUz`qE?mqS`C_)BNv8xc{r2 zXU%JMJwil&e!c2#^-uFQ-dZw$T0zinmwU$7xVJldN7OEAy(TW!8N2q^@ATVjw>{@1 z_DZ~{HMv`QwJ&k&;d2{S91gz!ZT^GY-5Z??+gxQ2eQQ_$y(wv~n0Msk%hF<{2cGWg zx$b@Fzv`W-SMLR;x70INA5_X!GT?b0FUcez9}{`#mEwNZLr<^gt5zJCb=g!&uwe`D z?eFKOrieIypTXdvXMcNpvJ^v-1V>Z5YsL(->K5U9EFO2}{geGh@NQ#z( zB;{0S;-`(|wb#wy%(UTC{+Xg=)AX;drs*3Qd^TS@wQjlo6HvL~>FVdQ&MBb@073}T Az5oCK 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..6e802955cd94bcce36499a72c0698b2b1b4c9771 GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB# z0(?STfi%^D$b;G)KtrWVg8YIV7z7jy>;vKx@(b!4`X|g^uzth-1LrT?fAIc8@L{1; z1_tK)o-U3d6}R48U}R%Tlwdt@UF%1y#-#WEzMo-ZtZbMzQ`u*mcc<=5A2Y#hI z4N+h}IZ4%9Y*WerP_JKG?YB)i`Rn_d())8$P3LXyUgP8z_Ev56cdNQ2Y)CD;K^fb+&l4vxCP>^l_X{TnhWN z`7gJxd1>wV^Jnt5sjoZV99R`TsnSF6Zs5uy&Tu1^)rzKD1qyBE_+H9A@ms3ls6mRB zVv?%;?WR`amkY&ZI#)K`d~4TW8j-7&pZif;kxQ_<=fDhajt_BLJKC*Is z?rF-VOk#Oc(iy5Za9Me)zc5}xo}M(u|Hbt{HnDNPfc|6d3v!}G~d=Y=#ZlH^^6T+dyLjN%z3_8=hUV>|8H!a z-O@7q^tq(PvKPL7yZ88_e|Ssl>E+Y5EWESPQSf5t)#)v)JLVpKbn`_~!%Y!Eap?^Q z<{y4_bk~B88xoDIb(W2xnwQtE=&+D%IGXON@5{f=9)Frk* z*yTvUPy0wqJD$t$E*Wj@71uqeBFB1h)~>1<+iIHw{^s20(_v^x)aY>2*!2IfXqD`bA2Kk(K1!1j)HQes1cECtp1IVoGx=SPU)zQPShL0Ye0; z1Ev7T4Q7}IG(sg}L&Cu(R&OxLJq^U>7Sn-{5ny)21{RC?Wl&Yizd=S3`gB&eA2boFyt=akR{0MxwSe*gdg literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/font-weight/normal.png b/crates/resvg/tests-hinted/tests/text/font-weight/normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7b50a960c2c8165d689b3ab9f435c9441d580cb9 GIT binary patch literal 1231 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 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..9ce5af6124cc050c0c1789b4eaf4356a60356b4b GIT binary patch literal 1301 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z1o(uw0%;-vA0Ho3r4ktA(3h~2qeT`k~f&mz`*?8)5S5Q;?~xy*8{ z-DoZ!$O8Z3$QxJ9Z!Rm|VE2BvB8pk2_n+=uqGzcZt8>zj=- z5$+pu`a_o{H(phX-+bWH+>ofCm9GHcWvVhi$a%Pb2B#2czaDc;&{|OxtQ{ct3@L|HfO(G zYQA9-pI+?0BfB5Il>4%4_xyuaSLeLW)!)bd`n>ekFtaG@&k1v78lx*tZ@FgMQ2J=Y zDzo+WKbgXG%x!D;?z|Lb-n8}f{r2_d?eAxueSKcf?xKnGjKhob`_~6Bgo)MtDW0Bi zbmOd>PCB1;BMjH*{5yOown;SXyx4Ig``i0v?IRCH9lI#ReA;uXD*LsBlZ{KI)_D9& z^Dmj=e`ls#>-5o-^4oy}fr$$#yS_4JUGY`!(igO|L1ad$%b z;SD+gjIUX)F@;%8Yh=B)KkjVijC)Ee*}MDe(UV?nY(#ti<*#QSKK|0bLC)Uqx_Q66 zx}Wp9NOXl5Nfui&9vCq}XePiz*Q%^(Pv^XNID5^J6En*@C;n$%?R8iFz0?6vk;dTZ L>gTe~DWM4fR-^yl literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/all-options-comparison.png b/crates/resvg/tests-hinted/tests/text/hinting-options/all-options-comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5535c67fba78e818c84e402b95f58a32eee53c GIT binary patch literal 3867 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/css-style-syntax.png b/crates/resvg/tests-hinted/tests/text/hinting-options/css-style-syntax.png new file mode 100644 index 0000000000000000000000000000000000000000..4279ccc50f6209af02d2d4d254bd0535858292a2 GIT binary patch literal 2861 zcmaJ@2{hDeAO6n_Mq>#>vQ$$^*_Aa}2C1>e5JQCwV>e^Xb~TnsNQf+xn7U0VQ_NKM zGBl+{4B0ZdOw6TZ$TnzveeTye-}%lx=ezGY@9%kj&+lE%dCzms`^#~4IVlBGh5-N| zWsf?J1^|%u77rAMY(I5;>c zCzy7V7Q5@RE9Y8W={9Wf4DD~}3 zBvFQ~KT+uavmHTkt?wNt%r8_IT&%-eo$@Qd*HvHaWfu}A#u56&)Wg44Ch^zFXA*?-E}1!nX^CM?0E zf5uj{Ab-!^pk78(Yx$sLoPkVAjZ!GY^*4Ae`MYS#Cy-_&g|=wyd4E96gDH9EFly7d zR3zE9t=}l8`DChf+b3*NmMMv?b?bijF4K|*IfKMg-lVe{T;q_3?5zz1ClDbCF7aI5 zb5W!wt|;gu3%p=L_v8=w9Rl2nw)Kl#lZ6iO>FP+h+5t@uD0G%+Pe|`!V<#*_s_fzT z03~4K7)x0Pq8S>feFGCpxTxYd-W+_B(Yo&~k9Qfes_a-7oEPvfuxdA;U`|x(7{xY8 zJ*bG{HVOlEES{yqBFQ7HnDlv;&)p1*R~h`ho?y4z;I=fz39io$8@#~U{XL0e5pG8Y zE-&%uoj!-0tx3%}+v(t5=@w>8(<_H;XYFG$ud*=`Pc@diWEPD)RUyy=Pr#z84(>Tx zjTrFB->dbcO4Gmy+Vx4vWXY1g=axeqz%h!=3L$3&%xpU+kDe7-;mOsGv0z_6F!HI7 z>tw&q%9eA=#_tz58kiP(&d*wuwuDn2`M#&DfeDuF5;85TZECKu2IJVx=Hu(Kt*+wP z6?^ElwT}o$ z(O>PUE1l#BMw?+!!6RdSi+YWgZdOMu)i56Jc%m0P*+2Ef&{<@zhr`Dqq_GiZ0Z}e* z<8%7P?q|QleLJ$@T9aww7=HmyeORbYd4fDc0EK+uVC*aXXlB9mbumhI=f@+qcJigt ze<~?nsu-1d5)m-id3!>FUSTgi>V7w|fVZopAwc>?MxblD>itOTVVRAJsJ$f|b+n0X zBQtWpvydxg1WEgi_Jj50&tUO$$2^FJFa(U6em1%T;?zl6R{}aZAc>&5#&h*4G_Wzm zCE8!Xqfnt-$_SO4uMkC7vvvQ2^%fZM>Uz+V|3p?i77p~6h`Lcu#fvI_S6oc&b(n0f zi2d!RI|3gt){_wBI1?Xw1D}%1imz$J(2O+N#}DQiTcqtBPex@Pl4(r>DGHydq(+h! zWwfl(5zo6uQyG9lm>910x@bgO7x`fxKn0N#j-sKUFp8NGRD2er zD_cczz4YF~F=pb+-XU&~PAQ$xv|GbDD4GqIcTHbuQ%cD@fPlYC%sKsZ8?ao|l#x#& zcsw`T5gqS^6AacAr}%*aX2UajQfAbdBzEhml7t_TrYS0%NZLq)K~~T3%tV>S+~>1p zNFGDtM$=2i(C|h}S?ek=y)+CP`8uZx>`ZOy+K`HusP0@}8Z=Jr+*j`;{N9!?6!3=y z|LeHcYB$)=SQpX4wI*sA&eDH%;hvQsiy7U|ga%BVKDryu9Pi?q%S^@P)&S#Kj~C2U ztGUbgn4^=TsmD}#9~ybid$5D7_xlRy4Hq|J>E;WM?2wulZh7~UeLtV5xB)|&D0qlx z51FbY+lxivzzEz>9m^MeV@-%TQ2OCM@$Pgn@p$g*FY<+{<_fw{`+IoYz;q-nInCB? zYS|1Uh_OWbUM&&l25k}+i`#@7CJRTJtG1h$Eg2RmgJk``>|Gf!1`fZ7 zzYB{#%qh9xOVS3)zpvBP1di3#US~$LH2Rkvt>lJ#a%p`-8P3sBSAxb~G0KOs@|PI9 zTY?x%0cIHz<>#SK_ss>=cADPPDD82!shTv*oIPSf>I>AJ4#iQo6~g_+s2yfNTU*YG zPe3yG(0W~aQ$=u33$OYz4>X#qJ8gXzCD8%VWS=b0ziShGcD({zrUswB^1Wq*%%^+m zI+n{R^j|jB-X)@!NYd!@^xYFYh&l%v0NUr3-nP#YD&IFy)YrxF9g z;0mvogYNJ$F=Z=z*EaVFg`VBn$k$)2UOM6pgcR~e@9S=jkNq^ylIaL|luBatn;|r@_7Uaz@osl)$b0)I@OU2dP z3cvIeJseGz3OAvL9dl~Pr?*R9##$R#51$Q!&BHCJxOp`1arbd5rHj zH(-}RMePK*BR@;4UO)cY{8OomoFHI~Oss;|>kTr|Pj!%?h}1i+vEQm}R#`eR-2EE! zMj{i~gYu&KKf1k@i4p?sUQ3buZLIZ4jPZFyZtElcHB@Jc^JW6=JRa+&DWLhZ+?Ff+ zb5`%&1)942&zv+yX@#S?goW8ZB-MbpjI;1S{iVz=%ziK~I|*XIPY$oKhJ>gt3AAe;-?j-! zl6WUD>~L0XGKJoHws}kAW2OmaDN8wmON3GA2!CTsQV`S=7Thkt>|gk%Sz_^w^s+@) zazxJc5dir%1uf0IdFXN5tC%5C0~b#TedABw>R{YdmeTE!pY2@!@`d`iYsxJdGvV6X z`CfYR-5w|<<;s+KUK53!Rob+RIcpcizI&YbQINI@>gSNZ|8FSk&S=GzX1rmEPDU| literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-clarity.png b/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-clarity.png new file mode 100644 index 0000000000000000000000000000000000000000..208a2e3b8fca9ffe3766cae9edbc3729e7b9961f GIT binary patch literal 950 zcmV;n14;aeP)I z|Me>!@Hgte)J5Pf2V5is=!*l8Z#XpWS9t#UCQ3P%0_y=(SVXDXE6%;-FelvP+Oo=6 zdjnyrKCX4B-?ZHe=b3xXIc?Xh5FnUol@Hw`sL0@n1s+8x*3bhBrL@wr(E z;zyIUhB8wN5!-6ulVIUAb&jDM#0RI~Z)UgH&7NCf9*r*#^KpRf9SWfGQKpHN4uP+o@*&IF|1(J+b#PRrxY1_spI!+4Q;O5)(A_JnWpS z-F?o9F1dN=gU6D*5mRP(>L!EQeAAAozCkYS5;!MK8X2+tl8##jpd439EX(vr?B`|y zP8=>cE=?`z1hCIMcrT%olXhKVKFxqKV2MCf0;vEPj9WY-4NEKqzy<&sh=fXy#?;sV zU1IsLKq;ky5abfT6Caob4MF}uN~|ztgJ(eXZS^zWXg$Ttz}pE0o4nvjQakyYu*9%C zhmhSlXNi5o6p1YqpV3QT-mOKw&e38cN_o{=<0}csZ}YPNCH&VP*^>syixQ6z0HvWR z-|Xt4CsWOFolSvGkrk>%(CF8lK9;AxWcG9eEFSySYlco2bg9wNSGFuG9D5ew+y2?I zYjb_?eiuCIJ%7Qjal$~%R~X8y_}s2BzHjI#8u=CGY&xqa7#bv6 zmaZ)$KceA80i||h&R1B@$Qxq;o|HJEPBh8?G&rY>l^egp5=bBfN5I+u$OP^37JP*P zJ}p27s5k)}fefa7l{uW#7jtL8E>WN%1b=E2;5D@O)L&ukyKcJYuJxbE;$6qq^41v| z7N0D037o!6_zKH5z2RZzvT0Gju~glPH0pf2`~Uy|07*qoM6N<$g6##Z!2kdN literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-engine.png b/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-engine.png new file mode 100644 index 0000000000000000000000000000000000000000..746cbb5f1ee5a92f78217c7e8ada8a8700b7b161 GIT binary patch literal 1620 zcmZuxdpy$%6#uP_G4IquTx>V5P2I4Bb@OZ_kC@q_jEo{tVcNnkiRN8W9_85-#&&h5 zceXN3c~+*Y^43F?DW7P?U48DS`^UZC&*z-)_jAtYoIlRzoWt_n+7HOZ|Kh({c|)?3)u^2G;{Ck+0ZpUd9DRJLv2m$jenCYgm)9!j=^Y;VFzYC@ z_yhn7pogmyF==qROj&*0NYyPlpT5k@Yccvdq3YpjT_X;e%G%hm*LB(nCxC+6^f3h>IY} z8(rFmi?i_p?A&=ogW~$SKEQ7^7#wnvkfEzSA8SHDT^QW_J z44M&FzCsoMg0^C(!jL$u&$`)M<*Q8!K;`u5v(6_GmLdM#gitq_60*)5RN&;aSB_d> zBO9pDG|^t3JfOpU&2yf!xeb4`U%$G}3lCMf5QBd&Ky-(S=)Aa74n@>&(bwUmUDr2< zjCd6me%MadLDF#CNm_Du=+O$kp(F{i&2z|p;uVm~5lNh?CfEOZJ7HFWP9^m+;9N05 z1Z9O7rSy4}I(*Oq@=Xr@J0b~G9TTF*o&5vTu6~OzhE~$;r8g}Fbm!@Q6SD0iBLiq* zsF1)LYvje>+mW%_@Lt%Z2z}R;satK_OfT|PZq5Y}EJ!IBpuPe@L#`#kf@(*_SK#9T z-~5;j3^o|RU|-r`Lw`}~d_Ul&o96UMT7{Da{k)T+&Wp#f2^FyJ+``dUQraXp1%?rn zyG(5YWQ}jV)w21+H$htK{3_&i4OT@SN2&c-@2BcLvNb$O$~!f3;=Wa33nL0C4jhKy zLneD*-X{3o;k*8=32U(%*ye_Nl=U-18<9!Ed;Jm>{6m70)9EM-2RP7zTuXHaAm2w+ zr9&z3+xexD*acM*aua7~uKnJ_s#t84T0!s^=&e6Dh}58PEv#3o7B(4q7f%MuMD~?Z z4`U{E=kVj!lcL>u3&GYx)Tw;e+nVR{+>M2(G=t^vi(9%~fM;JvmHIFQyNq?2n`G>q zO1@}&l-5YwRdi}Ovt-M1INx$i`w)}M$k9~ICKg%`pPg66AC#Jti991y*YJe>&Q5Is z+59)vGGxQ8*i}{QwK;0?q6c=#iuc35Fa&nHuYx$Ntwv|n4l`raYjg^}c|@P&MC5_- zC3=+d4BOCL>}rnEh#k46uiqyA=+YGhgQp;R&5?I!MB6tuj!qB6X>%sr>uWNmFZ%^b zKc`LZn>rUz?OWB^PoBQoBG~@QVv0TJ!?$I`ywfxRp9J&Cb(WHBhXtddb=Camw_=3L z;`$#q_RpzpojH?vm}9T%n9obAK;QO?<}EI3Bx4K8o-;ihh`EEEx;^j97r`ZQ&zM07 z`rupHUqI8+bhvcQAqDpb2f#(^BHC*!jo$pOh^JCw)J@S7H(;VSDqS|HIE&A0wSGVj~Al`&KX-4&6#-~!%|qdWGu$(NG;v$%W>@C=#t%%mIc-!)AaVw<6kYB n@PV9Mc4}JlP||p=?GhXlvtrio&ND0d#|Avyyj`1|scC-$k@4)^ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-target.png b/crates/resvg/tests-hinted/tests/text/hinting-options/eink-mono-target.png new file mode 100644 index 0000000000000000000000000000000000000000..0e7c7734100c0a0ead48ac95143752957fd03380 GIT binary patch literal 2535 zcmaKuX*3(!7RM7YR1HDZ)Y}%VIW;zC}JL>hPtKYR?Rg;iQ-mJxrQbZ zA=FT_lBBBDR#9^eeTXSh&n@-zb-nk#ymj|FXYb$M|NmNN?QbUyX?s=VsN7Ki03c#v zZi)f`fRID>IRZM&Leu+OheZ%;j*b8TM0O7c`uZLkFc^%V zpWh*eg@pwM2L9y3_GcWbhw$Iw&-Op!|2zQ!0Y5!||Kk5u4F*9ahXO1TWor*O=uFTq z&Dj{5p&k$tj5@`%J=Zs8a;8h=ksWWS*dYQXJ{u9{k?j$74G~XyGrf-O@I=as8CCHn zGXa1jWfrE!4l(1a_>`I?Z9re{!NHfNd=oPAGJ2XHKR0 zQa>$K)TBDl#`hA|#&|^VpYK?!SAwmr5XaJ{gEF5@2YeLFEmq!T3(PyPI_X;7ePj{n2=q) zEoxL}fMd;kLR6GM_7+MN^WjmR()$+mA6p-;e(mckGkVCMf~9_6)df4QYBtu!#vT}a zJ3~p5Q?lXoEHxy6-;_^|$u62^baJk7beS=;CnRSL%Xb#C{rj3?a(|~_KW}!z;B^wQ zg|=zwD0x12({O_Zu+p9WkE(aI&}QYkcgJ`t5-*=-%_PXTFAz;-VhZXnQ-FcCQ?&t&@FYlNJJJStcY#<*K$H}-aghT+e>4U$>4b3*ibNh3obJztm*LBlZ# zw|>o_BC9Ojg5OZoNMfXjFW$=~8I_zAl={eYqbZKBq2|g2wS%g9LuBMtD@hKED6ffk z6r>}iOr8QiiMy7Xw=kH{xzD{&6;;#|{_2zd1O>|}47xO&uJgH?n4W;Ue!5nnUE2V< zWFr-lpwm`B#-Gsd3_d&P4ZaqcNK#iIGwHAZ083xd4! zQL`+bJZ1Wz{mp`f7Im&x2m1J##bappX&?4SYCx3m0fAIanjgX#W80@ON{qEdED;Tr=Vf=drTg5vbHSSQy-lOx|oFHZQELbKKxdkUz21b zWg>INnHKC}f&f8IB9t>~e>+F9>A!>yzoV&z8emt4w!qmm_&t$*w^3{!T{BB6I0F96 z#>qu5mT#H7##oZ8#dDhNf@vdX!ir067hQ49n-kd2E6sIAIaU{T;QOT{lG~`D{>pSm2gG4pTOvwGaiyikuDa&Q;! zQ28*pzj1HP$TBWtbcM2WM&Na_<;8WnjUr)Z@<5V^#%0R17-Z zl`0hHqcu%W0X^Eu1a2uR+K--4=cyLo_NIxNH#d=0^RG>1#7nyBR{lG?ii-)35G74Om_fQh6Z&a`*ipR;KMGZ zj@l<`&FkCV9+3fs^Mqd?S_~Plxf+d@^5;S=*gBRWaHjr9-8N}O{zN0tSc2vuJo`#cBkz#v<~WvqURNXH|hAs=K~B_kd1i1$OHf zWg)O4Y#y-(2qx3(`7nR!H)}kOcT@FQnP&T=4}qn257J)jYEQMT!Eb(t60+?dxN3d~ z2oeXqxjk_MkF%ePx)q;$yh}e#QP5E7zVn-uMABK@#4ng#X_R*vJ7QTM&EejH)6*wP zW`;*LRtW=@Kz;NLur!!`9fY-FiF~Mdui9xlG{&8p@Q@-N-^@Y`3=ij!Qwcy7T^Qfg zDIf8X)Ta=#sRREz%OHI;FOe(f#g7|#zX3IM7{?SghVmB%8c7Uhl1y9Tie=Jt_Yxoj zY3p89d*4lGkD(UruRE{Aix(XOU-yoA!UJwMZp;o?IT){G{W58+E!;B{za{4s*1yxy z3t|t18%WgJr7PWTZ>(Htsr`94inhIX#Faq7j3X)MiX}uWjrI6C#QRi@+gzu{70gWY4(oS z0?lF8et=TfK;mvcH;>7{1jz6WfZ~5)^?$($+M~{=irg8!O+LG)p3*obr&!j%+_Hw? Zh^AIA+?C&tuley4vM{qXt-a!T|6e=Iu;u^& literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/engine-auto.png b/crates/resvg/tests-hinted/tests/text/hinting-options/engine-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..ea694632288451590dfc451f2c541a4a814539da GIT binary patch literal 2792 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 D0Npb? literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/engine-native.png b/crates/resvg/tests-hinted/tests/text/hinting-options/engine-native.png new file mode 100644 index 0000000000000000000000000000000000000000..8c7c260b3948fa59f4a2c71277454bf2926ad82e GIT binary patch literal 2942 zcmaKuc{tSj7stP|VMg{PiiU7?8D-y>DY=Qt&M>KAEY~vGQg$OGOUS;JCA+~O*}4oB zHDt*)*>}n|lp>6u``qWb&%J;A?(2Cz=e*DRob#N2KhefFuCO6aApihiyQ+WL6aYY| zW9`5KIgYH;hug;q?x}C>0|4xA{(PWRY4+2{W`XfFbG_sI-#9rrIXgQ$Iy!oIcpU3v z;p*yoERH$${}O-2zsuv9fBJuy|9$BHb#IDQk&b)HcTI1Y0Y^km-1KH5xj&SGCUPG2 z%X;?V@{GwdB8hF&^v&wrgwWeMw~Z1!s&m`=^5~w%Ga|AS^xg~?9sm&NtCugD`;D!Q zM^)$QK#NXt~8uh&*7{NWS+z>sWY7s@?y*lgV2Xj-t$RQ*;) zT5mWyQ(U>=Q9&AaztU78Ykwq(JGSr`Mp zDxNMWG&;wVCf~C${miAY%*}{k90JJF!NVeCN&sh)T8+dj*?I;$xH5^);j|kUHD?76j4vU@lSA zFkgN1CVvs%+HCO4tGc$gVlC1i0Juq>*m^nVg7!6F_VIJpXif)=Gu4=XGomh;0DvwAU|H3|7G!k4eI7Mus`<`NVi0DOwdAW zu+yi;%;>POu*FD7ciu|tKjH9kT?2BqL8>fX%b*(W97J216BDCBQzE#5g$ zT=w%C@QSdw;mgO6LHQEjZ`$o-BA3W*WYts(34I6uw-w6#$Zx!#xbGC5i6IyPZHE1zJ<%v>PT$1mqJ$j_D zV=DR$jRlpB10gQCH8H^Lfa?DKd`W4s0*2KZLfKTZ~3<@{LdBPw8RG9yejgm6}nmK^1|zNK1*b@? z9yDMGm9!t2J8gATZJ!BiVXP|++QZD>#ch`1a~p7lz6mTNZjR|hq&gFel*=@sis7fV z?%&6`6yIY`Q|vG}vvvP%^KX+6uYB zbfQT{5*1+GE$9aCPNI!01v70oGli9(J&Ye_5{#3y6C8+p4fIRM7sHD)H8LYQ2V`n>wGhnRbFqScFWF z31Ipteu5p^G6{C2eSJrr`)!=CVJNd8b8?^?!+VaoTeylZ>mF!yDfQ89ysz6xH>&8Fe zx4bIWl2gWWdk3caFzYX6m%tu%YtMBmTwUqYx;trwzjvZ${%-{a#>c_$}8I| z`BWl?)V2dUz4J*hm7-Tu%bJY@g{SBfIj<*&EwHs%zGCx-#?D?#c!Vx^Ag7tSfEr#` zTy|X+<$t+2#I6Dn+2I)xZKpFC&m%+WD2bO#2ME*_Sy55fVEi5UmZobzvwnP4`&xVv z7O^G{IgO{O;ANOcsI8G^4=!cOhG~YU$0!OQ3?co&(M)5AJa*0iW+IKFru?3Yk;QNo z*|9<=BnUJDl&&L5cf=6yw7E;X;@J1L6jp&HLxfw04e_A41X5B}N@Dl^LB(kcqg@qnL3h9cH72+D_ezwqwxhIe|9 zPfS}V&d+PVJ|MPyY(|{nA+OY=N~T3Ed><6*sRJ87Uw%ekeZ0PgwA({mcZGR#;3`5R z`9jiMyn-I^MK!_yu9}H*FGLEdD(z3c9!y?7sbXyXWE*mn-(dzKT}VIP!9~O zio=^@XTSW7&RALUuw{}6vEV*Zx7XS_d13VM=!nKIVMfdTJ|`nyTK9oSWPReX;oTI$ zE+xeKVp{`IqB8&(U*w(DFjMsfN0}C*eL!i@4(70k%fBd%VfbKmJa4-sDSnI0dMcE-h*w4Lt z&+KfUz2+n90e+}GuI{e5^SIQ2!O?`bk1k!MS&?$ElAalc9y69i@!s!ZBb{R9vK&`> zG0lZ5yw^Z(av*p3{+VvWxktk_hr;$QoDb_x&6Un_+fjw=S52^esZ z_4B=Fv!)5N0nFFTK(wb8f+3yFR_NHe4?f>ks*$W*Uw&~~s4QCf>&wSOe+4 zTsM`u9HrhD>4VWYDS0h?bPAJc7Nz#BLyVwtL*okmy%i}4JE|m%JSbm?Jn}M`-)yqC et-_>tho0=Nd)7VB5 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/mode-light.png b/crates/resvg/tests-hinted/tests/text/hinting-options/mode-light.png new file mode 100644 index 0000000000000000000000000000000000000000..fe9a5c8a2e565da399c159a6e8599ea2e053e56b GIT binary patch literal 2830 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/mono-hinted-vs-unhinted.png b/crates/resvg/tests-hinted/tests/text/hinting-options/mono-hinted-vs-unhinted.png new file mode 100644 index 0000000000000000000000000000000000000000..fa1006cb24ccdd589ec69a645897fa62c423e479 GIT binary patch literal 1772 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�Dh;_O$`t2$O>l zU@8B~Wi0R7Rx% zw>ruDm#}f)Ak5bs^wQ!^-1EDSen=H&Px;Zpcx6M)Q{8uR*jTd1;P3fIlb2_%4Xu;m zDQvY@6=u**y4%O_%#B5ZEb@!RUYI#k~Kz3=E%KcjYGothg@rFRU&$V{n0R_y_(bJGmaNzwIN zuXIPP2J;A^P8K8f3~9r8e3u@+@c!sKCVvjiLAhe^%Et+3{hHai5N3l91wn#Ts;UNP zDZj@4!r9kwmCyr#Zq?%0ztQRHL3`*ty!#!iaT2KgCI#GFYyOTDd3%Z2(ssWXrSO~$ z_g3cCX~*#|KHT)NOeHyb#nY?bCXIrpnFbAta1lB4G`d}*zwXTiG2*FOibJ*hYUIq% zi(^0ZOR3qc?P3x9gHKQN^soOd2Tkm>+)7hshEx4Kp6s8A!`6*tcZU`!F~CY?I0|Mx zx^p!f*f`9yyiI+>dz`ulGLuO-YBHAAVEIT=08UcrwwS2(Y}2i^e*NM(2R>7uK6%-E z5rgZPg{cMM4?I0=%FJB+-L7o`yFpFgjvg^fBfGP(j=t!#Qb^}3_1sdAsY z%gVCDPq^nH@%!|g{H8@pTsbyfdLaPumcV?*tSXYw-H{;G2O+^uhuZHmKph{%;CB36 znL!T-qrmR2KWb69tf-*oh7YTIP`22IHJ&uyK~1k`*u^DEwaVSIprdcT7y zfOMyAJDYUveqpOE&_WBW0as38&)u&UsdIQ-ob)Uj#VRJhDn$8N`Yb8f!NxCJ)MPR8 zwW>Zi00<4J&)&R%^2~wNt_8YHa0>cv)9BR*U$q!p>U=K_rwS~f1qFD5YKtUgExOS| zMDdPtW(?J{I#lG#9cy%BlmLewK3)R_2#l*uY$OKjE{k@!0zB-9udxLDn9a28=Gl40 zy^Dh=#Cjx#%j{@!%J-X?M6RY?FNS zSf0fT!nB`ovn^NJ;ryXz`vG+bs2BBDx;^_->QMW-Ecks4wi&Wm_yC%-!m6Gu;6VT6 z{rz$%hN#BXid6F#yU6*e@~DYlXOjmpomld?43krnkqPmWT`}BqJ7Pga3bH8VrR`Vm zXqCv3$QMb8Hb_lpl-wSe-VDP`lCAo&nW^jXnPqu-;esRZdc^8L2{hs-lt)9ZQ#Wy( zotfxH{jNQHE4#FBtQSZerK{zpo)eqjcA0hqBGh1gycy!9q)uSBIzz{lr!TILCM~Z$ zqST_i6=vh3slpoRlAeO@d!tA&w`|y> zSR+kX?ve{e3H+UxMah;_X0gZj(@n5oQk2q?#|nJ0Dh_zkEbAv5*tguHx>vke6xEHvD_YpF!VmlXku!-?SJ|yj^%v%xL?b6KW3T{=q&sporSa zr}fZUs0-{~_gSgQQMcw-jSpUkXx_RE)QhQmC*N!E7f)C>x{hiWQHwRLQLe7s@(L-a zIRZT9Efx*omT_fFBL~zmgZh%n^jDgh6BRs)C1N@is#Y#Z6OMOkCm(pVtQo!WouT-@ z$;aC}Tx(Z^O*giFUf`6X+K&39E$9+!;)Y)P6L9jlteiDi*&2^WQ?$xbR$AnIzlEt? z;g*L~@&tWblI>f&QL}BZ zD+bh&dkYC^vs=JgOx>b0XUuSga#0vhT(5qHLNK-!@Z;d zt;8v}W_MP^;UuS8Fj)b&Yoi6ON;ph1qC}iD*?yA_n`8E((gStx=GjfpTKuPYxwDD_z+cEe4S&6Fm9azoJj)N1{g}x58Nd;C zi&3JE(T6bJQEvY(3Z7eF@){E(f(x7LO^;fDT+u$zDhZduzwUUqlI=Qiv$cR zVDiY!x9a==oAF^)(?H?5$7WrgLS*Q;aPkQ=bFAa2_1CwE-II&a=GrHP@&Y!S0fqMo>8UXhAj^~(OnFG2=UcPHN45QSPFfSk#VZ%wN(fr-yoB&Aj;zatpvXU;dIKF(cBtkAICq7Xd~AZqR@0#Hk(Vtk#KiKOA-{iYEk6o1QhsC? z)Ae)3Vv*l+5h{$>|DO5(vspzyLE=6dio>1-&|E0N ziMu#d9EWC76$wMo87FeB0e!osZF;bHk@kfdXL%Y=s|ji&e;K6L&P*F9QggVUuLHoY z5WC|T=kUq-yp&uiZDlE!k>%-0f%P@6*@C|Ybz6E%%l2(L&K~hFM2D*ru&_0MOjD*v3vVXla^5=X|c8+MXD&L-~Ekx#NHOrJuu^ z9sFw1_?PZt2j0>z*wydsgVsX>Hsc$`IBoaRV?x1Kb7xtC*p?mop2WvjVbxP_84KGx z-3y0sraV{9XghTx4lXGpcq zHaDzwsqY?rHNuenvbk{zk0R2$%j93j#S?rEExMH$ zV+ykiMqMU?4W+An$il^W6#D$;>IGB%`5%q+ar2j1o}jXnyDP9fJID4YR?BW#*{!(& z`-BJ+EW#Dd`ST9AKPGLc->8tyg|R>c$e`Egnx{G-b{j7;_t1_qZKkom-3F6NG+!V} z^Z#_)yQWs<#$QK_IXA(F!v~C2iG9cSv>2_{2}6T&V2y6gbX%B;0lYs4)bNRj;+=p8 z>ESyWR?YCXMSRDVa3ZqZzhRZerjO>yPr2`ZR%7zUD{JX8YNT_>qBFgUveRdO3cK@Q z_1yf8;XC!QG#AwivVrV&Ka#YsoD512{S+?6u4f|yA`8XVtcc&(iO>7M)bY;IL~*`- zJKsDOqh=P}>ow-Hg-q$-lT9@g{!UMXH6dc^jX~PhY~P+o%%IIuVW)6R<=(FNu&wB9 zplx8Y75d_XGI_^0)$4*uW(|2g4p%eIUF>yV#T=%#46?7i^P%go7aF(hP*DtjMS9<* zE6GirdV%!jN~ueqf~}e}d#dp;-P@1G+#a>CZrIGK;T3yj<9?1HFGVWRse8@tLKp)& zr!`^sVyhT6G`9Fko6WmrIkQWcBFjq-Z=()wq)wlRrq=c2vDX=&2l3p7Yg4k-v3N(A zELvJkHB~MGg+A%@iU;;|ih&2sYiXrdwnFnB5Z#oTTvCoK_!bb|4!2KM<{OJXzBK8} zGGx)%M|sBge?P{`5A>rj`y5vwF3Yncy{4j%go4ZaqkVM`^_Sdz_Qv3+dv?S>HvAv8 zBIpN;A*~p5llPXqNd1?spw;C;%Qt;SoWO7!6w<)w4e<2|Q@zCP85jlfdDuOKaBc`e zI}X?R%2N!-!fExma;L^DB^@3?RD8S3@VA>sq?#f#6E=eu6FDdX~lumR(n zcUgkiXbdZFBLqj;P?vT4GYV*Ldxf;@&io8ZV%fZDQ6L|)uS(p@J6x8c@9AM=S)qb9=Pex@+e*-3CqFEvvE|7f)+|?lR(967 z#f}eJae`*-Y%3Zd2fypI#>m4|yalRNTo%PRsX8PeTKA$)Pox)qqsr~MwaH?(ju}@_gDl>Sn}oJJDF~PrzRHrxrv&gMac{*LJ-6l_r=f)|f|dJvE-= zoeA`*zz2rZa;r-rV|;VdZo16NKnXFS$ zn>`251Tv`*QE;tHf(!i{Td99Z?|=~F!c`X0w$eSeE}TD5TQcp@`jLzYZqZKdJrr_|hJSoNh&EW@ct*XJ=<;XJ%$*W@ct(Wo2e& zW@ct)W@ct)W@ct)W@ct)Wo2b$Wo7^W{{R30b&7JX0000JbW%=J01zNBKu}z=*`LMW^ zrh?cn`v5FUuQ698&>0@ClwvOGtP1RASa=QVwxS%9&aGi(ujG+B=;jgs($0+V;Kc@CHu3^1`)m9> zOH{J{dhsK_l$%C0N}C2a9nWR{q2x4QGt7f%Vxv>+d=%ba`i$ zr#fjZ>10?A!xHuZSY@pCOCezc%Qy@R>|uHSX*eCWpN3&d&H}4s31?&jxumedDPQNC zf9~kth7D_}R;$%&wOXxKtJP|?xIL*ux5q~6X*H_$f$r6XF%`=FI`J%rogndeA6Dob zSivZaiQN)bgq@4$A?xvz}s6SziMSi-`k)T96W^ z)GZ7pTb`%To@a^Kf@ygnC+5!YtWaG9cCez$a#%LJhLtkNp&~rI$w+y=6;?PmuzU{I zV)6O4lf%x2RpxpJRtY->D^FD`%Z=u8ScvB}tlTqcuV6}ZGv}x}PlZ)S>NPOe5k?%! zH9tlE{4zDHR;$%&wOXxKtJObTfaIUt4&PNS=2mz$CX$AkZ@H1&Kn;FRl%-UZ*TdrV zG^E-|cc6*+Ob0didRU?3uy)~j;lh;fdM#nq;P=b&a*Yrt2{hBhgg1Mp9AX&L8ggbS z=vj%R+A9-fJ)eUG3s|LxAI9W3BAD{tK{B6bE~(O}vfLOIkBN5~JOnGws?;9d!HQ8& z5-Fydx#TMiUFIsiQ_b`afRkatU&Hb#Sf%SsV`T}T!YWUfbXI8JSw00TUe?TCG;A)oP93u7>q(uwebSO5(5*#9`+g^F&G(VDg1G1(wuR&Vl8g`)jcF z{{zx08BeklZBqXzSmQKU>d5C{87IQ3{|(ITXlng}HSG6cy&lN}yVOxGxJLn}!iu@e zD%P-!Be2SzwPv;4vlyj7w|{4MmgFq3k_?4QSYQvU4p&y2&bl5}JiP-;Ek0QXV2R^< zu#8h-`8up|99F%c#{Fku*%lwJ68ptB*E_I`vtY$miMnTDI&lwu<4b9d%m-d(0frQ* zMqUW(O*tX*SN=AH{@bGm)oQg`|FlasyA6au3^p@{1haqX`#)?2yX`3LWzQ%+FnqG) zgXIk1Q6GU_&T-7f8NmAiR%<0Dls3Rcl|aA`4I;-Gp6&I?z+`2mvn&1}`TW1Ec9q2p{#}-Li~w^`GcK#F z1-?oI+Jyjoyzr)G;7R}z-HVsh)CyNMi-6Pywm=Q{GA0xaw?*C#_$VdZ*Efy_^6>|$ R$p8QV002ovPDHLkV1f(!{+0j$ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/hinting-options/terminus-mono-target.png b/crates/resvg/tests-hinted/tests/text/hinting-options/terminus-mono-target.png new file mode 100644 index 0000000000000000000000000000000000000000..51ddc5e30138d871ea28531cd2a8be969e7c16d1 GIT binary patch literal 1351 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 bp-*zlu4pfo*t>5XsPOZ2^>bP0l+XkK6a-a4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/lengthAdjust/spacingAndGlyphs.png b/crates/resvg/tests-hinted/tests/text/lengthAdjust/spacingAndGlyphs.png new file mode 100644 index 0000000000000000000000000000000000000000..57978f33fa67178bc1ad4099b359a2de9bddaeb4 GIT binary patch literal 1541 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfizao(9i%BudlBMlDWCL5H+!}vHt%45Vnhp3y@)DWd$UGiXke2Y)wr~B_$<@ z8W|ZG2t!<49Kzt^;{!6dxInIDV`GB|GBbmm${{hk3`psg1o;I!FbF6Z*!u^>$0sCY z<`)##);F~GPn}{KAp+w)~ig_{lEZm$*TNW(YBHa1s{{P#%cR$=Te~E9i?Bce% z%6;08?4myBUk-5her2|X_jSGWwYJhTb^6lNKJ0H@dLzVHLGngO7H`C~I(F^%*4Nio zl?c=wK6UO=+tk?~q{GUlnXS3ga(_e7ZPPEOBC_(&oZQJRX!%?!xhyzBw{_2>l`hT; z9Y0im`ujxl=BkZPsvm2flf8F@L+tv3qd{S|t+#$_uVnu7_;upRXHJ*rM)Vy0+UsO> zo~!O!ymNgvK zC#y3|MG71yZ`-9QH|b5>>|IT<%F`J87f$=57`b?QpBsCjU*^mF)vF&V-xQaYmEtPx z>0h$An0JGmTSwf7_AiG|1Tb8i=rpar{dtsZ;zy~iYHQ9li8q7>dKB8Nf2x{rRAcX< z^*Vh#tO=agmJ9S5VtgkjrO05)(&{cXeca6{np{RtVK%Nlqh9ixp2@gBF%q+Iu zm(XX{{=YZqMNfp{#f4%~nsFT0SoiDC)PF9RUDI--KALxuc$4ajnF8FKMa((kxWc|J zj<9fguqu#a+TTc>xVvd<&2(fG70wFhMr>+-Y@;pez4^_ujZ>Dlmn@9Px%iInp7>!O z#|YEbFGV`Og}#;%T~5c3MzC|u&Hpl0cxgi6j(@RTt>!5Op>JF@BhtBEx<>4{pDJH& zv`34jJ8(sOlj=b)_wU@Rl{S3Pu(IoKt+u%O!*_P%n$y2Fiuk#nPYPZ9J9g313yP0l zg{+g~Ue0cGJ~4CFjrUAz)BYX4^!oUr{T+UvICYF`osV65v#7&;jgb+|uIYF? z&+wR~|964xKZT2q?CYQRe}&(%J#YVg&FgvnR%+vp4d%1>HwyKiaEW@E?BX80mLXeG zJZWR5wg<0q_o7-+ofTG>bGG|EN}g2tJCmrjW6cKMUK=6n6#i!*LS7_;2xKfox@ zp#C?g_GD#GM`h%0_aifkuP^icJK@rnJ+oeaS^D{qny83eM{tc^= zU$wuQA#-Z)`^1AytlVNc5gQT)8-o+#Dj|s5R3R?(hPZQD!a*yJ)s}BP&US4z7Ilq$ b3_xJbr_V#vlbyZMMP*G9gZ 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 bc%5NAc&RbAF+Z9cRQ!6n`njxgN@xNAAy=%X literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/0.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/0.png new file mode 100644 index 0000000000000000000000000000000000000000..b98539db454e1c552f372e38da00acf50a038ffd GIT binary patch literal 1631 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0%?+fl9G~;kPuJ{7Z;bavonw(BO{ZOljG;-XJ}~X;^Gn$6QilA31o|li$_F6 z0M!E(G&D2-1%Zm0nVEBQbNTrA@LLL0UteDjB>yMu?E)$_EeY}qW^nj#f1ttOeZcwq z3+BhyKiF_K|6xb}&aApQ?Ip`*A3neS>-DAnUo)>Ktlz)k!i0hk3Ig#7`={{~Mlmq3 zs(QLOhE&{ob8RallY;=m!Traz56=A;efT8*_M1X#w>IUdT;Am3yG$c6eWJ%^XWu#i6#*&*DFf>viSe~N;_ELah|XQR zkG>FC6SBGL#bo={m4%x5`8?Y3tyA?9p3XjW>U#6kyuiez(g#kNw@qEotR4I2hWUD3 zw@L{PY4sZ=|EhNHZRxxB|KT?M&4n|ztbLL4PQ&vH6}m)ot+}(d#L#$CwE(7SEDQ6<)XTTe+M_JyzyBO z(R#i~azmwnigy>qTE62A5(GiaezrQ&@nnTuZ|I4*K(+sm47QCE1L$?M&` zyY$ek<{<9{DQ!R6ef-XUbyL@2xt4Rr^7fMohc-_O%efm24$Wben<4ODpw-htYUu_( zl?`HFRrq_kyZ$q-bJSj=r(s+(p)W48FK*T36|GM_r_Bv}oAP#b;Y!!Atk$PL1P)s# z{af`V$?b~S)(vh`bkz8`Q&&Y!+91AmgF(y5fRDR+yV7m7W=BQrIOXcA{fF5^>ga}` z>a9WdoS!*_9^7R9!lwCxsZE05Wv@F&nZ-Wx*BtxOAo|N7Nl$Kr$7R`bVb*K*?hI~K z<(B4;sCm|*xwS50=1%X;;dx#suU5B&9d7v=v2}w-@XT(88`eK+{t9PS8*D$FxKb{D z$qv`a2F@p4r@gAaQL%Od%gf^Z*)I=y;KL-QZ-Q{Kl(X+{rKAmGB zEZOAqi@4R*Yc4_bFy&lUvgGD4b zP9}FtVuafEfZtj-v?9gqe9S+VOj5DUo!wV<@&6{9wI|9F5?ca()rY<-+r4R3SJ~Fo zJM%uK^=5TTyS+RMA%NhTUCunSKDoV?ReqWaWUW>(GPE=@ z9BXQ}oLOJ2qOs$?-P)E@lT^K@=|pZyIXT!EP7r6|pw=v1vybstdg}^f(ImM?C-`@0 TT?)JjDx5uC{an^LB{Ts5#(Sp3 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..22e9910c5fc31062f30af287e288a88c9f54b921 GIT binary patch literal 1677 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_lc^hWh$?APHo{fti^ZoDE^{@$o4sDG3P)0aY3r8ag{W=jP^WYHH@>EaktaqG>stvi_<7+MbQR?kq}QT%s$+hlz~vwGIwzFVH=FW<2L z(znDc^);cv7hW}8?P`+JiP#V)?7bo3U=u6%G%zWq17eHmL_o-`dxAxQ9Eb`s8EgEH z+_H~r2AaCYCL(i#*x}+0N^4&JyTko=&D*ye)7m4DN}?V2gEP{l`Hu=qky z48P0ET`#m>PH3Hec;DLBY5R9uR4A6ko1Bp1x4oM%d%^mm$YpH;X^~3~ZC$0yYLTvz zo%5ovu3h2bveZt=6dB!$$k20}J_vV4{9KXtubzc7MU!nE&!6mTn_~PG`4kEt9b*?d z`l(z~Ch*xNtF8+kOFLpZ+-w%s`}oaW)3@l0#Aipnpcdnd$xmOlO`f?|-Y4+lRHdlQ z+8^tMGbXoA6I;bME`O<9W$oUqby``pZZ;`;*Mu=4AY#wWJj z%BZ`sE@qq4SFMSyW_JP)YnaJB)5(;yFkN63sW$6qx@Y?Y`8^u(bJyh7=&YLN#oYOD zpFp(ZKC#G}U3M2g#MrDf-(x#%z5lgNeeaZjHO`3~64zWU7CJ>1g?U|5e0=TYqJ6tA ztDjb{ew>`7{W*8n1AX@Zjqcq`z6dFw_>jjYp?m+sWsTQ!-t?s>vP}5gd^9R=c~na7 z#lJQ`yM0Po{9JJG;SF_K+3vNQ7SuTDOqIJ@9Q;=Fl#zc{)aSoXjlVak>7Gtk z@~&up&$+U3&L0nZ#q1M4Vlwj$1b0k#;XnE3!_@H8zSmCZ9^7?&SzFM*ovbs@H=VOd zIp~wKnp?`2L#g(`GV8F;)AM+BXVj#8Eb>w2{jno^sg$d9(Ies9(qbVmd*Mini&LL5 zY2R7MHz!nj-^;v5KNBx^zVB5|Q{cX{R(I3ey8myBcFKJFy^Y_z(em50T*Eir@yU>*5?;J&wV&JP)NJ|uWwO{V zvqcIVj0{%HA9vMQc5Y+&mH+lmY<$<}YnuyZA7Y&&RT1*W!q?@Js)g!G!GZ+cm+8~D zZ_QlL_<*f)`#jd$A~we|6f0gTx0uyeIPPD2-O1zJ&L2|z&Xv~XKFka}%!V7BH?%m2 z{=1?jdN4oooB&_LTJu`3L}&p*QJFzuk%L`3C!_!qg2<{uN;O337j@{B^pbxOiL-)* amsQklq0IKQDF;Jv|t z2K)aG4W=9c3=FKEo-U3d6}R48JDTWh$iV9Ow;;&tjKbIZGjD!RUv^XI*_Nlta?AQJ zWzD$7m3^bh0e7Sn1U_dUn~n%6DErKkJGF_cfj4O{TpY6KX+hjpI#M zPj5{4do*H$n(477(=!_rbZ?sTtL${t=y+tLVSU@ZAb>6N!9VljGXF)bG13c{X=h9R z*z-%?v?EriL6yHWcG}a|zur39D(HMYb&SvZ>Qvi_b!RIjx6ER>{9(Oky_{}9BVyru-+0VanN8^UqaHa1hnkS*|;A9_QVh z%>t@gRjNFTTc_UUy?SW%&FNMFAK&+PdvJ)Qv+fm&`>JuZSLsX$(*}vvIWfi0KW)v| zb-7m|(veScm+QtiySW?_kSun+n4D^gvk zdFdW$3y-9wd>i%Fbr~41Ja|ZIEtA0#jvwspN-YmPc*9zca9xR%Gm?v%H+x$kFw%qP zvI;(vJ9G9~dE{b_)S?Y)VW|PzQ@0ujHB3Lg%7^b-$6LM25^vm7k2|saaazLeoqUoj z>}KEI)MlkODNP$bJmWfSq%@~?mWdzJwB47d>h;$%{ANi!Tekn%-wWasmDXH+cYW7t zIvvrAWHBN_vi9hvn>&{y1|>ABMUR~H}7 zkz2!5ynA=HguWls9^uwEObvCD6g|1ZV}Z=VfEg!Yu};okaD_T>IY7n5$RNU%Ip{v$uC=)k4N_LJsk zZeg%GT4t}k!!vMwtNX*~ZBZLD!c8U`9-K6@HS1;ehcXBKBc>W|g$WnsxOYq}JaFi* zoyYZOkNUqJsG2xyUgQbBuO}DT@k8g&(5-S_WV-Q?5ZBqx9oZUA z_m8Ow<;uzGXx#T%H!+@re^zy_$Ck>P4GZ?DF1h9T_P4&e(7^+XLQgXvsM@*Kd|$i$ z62{H*XI3bv>9)SBD)rOj&dw=@9>qnJYM+ zh=zokI5@b5hC0Sg3wq44J1kH%XW^z*bCi5CzPvblvDl08?S)2G1_K_J14^4ynoj*& zJk{@m!-Kq*$*SJdbRsvUoSZb+7_AUz;i9}FYni{C=Q3Qb=3<-S`tkjN1cB3_a@y0? K&t;ucLK6Uy=EBAR 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..03519873cefe7250c4ac7dcd6685befec64f91e6 GIT binary patch literal 1661 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCE z2Ka=y0%=l#l9CcLGjncku8@$Bv$M0GpI=N&3>zDpot>Sbp`p0Acw%BA4-b!vi;JeF zCKnf%jEoG>iiU;;Aj!wahu=D&vikaZAUW&rF%h6rPmj!o_+ZA_x7a^clKZRzy2U${r&|L&VNu4h)>vm@!jh<1_oAdPZ!6K zid%249c^TC5MVes*Vggz0o(s~3jQ@mmvVf4W%NIAQ)TBYpTI?C&YiQW*JyZ&Y)ClR z^mW$3CRT1Sod^iIfd$0gkiZEh*PgQ8`pX5xhbkhI@#^Q%=v?Pb;e6tUqLkU7~zY)zzZ^1)ZnHzt&Rj@TfTsS^=s{$@^l(Q6AH zSH*}Bef`{O&v5Zc|NrlJ%e`)^lE+!^iI#SkjVGMu)Z@JxJVi9L^k!*ptURB*#_Ci4 z{@0Sb|1VwrCU2+3MqbvAy`fhp6|CR1qOZ_1=Dfn>f|V%6%7^ zmj}P>)#39`SR0U#IIl!Nc<+^;%G!o{kvyl1;{QkSCA$4P@rd8DF*NMqK8B<<;#U1B zg&XGz`5BhER@_MRH$#KhTXI#=Fl_ax*EKYAa&%cMcbegJ=;^K3g zQZ(FsAFNy>aIa0sbjIb#X%1cPTk1}odZ;@id3}3O>>sfbo5YVVBj=}ZvQOQ<*y74W zx!<;TCLUwkCuL@Gc0rAe%j8#_McR*6R@t6h{_lj+xzo3Od5?bbSfIbDgq zCSv1f_i2ynDrT>AjOPDqEo%07ze~QcDbN4?Dh9U{v~O+J(YTj#_0fgY6q}{*RkUwx zU31{0(wev78881kzpT65aBHhhY=8WLzNeQQx7K;sZ9UmlBK|Jwn$5y@48oyYJtb4u zE{uP4Q;B;*>H8=#jg(_o`Guz%YAs)xXcj4xyUAjc#G5FwFDqWk^%pyYN=Ex_49dBa zt|a$(ifdTY8QYg{Gvhb?&^CNr8!OA#zG~fRKM(f9uB}@>v2W6uHKFtNuaD=y>$~%O zQ|-<@sZs53GkMC#IVzDcI}+MAHB_ZXI=w&fJ9w=Qch}w1Ns~_MdC!w#yWRix`?qg) zf{_N|8XxA|TGn<(>hgP~-D~%rPD)D_`+eoFp87-P-rKjUyVr=%Y~N~c_t1V%&a+qT z^7@4b-`>?f#1`{!wfDul-K;_Gcc-dualE$r%;DF!KfgVD^yt^i@-gu-F?VV{|0=Vn ziDFpbwo-}5c`8du-Ir%SEtl@!?##~0;9$VOu<*dFHT6~#67<*a=1}*ZrW3g-<>VyQ s!N%Z*I13k5mwHr3AuddCZ>qkMIU57dky_)!f}jH2)78&qol`;+093EMssI20 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..bd13d448f848c5baa688a1cdbf3abd419e1c4fc3 GIT binary patch literal 1032 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC4 z1AIbUfiya3U|^_VU?^Z<$Y5YdU|@(~U4ayoKB2)JN zU*Yk^BVPR*$2p5kDNoahOVToC#E0=oDS1!RiQJT;>k6h6Av_vVvC;H=U>ffOm9zfz0v5FsMs~Rul$y$jl6<3(*#qEsXyNe z>{WG|Ij=5$yGAzag@?;q9<5Pa7bIz@zv3gKy-31j{bNil*&R=}e_~O285m~q?hLa< zcE_(Bp{Fk_T~j2ZzmB1MkKm(#SK0lW(iH6V&ATjJ)VWraXlmQ+=6tsIn!w{2q=^0n*6hma7fsYj=7QYo}L6dks}?at;ku6jv}Hht65j;#=TW)yO) zkA2T6(;SCRhgTufYV-BaFl^RtcprR?$>0QQi1)|WUCGlo$%L0m$S=3%QrWGuEiKiP zWyZR$4+Srh6&P-KiJ!$C9S&3At;-)a5lwVcV-UWer>wmoUPXUq~@nIt%|Ibh*I?l2QBO*w9EF`bAF z37lZ^pb&_Cut^n6vU&sAuf75KtPn*Y#R6h1^BvI;7TTs_kgx|VtMJ(;k*!fUeD zMyBbt`?IbwKKp60;2LAqHC2MmXJn2C>qfLL-*uW%4#je*nU-y#Z)Q|x99m_1>dfV; zy>SP%OwLc=X5Mynug~n-w0B~6?cYa7>^*HV^PApe>CEfjL7qqQEQ)CZE5(8OI@R7{#XD2 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-scripts.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-scripts.png new file mode 100644 index 0000000000000000000000000000000000000000..9297d7a7e8c7ce8b97bd9a913d2cd15dd50420d9 GIT binary patch literal 1544 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOk<(2C++Xlu zL%{j@*T23#n^}B#;`*I+b7t2rojvJcM^<}DzkmGt{Q3(M_P;MsXgFa1-(h87{}ToV zmUEsijv*Dd-dr#gZ7>jF*}(txGUK`ZW)&Jc=DIkg#j0L=vTTZZcKe}!n~YdLt=Ea% zlyY)XD=zAs^E8N*syE#kwr_5+ZhK@P;qb8DBkRWwYrWh{v;XGjF0nlNY;H+~-rgO{ zYAl{?Oj!GM@$sPLkA1E_-C**rG2!JVovZVGH(IOIn?*@!i5IVVqrGf0ORc3&bEQIr z{7Ie*aSsd7f#^e)%QE?^wK(!lob5 z+Q2X3t=FBpar%)-#v7t^c2E7k_UJ36|Iyv4a-!3;(x0Yo2-&G|RrqjJUh)mS^G7e$ zhG~1m7*DI#iCDE?%VlZ8xx-N#v|PBjPqXQK->|{#x5d$0M_%bivK_UIur&&eT(3|S z5>b}BYS*=SNv=;mZ8v?Ap0F~vwu;-UhPYe+_uhZ?)Qs{-0bPHY#U9U zRh)=DnIbh!Lo2k_e?!oYEA2rE`3EgJRF8*Gm41GvYAf^YoN1>$6~(79C%ospCe?L1 z;pl>I-~Vl3)ZUxXqWAmJ1^(;;{|!YQdd;Z|x7)v-&9-LAJ@dk#a2=sC$(ct ze%}7rU2_e>#Gh?`nZmpw)^B=o{)JwZ5W@vppTn{qzWX!%5|c+-)RmmulWX^KX*b9? z-jBC0yx1TbC>}ihsh87A#^Z}PUCeuzPCu|^Mdq{vizYZvlZda|w4%7wr_QKA?sB=( z=C@wn%+n%lrd~D--KPGqglWU6?!(oVd*jxe%T%t(U*+svbNHO2{=EK%kFS4y_*e7z z*9ZO@dn@+6U#3_8UUd2Ahke5DJ{Oo&{d;+IKKEX!{XT> zP5SiL&$rK?zU$8S{QIl#^1q)S>wf;V?Rz(aKb1z;rkDSZd-U>L>4jzYHmmmC>Qp=! zq`J>;zopr03k4&`2YX_ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-spacing.png b/crates/resvg/tests-hinted/tests/text/letter-spacing/mixed-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..cb7433d1ab34b1d71cd98a9c385834ca9ea6c16e GIT binary patch literal 1421 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0%<%zNlB@pp`pIMUPwqNH#ZlkGB!3=TwI)ujSa}=;^MNhvhw%$2eJ(f4f*)^ zTwGj$>LVf|AZE(Q$S^a5oB;$tqaY0YBvAV*Ev7 zW^O1x{JQ_)#M%k7ueV=6|6u>luj}V;C{S2%-{Aa*fD7*v4($JO<3tk!152`}i(^Q| ztv43}866xLSPd8)^$vX1XBXO|pU}M_?WMDh?`^@X?`tlxX{3kUX32Pec9JT0o8NXt$9qX%n;lXz(;l}6tI?T7L-%G16Ik@-#<+*DPOc50> zycPE^BwFH)zOBK1xoPt>w=UFl-oGJ+f8xKW4RcO69o@d3tNWtiMAI)@6DlXOu0F8( zP|^A5k8QUiB)nd~ymD%*RYmifSw(U>FY}iLYg#>8`O8`J=FClt)z9;6_bS{n&8@)e zTLiCb?Dc?Cd*#-Mz3ocoV%R(Pd+-+qxwUJuxi0ZDJlK@5Rp_R=kl9}5hW0C_Yz)V$ zqtuxLHO_~5OZqEV-Z5jg>G<>d;G<>p*RV`;+4j2Bpq2Bz=hj_w9$QY{D>R3(`(oxL z*_=fWjtO}$KPhqh;PcpzrOBS_r&~^yNf#hzUl1r%j)3F znv(QLhxuB=lt8tFlM-dQKC?Mji{9b3`}HjB`@DM`VuhR`W;YgU{dl@LihpIIzSZ0u zsrihje|Z>d#hyoR(HoezrF=7h+Xo3drO^f#IrEXuNLyr_rJKmVoWz-%Wm@0{F-2tF!A_A zD<}7z8(d`jt|XgtW%Ijd30Y4PdUfzooqyMg=j-qAum2dd%k;&oPfQ1n{tUbF?%>}^ zm7TsfTfVxM%zt<1aozKxY}bW1i*w~3{m^@Q{ML-Sa}OV$d)Hu&##NS%$ayl%?d-p! z7j^&sJ7ZhO_R{kHX5EY33Ay~cZvESG=DueQ(VgCcP5aaaG8^H@&7dLx p=qwym)$FU*4)@mxY+dGbhH;n7PR;tmujYXYG*4GQmvv4FO#m7GVAucv 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..8cd33c7bba4254d3f779553c12a17daf6cf95f5c GIT binary patch literal 924 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC= z0(?STfixOuXlMY6)YsReiMzPCI6FI|3BtL2e0*>=gt56@VkeL#TN30K?7$$PU|=5~ zpOBDWP~Xtr(LZ6qhW!W5U$}n%!TS$yDkhv~U|`zs>EaktaqI0J*D_f{5eG-p8Ft3m z|4*A}tVu2xF!+E!Z z*67)7+r3&ud*P8#&1+h{{@O=h>3v)o&~|m{L+@zKFylUd+1pBMYL2erU48R8gJsyq zu29A>`QTc{Yg*-N`Bu+VYr1O?wlC>w*VTDKhkh)NSY5NuX^omnOYv`=FuSs>RYy*R z&wOeSR_zm9zBPI4^d}d1lXNeixz_r{#4)FBgOktK4YPtLaWF^h)?d!M;hoS?!{eu} z@2zEi&F#16^u|xd;So1qI=4;DZP~ENdnS+eeU8M^=@R~rr(avM`*OLo;+nKwT+Pe* zUhm&8Se3xY9oA7F&;Sg%HUFdc*X}$md?GbrLH+-TzBZKbGwrRvA#%+a6r$4>D?&mZ z8r-q_-P+aH9R8a9#XVyC`itsoZeKr^F%(I2yMu?E)$_EeY}qW^nj#f1ttOeZcwq z3+BhyKiF_K|6xb}&aApQ?Ip`*A3neS>-DAnUo)>Ktlz)k!i0hk3Ig#7`={{~Mlmq3 zs(QLOhE&{ob8RallY;=m!Traz56=A;efT8*_M1X#w>IUdT;Am3yG$c6eWJ%^XWu#i6#*&*DFf>viSe~N;_ELah|XQR zkG>FC6SBGL#bo={m4%x5`8?Y3tyA?9p3XjW>U#6kyuiez(g#kNw@qEotR4I2hWUD3 zw@L{PY4sZ=|EhNHZRxxB|KT?M&4n|ztbLL4PQ&vH6}m)ot+}(d#L#$CwE(7SEDQ6<)XTTe+M_JyzyBO z(R#i~azmwnigy>qTE62A5(GiaezrQ&@nnTuZ|I4*K(+sm47QCE1L$?M&` zyY$ek<{<9{DQ!R6ef-XUbyL@2xt4Rr^7fMohc-_O%efm24$Wben<4ODpw-htYUu_( zl?`HFRrq_kyZ$q-bJSj=r(s+(p)W48FK*T36|GM_r_Bv}oAP#b;Y!!Atk$PL1P)s# z{af`V$?b~S)(vh`bkz8`Q&&Y!+91AmgF(y5fRDR+yV7m7W=BQrIOXcA{fF5^>ga}` z>a9WdoS!*_9^7R9!lwCxsZE05Wv@F&nZ-Wx*BtxOAo|N7Nl$Kr$7R`bVb*K*?hI~K z<(B4;sCm|*xwS50=1%X;;dx#suU5B&9d7v=v2}w-@XT(88`eK+{t9PS8*D$FxKb{D z$qv`a2F@p4r@gAaQL%Od%gf^Z*)I=y;KL-QZ-Q{Kl(X+{rKAmGB zEZOAqi@4R*Yc4_bFy&lUvgGD4b zP9}FtVuafEfZtj-v?9gqe9S+VOj5DUo!wV<@&6{9wI|9F5?ca()rY<-+r4R3SJ~Fo zJM%uK^=5TTyS+RMA%NhTUCunSKDoV?ReqWaWUW>(GPE=@ z9BXQ}oLOJ2qOs$?-P)E@lT^K@=|pZyIXT!EP7r6|pw=v1vybstdg}^f(ImM?C-`@0 TT?)JjDx5uC{an^LB{Ts5#(Sp3 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..139deff3585848c3c426e294761c1b6c7f9ee666 GIT binary patch literal 1705 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB} z2l#}z0%;uD`!O8ylOUp`n$P z6;MG;OiXZaa86DRP#G&LE06?A0d+MrG&nmu6KN?#8Bj}oeZ9lMRgplxWl4}b{rcgr>zD2{`v9i`}aTCaKHZi z1Oo+u_=JMm)sq+)SmQli978H@y}7Vau)%`#B?I8lQ@CohJ=GcV6sUS#BO5s29vMrvi^Vahlp@Plr^yq0Ap9y z+o#9uri5L6sL+uA&D-h!tCvr&UCvcd`Ss7gjCJu1QH$iA`!%PXS@VAlufY%7GygZ~ zIJeG{Sg_g{Guc*AL?Ao2@G(9_eMds^tr;nzP>GT$t7k2omMu%Nwf z6^rB53_oA7@W5$z!moMc*Pdfhy~WMT5UVCKrT5vEokvQiJWV#YbURxcZ9V1bK5wfP zMW1f}X`Fs!+uPQd-SsE7-6{7xSNtV+nrgI5=(J?@5Ey>VpC@_rhj^>#=K}@kLc#Ouybw2 z>z@6Q;`tRiPxD;tw8Vg`6Ox-Re5eUyh}d<1qgzh@6+_Qf)~M;1Q~YM{km0m`*7JVn z%=6J=FOu7mbt>za99TG;ncR$z@fa@dxU9i%T(*X_VS-6S!oz)6)PH^|ohLlqvPnl^ z!z1Q|s(+g#m^hMjBsTGg^>Cm0vm|PoYRBaz`*gq0VBWAl=$VG-w!(9_)q|h0=%uq% z%u?l4kdIrSbDv@1F((DlVg*he1)=#@y%zT82d({T`=bANZ`*Y}~-S62NAS--dbv&-|thd-Zw96c%jzQ30K zZ{_&?QMF%6?04#)4VOF7{=9thbAI{0=XYGcej_D=cO$Vj=b!=@9*wC zzkgI#|9pM_@-e%*nA$G}xvw8T-)i}P*1Q$2k-YyV$!cyq`AfIy^VT_nwWn= zFt7QsSnk~6Wj0R5Mq4Ain6{|?ojT{Z`%*)0XW7 zLgs$fep>!!>5J~-DXOm&bJjClcwL#&F-g+cjoWO|{JVGmo)DUU=3&X1O4Flp&Tijq zQf(#6^<|kjBDLzoj`p|o=-!$TBf(X&AgoA@{nRGq(s}oFjLz2Gxtq!y#K_S;F_241 zO;U5q6IY$g&b&jeeS7=5>(9rW2;8KnIc1(}c9@3dh1j{pqN#hUQ(UEGzQ^w_%VAbv zU~&jpB-Z2Pf1}<+SY2V`hMn>cUzxXknOeEM`&bdn02Cg$O04_MtlZN;WgXB>5HbR) s6za;qGQcA7)s;n68@K56aq7-ymu0EE_|)&DH>mvfboFyt=akR{0Pm%_wg3PC 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..7edb411fe208ee929e7336f0a81debce9c5ce13f GIT binary patch literal 1026 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBl z1AIbUfixV1GB6l3Fz_=lq%$z&GBC(6FeEWBl*6SN7;40TuK6N9Y5MQZ5Pd3ubWm zZ@>TjzxIOPb8H0i3tInt{W)j$mOt-bTo1p!{@gS9Z}AECJ4|0OFfa>vx;TbZ+M)(wl^et-KvEM&#^`ib2kYTNQQsqF4N`Rh-gTGh7}#|m|^+3hnkgLRyY zqj@6yxzE1HJQ5``>mrkwPQ-?UgS*xz9Bg9c7Sn-{5ny)21{Q9yHP@BFDxe}zWgtCd zh5Bhts6J_m)iWn0|fs7x#$cx4(Qn z{n701+s-YItD)A0?QAy{U)?8kEoRN%8l4F3h@GWct6$uH+7ap=61#8FBZHdgqm~h_ z#*sGin=jljO1dhlS+s#|jz+Lmh@gGf!aUJH|L&&_(=Ihk^Sf(%&1jKS?zXE9CbgIL zYQF2*PM2Iu&#dv-v*i1gH5G}$%<_9k_bfCG@Qv%njMmYZ0$1K`jw|WGfl`9 cn|1S>-Qf%c>VrE?)A6^1_qV_PZ!6Kid%0k zgfbpA5MbC)ZIGt;RX=~pgMYI=SHVvSaf#kA&LIkDQ%OOj7lpwr1C+2|!9G z5|awEKLt_&lu9{CWk%LnE3Yn~!Fpw9+f0KbI1c~3bxKJzl`|nxwP{nwx&QyGudiz^ z%}X*rPWFiJ2levXM_4H{V)5E{dbD&d1ilg#ltC6 zds>6TjIL^G&wV##D&L$TQnl& zetWfbUtPl2+#$Yqn(FH3|4p4vS;nfgCx+&V+TykpF6~VszKBe-)O*$`^34PcQ$ff(i_gC<~nQMI_ z_M z6}Lzr+x6YfQ$^gj9@#$odM@g_TG^XZ=PVskwY;Y{Y^jcYwsvm$VNp&+&PCldd}m$z zHf=bjeE99(PbatLF-z{-`fi%tr1eY0CIsw{)q7u>VKh0_MrPr}->>J(D9Q#HO==Z6 zeST9{^Vzi%_3P5k#7^60d*p@3>vQJru_?+I{3K61t(o6o6gF+!yQ2@+)Zf~k?##)+ z(9v|??7Z18{r5SuKOf>%zyIPx#L92g)=6vHC2L(D?TpzPs5!ms&z>*e3buy+N_1+? zTK#|F$EWI3wN0IIe|GJX`QI+bKghJVoKk)Na1$%Hm`=oogoA^PAp~)i zD#UHx5Eo8^y7OSuR`oU4Z?j&?=FUD?Qdn5JF=5v#X7Q~H)`#`X?gW)!p00i_>zopr E0CsXp8UO$Q literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/end-with-letter-spacing.png b/crates/resvg/tests-hinted/tests/text/text-anchor/end-with-letter-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..449a0a35fcdf613f17eecaddcd5285390eee1753 GIT binary patch literal 1240 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDj z1AIbUfpmR+eM3V7kbwvA@$oS;Gb<@6X=-Y^xVYrz<^r_&XZ`1|{_ zv9STUR#sMcjKV6lp3BM*D4|;tw=%Zv602a?dZ{Mx{H#lEw%OjZV{a?J^^3?2?7vl*c(93; zTTBN+Mu6E78(4rM5gQUXfuwnV0#t58!ojK)NF1nIYKydA0UCU*zGbUbnd-^q$>Bf0 zN2|UqZz+wNwB_mkH^OWFy-oa@Cl#@G_JLQi#?n^T^t*rBZT`7A_vxRvY9|-XG4pj$>*PZk2fZp zZvJy|^5N&He!kT_g@yk)ysLj|RhXKr@tjnXw~JYM^DBYf(oyk!8|vDb4`)qIDgAhV zqur6^zNsyb56p_Ud+%T0G3A$ldOZIzUt_y9xsy!F|ILq+PrBV(U=tyGVBwstE8lF8 zPSW(B>~o4^BVTzgU%1Mw$xjSVPEPBI_^l!@KmV)A$%P?N&$n&s5!C)3dQ@xvXZoIzjuDEZcnkjC%Mk+{EHEt zo^!qa)dU^C={ap}S9OZB?CZD9IKN8&L4W%8;@Xb0%XaVN;azPqziQ9znfEIH|9N>z z;QC7`zOd_6GdE9L{fk4Ne|}_c$L#mgub)-f|NZf&a+3J@|KDG=|2|hgQ)PYrxvKdp z`r78-pI!Yde)9bJ_`S8|pAEhqSoQryV%6_=7Y{$VeyZ*kFC<+e5+se%ATX(uXtFm% y%QUD)^z3wvIkEP~BDq?N#Fgo}nNeTY{N!ER!d}XEx8*;mZ18mTb6Mw<&;$T6FZ#j& 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..71ee9c5089187d1a90f35271f0bdf1ea783cfb58 GIT binary patch literal 2387 zcmd5;YdDna8vZm9gV78_m=2Vf8j4D*)^ZvjVj3f-hGjBB%#=$ti4|i$G9kM#GDD^q zhsr6FLu(TmGi#i3N=aE(D5ucwWNe49r^D{o{oi$$SO<}7nK9FBo7=H}*MVPO~yhC-o`Ad(KGqXa3zU@#>m zB@&6GqoV@=0186MQ64Y|hJX-;kRb)4$V&tQ@m2n>p(!9={#bzDId@kNfaaq__3*_Q_LW0{kY@APJ(0@vfJR^d9=1cQ` zK&)o66FE7pn$7p@%Iiz{H(uMkyus+Q^GPuBe7DrtVjgO(B-m3UuBF@D78v(@p1etW z)~JLFoZ4MAeRyd36j?DJKc}X)a|J_Qj1M&J4hWX`?qOIduc_*&UqmL{z537!*L|Qv z#?DanPJZ!mbmP%x4Qd29`!*o#c|Rhpg|Eu({-r;*uz3i^Wo{@Vx{}SRR_p_a4`H}e zjf=q(3Bk)-%bsZ77SH)^Of_7Y{U@TTLAf7E#_yMH)q3T?z5YO-1R(9f-@;Czt!eL6y zLm2at?R9o+%$JvdQ6I#S{3h5n11#&mPTc>z<<2gz%~c*FmAYkk{oK0xy%+O3%tO0_ z1AL2hlTAw~JGI~~V9jnn_?n}3he}aQpv>U$2UorG652()pdvImdD&N>eZB61&?T;| zUJai)nl2sdiB5U(ETO$aKgb_jh*b8A>k$ag5!Ncd(rWUx%zt>Ws+>UXunYQh;94=E z2W`rMWvFNfR44}rnq2~yc1fe3L6bM>mH>hC#!2P*mMQSc38x5g9o%m{MD;e(!OJ_-x=dU)^1I&0f~38#Bas*2V|5+wv|M zwxb^LyjETI9%0QaTxrc3Tv$`~sI@LV=7LDi#9~7#4d0?Gbho?TbnLa+du@g!zFu^h zWbvyJsx{!ZER>V^1yZ3lmfUI0{`-m-u?as%47%gj3lMrIYYLO@=qi$J^tor-;&vez zkeW)((?%7Xg3bEsr!LV#ZhJzk=-?Qo$febiJ%!d3=7oR`=m5BPA_opz>s%+C!_=Oy-$7YFI8 z0FAu5m7Y{apJ~#gyVP1nDHmNa*)|&vFRixvOw4lW7~3N%Ny*L@H(!gF`6E3k^pkKd z=2rqS+!%U-N;*ThE%96h~)Jdf1z z5(D>@*wM(2;)c58Ysw3*J$}@|h{&6Og83Vg!y`BMc^Fkroy@YJ3g*t9UW)uVcDO}} zIPM#CW63?X zVcmGCGPl*Wt{$dJTi5h7)T8ixK~@5rhgR`_kal{&af4Cpid*9C#J4_0$q)ELC)<~wy;h0TVm*$7DIFi(T^X3?B#$AbtZ1MwPoL4a>l{Efi&!-ug#7XQl zwzzX#Cq3G?E#!X8u6`xf$i(Dax$6Gpmn-x7tG8CSQtX{&_OfWPc>k>KImAiu=}(Cf z+nKQ`bt4#Wt{c9(bVAq#pPrw5cm8b_u*C#`OoTfWX6KFaSO_HTQ|E@Vclrbc zy_}J)u8kuLsZH^Us{c3SyP5Bn)_yal^35I!NA^F?wljwR%yqSNcvF~Br25BFfnr#y Rg7cSOg0q7wco$EN{}-k+1x)|| 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..d64f0952a0a07fceed4530db1072dc4d03bc074f GIT binary patch literal 1295 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 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..a960578fc59f89e2615b7120cbdd2a015f6bb5f0 GIT binary patch literal 1431 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfi$VW#l?l0nVFA|Pf1BBHa6DK&`?N7h>eXcH#avYC&%C4zoDU_zP?^YMh0lI zv$Hcn^C9ZrP1sNbRH|1JS6n_EmLVnYHam^>&1VjpZ$1(U4a zKz7v`kN_)071bEO%pmqzeOvL%7G!7aw9tsa+UAJ%DDz*JR+I);7ys5xI-46?`(p9C z4WIHhJX$9kcBf%#d7Ef?)uik=&q>V=0>escOUute!I7c;`CW&`>*`Yd>`lH z6narWY4x91v)M9cy*RF_icp;Gbl8^n^{#PehEQ(4GR#_j5eQ)g0 zqGSBvP*O&}bK1@oMMvIM@tl|tnyRp=%gnN8`}>(1o}2a+crP!Tq}w5KXweiE?PJYK znaOKQ=P)c;reo1z*Rry{tt@~&>+q!14+@&*#+&_dSY388>BYOO5}$xbf5@5huefYHw#dzH+wE zjNFuTe}lovZya}L_7;e^%~&IOULi8Iac&6b%(ti(t2A7*lC{RKuQzm#&Z=eel8xUyF-qlq8NuE&?4`ArA3XQqC1X=xi0tRLuerkHC+KW#nkL`WA5uHnqqXKxd7H{Rxn@u&h*0jWn6?<@ZGJ>wFR3p7Hlu6{WAZ4?e&;> zc0ui%Sq-&!-ej5fuUzEs+vAo7ky^SRn199WKDRx#^zhfCenPW!QkOm7lIwBOA*75wsCsXMP6i`v1HN;y^!efG{O-V)~eVz*;LT=Mhz9$K4A*w{{-Sj5TU zbVskly?;eV$A%380TU-|*wHaVBPK>_QK*wpx143i9GMsfA)Tl-3l@YYrzWbbG`k`z zp`dK-Al9F!A%C})Kck&5i-93gp<$y!g4476@|;}nw)<-@+>~;1lB)MKoybAQm;iAW n4k}x7b$-LYNX1t^tuxp+*gcb4kg(VTRML66`njxgN@xNA7GX<9 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/middle-on-text.png b/crates/resvg/tests-hinted/tests/text/text-anchor/middle-on-text.png new file mode 100644 index 0000000000000000000000000000000000000000..fbbcf7c2333c2ffaef9b896f134edd02307ad9a2 GIT binary patch literal 1459 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0_pnt`i6!EAcGiSWn~3a2GJ558!Ij@o|BW4o11HBXz1+h%*@Q}@9!@oBg4kV z#>dB}q@*MyB*eu9a+`~b3o+&c)!4n?yA((nmIV0)GbF?dC>XrIe<5JQ{QC9&3ns?T znO%H1D|2?o*V>)0udhG*u)jV3!TE&!6Fw9iXt4k9u<`J`l?)6lot`d^Ar-gYTnOZC zFc4tf(0np7;d#6)3#4d7y94e=Zst6rzPj7t^dwd9X*!Yrl|baC6h(Au zP3>f`f=wwWAu6fJsCpPNkv|P+?(3xMHdAE68#TNnr#$^|@7c+~$h?35pQ~L|RW`k{ zsZzW|>-&nQmo!cHF|T7tnEJG>p*~>RgyJgIy~C7&B(=X1AL@b@jcA+guJFhXRa@BV2 z{+#$GX-f)6bd`SnV&?Gd-;0+x%GhP7ifD*C&-gSUW$UqshU_T`!i#3}KbrRCr@r?L zX7#vxm)HBq?4I|nQlDGiD%G29)|#TXVoJyMEl3G{!W(p@wtQ)sn3D!ap?Y z-XAZ*4Q+Z=IuvESF3DW>~QJ(~OVuGO6hFYeva^6)BK z{MTk;o0CEB-B_j#J@5MOl)dS?lJW1Ld1Q(6`d!r)`!;BIr%hzky0p)t%+*4{cc-=7 zf9=^9#Uqc19sJ_WZqyMysmOHC+bGN^5tKw{9Vq*7|-HDlRzdfIwm4VTLfn_11=sWJeryH3V63h<$F~5CD zZ_Sr^rm*XEB9byOoO@#>NcngSs?DbD*|-(qH9e_hc0bmTeIit bp-*zlu4pfo*t>5XsPOZ2^>bP0l+XkK6a-a4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/on-the-first-tspan.png b/crates/resvg/tests-hinted/tests/text/text-anchor/on-the-first-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..a25e38ce0b7309f93cc333009b7c0611f39e78cb GIT binary patch literal 1377 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0_pnt`i6!EAOjcR#jg7UkvSMat77`Nj z_xIP-)HF0SbaZqCng%ozmuUpWcb^lN11d5s3GxeONQf5*cyBP_!~PBDueU!u{5o^} z&fykx6{2!L7`AU_wr+c6CE)OUl2+Ya*45wN{`r4>?^Hjo<9AOb$#+ihIT7d6@J;14 z@2RXX)|QvcEKly5Ds;j~VY++5s_5A1PamYtoN%MVV?*{6L6+_MVON@`Pn~>Hc*E|} zjU5k9XRXxFc@@7kcgwAiu$1V(#_K+=zxAhFV#~@J=bLS7R;{`e87+SxO#0=Gkg!=( z7Oh%!^FVy$(Vc623YWMoK4Qkwp~}U7S4fn>RmC=0B>aE#oeOVB1(x;1UQIa?D{^essw?Yuvt0MtTJEk@{h>QDR3g(bP5sk#cFBJ; zmuhi@_pUbkyINJ@%G~Ju1z)^M0_=C}RLMSmZu&;GMWvn}r4qBS$V zxc`sn^O`ml9XzqRzN$vmE$lG})vVm2C2QmA8K9`FT<6CaZRGS-SUr6%M|+ zI5F#1^2Dooz5n+GWf|>CV*XYYY5DNl)>*x8B!ByVS9`d=&N^$CO3t_WJJ)El>8)-v znEQtRwb%@Ypi^Hrsj#VODpWIxtChT*vm=Ueo3~T1W#K=g89r@4OVgkH+%tpu@=^8s z^J-&_Vrwp21;1_CH|HgDx2n$me-g4kY}$9O-t*spb=m#<{dV6jKd&j_*V*^s>GSs& zUw_bud>_{yzyJPTzUA2;mP?EM-|l?eg`vTL=Rn)^OLGtJx3Ul^N%mB683cI*d&U$4 s3jhEB 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..ef91276b6fe210db5dc91c1a6d08e88e5b72edc2 GIT binary patch literal 2436 zcmb7Gc{J2*8~#nhSVt%$OJ&KDnIV;wh(u$_mhERL(`3mmq-Zg+%{11SL6$@aWBHLS zSsT<$vJauWLW<;lN8UF{zNx;>d(L;>^PTT|&biP1T=#Q5&w2j1p8I;p)|NP=ptK+W z07z34qtgHY!+Z~ZIJaV1cmu~x0zoEDApju4_#QAST119hOtU^^XUxt2*MP&}A|fK< z;^MNhvI+_cnwpwMMn)(U%D})NGBT1#B<|h2S5i`vTle$xv$C@C_xBeR{C>CpWpKB1 z4+%N1vB+g>hMu;x1q?RziS791-&2CBr|t$?t&a9KRprFL?a0Y4dXnvP-FrIOttzsu zFaNjxeb#cKZuq#IQ-uJ)?`&#x-0sTw(yRFT0y9+iA7}0wpFDahugS)ku=Me-$VcAC z8PWF^-(HxRd#y7#mY)U z741s~I!^LFD)d(TL$#S_5%0lxeuFffERSM1a!IW5!h89i{@2J1V}6Uo)-kM%d9s0D zt}Z{od}Hm0%UcSF?6jC`JuDjq8gI)vP;&u;jWU}%C-t>vV`q`pX{UoU8tKH{BI7&w zvW0-1iv#1&Y9O=W3SDdhF4vju{xKTF@B#M?X90b zz1Dfy*JCHBUPhfyj|ltJss{v)}%EIVF!3Li2-_`&7gi5&z@0#-?-H$ z$(hWO#Om$dzH%-|8mztx;@QG8+LzN1=#{pywV`h4-25P!motJ_YMd2KG}1xj`T;4^o^UYyqAJt-FE*?l8rxWc z1B`P+Axo53hqf4|Rw9UI>}ZdZm}tl{Zo9Tt#f1aA-Pj%%LXE-GPZFn|d-0bv(%v~$ zJ%V3S^X)7PY94_>&2HeZ=OI?{mzCWGYoBC3=^aa&`nIC@I`Z@S)3< zMi!bTPuq-|3mX6}ZzKjd7QG}u<0f;C4_aH>cXSXSGjv=2lQ8W>KPf>PWn@I{M(Jb& zFMc$d%FEFiGIPt+mAbO+{qGf0kxj02)s)dW$@}#5@Qxy5QP z%J9v?(H6I#6@@~en~R~3NY3-dg&c_vGMi+y$4IAT()}JNn198xjuI5mJYj-j>B{M# zRDP@O3$zLYKNcKBq_m~+`HSEtX?pE<%G`ND)b$cVZL0aBmmlht-WKiG=uS`5j1DUW zrDy7!Y|eN0Z5s`CjQ73gdY}#?VcxmJs+=$S1>*SI*<%?zE$(=Crai0cc74Z_H)Y%I z)N$#&hCQNQqZh*&} z8L_obx~u(R_E;fDS+e-#*O`L!|8B0o-1(Pr|E;@>pdL hCqc?)MrvpiUi0~Y_p8#8$KO9RrpA^=m4^76{{mKOL#_Y- literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan.png b/crates/resvg/tests-hinted/tests/text/text-anchor/on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..4de5a06f1b6b732238385e7e6d2da29e0bf96cf0 GIT binary patch literal 2555 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-anchor/text-anchor-not-on-text-chunk.png b/crates/resvg/tests-hinted/tests/text/text-anchor/text-anchor-not-on-text-chunk.png new file mode 100644 index 0000000000000000000000000000000000000000..6940ad224a0c59e6eae17c25e8f70c9e4e244247 GIT binary patch literal 2030 zcmchYdoeacT5hd!;3RgW66-`{Kp7qu$lCoObUP>y8 z#As>6kXER8&K-%+Rzu4mimKKlQ#B*19vvM_I`ijUcdh<4XRUoc=j{F6Xa9G;*L;X> znlJ+x005dE?gU=|0AW6d8d#YjR%f{>p&su}P67aU&*uQK&~QU#lH+sI&sE7UTyQv? zKp=p@U>FRhqoadDp`cKxo}Qk$xjBVGK_Zc{v9VYz*4x|L#l?kAr!yD~r6xEy*viVv z-roKTr~D~X_9|Z>>xUwgciUuN;wivs2QOlnOe?y4?ko?E<*vOMXjqhRliDMTGV?fW zK{A`!aMSzD`O4RV_(J+~>S66O)WI3MNdSPhc@U2IU6}ZJ&=mwerVR+fO~au(6P_@+ ze+R+&$98A}u^m!mOrAuF)>*7m0J#K1ZVK~4Ybf_Vrs@BJ@<3VGg#1}P@rPQe`-=|T z;;ttKAGWf(Y9q*LsRKFo2}akuWqKRTkd_TfIXiV{hki-B{~9zef%84{A}4Zvl(jSz zp{{>5N08;3TvxxWR`1>N=wF{EsIJ~SrIGI+ch`aNc8_ey&wduhN(y-r3pYs=T*pmZeFbQwi+_;I5Ii^8&7WsIh=brydPgq@m^?}+;*Ma6Xy_R^So?46wlZFST*zOS(BIcz?*0P zj)sfsjJ!1tZRnub&U+m-O2V4px2Hn(tqhBOwZ`U7s)ylt7=hKLO}C-M57c;vIcn+w z#JWU>cHirlg-E{JH+xHTp*D=R6r(&S+N5*vz{DZE;nF!{>HCQUzh zU*i4#qlP6T{cj5d0be&C_v^80v9U1@e67fxmyCk>(3vfP-z5xYKell4b`JNLP0=3J zXt{$$uE<*CL)tz@`k`KCPnfxVbv|4>4PBpdsA&%@`i3_iLpFw?9o3>03C7?II*nv; zaMy~BS^#t#ASJaW)2yboPT1{=lgQdr{atEoHhO6b`zaBHMv!RG5J1vs%VMyc1~t$I z83xzg4>p#K>&`5P(+-KI8%xFgh7dF)TOx3N&2}ifhzwXfo&y$G=kbT-h*FoTz_@om zNt)~+>;(*`w*sCcOw`TI6cp2Goy=?SH6zm0l>?EpIKkP$wwkPe#%{vyG~hfRR#VGr zqdKK$?D}I`dsc-wM3qF)jhyjljW{sBm*iQ0dh4F{y4cz&c8oZFS-6(rX|k}CMO2*P z`MgZ?PKhE@quj(QwYRvTCesXQ$6*l$36q{kVvL?EVw#Sa;&#oXco;Njm2i3v2PR8* z>R#0t5~Py`hn<@r)p=nR%xo*cJ&a$*U25ci#e(l!oYIjc8{6eX*Tpr-N;yX;mtFHT zjqa-slR2d2^t{^zKmDIixWx@c=OlYL>GkUByQS9Z)>htFaBxV4d7>(hy=dd4$y+W= zNyWeXb%C7*OG)g=*!;M(lFV8ijg`kJ3Kb3iXlVa|{Hn6k+~UGTxZXEfEtb^C-`3-B z{k<-z&8MAa!1U3-$tvk?m5v4PpcxlJ-s}t+yD*kNT9(tIE?@r6jby6pM#448D5PQ~ zt=~7Vt)_D(_w)DaGt7oGVr~`)g1&~$8qwCC)|4qE{g&)m0u%-yKJ=wJTBE52aXmCxqV$NYc5H-#d!E$j1MHR%-@{wDo9CsR?S_Sq9X MT#1AS&eZJR0ThykZ2$lO literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-comma-separated.png b/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-inline-comma-separated.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee31339234bb304742e35c14c833a2383caedd2 GIT binary patch literal 2070 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-nested.png b/crates/resvg/tests-hinted/tests/text/text-decoration/all-types-nested.png new file mode 100644 index 0000000000000000000000000000000000000000..ee37fc81da7b30e9df04952e1c353b42889b9acb GIT binary patch literal 2225 zcmb_ddpMM78-FH^YH~^r=|fgVPAkfa98%5fIyLN^nn7z!Bhq0;4WZ2Y8XBj~Xq+}| z3L)plW^4M8kkeL@xQY&lRT@e;)EK^3+UxqhfA-oxzWchK`~Ds7=lS#bC3+KnP{wS; z005NTTyaDIP!>yPwF06L3V1&tV-3fZei8tc=B0zmFjx5(vf=FQNya1QQbB)p1jPI= zh5!u100s~QA#2CrV@IK*2wkc#xBMVKFW8F!5tc*<;9%TdXzwz%hwQCk>t$>TnI3=- z7{Z1KHG~Y2OYUK073x>0H{b5f>9AD5CH%e01iMMMuEeBy@rS!0FDC?48S1(SO72q zU;sb^fC_*&0ImSI0AL4z6#ymx7z1Dczy<)+09Xx>I+`1E2N`58kw9_*YH9{nyLP#F zdU^Z%GZ=?M*lZ4m8_k2@_yl39C@1eyQDs$Cb+x47c2iSx>%9k$9(6zJ>wEEhaCm5V zbYk-ThpCy_PcoTIJ}+OY`Nf5jCTB|k6mPoWc9SEXzU@UR#xiv84zjn!(yP4z>$m8(l{9;hR>__7N|Qp35M_q%#`%=(Sqqix@2nS~a6l z{Y&R#moOjgfpp39<&|Xv+5HEgH$Il~d;H^BX?;>_)aVJbO-Fn%hXvEVv_l)JCREBG zuIz+fiqhY_)T^e{>!V-na!_zR;GV}No!%YS?l)quUp-&MA6}M zQ6B=O42>j>!PTn0VpjZxR1PiCpin2|eZFQztfRJgNXXk`J;*E&u&zzGuElA_IR|5LaUT1u54HPvxvuAqJ9HBw zTi-CvdYlSaZrYE?21K=@JvGwoUxS{=vHO11>YqE3mW|Ff@?genQ8>@H($%k-Z!2YF zrn=Z%E2P$Dw(P9)Ml*HeY%F()Rqkqdw#TJ~9lqR@BGRmiuC~-g+gNT9W4H&WcV3;@ ziGNm&7pt$2vRAo-I@g(49-_h4)s!c08Ob>tv00w3{^{Ww-{c&-7RUB{laGzva)*!# z^Hy<>#lv4wrm~sfRr>ybfxt5IF=%C_A{bLuQmOp0(FIUX*qw1p}QxQuC!cKp0!i|=fe1l1}VQ9adZ zJ;|H?kawnKQwcFS+*xW?RH$Ne{ad+*J)86kfF`d#A&CB5#otJ}nG+aFx`SX0et` za+df|HEZsj)Ctc&zRkf)ob<~h8*-gH^qL<)IB7*Q)v3ZOyG&SF*@g zpB4y@{7Mx0T9c@ns0=SXrz6bSdL#O4QE8kWspGK&Bg$;sT(cb=SKL6JwC$nY>8VhJ zZ?u(C`I(>TTW^UzV_O0qd(zQCxEv={!Z5*fiYy`3#5DG7riZ?9CSoadZ{0OsmX*|c zcv`^H-ME|sbF2Saa=E)_S3MSEhCVQOolwR6&n$uOSZ@ofM*R7ZCHmK>! znYuptdJ#K56GqdfZ|~Y&3Q5Wo61+LdgPj{bZJ+k^&0g zJ1K$txp+v%rgne;p8xmGX~QM=MrP)Crw3AU0%r#5Cm)c|)r@^XXT$9Nm fPFZm{M%{J+jC%&;FO+<@V<{}%@C01t9tQtE0z$sB literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/indirect-with-multiple-colors.png b/crates/resvg/tests-hinted/tests/text/text-decoration/indirect-with-multiple-colors.png new file mode 100644 index 0000000000000000000000000000000000000000..456973b3c7b75fb664e201e0214158a4b415b783 GIT binary patch literal 2700 zcmb_eeK?c*8-JuuUXrOSIdwEj*kccaY95|K0_3u$>9J5*Gxl9*Mb z(uNSjhD<4B@{+fykyGBzqjUcGUBBO7zw6xB{r%qG>;8P6&-1yS=a2iFigi3JC!;I_ z0DzpGtu+n+BoJ#$N)qfi-XR|bi!{j=e+B?Hzgk-oH2CIU0brde_J}J61i@HY0V+@^ z@NgG}T3rQ-wY0#!1Oe)-L3iPBa0jzkQxj|suoOTvAt8aGr4=6^50X%mh*l60&U|OQ31!~f;SP;s=V%sS@ zK+QY{2T&8#0kfw^6HK~|4M-@kv;_IrO-)*mlq{&8XMn5A{j{J;lp|H=o#$y7HzquuRk{@D;CSHnL!}_hKkWTAUgF%s>)Th1dRrr zgRh?Ilm<0H!s4RjBu}OUi3Ia=o6Ivu=bEF~a^r*db#(5bbvS|Qk1>azSlc|dwy7{N ztvF~>s;5_~t9M^lw^T>>o{sLCC6V6pl#XZt_%V)H<^IP(u-CcU42BBvGTPr25Anc5ql+)KXHm7~}db-pVqwmw}kJ3EB* z6lgnd))sQQjYw+t4{GuYyd9@lhxe?*pLp)Gn?$-69-fgEsc2CIJjc2`cfwWK*gdha zWty5XP0UL5^uf<=VZk;x=Ku+7KN(yyqOQCV zeSBis5Vti|f}grUl2XOjn%J}0d_U<1U}gQ@!|_ZzVz{$X1^Wft^9y+MQPaD=N7@m7<&6%^2u$!5$y4!c*))Qnl<{e zL)tbQxSP%54rFOsBdq!yW9$VJjxQ|jiXVk=T!>0E4C6-2HosCSHRg-g1uScmN@@k{ zw6y5QSl;p0))V~Zz_i)6u(~^}ripn*J+NgvPI2!R{H0`#d#BkcLS~Vv7BOlcWrK@1 z|K!{?0W00ct7c9D3agsY&NlGhJJe~^yMNH6l}er)CnA@`1GJo7=0r&&l?ycy!xyi8 z{@6DScZpjWKNu=>zefGQZdrXn7JWQFdSp~>;Y?PUTXi8cO{Ltd=+;5^>5@3o6ZV|| z)8*$_eedNY3b`g2HKMXPdw!N@<$U2uGUYd~CwZ(!Usk#CuZLSEdJFk;Lg*OAhjbceMD6JEJ6F!D zm%nW#g5aT{CfY7B9)kMeCbgog57GWtH*Q7FGZE7CUu+EnhLq(W6mc0hX$J6ky#J6v zAlWhRXstT;E$*cEjp{N$Nj~%Z942t2HCUb-OZA0$;~$_tQ#(SDlwbV6_b0J3`lTb1 zc^GIvv5{eE^+j4L#!Z0W?8tuaI_M$ATJjM#D8k)@g5;W3gp&8#pQuu~KsIyK^Qbh**1(i10i(N0dQ9LEw3Ii1& zS0x#__kbsV@=~fuWnIT9vq^o@*;;e?jiVh#PQSgBGtRnx<}#(ADNu;r9w$)SztY_R za2mD)KFgo#YJ407*n?$8%zQmUD~nM0^?(RE_bZ_WbBrA=+w>T-S6`nLz*nzd4O(0=Vmegb30Qu6OvB6T;jLS- z*ieNidRcS4Vp{%#Q2jSDZP3z&fc_Yq#>?6tTjks=yP&%|vJCv)>fVw*ZdLxhS}!C! zVbJ)`3j*_LzK#M1y=gsD#e|mlT|DIpi5s{**M|N1!jzXhMEf`0y)a{p1vs{a{> ii;8cv-Bka`p{tA$2ub@c`=G%K0APo4v@W;uN&E|3=pp6+ 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..603eb3025971fa3fddf66f191a0398a14bf38efc GIT binary patch literal 1481 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDj z1AIbUfpmR+eM3V7kbws%DJi+QxbX4u$;iksGc$8>amB{Q0(BW08VU&s<>uzHv9STo z0Se+V1dr6>#4~%7{ z+8Pd#1uKP0QAH%oZRH+&ko~nTE{9f$ns;1%z9+HU_{pAsHzLko?+(@XR+sHFJ+$gO z@9H}u8&2_Vc(wPS*7lU^eUqeH6Ac)$k0msGVapX}GBXqWZhv1d**A5A=FRZz|I4rF z*8N};J^6&WHDTuaR0)Chhp%tH+4!p9ZN;wa^-NcLJg*6Dyk_ktX`iI?;&2vsyT+x9 zx1TR{6lq+VUvXlMvX1OEsj1nk1pa=zseJ0dD=D8#B|WU7;z_%fGkZqdpK*5X#sjHb z6T2=*c}B=Nuc`h~8oSro>vY7iWvw2r5f?uv-ks#LV3m$eui`m|qdp;>ZPD#!nl85r zn=D$l^IdVjrI&l8FhNJ*z_*ANFQIAYx3PwF&DwaSIKIO)UY*Um(D0~X;!nqji+qpY zEtgVBEZy;R<%0?CJNh}a_f5Cba@yr5bnQrP>bv*1IlR9zUND%$<{8m7ee?bgEu!}3 z?6-P*o+gwgN?y9~U**`Nc1Ks&8_ha8^1M1bpD#?-iOX@jleE=f4X6L)!$xA3q8x{d z#3RniaqqejD0Pij-znnd+Kj0dI)B1-QY%mGJM^pHG`VA1*VhRD;v=gj8lBcYoPMC{ z_glYi`<0H*E??N&y;SPS7Nd=M?~{5H#qHJ#-Z;3pihuQ@i4&?WJ4%EdJ$*ewO(gMu zail6|H~-Id8+SBcwNc4(jIepXLR&{KQl7WdJTgL-GbZ`vU5^|8%GSh8t!3+fEh@G@ zhyeA}1-qj^xy2`3ZJ+ISGe-G+#>N1htCO$IiYvZ;eEJ%_%xA~%{G6dL!oB6_ z1V`s7*RS{N5E9$^E+drdvSXS|)Ttv~{9m5^{`711`KNXd#EwZB3-gI4C0|MuE{wB_ zU*DfPhwE_DsU)+W(A4;&+h&-3lKWn`G_mnr{c)p^mgn(lk8Qk;GleGW?d6QvzIor{ znU)+StjU2PS0CG*j|zVMz@LA^wL6Xpzn9lmd#sV*VK9iuNmk!l`TzCRcbg6G>-nig z{Y|(3wrNfNwR1w(yG&^LnhM^ZEQu*YEo>gTLQUtBjxa$1*}FUB7s< zMb9#erz9=H&f8ef4-%#7w#Eyxd}IUVb)j0q0Pv zWJ9XtYaviRKG>uRCRx294g-}ZTc1D*l{Jfh3tqY?eXZkVVfz2VBU}FSB-`tEJJ;Mh Q3@Q>mUHx3vIVCg!0104Vd;kCd 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..8717688c2e600988ab7a3f070a95b74643acab0d GIT binary patch literal 2153 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 Q3@Q>mUHx3vIVCg!0104Vd;kCd 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..2fcfff11ede2d1412cb88173dec7b2a2b1ebd57f GIT binary patch literal 2108 zcmd6oc|6;B8ppp;l(-@qw>Ayx%9;|!O(fJ&Qb!!=imTM9x`r-YnuK+w>PXbp)}Yo^ zw2>}TjA&P@!I*7pq*dzf)VgJ=t*hpzX8zmP?!WuIUf<_=KcDCGJ^uSLJxES6a8)<} zK*q({!3zKwc7I76f)r8>%?T=!an6(k0AwHUFIcgGtQzEy_i!USLc{%_|B)d``-35% z0|tWu7=TWvLmbVBzDU0awfpg9O8`CK4C4%mPTCjgfJi4EfCb&ch+%ZVdUQQ1gNk8b zpcX^NKsI%{`oTzvp#-h~kP46tMM7!4DKghN3u4{6K`1L-a$U zG*NIFfOr5x0PHdhVpuW^Bm)o!V39Bo3HHrjTJQ}3!2tLJ-~oU$0C)h*0XPYOE&yl% zlmS2hAOWD5Oe!ydiff`5$r}$42=qxiJNy}sprGL3$P2NtadC-PXmmzSK_UBQWmVnX zd-ph;&Yp+8y^n|f^=$aX@XN{R*_qj2R#w-AA2zqQw|94Tq1b7utc0!+PjPXuCnvvN z5vEi5R!dXwwT5aE;r^W9 zN9kfw0Z@`s#QGm(j_5vff+eBsr1QmbApGw7UrN(2!4(sJg5lvS9hLmwDN1skQ7 zFQf$=j&<)+g)LbyJV@+lmh}<;FUKz0oa2;S+1&}BecUFMF|6Yd_H3;v9bM6SGDA0zvCvuihF zxLW0C`lqy=!5dZW$HLae-W#%?SS5<&pKc=~LbHUt*zCosri^A3cWNL>Bj4chC^^@! zH(EG{KVtvNHli9kIGua9JkbgXiCD*PG4B{wui0#{8j6IMh-4%yZhRx9(pla_G#oFWsqaod%P$dqlp zxJPXj6lXSvy?OtQf_=`v?1`ki)<#?_yNAboS^NlJBmpnUG6P7onO}*W&i$oQT z5OFCUio&Gp8JsNjKuOBfI1;y`85ZgOm8BQek(FGnL}vSF-qJf}jg88(T<1w!DIP1Y zV>e?i8OaP;Yc(~f^|SP^I$SFX-)JZ^qXa976}UX<3h#HiqlnMD(kQ2 zwj*zwneMAZ-w)2kz4?XTn(~Y+P?1;o6sk8G-z(`$l*a)1w z;PGQ|p4IEZHcalL7@6~}KSqa>>K)U^`651@^M@ZMXpo+6tSR>skorLu+*aEY%+yy3 z58f;)ZEmtNyDoO)F)Y+%wMD4P;N3(_`_%xg6KA;iY0Yw~9e?VqJ0IEDrCqDk)onm_PlndnPC` zB75^A9q~?Qb)(3>Hzz0SKCyXD|um;9?7X3NBGDUD{~Vbu ziv^4{G()36WNlmS&z6s1nPC}xw)W`~EQK4^|NjPrgJ=E6GUE*mQ*@UGZ(n!Q9TJ-$ VqYbts#vArOITuHg!(Bpf`fpW$eAEB{ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-1.png b/crates/resvg/tests-hinted/tests/text/text-decoration/style-resolving-1.png new file mode 100644 index 0000000000000000000000000000000000000000..611f028024d9c383b759528f2839ab3fd6c1eea6 GIT binary patch literal 2313 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 w3;+A$JsG}6;3e#ewWYl=K0B==B1@! zpaB5TqIi=708k+*ZH20Wp_QESQiPRycia4QA~ z0-$ElA_dcP!2KeKs{=iM05puQmVli50L=x`X%Jow=w(1F9TfKflU(qf02pNh;~c=M z0X78y#Q}H-?+JNgVeH|0K!@py5ts}BV4%%aPE+G3y&kL=289v$z*?XZ1H}*_B061V z9kdR`1}oX>PLNZL1dw5}qDqaey159bz`z!^-E>~jL`93EL4#;G7`L2*+6C_-!bH7H zaN{XZg#m!ThM$4U1#k#Hq^woUQjmY?#zGKSuEcm4ukaUplvvRju)&4`C0>=T^xx!w zWlJS&L`VB3Hl#g(~Blnv4g?NenWL#I+r6O+@4eF3UxW@A(M#^DHuV4w1h(HTvaR zpBx#YBC`GWTP1x`1c|H8LBeHpq*~S^ABNnDFUo3Ovlft#eUCr+n;hQIk_%%H#2pD| z>2gPL0H{M0@()2rpH1~Tsa|a_rmoTzI3)3 zQccDdMm+ztIW48Ksk_BV`r0nJp5-^!VlXNsG1WiAwgod#*TjBY0<&n0!{SywOrU8W?EEVmS|6Tey4gPsdvZ5%T!V>LUd{Iv zt0o5b;QE~{n1akJ{EWO*p98Z=kc3&-^dv2K!z&%=WPpxmL_i*zMYF)0Mf~|i^P6?d zLxeH{M(sCZ*L~s968$6CGkpJtn%PyO>Sle3cRMHTMYk*oVw%fZgLU5bP!AOEi+&l> zo{lvR7`Q6%9(ba9a)c1U8&xASBo7^R4$T?TD;!+}q~T?2KK1);!37_j;Se%~y&(9$ zu#ezjhYX9tT+FXw$0{E zYp8JsMW>V7LRzQ9kDq3-&I6{D8=X3%W1{)Jf|@w3n`^7Kmg-gP z>X0+~@y4UZ=ce50JMwwMzF`NE?vKUvCSJJD^5Zv4=g@l^=%s(3|6BTaP~c%)OX`s&mHO!qR+IN{M_{X=-ZV~OoTCX*RULkjEm3CcyInhmXDXVGSkIQ)tGX>_5?jg*8mW~ND>G5I=%Mc`ev*DU9aa9_4i)I*3+o1+-+Sw=0d6uH z?okL;9A_v@>3UMK8I*Ne26M1RNp-tQ=QqBMkQ57@udaDEwWqhst>bA?ytdFFmly3V z2ozO!2r3%i`6RMBss`f27JhF095bfFBpXh4n_nPC-rJUU=aD({Sbh74-#^#He6k9+ z(&Q7pQ%p1Uha(DC+xB4yevQ2NsO_sK7Dv|mOqK+8JU3mL(CNH=FkCnmT8m0}-Eryh zF8MXK^YsH>RqnSsP;Q-gXFdN$<7kc1d3-0oR3@stz0cq2S7XwMY*16iz}cp-+h>wJ zs95yN>e61zED}?4X7h*|L)%`G>AuDN$K;etz3&mT$+yyo7g4T>E#T9IG8quDyS= VE>>+G+Y}!nplqd)uX(UI{{*3F?cM+Y 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..be82a695608582b392b13b9ccb2bfae8eb6ff7c0 GIT binary patch literal 2112 zcmbVNc{J2}A08snWxC1|#-Ju)$WoS+A)~ow8hdkpmNG-OY()yi2&tJYaT!7pms<>G zvMbwI;vHS0#=fSq)i7jd-qF4N@!s>k_uTV-&-pCp`8?0(ug`P7Br6M)sECXR2m}%} z{|RXW0`b9jV$UufVv!q;;uYa5KiLO@Kw`~1!Iz>YCd&i8tj^h)@ha~{L_`pY#6SAK z$x2E}78Vx&ko=cDZ1|UX9(3rMjfE|U=!{pm!q)7<*LP<5CzOO|WLi3BmyFRyt>zyz zMC?Owjbl8xk|2{CsKi8GhTA`X@YljR&fFpJMt?B>Nke^6Yv|;+{}V%BqlTaF`oOSntd>GM zYK54{j_iap#7WCo_wJleT$OTfqs`XeD3k81h-0bAhVqiM2tlgRc!3;kO0W63pQAY@ zZ_phf>%A&Uk96V~PP+p8Y27dQ)C|lT(8U6{P-Q%91^p1;o|@xJ8d%=AKjeZfd;9rf zc?GyYRB)csh8J2OM8~}VyBr|vLNN;8(X~(1Qmw@A0KP8OCPgDt>po% znaTN57n1hLd$+La0gTWmo}VNzQ*8>Ieev4LaMOgdVOqZ%L+I_n>(RIH@^Ro+dfn8#qrk;TeZAXE4lywoX zTmxxtCtf%LEPJKtn`5L}ImKPR+s8?nG@0}l4hwJZd{k}ajAG*SqJPeiz*z>mv)N#I zN)a?7;Et`5GJF;x7sAk_aI5<{@A~wi)EEjBE;DThmTL;0sdc2oPtk3Msv zYxq@qP)Sve;jY19co^}8PFFp)pRjOQRf35t)14#*p<8A=+Yv?Weu9>|qJ_W0n!I~- zb*M>D3r3QJzwnxyoqO~L2nR-35Wy8?AX7vs^`mrQAm(n@;Niy{#${kE3|`(ZF6IwW zOMPV&rMx0W;ik;kK*NUHmV}x)l*yD(A@9)8o<6OL2fdqPCUl?I4&%08sE_L}y=!!- zyZ(L> z_fme)%Rp96eA?P}xVF_uLmJo|h8D(#OBh;JJCK1_E<(4PQdsM`gsa`sMJOeiAb%N^Du1H( zV+n%o+c((I{F3sktB~oEy+8v$@1W1$azKP1fTFk8fhFc7@4nB`yPFX6-)4evJl~(R z|7^oH(zn+)278wjsffD#`t9xa-VEvRZ)|5M&m{j#_usdDLn*nx4lR6>eii;%P!d(I zNC_H5JE#upZuA39iR^ez|NrT(8(-8e+oN71q$I2*ff=ObaPr+e&u5{tIPI9DU}}C& zc7Z(|c@ToE%a=4D)LNA-l3~~M?`>l@IgQ#&o^PezXX>O^5n7U5_3sU4teWdd%^82D z(+>1_s_6GG9!9s4N3s)2`aA+Mtcef<-SIP-0}>d`vH4Tcy2|iUv$5a<@5pW?gC?1q zy>5|iTLcmRhaJF(M9u50{2$oMvLixsX96W$*VuWjvW&vlB89&hl&-7@ftf6@aWz9F zaX;lNH2xGpn#mpVS-b3$3C5XXlwv7IS_f`PC!dNgZ`;e98yT@#)G?Ao071v~3OZ<^ z1IHp^CiUFz0K^+!y zNWEU`r4cQue)!^=c_lj)SNxMc|81bp6zGT6+E} z%S|CB7ajC0q0aBp`g_6}hJ&t+I&r$zYfjp+%{zQP8>nzEnpe4j>vVoTgV!2u`TbRg z2|Ze7+PW~hcWWcAO-u6FuveMlxkE~WPbSiU?b{=torbv69#{Rm{90y|4CUmT(J>j= z9LI&laH4w6HXg{4Q%OoVf3}_sIqK9VJCL6c1GC%GrA#UgZFTxwOwDx_HngTX7||?l z&c=IBDp*0K@0Yq^2aA81$cySf-4H;JY8Xd*Z@r=Ed&RO2{TNrH7k6N&5^=DTOjDVe zI&!+FcR+tLeyR7*!&fybf+EOZ7%>dK?iSF%kMjed;H;Rx_Y~jW@9wzs-9Tr)D-?Hp s=q&f$S;uZ9cQGUHhzBxGCZ}yd{TuGnLqzt}?flK=W){feGx*4V1D$WVKL7v# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/tspan-decoration.png b/crates/resvg/tests-hinted/tests/text/text-decoration/tspan-decoration.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3ca418429ce10e08935eb93de0b09f1f8ac9cd GIT binary patch literal 6465 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-dy-list-1.png b/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-dy-list-1.png new file mode 100644 index 0000000000000000000000000000000000000000..417be1a2b72d586ef5815d4242e42e1e35acc36d GIT binary patch literal 1532 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-3.png b/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-3.png new file mode 100644 index 0000000000000000000000000000000000000000..177303e22ade42e67883991c59375e3b5b648016 GIT binary patch literal 2130 zcmb_ddo-~P^b_C9B?v(8!PiYEc5 z0N)1(fj|m)H!KkZ0s}iP2azg-d#N~SkdJXA$ALh|r#lWVFhHtF#k-y!J}%OjmX^j~ zFr?%!O;%P`TU$FSDhdvVM@B{}DJdb5NM~nfQ&Uqc7OSqV9uN?4=$k>IP!tL!9a>pg z+1S`fs|W-F1Oh>$(SNziza@-0-?WlShtCrU-k?B=iRZPU;WT~>xBUcTt~Pus;`w-H z38yvg!Tq(FM?JZ`)RoS_=-RS(y!pw6+mr))9kw0)nOz$o5KI}5J?fMAS~A?llraH; zc(!kv`5Ldk;yMF1JM$Dj9l3chXcY~)GOb^&^quDft*d?4(|3J&823Ve-1{HGoP*BJ zbUp3azY_kxM0hi#0Fm8VgQW%!hld8+7a?q){6N>At4p@>suYISe>7kt8eLBbHAXSE zvv+EmkZdaJy{mg|a~ZrPg8XFr-rJz!(zA7(X`j$YOR)~k48J%*2Yjp*@*6uIkn?~(^P z>xccAk_+?CeK*JMEXBBqNDj&>Z+mvFCF@ze`F*Qdv_LMnKoU88x(zqjB$I*)dbl6a z!agclGe7mzKb-B;i> z_QQx%m`QRR20wG=QVMP*adf2Mt4=qBR(@O=yjXL?nV6TF%Z_JX(1q7wnQw zdY0&F36NdRvJtuNaks*V9itg8hrb`!%kR|ouT0Pa$Za`Erm9=P=4uSpA#nz@+nisI zUHy{%=yN|sSKp?4b|2y`k7fsG9j=vP>Yh1a((m@b@n%;$ zwDIY>7QMR}x;Ua7qW12h`5=(7VwRpAhv;u2_HL6%C)%(QocF@SQiWtiVx73r6D?T@ z+E^BD7fmkPuKsdyd+Hhbk1UE|yJK|Xu<_c5mFMe*qOHc=E3@-D;-U`5K6EfsHe+jK zE_6s_=ZvqZ|{Uf+1vMCWlKK6a)>ppt$Pjnu+>)93-H@t z%iHLZbe#m0X%uVDZf^7M$Z9L@*%tvaY1XsK{z_t)tfE{*W=pbDzQmTAp5 zMhobcc;)+DwDr%{I6?TkScQ=U5lG{be9Cd2&H1HsGjhU+b7ZF$LbF;iPJj6%Uw}Tv zPG8;)0W@&iF7dZ{^5-_nc zNf$e{%Phz9^D0^PwAD<0UcjEVd6kOjF}}doTcSndRm%g5jp~eI#OQbkdDz+U9mGGI z0*&t6>pHTh(#QG>;;UY%wYCR@v;cE^Er#Wb*_cnMw2&MSX$|HUA{@Fw#TU87;eM@N z(E> znHoUiQ94+dZwPhY;ZQ{3H$(wD90f?<)DH4?eM5@;4ySY|{V#>C$z-iBtzQNIbrJiT iR}so+_vaD8Ka({%f$`?dsZH?Cr;B$XU>`YASbqWpG@k|l literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-4.png b/crates/resvg/tests-hinted/tests/text/text-decoration/underline-with-rotate-list-4.png new file mode 100644 index 0000000000000000000000000000000000000000..3fdac88765ab5b3910e960a511121b84675cded0 GIT binary patch literal 7987 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 Y!o_(@!rNI@$HvC``S~?8G}PDE z^YQUHJ3G6$xDaCtL`(gr{{cYNh9yCM!3+-n?dux~-hT+#us&fyeE$ajuO;grPFi+0 z^Yzl=y4iECceKyX-~ZtJ1%vw&6a)^$C$LD(JH^1j^2pQ0F{I+wo7?S0ODqH$5?A_4 zO#1xv_8wu!8}I)YiB}16Y}jh~;s5S!+7@-KE7(kq#j?1ai{R{8vvE=cmqwsYwuS5kn{xkLT=Rc*oC>|dda{_=)x-})y$XOGmye@xjOkJR?P@ZZ3;x*(bD=%Pl`h}N%D7VTkp zJtyPl6PJ%{I{&Ab-d&&Y^Z5Ca>(7*#xYwx2aIg8%yz#)M;Jtf|4EPA>uUQg-U^P@rQvK0S*+O*$ZTU__E_(J2qPtuQH z+O#7pdhV=STHBfzUa92XC?~JJNiu=e=fk$`0&kBjh-$oQJ8jcBr5MY{TbaF!XMc8D zqwe;7ZNt^66CQ2hNPaBde0BMROSfZgX8tWsy7}VgyZ8UAuk+~jUP{U;**|5zu=cbA zYcB3;{`2GO=G}KrDp&{W?Ju9MCa=HmvU}g|tNr`!f9(}~d-k#VH{%$O<;T4brIfTipK~>{ zR!-{H;nyn;&N|R#-5zXw=O*j5C(2h-D%`o(oOEBc^F7nGgcAQf-ACp!XE#jceRn$L zUUK+`Jr`>qp7{b~@afjhIG22VSvzakrP!8#PBBeakKS7LxIg6cy*~`ow#_pr(0=c> zfK_|my@uC!Iap4g`l0m2+^AVp4wwPI#wM61)H*Cu-F#GQ@q}4=VK&ig!kjkU6&HWw z+t}9R3xf>i1*TJ@S*sXNub;Y72Pklq^WW!h`PL;qEDRjXj6HH;yRPlGeHZY- zd%KHM%E?Kp-qUmx}^fK{wwbVdu^AwD+N9?G(~Ye+!Ojq0#vYiy85}S Ib4q9e0C2ylw*UYD 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..22f07ffd313a7c2ce0db5a151cdb4e81e20daeeb GIT binary patch literal 2120 zcmcIlc{tSj8vhO*Wz>W+cE*-4mN|13y0Y)gP|akNW1CTg#*$_dAt5p% zEr%gXma>*5TL~R=vK6kiJ95t-_qqSw=ic{u-uL~ypZD{ApYLDq8*h)ZH~^P`0{{+K zS(=^#0EXW2eY{)-R}f{vP5e|#QXl|`rX7bd)ew?g#bJBfGiKc8jzND#F1Y#^<^l-N zXf!|r5Cn0tFU{8n^5K>{_G9EcbRJK`;~?A)2?0}@sR?AVi*+Gg3=Ol3RUj2-nzKAj zo?FU8@?519B(>WTrHO(_03v`eP5578nhJ;lToOS;>@ZOP9tGcJkTfJ;6yGk%Wq2Xp zJyCl=C;k-B>;v1=m4Mvz)=8D z0Eht~2*5tTwM+3;rrcx`bP9Lc5C{sQve(+}HoflZ?(6Lv82>Q&adLWYesO7KZDV6&YjcZhoA)~j4FK?6vobY0 z6Egf~_dOwFBSFK;);vS4T8`hwJa4@7_jKXjP)&dD%;M>m##`QDm8obFi`*7QL~u-PdIV*sk@-XSzXgy%@S9p)U&;NGqS93QF;e)5-o@Di&ye1%qH~s2WXUn>cFWM5 z!4_J>`u4a-f{XaxONzgwJI7CrL&d@)TW>19Sq69%DP}3LV{SzYd}8fc2!X#i|85|I zV0(JxDLNmnIv1UgdwmG>dO2|F*ky>IFksC6yzJ6WYz+70q0}a9{x@;&?R(PY*Xocg32GZ*BAmx1LGq1A&TOT9CWpT$Ub^@ehD0D4Zi_1>cV&57A~`oQj5EwWUnLsT2m24FtCM=@pYEO= z7YS~EZhp{1MjxwaQ!AznPfO5p$dNwrUbjOEeKFzZ!Csfx{>~mn5)bdTx7;Zqz8Pg( zS(1n?QBlwiUCcCNIX;nnWt^0l+VY12XMvI6rA=kYs0R%)Ss$wpwp8P>68GcFc=R2& z{PKUt5q=#zLQ*>vrmN8?ccaggs9knkR%E#;eaTa9%(A`^WuQk%(`i+mRZJ}D=CxUw zZ?7(w>R@oDr79lmQ+dWwup!>ts_Ly*Xg=dka!6gJN+CbEcMtViWsdwdaS+=UzMy8G zLQ%iA8J9pMV;+(TCQ1SuAqpb_vLJa!th*h$_umMK) zgfp(Y#=iBf;BpXa&|k;nr$wWfWL8oTOX4w7FT0~pLi*5)$ZTt3OdT1X^y!ELmW1{8 zeA1r3i92V^G8g|vfMnXm#74kL)2=ek4~}`Ihj@wvF(|aTjFih+gl2N6#!K9kiRY|h zX`G6k$=mm25%m*wrwZ-z^^(c2?K^YO`8JX=dz+V8{c40^#gfV43x@;LhB64vN#%HT zZSBhY^H#(qYXTd0G+_DQO$oE>1{55!r!alll`e4(Q#}d->Ckoihyf9X%7r*GtT@tn4yfwrZmTg6HPd?ZK3Yl={pvi(g@)-U|dRSsy+-Q2z&DTl8!Su^Xx^T-tAuzl_8vwAn?j ztT;X7?YU6D95DZ$!qKdk78?Ij95+Y*6aV+Mx@Ggnzk7YrA6g6ewl==Hc1QIUWr~$h z7(Ti7wRdzdge2{Q$kpWZjth?LMRiO|My~>LWX*AU;_EC*(AQ8ej@wCz>dV-x&{^G*^*yDRzsv3dWSm&?MrQ^vc$`S%o-xO*I`Wn=V784Uiy ZHP}~stx->(&--_-os}8RwA|P=`kyCgsfYjo 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..6debe9390282bb2b6c4170eb851c0b096d7e8e95 GIT binary patch literal 1129 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 VAGTx6Ope>tQ6hnaZ*-!h{0sk*m6rej literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/hinting-comparison.png b/crates/resvg/tests-hinted/tests/text/text-rendering/hinting-comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..4c9bcb1bf672f382ff8358fcbdebfd55c1787e9e GIT binary patch literal 5931 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 oEoOeI7$dCIC(s?o;6CQ}hW5Nv&xH$}-aIsgCw literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/on-tspan.png b/crates/resvg/tests-hinted/tests/text/text-rendering/on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..fbbcf7c2333c2ffaef9b896f134edd02307ad9a2 GIT binary patch literal 1459 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0_pnt`i6!EAcGiSWn~3a2GJ558!Ij@o|BW4o11HBXz1+h%*@Q}@9!@oBg4kV z#>dB}q@*MyB*eu9a+`~b3o+&c)!4n?yA((nmIV0)GbF?dC>XrIe<5JQ{QC9&3ns?T znO%H1D|2?o*V>)0udhG*u)jV3!TE&!6Fw9iXt4k9u<`J`l?)6lot`d^Ar-gYTnOZC zFc4tf(0np7;d#6)3#4d7y94e=Zst6rzPj7t^dwd9X*!Yrl|baC6h(Au zP3>f`f=wwWAu6fJsCpPNkv|P+?(3xMHdAE68#TNnr#$^|@7c+~$h?35pQ~L|RW`k{ zsZzW|>-&nQmo!cHF|T7tnEJG>p*~>RgyJgIy~C7&B(=X1AL@b@jcA+guJFhXRa@BV2 z{+#$GX-f)6bd`SnV&?Gd-;0+x%GhP7ifD*C&-gSUW$UqshU_T`!i#3}KbrRCr@r?L zX7#vxm)HBq?4I|nQlDGiD%G29)|#TXVoJyMEl3G{!W(p@wtQ)sn3D!ap?Y z-XAZ*4Q+Z=IuvESF3DW>~QJ(~OVuGO6hFYeva^6)BK z{MTk;o0CEB-B_j#J@5MOl)dS?lJW1Ld1Q(6`d!r)`!;BIr%hzky0p)t%+*4{cc-=7 zf9=^9#Uqc19sJ_WZqyMysmOHC+bGN^5tKw{9Vq*7|-HDlRzdfIwm4VTLfn_11=sWJeryH3V63h<$F~5CD zZ_Sr^rm*XEB9byOoO@#>NcngSs?DbD*|-(qH9e_hc0bmTeIit bp-*zlu4pfo*t>5XsPOZ2^>bP0l+XkK6a-a4 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text-rendering/optimizeLegibility.png b/crates/resvg/tests-hinted/tests/text/text-rendering/optimizeLegibility.png new file mode 100644 index 0000000000000000000000000000000000000000..4a2f4032dd37a0fbf7169d241b3ca57d3e72ece5 GIT binary patch literal 1557 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0%@$Ep`igNUSD4iBy)3fb8>PZ%3@<<{r&wRY!??7XJ=<1+seucNCLGO8X7{h z0J%y^N)Tl-GBOZ`xVX5GkPw8;$Hxa`aB+d0&Bn$C5oBftxjD&L1mtFek|4ie2L=HJ z1AG5~`1pi`%&h!^;@bL#_KyCE6K2nzGk?MQ^&58XKXCZ$`3u+YKYZ}|{fDn&W(_MD z7+BtTx;TbZ+hT4`pYZgX{DF8 zSUlIc^yR~vlh4y)^`5VJbJJ8_bbF!%Uv$yBy@J?U+xquGh0Lb zZXJy~r&=~~ipD?u%M@yEpc~mGBg?cn^7{JoNnIDa)N-Egz0}M1;@h{?lN{<M=9j zSUaoW$efg|2O|ztPibS#eJ}k{>Gh=POAj|r)?fc5Ty1--Dv*1W-}ca~IJMR1cDK&k zsiz&uyx%d~>t^Z;(?t(o%$urn)-UP$^v11anTNQFCLQ(9briZaIcguLc_Mq|$yYyD zs)j9Dp?bpqPRop?Ybm%G5QF z5+f}>@9<7n=f3-DHrJ<5p`8qA9flJ!rOjshmup33Y?_=ZKRNVF$>Ii`;;{Xp*B)Hb zNWX03{BlpA*zz^29xRzUQ^)X^@TMoWzmDEA)Q{YA=SXTNXy`EIuDP*0K6+$WtTb4@E`;?x(Fmh4Y@b7QLJ%|Du!kx2{8 z_spAj&+IMkou?;w9dU~lS8cLnc9yM zKZ`VuMxENkV9oWhxbxk^H7nQ3uq4gjpyL+)dV6-xzJd}9_xZbdTw7253y(Zsf1dll z{aed(`JAUTvoc;Vi!$EY$^HhIsXLms_TISmcfI)SXK#}4`mBl9ekwe1`|{-lTmJq` z_@463B=zUH>q3j?^Dgt=dd>fd@O}T+Im&CMAJ&nnwLG(D;ho*@6Aw1Aa*OFiC`oKc zICyE%MKsvB)O9hDklDN24Gy0rZP=25AC~oBy>&NVV|K3Wg)FnLzpF0qpZnF~v5&>? z)-(MJbGrA<__g=5+{;*ApyPl}gSe7nh9tzWRER;-pvJO+LSRDzP?G)FuO0D8-!2}D iDk>{2E#CU%%`(P#FAY;s)u>ER8S3fk=d#Wzp$Pz`AE7h= 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..a850c97d0f96235e0819c5e1d0cd265ee7ef83a8 GIT binary patch literal 1707 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 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..6d3f033b38e3a79bf6630fe68fbe1f3ccf6a5988 GIT binary patch literal 2111 zcmd5-X*in;7XH#$gJ@k#i_#(`l~GaJ2GbyM32khV1c_yAl`Df5HB3acwqhEpwDz5r zUTLT+D6vFZ<#J2xirZ_ip?X_Oi%ZSF`E!5GGv|5EdCzms`<(avcarS!Rx%J}2mk;w zIBTpU0Duq&DFNP};7g*d_CYe(+T{iSKsyf-^gtJ?vOlb{ze2Fw$3GcLN=gvOfr_fC zs+gD<6bhx&>3BTe&dv@D24gT7jc);m!vg~Y_bU>K+-FiKl$e+pCX%37PA>hGAj$6X!{h-Q3BtYMea z%5ob+b8^#r(-Ly*f^K-!v=%Vg!S;Qgr;d7f!a9Id01*3x!VTD^%luhbm@9#SC_-2{$Bj2 zi@pS*pa8L@N}i}o_BgIEkA`FtSbZ^km6@!6Wfq}JcD2YYD>DV4A3{JfM$V+(uQ)cX zZSzKVu)|JQ`uW}3Zg%@Wz9KJ!G6Os56O#q?Tk|}QOw6_qM(W&MwujxJ;onb+cs`!>jiC8Pi*uS$A`?Mjp+1+ChR?09? zXG^L08bU~ACoh0L$a)4e!>dnR&e4p}KSt^YOw~G#5EaG5JT;K7`Pl0m(_A;s$=kjg zK9MA{sma_TC64xV(84vXTqv#U1bK588wxKex2v|n$e&@J-4$+v^y7Jm& z9m|a19~RH7&+^%qRJkGYbMpFAe5ch8j>wS6^Vn$vlW{AJYqHDL#jxmiPa>cQG!zZ3 zua)mIVx&&;HFeyo^iYesWDck+%p33T!+!jIg*SP_YS60Pm9nLy0KD6%vv*3UxVm?A zMD6r-=yz_CXY%nb^A5-~I z4wB53!piz_^5f$4hufQdFwhB>s^6or^itZ4UulYA*e&Ns zJgQqc9$8Rnkn!y?bu1nK3RV1$ud9Wg^c{l}7Yaja8+4Pm9Hv@-TXGXRZk@kNd3YvSd(@1~nAh_p+ z1Xc*g$ajeDV;Dii0P?o(_dvLaZFuTh+s)pGwppX5fzeDnT@WG3;%bD%;a;!>;@_n`GvmFsHFFY;tL$rMaeW8lQn9I}O{;r@J~ zMehlyhpQr}wP1Ovo@0wDs?Y98zvdp1GJi5ltN_IfPCg5FEmdfI#kMxRuSKgIa6;Z6 z&QpJ8ei2q3ccoZ)iPRYE=v`PIRg+d0bPVP&&s?J^K%njR?-eP@`O6b|nR|Pjjz=aw zEmBq@^UE7!+?VL7-JRiy&6(Dg{3QN{-N?(3@p*UN%?lXIk=3+w34;wR;^^Yf z*)<<{7E_yQVI+SuE4#Zbqir4!p{|d}8AIAcwpaPmXriDWRMPBQNXbY^B+heZPE}f0 ziB*N@3l`!&p8nQDgFut3!`OE+Ht75;dxOsG9%Av_Z8;w-LSXm!i8ex5?E2SyHlF3u8<{n5fR_758?hXw!u 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..d3252db07c09cca3462477b73264ad53706cb254 GIT binary patch literal 1372 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfixy)XlMWm*4Nj=rD9`aV`5?;To)G?2m`3h(9jU53`hb+G{HbgNeRe?kPu}; zLP8J*A0Hot!N$f0VK6g;9C>46t_P6PE(!7rc3==tFt87Zk55R*FDNdlZ)oqIFnji# zISZC9Tfct8hW!W5p1*MY{)5-=KYU&Ort|>=1B<(-i(^Q|t+#isCn@a|a|raD^3l|H z`^z~8ZzlZx|NZVv!K)7re7X2!%eTn_`KLbygnB*om^*dKDl2cztCg=jKDSLRa`)Ph zaIlG$`&zwr1eoOw;ZFmLis=C5UjJYb(*a8URo@5|gs9{Oi-I(h&Da_$m*9K*p5&V2 zb4_QwWL|SU_r2+w*ORHW}6d28V?eVE)C)dRDMz8slvn47m z!awRt{@u8>VWrnuu3bKrYI{ZLu+@bPmI+@K4_ie<+AX`~W4va5c13OQcir@V&Hw9E zeeLUGb)ID=-7%Ct1oV`ApXtB%`z#u^zW8@u6L3Hhr2fF9n)^x zkhI1>H`y4d&USyc^k*LJW4ol@n>2|g`(|f1h$g;$J_jiD>q6Y!lnB9Vb?1QUrsfy( zt&wVrPwKdy>)*R>Ex>d`1&Ht;{eA`N2Jm2v3 z>6f>s7cagX{(4s~-|Nhka&L?dbFF*y{ua-Ms;zqMJg*B5e^R`9_D=nW`zz1H&5zwC zzkf4-_rV>X&(Gsc1STi#x&K0}8cgTpd2e`R{9kWQ(Usn8U|2QbZz|hT=@{! z#&yT5^AcMl9)DT~6l%LwH6Li=>TSEMfJUCZo%C4-Xj^2y`0))&Yi{NN<1}gM-8szK zM`o=%4vL;q!*iCvc-uGy=w{tweX%vZFOM~uo(B5oToI6WmL)7ADrfeymMj=2$&!cpYY&#v={>e z(+f`*$B>F!Z*PY--L{fw2z<$({@~sr153Ye`;T4w)WE*hXzqK@4`ofuuK0yS&MsQ9 zX-?6ZO zINR!o)VnErHzu52EX93o6%gxWZA^&OUj-!Gbj8-F0eM@y>$Wm+UsK!VxBmFXgr^!$ zZTeWVWn*WX^s%mv-<1UvJG=PGl0uz`>Wih5j{$j$vMX)-SYLm$NS_vWa8`}p*Mm`0 zf7Vs8X3GgK-%zzi&Fk~^4Q7HH8$&nP>9k#z%htEOQu3R3P1DznXVzU3(AMh@y8onh z=JpM{^s46C9MM`EzWS=wqldfY!>Y@w=X@5)zTw;SwO~`?&3&zi8_Tmy4LV!|ta=ce7^S3`;(k6$A`|*&#q)Wo$2N_OyQ? zYu@_5w)yq%wVL|z+lk^AOZWZ#SSx((-Sv{9J-8-g_%St0+mCkar)tkNvCoEoi;pbixeNgW4boFyt=akR{0HFhT A_W%F@ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/complex-graphemes.png b/crates/resvg/tests-hinted/tests/text/text/complex-graphemes.png new file mode 100644 index 0000000000000000000000000000000000000000..d6d499fe54167b110b2a40d9a594030acfa64f78 GIT binary patch literal 1033 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB- z1AIbUfiy8dNl6K)jE|2G$Z&Rc&dtsB^YfFDk;%!)5f>M)udi=tXkcSwgBa!F;)2Ue zpfaH1v$MLs09B}$1o;IsIQ+M72q^gQ{``Z4{Phd2Z|KOZ+nIHE&g|D0*0}}2J6Ytji zSl?pv%E$7^m6=H$nNrr5wj>`*^j%Ro%XhCUpYy={`?s?xe|BcdoSD17M*0xY{b9Dd`{y5&DxdF@7^@m_H)8sR zT^pBihUs53XusN9IxFF8lCRL3xHUHM|G8H8hQ5C@hiAjB2*asKEmx0OtuH^8V7l>@ z|82=I>DBM%cs5);c578RPa;t4+)Q4ey3*%9%xlc9rPf~J0ISfB$X&z#`Il&z^y`G$ zBV0fg>7~yPWFqfEH%3*C+kL|i`xnWjBxixzjcXmuUAJBli=Nhjb0SQM% zSc5bq9j&r|UJA4>>VAlA+`+8m-r$!!KpVD29C~$hRw~dNlNnZvzqUF6GydAV_Qi^Y8y0}_nWw9t%Q~loCIGe6n0f#J 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..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..b13af91a1238e7d45722125d25b2a5405bfdc9a1 GIT binary patch literal 1678 zcmbVMX;hL~7{(BAg$y`VY(`u5zmVcd2r}v!qeV+T==iGDekNdvocxYi>f0Q_t5&)Do1tR#;zdg~1j@+md#>1b0nJ&nKsw ze;eT`QST9j_862a<~Iiy&KmT0M7r~g6XZ(Ka~5Jg>)i0RxRL|tKeqQGF5aIunl-uk z9|7mDMZ(~qT6G;9G!MRmTJ?laAoxmm!Dhc;{ILD?tVi^M9=QkwEQ~jx2fxy7#7y)3 z@}2hCK|3>N25F@%slh{JI-)gl`;H~zDL52cq3O#i)9_`5La{;WzQHSjb1#h4KtF!> zcgS(6EaZ$WIO!t?{Kc|PWcOjv0ojsb`LJlvl3LM7f+n~pr3LOqN3I`2{;nsfbR#ft zrtJ{B=66l9K~@&AwYhx$}~z?`2%P}6>w6n)%y!>?FcLe_MzS@WMUG+G^xz-a%MSZNkVk3kS6nkfEeDKRFN z!5dvKT$`@1is3C%c>ahA@ua0ZE~v)CDe?IY&vD*7UEUIuNBsw&3`GH5wdQu zgFjpP2G0&V-iGJ9mFAhM`yQ2P&m`V*xW@BcO^EfTH(*S85||+`+_868^#1WFFLu ze<~B}>*4N=igtiiV+D;m%nV)HBt~fMsVA#B`g55L3iR6p3}p8Yug0yZilNrD*VN0M zAIiIupw}gLJ-iw+>#TP&jW>cU{}X+g35;t=_`o;D55kxBrf`?k?8%@Xu@gZ4$&iAYZaDFT|&cJAJ*6wLuG$YZ79W27=@TD%6gkz;th2<4@ zQYS^0Q!#K={J;ly+OAzb`CDl9;R?Rg+Ef!Q-YqF$w9Oo`|B*T_O%JD3x|%D~N=Wt; zfv~RFuWXHnWKMB@Qv_pTdJQnvbs5!`w2$Ikmn@f`20S|*71d8hgdrKI)H@XNv!^?w zs9rTZW|DUb_Mo$1Id>F?;k!fyVy49M<$Z*q;UVY;KB3qBZPwJZ-u_9#`Xd%vRt;i(q9(vUOckbJJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-more-values-than-characters.png b/crates/resvg/tests-hinted/tests/text/text/dx-and-dy-with-more-values-than-characters.png new file mode 100644 index 0000000000000000000000000000000000000000..952fbb1ee2cbbdf3322ffa7a8d094fc6c9e6a642 GIT binary patch literal 1703 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 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..c8cbe94799cb06baf2ee11bb29a9f2a07dd66883 GIT binary patch literal 1621 zcmd5+Sx}Q#7`-9vltq>xVuzrl7>QDdP>q2=05yt{HHKv*1R5g>0R$q8Bv3$BQ3`Pb zv||9p012RuNMjO-j;Mevp#>GeF+s!#7K={CqpgR*pq=3egb57B1Ynbf2DBeCT0JgsIOKX5fG}tT02_cr0I&cU0}%X= z212n{UM~dLqyTatphd*nC>OdaS%afX<29FfxzgIkisLP=D5{JWPPF&RHi(^8TLnIIJc*htFs)_)eZ= zCSn9j4F{?%3ap7dOh|L|qj}4fy9{OUFL-m|Z$TMq->UMzG+p2HMOCf(kQF@*`XRS5 zlfxm2HAr)9TD=F#(arJ7Nco-LmdDcKmT?<2`>v`!67sBzBVe=nc1lOmazYh~)5hl< zIy{FLw*9P4;m9Ntr#s;{b`DD>x^cpJtg%4-85%`tD+Xj)7QD2*=o}$`@PL|4zvF_v zpLnFps-Vb0RC~FhC1yZ(#MJFt%-PwFGFwYMn^J1bYVe-gUmQsn?J{5yf_=a8D;G}0M zH7%mb(MQn9p{nAww5q4uH1|`cJ3gi!IP+O_89C0Zx_R4ofHW?*#ZO?&;r6+SbfTQ=lUAahsUVr)Md7I53CmMa|K+*YkXM z=m2`We8WJ1^<(%A0a4UEEib!6XqL#zPSs~QDNJ1`Bu8a9h2$c)W{3)Z9Bqf!<+W#guesAD|45`E<`QYqi}vMWez-#f}}M^cR24`YLZbV6H=mr$vgRsgUohE-b3X}3yd%BMRJ}tb@Tys11*1s z9!zG!+~*%8tBX-0wyI4uGk2@_`k?VEmswexI9-LHRn#4`w%>bJb7YwQEOv(9JQ10KhQT2zJG?;;wr1$l8Zf~lr7TeXB$46UH z$DJ1*^qPm>ZBCh+darM*9jAJQM$~KfRrc2^h=~M@Z4^P#FYa!@sqto*QKBO+vvF%! zeW}~LlA0f9)cDq(@_M0hlX`G$9s411Cj9J0!=?MO?50%GiCa2TsucB*Fbk=BO?*lylkyAM_{NznlxL> z;Q!X}zNY$`?Q25K)tq_=fkou6K~em3EP+#C%j{6`g+l}|7Q?}tvQUdFpD)RW?A=JD GW&Z`KE3;Gp 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..3f6361b172186abc1f38df47d2d07ee571fe60c3 GIT binary patch literal 1562 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfpmR+eM3V7kbxhFi;FWeGxPEB2?+@S)dO{DYHG&D#wsZ(`TP6l=H_y7aj~(n z85$Y_&54PL!EYL-tb+9fCZMQZNswPKLqfd3frJMJ_3tkfe}S;al6vN$HfeeCztjI`%b<8fBN?O zYX79Refh~4@yPg1E-$O<377Q+&H}Q+}HHv zRE~>tiiPGH&s|cP`15+b|N9#2$=`kE*YQb|_g+;l_;7YZ$7lYX1~&~NlX`z2YjQAk z?uq)i`NpcyoFlWA_4n^}*IE8-Zm2cOA%>WPv)U?mm2ZEtLEuE>^6cKLS$ia=btgEg zuIVjMZEAJcmeF)M_h44|h6O?!9^B#%W8}NMp)WS5_fSv>7xy}o4FWF@?lR|$pTPZG zu}#$4!})5T{DSFG54>2oCl+2j;^4R8m&xpnBB6Ftb`@;b<2L9xXWRX{ve7$h-A0kA zOT&v*TTJ^FUp~9MIXQJh*PfZu?z@jPty=bd;>z}H@uT+YpIu61e}CWFz#4i?y{A~U z+x6VS319OqRP)wNSr<4lGv}d~-03Tif;qc?tF8H;wyN&eBi;vIqTN1g&t&S)p8qAA zSv1Bn#xrSRcZL#<8XuJ0p_sNG}FTdOU>flGi#IDNxD_LvBr%j%4dE=hv zR|4a=W$fKBqvP}z-q^$3-P6~*s@_@e_`20~)*nwT{-car{%y%W&%wjOAmA#VnxkG@ z@c;4AZCl@Ozr44u>Z5$3Yk$~ku}?c68caVgeroF5gU}Z2ibMO4&(WYC zGxr>dd696iiIrPSCt|~(V{k%TB?NJsD#V4}KzIHMfH*d+s=(Fj{Kj=YixuQzXFlSr XcpkmK^uc@?P`T>q>gTe~DWM4fmJpxW 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..f07634954381a3d248420c8ad1ba1ad380be20c8 GIT binary patch literal 2101 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 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..eb4be4f1d2fdd6f9348c74af6d6d1c523029a38d GIT binary patch literal 1418 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDF z1AIbUfixU6G&I!L*F(7t3=94&Pv$+%XZ)cg6@F^IZrcYCiN7u(>a z`{~B7$@bZEr(gTKeS2$Y-i!^W&L&)qKDcW7hEu*k#(`Da8^NNoH_U~vz9^OG*|g<> zYoUn##{2(0^>vTR?sG{xp=AuN4rxr~uUOO{f>3e&{yJIOoLyjr8 z9f(_<{ag2YsC@?xx+Ko+-Ub{u6ZnJbx(Gs!p%84C9Gc*erUWqz@>V2hE74~%+8LT zw*UN2nq+ENP2Tip{dC*PoZfwrt^XEQYjWOXyy`Z8D{o>Q_kOX(7wkn8IcIOy>|Qoe z<#^2GU+rH@7QH#RVhz_i2QHpfQBrZaZerKwuW5^IWVF-#*CRfAV(a6(ud~Hv^4eW` zZkW!PEL!ku5|h5CuT%eu{yBk>(rjXvmR|7+_#^o|q zEs#mq89`)X|p?-!-dZbwFWYs%Kr3a$LHoUm{ zSJ!(6e{}_K!EmA>)HntST5=iR;AX zJ%^ljz4*K2+@}pMFl$#;%ib z6^c=o+Y9#>f5^>fn7&3YhpX?^|4+RmKHup7)?#rMhQkaDhmZY} zozFAJa;gC1+H14zmJ-U1ubU&DhiBQ?M{GF9PfX^ewi?Vr22`W~OPFhCA;nIFuD(a^ hp{N;79*K!wwl1#je#Xx~0n0=N22WQ%mvv4FO#lUPT8sby 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..1b0b25625a629dd86295974055e840669053ed17 GIT binary patch literal 1362 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBN z1AIbUfiy|L(9p2HzP_QM0jSH*&ySgz+27ya#l^+a(lRF}hl`6VHZ~Swppudjkio~t z2jQZTKv|$6K%-Vpiq!*EtP{z;BuU|@0Zba4!+xb^mSd(mnO3HQQ}=6jcXmlL1zHG>uDx2qGcEq6 zTM*;4rY20q5qeXDNoOw^vZWuvpS z=e2#dHy7@?`?%+NS@kRR%aXbu-p-NT#`Ha4?ULOGw%g1!&O7_I`(VI z5_qTChw+L<*vqb-ad=kfzx}V$lXgB{eK(@}{J*3%h4zxGHBLW1FeBr7Z2Ox%S1!nG zc(nM^%1?*2u1wojZFcWU71Y@rlZJb91k)UXafg;Wqzi>HV}FdmgTKDO>vCUb$IgySocUE`+DTPk zoezH>WLwz1v`qe*UAl>Nb-?w{64^I84r#7AYqQa3!z*B>A9M{H!b0B^hEES%}=wI*0W#x zeQn)UlUu*lUOuhWDu4I3cG2{AGtT?n-5WlAdiY__-R%4JU-taJzIfff_40>){V<+8 zw{AyljL*4y_iFy^`LW>gcT?syQNB+rd8V;XyPE#APH#id*Owe?Y9nUmMxELj&VTLP zqa(rGYqlv&PdWJMP|>?x%}*D9m1=(4n#xsK|Bppyb68x%(@s&fjUPF6`VTO1>ueaD z1P9b%*yvw}p*i;2;U=4^7aLA&KG4EgDfW+f*1w;!&-O*gf{G_kS3j3^P6^bxE*T+xzu;9Xj_x1Y~4m8;RchD&{{Kvq+s_p6G7*cWT%>{Et z21OB8gHtUtAOAEj_dR&uQ)S87?nO5@X?mTG(@gjqnaS!hO($|w%G{}~AnN2KOv-J# zsyA58$w@S4*uJ^RUbNUiCz{Ti-Hf1K-$&sIR}~AG zvQ-!T-QxBB>Upj*!_%8La0P7gOt@N_UCTP{u}PS+V7#!bUi{of(VvX-9TTp8D=%8G zvHo&HMSRJm2tDn@Zm{;sOclOcO37a?r z<{mRju$SOow0Gx~y7MK!ORuPJ{86xG%jKm^FMauTcyEk)y8rsq`RBiG(uscQvc1@r zM@QXGGJ!u|-L7w`xM;$v+@AFpP7AnP;bHhZ)$J^=!wU9>sq-t@b~C*xTr$aGGGnrP*=W%zwi`n;xZJrHlmT<<{FnRpVz2lO5 z&RM+qc+lHTe`a%SnEpj)>VxZR7>c&9Hv4xjW!G-GEBXDRG6#!{o6omKOsb15X50Dc zIM*v#?=8DECHLD-dwu-V+Gj;;_Pu_{HmhDV`-Jt>!$&T$@*nE@!}nI{srKxHNt(gUeY+J zG3jf(+9v^>bcImo_mR7dm&rFRW&F*^TlfE2FPD5%DB~;U4Mq!YMV__bUcFC%TjPoR znv8-7%>#?3*+)v9IDfEcdeYZ-k!1xDT8s;3g(^CP-ER~9mh{tp9m}DENuCY-Gba^q zblWR_i6K6H=|5AkTx;`4<|(;*?$+4o=oJ3E7rfz_$h54}0vg9Ahq?G4V@)^}*16?0 z>w%=3T~~55uWkPF>>N)+?C!*+^QO!`^s6z#{@3SjiA_6_G+LToC`R9TbiwJ@dcOHP zZtq`Rskg@`jeWA{MaPI&(aE!D$(4ob>BtZ&=vB!1-mq}$t*l^7f}+L8{N2eHchyLxcp z0%`AgEoaus?zzmM6R{!TU=u61*q~!TT?KU;3&e$-KzGiE3T^6|(tdSmx9M)5Vum_X Vu6JzA+J``;vZt$`%Q~loCIH@?p@ske 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..6317518d944488b29a2510355b6beec8b6b8c195 GIT binary patch literal 1646 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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..ffbed26b635eb1435d8ad8cff8819d6fe2e06394 GIT binary patch literal 1220 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*SX?$>3Jk2SAFmz$3Dlfr0M`2s2LA=92~r z_6GQbxB}_=`uc{31|S0u;N#+kPxWo2b( zXecf&4m1jAAQupR=O`oBKAeraay z#My^u&v_U>KYu~Oh5HW*J_NisXt4k9aIET+83P0JB2O2`kcwMxZnhWQHsEPUym8^f zxp#5*j51&Rm0vHI_}C@5b5ncA|FoND-ggKqGrg0a(H3xt`SPjgHNGot7xW(1ddQf$ zG)Z$>QmvAX??w@C2nyCY8U#j{U?Lk$pdv+6uUy)Df7|`vE)iWzBf7RKZJIBmz4hy} z5YzA1E=@mZ^yTEnrc=}Qe&Nws9l?M6l*sFY5t^FUnm3wteJxlMSQGL4Z$iOFcYbZz z9Rhy8o=^K3ne{Iy)XrjBnGE;;H7_o_lD}4V?ZR4B-(q*?9dDKR`Sa%om(04&e@=)4ZXVeoVY>JE5<6#ybgfuQiJ@xft)h3gtbWQz=mF)-Bxqocp1QyYX9A z_KQ9dNk_b1ysP7$Rv#kov?RiLmpZ@pU7_v1w>OAzb3HN>(7yKSVZ@&YOJt999X)=2 zYwnv{$2T2O75FN#?$-T-pVNy|uS9%d(23!^#^rcE@_W+9rAOwhIu@8Lx;EnI!v3tWC*nexEfJs0*rGQat2s1Df70>Jqs3b@j%Dpy=y5~$h*X*U=>UuH zCeeEVE#JjI`JCO=&+5HXgJ8=m|oHm>&k@f!PaE_;9=E-Lrsi_>VC(mZtJf~b9 z=*oZZQZwyOcD!Lc9gxeBDzI07ict2__WCk@?V9CVPk%mXaX$QsRYIbe%-T~A6!xp= zN&A1Alas#jN0e#D#+IUc2dux{xAMMwjA`>8;nhnX%nD%J$gr}5xm(-q$=12jD>f8d z{o$Ef@W9|Of78|ander#T66!-^w~E{s{CB0U%q+vde+nD>+Ak^tx7xSe*Vs{E5AQ& zeyMu#=a=K(_5VKqsx3t(d4U=9e0n8-TeYrp!8gzcSs{YM4SfIr 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..ffbed26b635eb1435d8ad8cff8819d6fe2e06394 GIT binary patch literal 1220 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!r*SX?$>3Jk2SAFmz$3Dlfr0M`2s2LA=92~r z_6GQbxB}_=`uc{31|S0u;N#+kPxWo2b( zXecf&4m1jAAQupR=O`oBKAeraay z#My^u&v_U>KYu~Oh5HW*J_NisXt4k9aIET+83P0JB2O2`kcwMxZnhWQHsEPUym8^f zxp#5*j51&Rm0vHI_}C@5b5ncA|FoND-ggKqGrg0a(H3xt`SPjgHNGot7xW(1ddQf$ zG)Z$>QmvAX??w@C2nyCY8U#j{U?Lk$pdv+6uUy)Df7|`vE)iWzBf7RKZJIBmz4hy} z5YzA1E=@mZ^yTEnrc=}Qe&Nws9l?M6l*sFY5t^FUnm3wteJxlMSQGL4Z$iOFcYbZz z9Rhy8o=^K3ne{Iy)XrjBnGE;;H7_o_lD}4V?ZR4B-(q*?9dDKR`Sa%om(04&e@=)4ZXVeoVY>JE5<6#ybgfuQiJ@xft)h3gtbWQz=mF)-Bxqocp1QyYX9A z_KQ9dNk_b1ysP7$Rv#kov?RiLmpZ@pU7_v1w>OAzb3HN>(7yKSVZ@&YOJt999X)=2 zYwnv{$2T2O75FN#?$-T-pVNy|uS9%d(23!^#^rcE@_W+9rAOwhIu@8Lx;EnI!v3tWC*nexEfJs0*rGQat2s1Df70>Jqs3b@j%Dpy=y5~$h*X*U=>UuH zCeeEVE#JjI`JCO=&+5HXgJ8=m|oHm>&k@f!PaE_;9=E-Lrsi_>VC(mZtJf~b9 z=*oZZQZwyOcD!Lc9gxeBDzI07ict2__WCk@?V9CVPk%mXaX$QsRYIbe%-T~A6!xp= zN&A1Alas#jN0e#D#+IUc2dux{xAMMwjA`>8;nhnX%nD%J$gr}5xm(-q$=12jD>f8d z{o$Ef@W9|Of78|ander#T66!-^w~E{s{CB0U%q+vde+nD>+Ak^tx7xSe*Vs{E5AQ& zeyMu#=a=K(_5VKqsx3t(d4U=9e0n8-TeYrp!8gzcSs{YM4SfIr 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..6faf9d8b191430ade8dddfc19858671a9954d182 GIT binary patch literal 1824 zcmbuAdo+}J7{_14$Yoq66xtZMWk^~?n2gCKnI^fsLuHbw-0!8r`?5`C)fhUaG#PBH zvc{#OM4RgjX<|@xA(x3rEEN@@eJ7{C_U!(#J?A{{_j8`h_dI|7-ZV1FMNv*u4gdf} zH&>!307&4(DJz9kNY|5H5Lq4NN{IykG*6ro*(PW$q&P#~?X?q8aX{a{2&8;x1Rwy0 zVE_go2$Dov5D*TBhe2UTMI7I@4!{TYzZ_+b|{`K%EANFwqHe zLb|rFEwW+**&v=<;4O&f7HEsu3Ieb&76B}TMOYismOzT%-7v?+Zs-K@7~-Y@Yna34 zs<7(HA{s^`AP37KT^U$rr6>hUA(tQ~YmNixlVU66DpaEQeI>we|H4E79EEF6?|d zI6U-rdS>p~!n%t9Af4()bo5GiG1+-rLed-nDnxa|%TgUu+ZG|kJ9@e7YfPreQrdpm zYP<@E!kt0+O_wri~bJ@Q55&H^xanm{}&`}y-W1p$nF_*VH>h7 zZJhlL*p_xX{Sm(J+=s9&(chlzrD1zP zcS?5dLc>F06qV-k7-12@^GL=~X|3YkdxUkA-0|MtgP)2g=GzwCaUTdx6}v4}2*W|W z;LGs1?wgFL_Ap1a^gct@+u-cwK6_SOf6LWpBMP(I^=||ndc(5X>c=SRKP{}ea-!Z$ zVUsavM&4L31eTCC^I|AxG`|9SL5}LpZLCxG6{|wlV;XcYf_)a7wFMp3DcDL`Eq#@A z|Mmk@xgX}{39fAw72T-}vnF3tjG#NK@uvQr<~mw}(9ikBIJRoS%;FS_!=j9SKJVY# z_n>mtVn|JJzQzdi2gRo&#EN>NWSx4M=A+k{ZTUfgIkba0yZ}^tg-(AYcZ?#>w=KTo zm!H6(FOws1O@uUF6VEmh9r`4iK^yBKltvrpfC+>T9lXcd^7;k!0cSK!)k2%XTuBcVIByKo6++3C zpyg<>Om8i|P#0Y~*PrN}rVWlOZ8NZ|5P_!r0E-QvoxbjpMq`Xp^4dTt70;hQsx zNsL#90sbLB#8Y5+k=E>cn!CSHj;0wp;@e`FLfXXIpiPGx+|^ z3(VUdhvK)l+?pIcXvN}KP2d=_7_ga9Ia9XvN+Pc6Y=peSGhWii3!~$#uAsy7Q`5AE zL}=W6YE@z$eRUP_n$ zI%#cT5=vOvsrhi^H#0pwyD!b25gn}|kA)QCSgu-X(IaO1=*jqi;S=;DHEQuxFt2K}=;al%ssfft6{Us{NQ&t^0%aM*dCXKHp`mgS3TN#mU8>Kh~|6={~xX_)VKOOf{-*qb(1;5dRx~^Nh2#uwyoKWgO!w%&Jh70QR(h1YtA(&u6_|Z4!2cM|_Sl3;7`u;_F ji%adLKhm;Y4fJ12_K&IJPX6R2{<{HgJ4wVc0yXt-6e}C9 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-on-Arabic.png b/crates/resvg/tests-hinted/tests/text/text/rotate-on-Arabic.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7463570937015e0c8777ab85b6cd4f9f726b5b GIT binary patch literal 1798 zcmcgteKgYx82(}F+G>(wlA032gpy2zGGa32V_V5KWmnuyCn;7o)rd$DBb21A^0nd8 zkdLh-)jbtqQ%$WDGn(?b$mMp<{p;Ry?)~H5=bYy}?|I(yzVCm}o8sr|340BXnuYHG|ozQqjBd4U|+MTiCftp^KK%eK^7HE*)~d;-w(`mcb+Vl^~0e0_bP zP-t*)Fbai&!{LsOj#Mhu*x1QOeMnXN`Aw7=Bvm*(Imf`^ZyGLcTWOx@0h+6+xt&R2Z2IUB zAc3`;G16@A%u(85frTam8A#;M^D z0`3NKTzi_;y1CvA9d@54{DFMm;pJ>%BFePbCL80857D5FBBWh=L{J+36!Y%x@MtXl z__4|SJJ3Na%+Q)V3c=_^Y0^d@rJ6n?j?t;RFXKcyMc=4n@ckm0r)ZO%*OCu8{N9$? zZgR=GW>z5C8)RR0ZAK>uuFqBI)3r^JSHQlHaZ?Dg39>dRq7MzmvLHhSc^vXqL7DpX1jI!K0e`81Iz_`?=q?y>8 zDz@sL+uW2a3%ZdQDK_se>~mOxcpa1bnB%f?sO{4j9GLmMxOvRF;ekp6(>xbje~Zsx zc+ZjKTN#5 zLtN@Ck%MLHnNfl&gQ~D1T~w^Bt5V^mYVen4+?Sngh>haq#Yy?MUxD=|Ng|g%=Mpha(&e3REj%X4zemW<)bDmmvk>HM#biylQNV0^Ad=F5^em9YS((~M zubm1!SwDN)sxh7lX8lF!q=wdK1PRF2*!@{lg{NQ0oFYi z`MW;4nipTzEWJKVI_&gPE|d?f)oX7`{d~IYnmr5Mztd`esMq#~=Wj*#Mfl@&xl*e) z*s4D3YHaAJnaB3$wfqlh$_Y2CX{27vv=7IQ3Qct$-Zz@jMH)Da?2w12duvA;9z5)d2*+p?3_Nav(iMlFYeh zB)4$O;y*HQAEK({ySx2lG!JbPq%~Q)EXN%ZnY~(N$l&rHVDL_N=m$-!dUIRExqR7d zkJjqtYJkWUC~gZuj7MGCwqi!zf8E-J#QZZ4$1nUR0lD@^-u|UDuE(&;q#zY#S;-c3 ZxYlL8;n79s=*opBC4^E)=VA<_T< 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..72f6e1caa598050ba5e3d54c56df296ed9c1e90a GIT binary patch literal 1663 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-and-complex-text.png b/crates/resvg/tests-hinted/tests/text/text/rotate-with-multiple-values-and-complex-text.png new file mode 100644 index 0000000000000000000000000000000000000000..137ec24268e3cfed360e134846593c40895dccf8 GIT binary patch literal 2462 zcmbVOc{J307av(-WO`m}mZD)|%viHdipEew#*#+A#-7P8TalRYc(SFEWk$QKStdL` z6@zRO%~Hr#DIr4=LPbLJPS5-A`=0YW?>*<9&;8!dz32XM&-s3CrVHVa3{(XQfk0&N zhjDHYhzR;D8xo!t&!Zmcz4|8YF*#yPcO?e>R7ju(x+p~CYVhj-)eJ$pF3yQ z`V{t3Bgfi48~Xm{q^%*H78_J8-Q8n%z?PxQP*J-?s!=5V4 zU*YTIn1`lz{s4`|mut}g7{JL*{a;W+qW_0NIR4XM`}q$YbT7k-I34U&t1=-pC9F1eRk;;ZWf>`V|socT}c3(%@6%a$DO%+N;@qbA_!&ktvRn>gHh z4#Rw1ZZW=Hp>UFB5L*jETXF)Ua3aiCdj1}b z=~i`{=pp_b9C_6o1fqlJLs#4nSk&~J@MiZ&7E~-c?vIP>ag%ht=pT_fdcmK@sGr*` znKq-Pz&c-boa+;} zcz$s1{wwImG?1^8xkp@m%LG{Qz${+NR$F#sJ^(e(g;T{yPz6`sYePO<5A2o>Z3f|x zn#oF=7MCivxb}|z;&!(Nc0Xm^?i~TfV{mm@HfB{O2MDDMTBk(i3gu3hVSgNmmVSK1SahSXRbu(W!Z^BCoN(tk)P5&)wRp> z>WWRqc3E1;p5f$%Igwa?sy~EnleiM*FcC26;UhRh7+$g!FP9c^dWsn>3*-bJI&l{p z%Z+||?W2Nfq}iMD+WwgQa(n=Cz&bJ;I*Q~my@$_kg%z$D1ttK{Zhq`;jA;6&ACChp z4b$~C+0VDH=S?$$5`fUJbuZ+2?_q;{(ElqqV4hdjfCo9=nR!Dg1iruk#6~7MBNg;I z*jYE(xz5Ted;r|9Gtiw~`iB>Q*g=@LLlwRO4IEGRbw$XPU~epVJ2m#u3^H7QBqC1G zzvZ(aFD;m5W)ijmSLE(2ynPTrCwCck8qvj7LF4JFsq9tPKO1yWY049&;7TAgwCNGe zF$-MrZOlpNit#jgeban^KLZB5Q}Wm_3R|4x^jj&&KhbfR`W|n4t>9SK3}`%v?%g$6 zW(rhIL0NrpY*+G~A{7$dP}y)bQtJW2v80=}*_L8`*Z$)rJ=ES{W4sz(xTBy%m|j&K z@nr=l7NV9XeZ&t>k9(w$0yX6~(hPMoJz8C4@6;zqZ!Ul>FAQ_6 z+w>HxwSYiN{op?x2K;ijoLvRvzsYzOv@DxHBU<;^z3{o_?YT1Cn|5yRqgbob<)>2f zY~$zQ!#!yuPct9#I|@r#y3||kg*J3wB4DbFE$lX_iBA`I>1;weWJ@{S!rR>Mx`OFVZL z5VHgHXdl!hMMq~u`bt3uqN`PdK&o8%)Jc#&z=gL_?aSG&axeH`OD0+T@m^y)E~!qA z3sRsRWTFFClT6<$WyksMjQWj7Hzd>G7R@NXbtp>)QtW3B?NH9KcYP?Z=e+6TkO>r|3p3Y2g5q{5n()+_(N72&42c|3M_6(DU z&>s9+0m>7?w2VsA&E6)@xRQh0);ps5V_vk6g(e&ZtdipcZyvSxwdi13lM9chVi%Y zO$8x!)Kb-wH*3fA)k>fbrLVNJ8|oR}7eu=W&%gv^lA*sPPbGRwe?8+sfSA1{&shJR z#TR1}gLfGKeMyR40?>n(x`*n~wijw=sPlatQV@-8Vuo3Qh5pR~xm)9u6fI30aiRYI zmEd2}{?CM4`mb{U@n7MSl#u+kr_VggpF 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..a12b90d1bcd3f4228c51bd9823cc8b79b33fa170 GIT binary patch literal 2781 zcmb_edo>ZxDK47t&15~BoGM1?~6-7 z-0#0x+&Z3Jk*LVy|B77cd*dA-kw`q``L&7KJn8RgXcAgCUe_SefScJ(*lkKQ)g$O} zHz)zbb@Ezqk$c0PP254Q3ME4MhCOOR;@ds zOZ_oIj&vZSaPnaFOUoAY;#t}12?8d>AuBR3FTFJW4JJT(e*Wsd(}(A-F>mW#bGLRG zT1CHe2jbEL&Q^z_LqcGd2cu&!4zfZS^w0_K{+Eu0`zIG$?zAq28f*Cwh#U;ZxKIRy z0D*+6txS)*#Ei@jwKvK;!HBOKjd15NwlA#CKb#=IJ}&~&sWsbfb|=?y9vqtQP|;?V zEi0PV-9BCA=Lsh<`fDJEAkNU8+kSL z#1LrdZ-OfzpOPtaQ}-1N8>MdfQ0}cns_HP+rnY`>yzH9n4P~bWMu*Qy;Pw_0yl>Lu z>*Pu*U$51C>70ECzc4mw)7xiF!@}8gbHbBx&!k##U`@6{DXnvVD=0ntv&aF z_TaEL+b;+a2xpthouJ`tS(!p=5lwZ%+mPq9kE1-RbB4+rdOM_BPo;KD-B-z-8Ff)ds&;kk!K75Tyu&x49qRg7 z?LT4`)M>vKN2X`{T8wX2w*%z;8=K_F3PqDHzYkJ}4~`B;Q2DXEqji2vGMN#8HK>iM+abn6`(U#UKecrm0W_~17VstowKYMz_06}e45z>%s)CA z$)jP#3Ai{T{{-Oc$>#`mkl9ISV4{oXJ&9%g@&nH0VqF2qV|~);?oOt+hazO&G;?Bp zVMhc9bQUls>q|Tw5f{JOCt3wK#D)WphcAPF#wJ7G32Tg6YnY_dcL6_PUsl!I>C?t_ z=}_%eMo>C3&|z7aT*QYW)n1CCHTNn%wn*2l?;{%_#e0hM=dYmIAga8u%ryRU91J8;ryQjkEIPr>`$u%CW2Rezfqq$WVER?&R}j=2DkUrMW?Ge2~^5R*c}OpQmrl zR-{@xp&)0QuKR_Go8ncDqV9Bs)ar6h< z6uCL;(!j&QUtL|U96zUIcPB4;jhroEms+CcF&_RE9*I%s1Z3RqQSzg|S=ErKuMjdH z_+}#McCu|utLq$IexvQ!PthONZXhEMKzraF%PRCGX8a&_gZ1Y0unv%RQ0Bthd2GX5 z(MAd8r}AqbI(=#xvbeFU)NbVT8F@u%hQVIcgk;-khmt14#fD>ggaSV*Q%P|BR>}Acz8f;vW2&ljRc*I22*A@n+iA9w$~>LF5sSi+?ZN| ze{@loQ#f83I{HP_2t4E4_2|+skj~_|j;HJ^WooTQe$(kM?+?F{`#TBjF=;n>tBk+%ZaN=MKl9aU@pYP48JKhIXmWOvSsT5|?T|7M zTB4@A2e8d)1K#H4iBf+XFHJ5}!RMo;TFFiMUi@sY z4za?Uy}_8#b5lR$|AO3lxF1OOTRU^{n_ev5bv=q{ara2;uvl$Y4;&U_uQb6i-qjN_ zL^-Uknw{wmqxM#O_D|Zv2&k&&uze|ZY?F3Nbu`(*qwV#HO7jLp@R-h|bs2@iH1Vg} zRWTe~%IZe7X))SzZPxw0i7p3B8)T0#Yicgs7BwtreN?KLwOU@LEW=4MaaK=!+1;&2 zOnfoPB$?UxyyYJjW)2$aynpx_mT4mys@CP&!`>g-~ 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..6b518b34bc5a65193a35cbb155f24439ef5dad5f GIT binary patch literal 2206 zcmbuAdpy(oAIDcpXw0R}EtxHemPH&PnKq&^Q7$V*8ljlO+){2^E-jZ_HkTHWOYAh~ z>rxb=>48Nrvoan9%Qct2k6&-?v(y+5DF=bvZF8Nw-9 z88sOY2qbG~i*p8nwxPa#W+qB-T`(ofUs$mc6*VzJ~! zpN_<{%Y7<})SyPQj(qR&Y^iHlTPvM;6&ZjQZ3QLC8WmGf9q~5b;Jblx1t_UO=aoao zWb=?T0ME3kgwO2SkA=^`J=0OmLu;>r#$!qxYgcRJ6N%BtED>+vU=b>mI_|r)0)D)x zf9PTsxSg2^_7BGaZ}{BQ^vVZ*-*MhLy2m8Y6+_Nqg%Ii*tfixh5hu1O?g$- zTzxv5YZ3qQ!qdJg_HbP^Tc(k4Z^%d1^Dw?N*xL8rq?YPegTp{*=D>9UoPONA=Tz<2 zy)}EyV=dkf5$Vo*_n3|wv6J4otNZ5dJ)r<1zgO=q^!VIHyon&k zy$kY(BJVu4VmgyM6|yU0Ggm$Ug{`6e;lA!CY$a^lf${4FS^=TmJ0pZ zi-I4R@oWn>O14Zy(Q~=D0baFUMazM{E`(Rr4qso;&r`!&HVM)MjMmohw!wG8{bBM zI@r!?A!$iyLw^k5|KcSr&wh}zm8$h@De3fXSTm+WEyUZ%_gx%r`XVEG$`PFnJ8*L> zBP^@$zAHZ1GD}Lt6aVI!pvCz*__>?9tJep%=cwGw{l>g)9xL%A-(fWXrgj9rEkSID zrP;c}AfD1Ah1}#fR)QdT&hbCZV=95An-t4ve#jSPE@J20S&Pn)ktOB43dy0(5QTxz zaS&0PKs(`Mx}mK0Ns0UtYJ#dXnF#YPA6YLpiSZfh(Og9@KLH}ok<}Z1zZa@Hftx=M4fG&@_Qd?kQOQ~Y0~asvdFfzNzJ?&Wuw!hh5jy>}t~ zO4Hnlm71+bM5U^SWT=x$AoAdWuu(`Bl?s(xOVEeDJTt{4Mm9N>te z$KChEkr7B3z3-uNeJSQTb6}OZvQm++uiGX38c70zn|zrrO_D_QUcRD8kJ$HNE7`Li z^-8`sjOG9<=%n6ypo8{cJmjPtlYNjF*@RqW6e}Ox-LefY=xB5C-(2)j{q6Fnsxa_; zmp(q%>3Os)04^pY42AJ1i5m^JSDn|)NUGeTumMq02y?Pg^C)3>qtM4M73D`?982Z3 z6(+8%)|A2N&W%6C2{k63~UdXzUke?sHCKCm%fmTQgUQ0bF@xy{_<%b=_ ziM{>m$_eb$p#p|W#%(9o{YjT`U*huZFmNC%K(90r%vjSHk}QhFkVk literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/rotate.png b/crates/resvg/tests-hinted/tests/text/text/rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..77f3a9470c9d333f62df770a484d2fcca1b1dee1 GIT binary patch literal 2217 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 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..52c8d75c2978c0744770adda0b65f694da05ea5f GIT binary patch literal 2072 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 R?ejK%cSl<^s@evZ@)tqu*tq}z literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-dx-and-dy.png new file mode 100644 index 0000000000000000000000000000000000000000..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..d45a405f678c2ad4d57e1fab9b31a49f6aa65847 GIT binary patch literal 1697 zcmcIkYc$kp9R6$EWiW*?lu|as$RN2TV%)-HO~zjiGa6!DM=l8sL++BahQeCOEhF={ zq(bf#N0Qu+gW}kdX5>~>_CI{uv-@Gc?C+fSd7k$<&+qrX@0T~#k!UR`ju8g{K+@KR z-~<2yIQ|kvzz(s5VGWZQ-NrQ(0Fa&hC6J?mRD{hUNBi@ZF#l`C#l^vXY-}uyfq{Vm z0Rg))cXxLpk+`b~1cHTy1+0yXj9@f0G=#gfwY7JIVi%Qm3f{scFE5Wm zp>{PAiG+o?IR6R4!os^I0>Qt(RoHMgOeeyeh$J&W`VijqoFj!orT*de*_lNyZ>^X~$pHW%Ut7YN^N|xDN0>r!j%cgF z8tbExw7S;G*heUt87Y}U<8}f4Kr+PIE8E8$E;0Y!*?ZrdDI_6>135orVW76ftL~tX z9bXGcuwblb@9GgBsC#A4PMF&E*>&SlUzZO*!|&b+|3|?U{%4E7&jK>{T^$q1JW{Od zLdxB*igdUg;@#QJ=1m zes(GX0CRgX=COV=&dDi|Ql)r-UN%%#iipJQrxiv3_kM-q$zWUX?N0I5%@SgX+Hj8y zXCuSg&T+niM?asiw44O}mM(%{yGXMR=SHAaT+P-cT(^f9-S`~fYd^KnHD z;ru2*4yR~WM}56QQ?=_k+g5g|N1c_a8ifzP9K;S<2C-upLoM>&^d6L+A69u}KqQ1Q zF3x!?6JT-N-IO5Tj%zy2`INQLIQ2<=VC4Z~^6N2| zYJ{DyXd+lEGUOgv6RB~lcl0%fuo;0XZe>Ldbd+WJnSkc?W(%82NTNS$kxW013XY6@J|4+1U(-)T(mcDai+wXIwil&!LuZ6E1j@ zu_GI15e{K(ee`GL+z`g|76m%rcXkh?c@c$8D9N+3vCU~aS>qWMz9Si6B|A;CR u{$TUn`F|%&?#`iU`PbE4j|NUcx5AouT-`{FJ)6h>!)+~zgoozT_`d*H``Wbt 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..d213cd15c023d6c3d7b5a66410d3f70a323e0b80 GIT binary patch literal 1674 zcmbtUXHZjF6b@$TLkrTyf(ip9BHdtNg&>BKASFI@(FZOfP5OeABkGR0qPDiShK2^82>hNF1aQYr0yZ5j;(cvNpdiw+fhQyF5 z)P%&;+v)f2W##;uS5gAQRn>LO#;#Yd`-ewIX6HY1fmtq$KnT0waVMQ41~`Ln(g#d- zQr+>2LLbofL1kA_A1-^_O9b57ZU=@!(Pc!itjiB4&w3M&F&tZ-k&4oNi3V0wDc|# z?q;`rj|CpPK;!HKmvWnaaY<97DY1;6b}iN z^qw3anX_8+#&p;7(y>oxs-CFAwL2%5yJg5_k?_a3gK_o~#IYNdpv!1OunB9lLb^V9 z;0`UPZyylSrBQ4Nw;%Rk)ix}_$UR0dP+{5D(UDoG=nm>V6xseUOH)T!ZZxB zXz^mIssjqZ7(2#v`}n!Xz$MYp@Ns=8O4d@eDHU7r94A* zklLf^m0un$rhv^!gdXl(c-7cv{ikL_4~KWt!wMOXj@CqBLp2>bUuztz-jwwHQuAVi zL#&!wYz;R*G*o->0FS$5XpTMurwb`j1^VoGuW8A{2V_3yY@j)-lTxI^+?a^B5DrHM~}KtRq_y+E7pC`N{pX z8(LbIRq{~T6zUsUAK@G$NP$wXWTN_8q|D)rwFkX`B@o8m3HE~1S!@Ci@z6o zGpnqiBgW&6uUeK>d%uHyCTecYM!oE|ep~=5%t!|3{l232qYprC(mUJ2&ca;vE6v^w^m|>67L4|PnQL89+b&^f2l_>XW>_f5sqbM6V~~BTdTBmP$Bu)cGITm^ ze2;bq)5Zl4)z(F=?{^G4PraiZ>2_fOK{0t2IIpvq=m7TBXJ9Ox4bvR+Vf{ zyGJoTwmHRUYkIaf)xWsEs{RSTTJvuTGiAsP9`|_Db}K0U)Z~VUcJ*FwF(fT*YhUB7 K2)JSk@cN%b7~t0c literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-arabic-text.png b/crates/resvg/tests-hinted/tests/text/text/x-and-y-with-multiple-values-and-arabic-text.png new file mode 100644 index 0000000000000000000000000000000000000000..7e7a11c338becf52297d5799927618395b8bf881 GIT binary patch literal 2643 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 K2)JSk@cN%b7~t0c literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/xml-lang=ja.png b/crates/resvg/tests-hinted/tests/text/text/xml-lang=ja.png new file mode 100644 index 0000000000000000000000000000000000000000..7d838eb692b84b345638e1b2bc830ff650b54eb1 GIT binary patch literal 2252 zcmb_edpOi-8=f&HG0iBUC5OyX4#Obl4h}gc;}FA-5ix@$QluPbkaF0~3});)ZL`A0 zIQ`_bl$q2TO{wINDN#)_q#U*=ryW;a`|b68|Mcy(?{hte>wfR&kLS7HKi(`ioC8uy zQ3?WqAe|g-Js=P$X2UnbL^Xm^1;lE-#fK+`cgrYz88W;#EuBX*~4)6#=IsB z73WWjD(z9TS22BdM1xm zQ<(%%dV;aFkJV_rBlIk7UO7~dx}pzAvH{DGnV>F=*7@d{nU~73FUzcr{s4X3M$35f z`@8FnFWo*x8x)hh3U3`~2w=p{;;+hAg}X_EN!XfihocHv{k2EyxMJgMaaAQN6}n*G0JEzYdY__*hlPk%Dk?}Yr2rjn<@+myhNw>FEGhy=T9r*c`><0%Wy&;o_Gp* z);Fx1dq%6~RIX737>o2(2+O6@IkhD?y9Lqn@hai+>EqW|ik=Sr zUL~qpcw&-GN+Et4Mj}yjBh5aP-6GiHcTQkP@!6i=X?n3zz0rtf*CE7c2R&3-f!NbK z1=-i~-1H~0F)jd)&G(DD?0~4{O0nauvN>#$R)j96XH9U}w0fuh#oln{KrmG}XR|O& z8cD(GeCy|u=s}}{eXTKg_>91?I-Teg=+et^Ao}BCezOhw3E#_J2k6HttD_zC1`YPPso8#uPO)a*=^qEM@~6P)9CE(7Dat5FZ|+6 zwo~Q23^JskqT(AVOP5)N7Xk7E6A)m>xT213xK<6qU;^oA%B5Dl&nj46Fy8`Vo(}kt zk~4Lfa(*ZCH0t<1*Iprj4jZE<30l(32eqWKjK-#do~b3nuBU^U}h$;V?P|MFB){{6&o-Y`i`e58I8p(<$0`k9$0 zL}7@DX6a(oWn*5~!twN!rFnN7$7I2i{OCeCa-LAZ=`1(AGKSe$oJ;9mKFu%)r+aT- zx%<$Ak#E|6@Iwp#x60P>x~2@hV*d;GN7uQX?lz2w=1XfQ_np0*r!Px6J`j{I*@zsx z<{?XIhI(E95byG?b8J-HXZ zI%ofzLV}eeKmP)@K>)7vDcM~Ras;-+&L#4lpq7@7Sn*5ozt(VeeW>Az-G z_$)B#b3fyY)S`{B9)4Mi@>_JsMU>9zAzYrxX+|fEthju|BhiYs@iB0+!`ar^1g8B7 Dimn5# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/xml-space.png b/crates/resvg/tests-hinted/tests/text/text/xml-space.png new file mode 100644 index 0000000000000000000000000000000000000000..e1591c3777d900b8bd396138e4f493ae9d80e301 GIT binary patch literal 1475 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z2l#}z0_pnt`i6!EAOjcR25;8P2w6d~dV`Fo1apB_P($v&+ zc6N@9jRl$jF-=KH31S*EGsqbvfeYU~E(0|fmIV0)GbF?dC^RJ8FF5~T{`H-iwTI8n zp7^@`;nI#`|2ebQ$LD{Y&|klQ{f2-GAKn`*IAH(ZVTWPdGzJEinVv3=Ar-gYTrd=E zFc4wcz#qGc?c9E=3XL6eU7XTlRj)l+HpM)<{m{QnMj}ey({v&?rTpy%ktZj$Vo>Lt z!3s`JQiZ4-Aja1T(Q;lnhYTd1oijW3f#q)MEyclO(}7r z({esPU%DsP{^x(jYdt^K2&`n}SZ-tMC!-RjWVbhpC?M}SPf5@m}?YyPx z+3#9a&opoN5VgT=1w*B1*lo+}lQ-XFJfOROllcYSsbz~973|ov-^s?2+mMHCMB%<8#p*p5UEP{A)~CpIC5YhQPD~mTjfs37SH)ehN)d zez43r-FEf6OH&eC6xKIA(ecs|Z(3lVX)1pFi1_pL8ApD$=sel9DD{+)j)pno&(w$w zNhb?-aECQk&0XTpl-+dWsm^lKD~*%>@c;hAc{;LJ=`+X4>S=8%pC1aXS$x|0KCAYc zM9~nT2(Dj`)zTk5UiPgdE4nwoNn(phmBykwzqf4o)3m5%4@>r)PaJnxwUZ{!P;Z*5 z$$hsgd4DALn$iacv+Fk>wL0O%a-hbCQ#(QS)%w<{or_vNv+Fpzw{Dv8yfP{9U4yB9 zv+0S1L>HroLyDgo_Qke+)QdPA*XFwG`x>TMQ)VpYF`eQ5$E^8sxu_D8lTn1_A+gjw zS01dbUT{!e&vy}9{hLl>h3_T|Jk0maf4tXbF_hF{uJ`%Kv_?wQ)cm;DW8dY6cFmMM zro*Yzr*7hLZdJ>+=aZ&%cm3@*NUAO^$k9(#t4y=Id+O7SZ<Zw3#yQ-VzwVuvrNiCTbHMV@&odvsnBLv|kJ~V%^oRqG z^TE!#vpMWn55C^N%fR^V-C2RwznnK^G&e1`af=N+?3&xG-u(M6)KT{Ojl=|F->9c&?;ZTQJf*iS(dy^F+}1z; zKCZI0He=vmXj0&4tzo@TU(B#Xo^i9PPsR7`kw0Y|b3SZHIN0>myoHrpOeX@w9z+bN yW1voAfw+(p=uUHX2-|hG$HoNJ;P@-GMpu;$Q+aaNl%CQD6^Wj%elF{r5}E)*$Wh|} literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/text/zalgo.png b/crates/resvg/tests-hinted/tests/text/text/zalgo.png new file mode 100644 index 0000000000000000000000000000000000000000..376c256d3ab02c51432d072e4ed965d30054a16d GIT binary patch literal 3110 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/150-on-tspan.png b/crates/resvg/tests-hinted/tests/text/textLength/150-on-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..6e2e7d4c3f62895e9007567999b40df9f8859501 GIT binary patch literal 1459 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfizao(9lp{Uk{YZ&CP`<@b~wJFkD<*fD9`uDQ~YHBJeDM6G$ zNO5s-At50Mn~#qV!eC=#gD{wxL5}>->}Lt2v`d2gf*lwH6b$VB1L6}BGV=>+>l@np zCr+3>d(Qj?OV_X8u>Zi}v*#~dzyIL%`ww4_*Id2Kz`!!k)5S5Q;?|oBjBHJg608TV zYjIWgSA5?e|EGo3j>Dw56AZ9G`sdzubJ zh4-{I`Y;w;h+M`?51`$qDzEQ`T|2XP|CuPuw{c~D@?~!wjz-FMFcqkIYEKb$7R*@a zwnF37p8vn^a`QFke!0&X>Cnv1u+Cqf{<24W()c-di~E}IovM8Yg}vu| zIx=aw<;EvKrc|xH*tC^e?*;en|1V)Fc9s3^we14im{w&SQOMdK@v60Z&$=WX+q3OA z80y((nEVm?>~P9(Lr#BuWppMlw-v*_N6*i5|IpQy<9gkec+9DT^=p>k$`=0*A@mU$Kk$Ucv`*wD@T`ur?OK)55>fU`XOa4zGaJs- z1nm8{J4;gR`nrEVR<`Wf@M4$M-hD1#opknzUR~6p`=ssby&ddaT9ZV&*?z_qbE;34 zo_5n{B@jVvdzg1Ma_36Y%#>a~4 zKbI|c@tdg}cKmXP)wH9oIolRH&+a?gKl8G~ZquE9ACj%a@_X)9l&f3oxG(iQzG(lw z4YN-1cAJY&+E{XaeMqUh^^cv22OY$xb$yL`b2{SQ!ShASMNYe{X=2;fUv&SG|2?@x zez{zxupeGqyXBtf&i%7)V}|XK?Vbm?;#NlW%#&ZSYxl87)88jo9(Wjb>HpIgg1?`hys0U6Ly^%tkkh-K{1;3s>s+wLX@`rNGbzRJcDvHtAJZ9VrmN`(KZvpiUul~A~V(Xm6dNhXEKE;Cb9 zRCfXAE3K|eNq2Tk>FiSe+@d&bRYLGeriqi4?s48Z#HIC0;jzfl9|kI#TsjWF%W@b5 z7+4Gh7^ZCaza*h)eZy&v>&y2p&&+&(GT`05c2;gNornzy2b%^PLlxpGZ;0EbL0t%S rXA|pdwKWTQmOMPdwM^yYq=ZvuMUNXl&p2}sT;6%Q`njxgN@xNAo_tce literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/150.png b/crates/resvg/tests-hinted/tests/text/textLength/150.png new file mode 100644 index 0000000000000000000000000000000000000000..6e2e7d4c3f62895e9007567999b40df9f8859501 GIT binary patch literal 1459 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfizao(9lp{Uk{YZ&CP`<@b~wJFkD<*fD9`uDQ~YHBJeDM6G$ zNO5s-At50Mn~#qV!eC=#gD{wxL5}>->}Lt2v`d2gf*lwH6b$VB1L6}BGV=>+>l@np zCr+3>d(Qj?OV_X8u>Zi}v*#~dzyIL%`ww4_*Id2Kz`!!k)5S5Q;?|oBjBHJg608TV zYjIWgSA5?e|EGo3j>Dw56AZ9G`sdzubJ zh4-{I`Y;w;h+M`?51`$qDzEQ`T|2XP|CuPuw{c~D@?~!wjz-FMFcqkIYEKb$7R*@a zwnF37p8vn^a`QFke!0&X>Cnv1u+Cqf{<24W()c-di~E}IovM8Yg}vu| zIx=aw<;EvKrc|xH*tC^e?*;en|1V)Fc9s3^we14im{w&SQOMdK@v60Z&$=WX+q3OA z80y((nEVm?>~P9(Lr#BuWppMlw-v*_N6*i5|IpQy<9gkec+9DT^=p>k$`=0*A@mU$Kk$Ucv`*wD@T`ur?OK)55>fU`XOa4zGaJs- z1nm8{J4;gR`nrEVR<`Wf@M4$M-hD1#opknzUR~6p`=ssby&ddaT9ZV&*?z_qbE;34 zo_5n{B@jVvdzg1Ma_36Y%#>a~4 zKbI|c@tdg}cKmXP)wH9oIolRH&+a?gKl8G~ZquE9ACj%a@_X)9l&f3oxG(iQzG(lw z4YN-1cAJY&+E{XaeMqUh^^cv22OY$xb$yL`b2{SQ!ShASMNYe{X=2;fUv&SG|2?@x zez{zxupeGqyXBtf&i%7)V}|XK?Vbm?;#NlW%#&ZSYxl87)88jo9(Wjb>HpIgg1?`hys0U6Ly^%tkkh-K{1;3s>s+wLX@`rNGbzRJcDvHtAJZ9VrmN`(KZvpiUul~A~V(Xm6dNhXEKE;Cb9 zRCfXAE3K|eNq2Tk>FiSe+@d&bRYLGeriqi4?s48Z#HIC0;jzfl9|kI#TsjWF%W@b5 z7+4Gh7^ZCaza*h)eZy&v>&y2p&&+&(GT`05c2;gNornzy2b%^PLlxpGZ;0EbL0t%S rXA|pdwKWTQmOMPdwM^yYq=ZvuMUNXl&p2}sT;6%Q`njxgN@xNAo_tce literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/40mm.png b/crates/resvg/tests-hinted/tests/text/textLength/40mm.png new file mode 100644 index 0000000000000000000000000000000000000000..93ccd5ff99d62f1be7049a302bef693bbaf33fa3 GIT binary patch literal 1472 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfizao(9i%BudlBMlDWCL5H+!}vHt%45Vnhp3xokwX=rE&Q3(`LQc{A5%gD$; z7~Q zP+VKz(B3~`_Ut+H7pz~uVdwq>htHnBaQ*(n2e03M_*%=g+kt_BWwED=V@SoVHy4&O zwlIjW9xS(XQvVV!XL;lO%&V)_uDct?PWC%$l(aQ)VcD@$uB}YmVmc8U66R_HiGxk7 z-e8h@8i);)0g|u(wt`p?X(}_U`hpr+xx-8&n0J>QkkaLADYTjSM9Wo6WA}ls?xsyT zr#}DPfA8y~3kjwrF8n4x*c-$vRR5jOS((LXB0g=+oBAV4rn=4A!Ixi{M4V02sr1?~ zxv$4{$A%+I#i#B0bZFA`_=ra$dODfQ>_o4*|639N;GV-MMIiy_fF$?W?Sde^|b!NUx9s^MmpT$tbNRD zCA`b)1SI`l0@d%^^}ugpvSIb#%@drCw_R;J#~~Tx*75Ye`!VMmFJEkU;PoV&JNe_2 zZ=x|~Ryy4YuQ#4yh+nq&aL|v%PF+vWZ(lTf--a*3cM_D2Xni}n$oz==ckb0kXLLz; zvl_47@a{pJh+-Jm^qbG$_8s!?uc&`;RWIVo;pr~jQ{Oa&9(+3g+L6kp{qGy6e%ksY zC+c{+>Ai^E%+nq&?>LfmV$or(heo$IX6;yGKl|2=4I<~yrLAH57vr`k9_Wj+_Q$sf zp7x7dsaA0Jdh$b_^ABFxf+-=#i9ujczH>f7vKq_gkz^G8Kdy1kXP?uQ?B=|;4* z8~ibxZD2iz$$PcAm=qUh7;m`HEzPplYZo_Kg!0Y!=977peMf46qyD8!D_Z!=+}G6K z-psm}`8l?ZNl@27Y^neILT+7uEjQS{V0unp|$- z%>Czhf-BxlD%xKBBgb>6>6Gie*LN)6a=i4-q3rrZ)8i&SXALcVK8;OXk;vd$@?2>`}lVzK}L 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..6e2e7d4c3f62895e9007567999b40df9f8859501 GIT binary patch literal 1459 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfizao(9lp{Uk{YZ&CP`<@b~wJFkD<*fD9`uDQ~YHBJeDM6G$ zNO5s-At50Mn~#qV!eC=#gD{wxL5}>->}Lt2v`d2gf*lwH6b$VB1L6}BGV=>+>l@np zCr+3>d(Qj?OV_X8u>Zi}v*#~dzyIL%`ww4_*Id2Kz`!!k)5S5Q;?|oBjBHJg608TV zYjIWgSA5?e|EGo3j>Dw56AZ9G`sdzubJ zh4-{I`Y;w;h+M`?51`$qDzEQ`T|2XP|CuPuw{c~D@?~!wjz-FMFcqkIYEKb$7R*@a zwnF37p8vn^a`QFke!0&X>Cnv1u+Cqf{<24W()c-di~E}IovM8Yg}vu| zIx=aw<;EvKrc|xH*tC^e?*;en|1V)Fc9s3^we14im{w&SQOMdK@v60Z&$=WX+q3OA z80y((nEVm?>~P9(Lr#BuWppMlw-v*_N6*i5|IpQy<9gkec+9DT^=p>k$`=0*A@mU$Kk$Ucv`*wD@T`ur?OK)55>fU`XOa4zGaJs- z1nm8{J4;gR`nrEVR<`Wf@M4$M-hD1#opknzUR~6p`=ssby&ddaT9ZV&*?z_qbE;34 zo_5n{B@jVvdzg1Ma_36Y%#>a~4 zKbI|c@tdg}cKmXP)wH9oIolRH&+a?gKl8G~ZquE9ACj%a@_X)9l&f3oxG(iQzG(lw z4YN-1cAJY&+E{XaeMqUh^^cv22OY$xb$yL`b2{SQ!ShASMNYe{X=2;fUv&SG|2?@x zez{zxupeGqyXBtf&i%7)V}|XK?Vbm?;#NlW%#&ZSYxl87)88jo9(Wjb>HpIgg1?`hys0U6Ly^%tkkh-K{1;3s>s+wLX@`rNGbzRJcDvHtAJZ9VrmN`(KZvpiUul~A~V(Xm6dNhXEKE;Cb9 zRCfXAE3K|eNq2Tk>FiSe+@d&bRYLGeriqi4?s48Z#HIC0;jzfl9|kI#TsjWF%W@b5 z7+4Gh7^ZCaza*h)eZy&v>&y2p&&+&(GT`05c2;gNornzy2b%^PLlxpGZ;0EbL0t%S rXA|pdwKWTQmOMPdwM^yYq=ZvuMUNXl&p2}sT;6%Q`njxgN@xNAo_tce literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/arabic-with-lengthAdjust.png b/crates/resvg/tests-hinted/tests/text/textLength/arabic-with-lengthAdjust.png new file mode 100644 index 0000000000000000000000000000000000000000..69b7f0f81bda7ae83de8fef2b869e9a2828245e3 GIT binary patch literal 1870 zcmbW2dr;C@6vr{f$5LQw;^cEfvei&i*B+*^DW(!ap};T7#3r>A!Zc-DMQmL&GjmCW z%IsxP##7AqGc!{$DK#lv(;Dq*YWOHqm!+*gx7pq9%(rnR!CF3rUcqXZl}^mth70xA@qaBC3ll`_KzITw`Q zH`11d(;_=9ksy!(G6=Id^k?H(FYZQ8rTYcQsH-%HDKOU-HAqYiHQ=WPHEHUNM7UIz5qSzSm^RXL zDM!q&ZPGlx-x@XS0_HJoyk@*NC4pA6kc_wtLX$@9n;EkB;0O(>68P(cTV5|q%xy)* z<&JgDl{(SEjJOQSlNv+&CyNJG0E}aMS4#8&L-Ql%yY0qdx3J(4%j6U%DA`nP<8nv8 z?*WAATjo+qo9#5SclPn*xvA2xTDLoWxO}G$EQE6M)+H#EYuisKMd<6D{gU4KS0< zgKtLL~oVckBrcboUGkPKY7q>k1AAgvfMO(f1Fxvw6upv9K3X&5e%EDHq%Oz^%xo1RVPHVSq-5j^-^^F?s;DkIM z=Y2V7-d^~gyg*K>5L#`ZtU@dVisD>DFQz^VD&gL)xpzQt*`th2V&z~+kM@bkT@@A4 z`PYhWx$Xt}7{Zvfg=g{z2nvZ&i^Es$>L`KRpBxI=(9?ZA0f@q)=6t(Uha|Ym9WSuu z!ty1GheoL6EwK@#H9iZ9_tolwCVF;i)>LxNY5m)z2^|S`$a(Za3;4RBp3@eJ2vmspjy!!NfjN2CpX`vm`^=m=I9A$u3>3K z(zo-cr(B!Wobuw*(Jf=tl17LS&Xu?q%Vy4?#dR*I+Jm`?I5uSvT|{?gdCmc-TGxfD zXB{%SJ-VYJJOCJ&1XxcqJ6zoWLD%r5-C@gloT|vt9~1437rZcROT}32(8Ozq4Cl~* z!U}mk(**j_x01!iQi+~o=bZ!aBrCZlwy*9ilo?Io#{)6>HSQ=MHP$nJ+Y<>d*J1_` z`d)clH9I{TOJZ0p&wm{|--Rx+$TU+P^HwgL92~w=RB)GA5x!N1U`nSKn=&qZbUl)# zc(-0S_wgphR-x@K**!ILqcK<>%qu0Izq?bPz6zuQAw8XDBb+j@g*$&)pyC=^xby7R8N2?i=@p QeEOY&{P7rxFYVXA06uOWLI3~& 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..1ee10e5ba119497b8c945492d44640cf29b9d10c GIT binary patch literal 1693 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBZ z1o(uw0%_s_A0J8yg!J7nhQf5;HS%Y;3H!xVV*-m5`8-p`l@YeSJei z1JKx~)x!F4Nj)Oq!!Fgh@ z71)h+p3a|ZJGU1Q@l)zPfk=g*ikW}lmr zy??@nM=P63+rIWXzh=r_nJ^bWINs~b zD6-E=dFEXMW2vco{$JK@+47)s$@)_Bd*^;y%(=g!G5UPRQptbu5mGOn9}H62B(cUw z#QS{n)x`a5*DhS@tz)-up2eHJWQu;HX$r&B>Bq9tcO<;BlgoZ$`nvdo@r|7ubR;^n zGS*hS>dMfW{4wg`VXvdNVmr>wjnb?ApH6=}C7S zf3>6fwvfvFD8n{ew-srJ9>q1iHdfQLVvvj5ab|nQ8paHE!C=Nsdbb72E?qEAoXSw{ z*0d`(QL20Ut>ca^jh%;s_FUN}dBNtC%d(dYS)7NZ(yR_LM?QXPWX>Ot_FP(b7ed%?ZDGZ%0iJ_YlJde7U^Y^cw z`e*4?dCTS7SKaaZTWhKJ%R^^!^+q9v5QQ*X{;*T~v;S)(Z_4*twwYD_>cwp5v+>@` z*B2OgDTG<^Pg7|L@7-i}JoILUj;D6aVHJlBQyN#Qy;99JA1xziOJ$WpWg4=o_ciFs;KXNS!rtouUtP`bTjU{=eg?2PwrJA_TLSE z^wmTb%brpA{N%XT!f6Z47IU>dxZTVcm&)%CYv|azQKBE~O^`Dx3QaJMUrRD33vJcI_ zTdY=1y86z8OTRi?>(1jZuQ%+wXxhK}YVPHx%~5L8d>MYI8GgNLz2TSJyPc&M{wzMC zSMHEB-}%jVslSD*F7184?26ihRli*QC!44)Jz}P^;=xnD_>W=h&R%lQ*HZrY)iC?8 zA>*g2DGSWFGgHl+W6gyN>hs(AbQl^E6&TF4R;TCa+0d|G@ZyzDG0_X v1QSz|>LN}M+i_59{;t`{@+@6&)n(Te^0^BhaXl6&0hjllu6{1-oD!M<+Ct)5 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..6676ff8f180550d67ce0f5564d0aa33ef5302a0e GIT binary patch literal 1465 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC^ z1^9%x0_pnt`i6!EAOk;eadDB6kzr$FgDCU&_Xp|%>Qz!w%FWHSw6p}u8X6jEYHC_p zS;fZ23JD1TrMS4bn3 zs@t3$1so2#|1)0Pd+N(SadEfniL0{PU;AABHhJaRMJmA|fx7}0;6=Kzi*pP6r zsWkdv6DzlvP6UM9zye}#NZoq4X0R>wr-3w zKl(ChZ`u8b_s_eh>VLA&RA0j%QMsl%;^jQ9H6`&IKK(uHWv+5vr{qaTqQRSY1~SHv z4c0vWEB{X8-2~%6?R`Il%|c#Y{xfmzZF3Q&)Ak;ZBnD^xWwuSEnW=h#V01EEflJujkbU|P2CaI7T zJApb^&o7B8OB6Nj{1YxZIRPbB2BfVR&Ki2?wjD+?V_vS zW|_@+w#DL-*W{zCHI4h)g%|onO8!w^YL!~GRxsk=VrI4*vlINcX6pD%JKe_nL#yTJ zjycc~kax={-Mn{;7vH zctqDkq=d{uwT{C1hIg1YJARC1-b)yx;ckjh9W(D&489z71VF z8YO>UuG)6zn8$twyp_=e+rz z?-?1X#(jsuTw>bR?4@s4J>I#-JLb|&HSSr5bWW!$KCw?zj;z0zJDt_9+ltF8Vq0kW zlaR~jQykMb>KrQMj+wOm?52`@bN{t-XXAl< z`T2SBW%ZVa<@?r`%~AgIFvERL{GUJR^B;u=F?4BZoczpqYkM+N1A_*`B7^_EQWxxH zG#D7}xmNs672nFOy?6N{pZ6yN-tB9rR?ecjIjZ1dg4G+6>!(2r0eGSDT5Zh=@g*}h hOk2vRoiDy@4?Am#3p>ZQmUd7%=jrO_vd$@?2>=^+K;ZxY literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/negative.png b/crates/resvg/tests-hinted/tests/text/textLength/negative.png new file mode 100644 index 0000000000000000000000000000000000000000..6676ff8f180550d67ce0f5564d0aa33ef5302a0e GIT binary patch literal 1465 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC^ z1^9%x0_pnt`i6!EAOk;eadDB6kzr$FgDCU&_Xp|%>Qz!w%FWHSw6p}u8X6jEYHC_p zS;fZ23JD1TrMS4bn3 zs@t3$1so2#|1)0Pd+N(SadEfniL0{PU;AABHhJaRMJmA|fx7}0;6=Kzi*pP6r zsWkdv6DzlvP6UM9zye}#NZoq4X0R>wr-3w zKl(ChZ`u8b_s_eh>VLA&RA0j%QMsl%;^jQ9H6`&IKK(uHWv+5vr{qaTqQRSY1~SHv z4c0vWEB{X8-2~%6?R`Il%|c#Y{xfmzZF3Q&)Ak;ZBnD^xWwuSEnW=h#V01EEflJujkbU|P2CaI7T zJApb^&o7B8OB6Nj{1YxZIRPbB2BfVR&Ki2?wjD+?V_vS zW|_@+w#DL-*W{zCHI4h)g%|onO8!w^YL!~GRxsk=VrI4*vlINcX6pD%JKe_nL#yTJ zjycc~kax={-Mn{;7vH zctqDkq=d{uwT{C1hIg1YJARC1-b)yx;ckjh9W(D&489z71VF z8YO>UuG)6zn8$twyp_=e+rz z?-?1X#(jsuTw>bR?4@s4J>I#-JLb|&HSSr5bWW!$KCw?zj;z0zJDt_9+ltF8Vq0kW zlaR~jQykMb>KrQMj+wOm?52`@bN{t-XXAl< z`T2SBW%ZVa<@?r`%~AgIFvERL{GUJR^B;u=F?4BZoczpqYkM+N1A_*`B7^_EQWxxH zG#D7}xmNs672nFOy?6N{pZ6yN-tB9rR?ecjIjZ1dg4G+6>!(2r0eGSDT5Zh=@g*}h hOk2vRoiDy@4?Am#3p>ZQmUd7%=jrO_vd$@?2>=^+K;ZxY literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textLength/on-a-single-tspan.png b/crates/resvg/tests-hinted/tests/text/textLength/on-a-single-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..77effeaa0eb4eb1106a0e9b810f9ff0f9b4e2c13 GIT binary patch literal 1393 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 Zg&K^wOS5Q{{fEKtQ`OV literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/complex.png b/crates/resvg/tests-hinted/tests/text/textPath/complex.png new file mode 100644 index 0000000000000000000000000000000000000000..3f077d418ea067278174f388f6a5c6e6a77b0586 GIT binary patch literal 4903 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 BHX;B3 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/mixed-children-1.png b/crates/resvg/tests-hinted/tests/text/textPath/mixed-children-1.png new file mode 100644 index 0000000000000000000000000000000000000000..43a60a95d2612d4e51f184f6490537624ad6172c GIT binary patch literal 4291 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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..9f19a3c946f4200c05f7f3e26df010ed07316ab4 GIT binary patch literal 3775 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 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!

#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/path-with-ClosePath.png b/crates/resvg/tests-hinted/tests/text/textPath/path-with-ClosePath.png new file mode 100644 index 0000000000000000000000000000000000000000..a467e219fc6fbfded906d7f33da4a6a111806984 GIT binary patch literal 4825 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 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..7de61a9c9cd374c105b234b7e0cfe34a8a29a928 GIT binary patch literal 1677 zcmcIkjaQOq6n_yJilNP5PB)e1EX-FjvlLqcQzSpaw-N_x6Pl#iIenT^IzSRD+9{mz zdaO2~GF#dtTy?fgQFBWzwPkM88ELttSt|1*iewLQPTN1wbIx<`@80`+?!D*Sd!EAx zhfO4S5g-U6#;%Rt06`eocAc=m!#N{i1LeGPEq@OLx!$l{j5^Tu1K>0u2}vxV?MEt= z0$`T_z%WSipZUgbCj%K88v1_%z^SRJ2!hxNY__c|I5L?GNc;2L++3Rrg6MQQ4u=Z~ z33(G0i^YC^ei#e}L^CrpIUEiai;aniq0wkWBGJRc1CPf8GLOdtC74WRczAela4;aZ zyEIE|8FMypHZr046iRR~BQ6m^(glJYJEgLN$5g5cO=WehuCCG0)z#g7*ZAP?kRqlNz2Z7jx-Vlkj7U2#XCv7V2}5Hv4ZJ9lw$twFjmi5UzFMZ9J&R2K&eiSayt zR9Ea@;~vjzaZf(%Un6v`zTw`hE8=c;-o|TQa;azqEL6WGIzd-7t-QzBJ$A}v+ufZc z_CMCJci5M&TsnJqYs}-mb)~mbweyLR~`_bQugPT(&PEm`q%j99By1t&lXiW+UQ4~D)s7o)nw|>=VcHKDjPE8J@Pg@ z+Jz+Wi;rf=Btv+!$h>L;WLS7DQo^4*n&7zz+s(DVUZ6~(9ZSAM#SsEKx=SW!VyozB ztyiQ$2#G%@xL19B#l;~~1A!EST1!-$zPnN#-eD$N>U}_GZpql&gH;0-cd8P$4sMLB zN<7JRl(>-CsC9xLRUT?4J_vYEXpUE-rahZzMZ;!H{bwaeG|Az8MnMQWy2!L6$^kmjSp#t+;rb}h5TmRc$ zf7`HK0xPzWeKD=7;YQu)LoSJ`fvt*4ZjNkBZ)s{jK!Y!y#$+5Hc0(P>FEk*04y@!4 zN(YvDc>GZEdW}wR@xHT!K;nXpOkowu+f8}V)#3oKf^$c+$UATZYKJepZgQBTQGtB! zk6$cgm65HpI*WeD>Vu{yTZ}EH4y6?<`IMj76moO_$oL`V9Z_Xw+b0ezbUIYpul>Rc zVp5z0W$Eu58&lm$ALa*YZ6A_<{CjUt^@j2FGsy2{tblUlgiB*?#9!wR>B7PH3&pZH K(ciBT$o~aA1kx-3 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..7bf6ac6a66b79d733bdb154b2af2fdd701af0813 GIT binary patch literal 3331 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 BHX;B3 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/simple-case.png b/crates/resvg/tests-hinted/tests/text/textPath/simple-case.png new file mode 100644 index 0000000000000000000000000000000000000000..91a6211320852a92d7b8fc62603b320f587f1ec1 GIT binary patch literal 3485 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 BHX;B3 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/spacing=auto.png b/crates/resvg/tests-hinted/tests/text/textPath/spacing=auto.png new file mode 100644 index 0000000000000000000000000000000000000000..91a6211320852a92d7b8fc62603b320f587f1ec1 GIT binary patch literal 3485 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 BHX;B3 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/startOffset=-100.png b/crates/resvg/tests-hinted/tests/text/textPath/startOffset=-100.png new file mode 100644 index 0000000000000000000000000000000000000000..2e451f303f7b7833b050e3a556a86200ec138e3a GIT binary patch literal 2354 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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..08fb289ac16beb2d7888d4eca8f188035ee58ea2 GIT binary patch literal 3414 zcmcguS5#AL7Cs3*fJCZP5hYTBgernak)~8B@enT>DFV_(x|&c#AV?WQE+Qg`NDGiq zRH~p91pyW5Ri#K#IzlL!qt2SQnWtH^*V^sd_5YuCyp5G9FG36f008e9Gb397fT4de zCkupF<=!%d6qmo5V;}(RYyQQsG{t@5P)4$ig}pHp{7*#qO@E?)Y$A~e8Gqy-{?M16gI8ylO*$VkWy4Go1P9*_6;_m`HI_VDm9F)`ub;9z5813?gq9y@l7 zot@px%uGZ?1j1QZSlr#+p(sRNUS3d$hlj`3))sOR2m~i5r=_JO3NlTU{GM5(hvm4*1*t{H{ z=*H9h36IK{Ougi#OH7D1cHS_VTMTCZ_qCO+fwt|RW1C@%Z@P{A?bXTp~`x!n<@`K zY)(Ntmb=!IAekcj+xZ_WFP%4MEz8PnBOI%%y31`xl@tSA+LD6BZ$|KuD~3H0Q^x=zg_hhXom6V?ySl*m(9u54Y6HGZ2FE=7Gm={t}QI#teb zc)0m}>#e{$;446%lVGZocvHN4KsT|<=d20m3G_W*^!BacTT<%Uqt@A^wjw3sO_ptL zDz~176Eo*>V#6VoJeT^w>$f`Wq9!g&oX{!i!=&BK8zWW=7oJzmb;DB*H^w2pFD%mG zo8@#K>gNYOZxShIkdH|UK09K(qX7>qGzH`GC@;H9u{1uqNdc4jGiIChMZp)^Q0VFB zGr10@?=4VIFeT+5GuXhp3V!A9c2}O|AH^7=YbNPM!*EP7e+ZV5aC`NG*yU=4s@Yw) z-FJHf$I}Gl51P03d?>nS7sXz4cCXV>)xJq6G7lze+Oy?hsY0m)ED58}E|f88AtFC~ z6deT{7dd?fSJLIdE1`Ao-o2|!u0~?wHoozVQ_(u-lZMI)kB3XnJmixi6B^VqL@j;g zEwxJyx7WlCI(ki%u~6P*l{bS5N;4~6UA`}wdBY;g7wbYUX)<>Aeso=UY0AIh(gM4Z zW1$X4aKJE5$w62)S~(aeVkN@9BKI)3cC9DiICfVJ2I_Y{}&JOy>ydFjUl+LucflC0(9Wn zkTP%2m+~EtN9o_Ty5C9W=ClI$$0KB>6wFyn-um5wOXG2St})4bL4^&SUA@-#zt@Ze z$+N0r16iEvFMm6>^XF_Gm-Di#+_;zonwSvw~wnW-$ypH8q%e5?mY&@ic}2uB6wzSQ@n$^ znpMQOEFGunb6EsoJ6pjH4*YAB@ZsJe?@tfNsKM%(Q@Vuk^;XpW!NxeV(RSyrNuIl# zQQkW8-*R`?mTshJ`Bcwy0`zilw)ofuwAZd#-xXWUf5eEDWMoL}z=$^dqz@A*q0J(G zd>uP|LuLY%;q9+m?+~A&u?^U*t8F>z0qVWH3}*A}4S+TFF}Q`BGI0)K571VIHD$Gf zlga6QqPYEO^GxMmtOUu3?4eQ&uM}){ zcE8ydeOIl*87H1p16s`Icz?W~FJIg4@kRmyaHT!-cwd<6|eHb57rG5#1-DLA!oS&4~}DC>mp_fU$J6W9fJWy0*E-XPP`fSk`_n zAj%TC=wu?Ick_s?jb|az4KB7ELwjgKLRb}luA_mk@OD^>lS0`jCk3riYCR1c`x2wd zj%pV8e4&n(pj;xtTg-|lXqIeulm!ychg}xBgi{uyh{8F)Tu+K>sdSzYx(KpSD76TR zxx26)oLFQg!kuN{8N)lGP)-Z=EFlIx>!BuX`BZTM5)8HC(-YlF42v%x5#WzO-|j>e zU_nXj7RV97EM#vKDXmEex}um}X=X8fzNiyP+F8TiwQs&QS0XbVwo32~ES>G1O9}_s z$ik^{!tUTxDPy5gd=FLi7s8xVik_~v2@z}wABx3F3=o|(JX#JM2DI?vI0t&>Q7LO~ z?uyV;CFxw-o{S(=vg-=it;X{NSXrsJX_)rzyf!0 zI#otEZHlcup2JA~LR@cEfgqgrQn}-aYM;QxGxUgWt@2enMI6HsnIVev)0%~Mjlaik zuayR%fYnb*q2AHuAC~tHo(V$dH>8sC=z7y?Kkp$Inviyyiw!e!$;S1W5h%Mx9pTW8 zniV45B1cKoUS@S8`3lkF5|=8{)HtC`957YHP$wvV^I4gc$| zYk!MN;<%{`ZiZtSvt$+GY=BMzt+`}ws;aTQUp1`kw&}K%w_kVu$R>x>gd~F$Y)t3P zmZ4C|ZO%B~F8#HNZKDNl?fvIk(2=S5&b_vQCvL@6O9fXX8 zi2F*@U z{lS66Ncj&jx_vT@aCA9f^x=R$QvU+F^B+u>Zp^`RAV~<5y2qW`RZz7VG&~lV^e=)62P+ z4*+GTBn=o!9fsFK$t-IDV+5Cb9zOJfoeiCeE8!7R#JC%+sa>`^%tSzK`05Q-;MokU zQOB>gvI{gCC55D1IU>iNa&rrVlM1KKMNQT|sSc!@S5AYUYQvYk03?=G$;FY_MGqx- z=xOdI+hm^0GMD?t-?dOD1%6_}G(7dmfpv`62meY_y3;343eY&!IlFZd z)~fCX-hV}!ZY$Q|9lRFbCq~L2q(pnoR{AXa+UHr+qMF1l?XM*CvzLz^(LM+!&fA6b zwSs8h?*^{o9(M-0(APq=dNW*>*M@9;|JoKHPBcn0>Ad=fRe{O95?R#JdHG@8$ANLi zlfEHOcBbb+qYJqB6|RM^$6?;JMl;-`{1M49!mQg7(fgzmkND~x&yUASoZ2xGxxSAc z8eY;>Ptx1kQYHkP2$5yrKJLEgaeloh;k>Nwb>Vav+2G|kQ)g+etE($5mmoRvB5XPB zGxo0a>?4=FhlyS#!L_?Ef4j4edW?ST-5|X^3B{wWPXqa2t6}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..f36d05fae9b6696d996ab079bdec1b893c3d0484 GIT binary patch literal 4427 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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..3c4f44a649dd9b7580e89ae14e1f31bcc205ef83 GIT binary patch literal 3775 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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..a5bdf49797fbdc96c2aa3ad4f4ce2b21e258a95b GIT binary patch literal 3573 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 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..8427034e9749f6319ab99794ce292a40d0ab1b12 GIT binary patch literal 2808 zcmd6peK^y5AIE zygVEZ4-O6nkJix8pin6K`uYG903im00Ve@9xWMrMaB5J4xBtGr>wi_hlka!@56|Du zf4`i6wgdl+9m(#uL3T09!;Ju7rH<47Go^S*UpT+FBaBgZ)L>Z3#4<|p=^34UlHuMu zsq|=gdWXBabXgkqS^D|QB7a6Im3HOME_|+%n$2IF>mOU2aa`$@JUj7XVtI6KK{_j) zSoHR}y(o@Pe;wx^RyX5VQp)d>`1dmK!_za<1{tWC@QxBylq$AU%FO6wq6}2;`7OKw z0L2Jbr`?C?ucrEJWq{p^0IG+6KXdJ%%nCwHtsi+Xpg!AuP`K_%ZcaV++phgwBuNlp z`2UbH1+-|fZ0l)QN}0Jya%?PhgL`M+<{{g*Pj%*|5u1JYez;J4Y}c{S2Bg+BjIcCC z-K-bb9FXR#qW<9~e_`yn#k%BqIWFAWOwEx7B+f`@duSlEy93ZX^S z##J6Ig6Byaw;6{V66dZL%}@_Y;Z-AT7aZv7olL~`-}BZc_^@c3)q-l7b4=UHX7#K_ zvDJgfm(W#;KS>!lfiscratgLz3YXT>plYy0uYP^Zv*zgs zX#Ldc&HY7#do*h@a8%5ZYll@y)@OE#gI9<&p6SQq&wnRrmR)lz{3^gXye-@lU}4X_ z9YH-kB*r4%O&?PjQ+X`T7*5rR(7MAq(LvlG zjuVT;8@BlW;G--kWvtY`;P^h`Z-3lYN})d`JqgZyE*fZNoyB@(CPAT{?32SWjw+Q) zOY!p?hp_kX)(Ssa{84NSS=9hMa*ej=Tul*_rN387VYP1f!nFTr#I=dx4jAs&^-DJ~ zhLp=$2-PiHn>$L}$j^^x+4mMPWCpS|G46{2F`XEmGuc^NPGicwtVgKkB2p9lK~ZcN zwHxAa!QrurS%%lC8u$kuPee;-I)xYguhOt4k)Pkn%ub(-WyNdf3=3 zh}5EU`xJ+pS<&;>c!3bfuQWA%)xPiRramtttAZpugS1wud)8&4d|wT<<8*9fplu}| zDXw*Rkigr|p(%W@pAODLXI3aJWuG#eX8J(`ZwQc=YvY9Lpy{IJW3#lyy#=SB!dQ55 z!eim*>-bR8OKpaJ7Q5gi)%VgG|D3Hk>z1pb(gYJCoEF;#}wa9RVw+w~)tlkOuH9MRzMWTUdSX*C^!kggnjXeD+g zbrbS3>WfV{HFv)uyi%MyY{t_a9g-E|XGQ`%Pm`W`azq?0B(H8f=eZ z=wo}+I>NFf%92aHZ}rFU05h&`M^w-yOUe$fTzl8oCK4NR9ClwOATRIq*z#klHR(`#;zv(0jWbj#*D_ynkT2Dj|ot4B2?-&wPERh}4v$FhCnWe@er zEw?fY_o5ItJ(72oS&fh{oavE`zjC>w*(0{Mu)I4drF2;Rk{~C#VpLO&y z!Vzf9VGTvowIOjMh;28iMy`zVPYv?+@RaeIPcoB8QT4#t#A6y%%h-sJY}Capd3(#0 z1!l*&EJf z?78(5I;;IR!G+phoX^)xrI5*vbETBSP$pT#sg65nxzg{lvO{p588tgm_(rMOleyIh z@{SlUh&+jB&pY`=UBfvY&)ML~s>~O0c#<&I$U9-s$fJa-Q%nOj9i?8+wtu+g+G1Yvk89!4wC23!bSN>i(jA7V>-#@Iyp+lt{y z^_8*km`H_TMUiE7U3=8;(Jc*(k2c-4!Ry4aYcoH$w4WG_L5ld6x9fGj^*q@*o>diN zckZ_|+d4g6-D1Y_LmYelI4LQJYE3?y+ot-CB4})EL~GY%%V4+*KU9w&T@@dFbv029 z@P{e-o2ui78ZlQA664jCG8^IGmpeen+4et33DtMyzXq~ySZN;9_tM)P>g>>E`qy8Q NtFxO^?H>PxKLHc!%Mkzo literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift-and-rotate.png b/crates/resvg/tests-hinted/tests/text/textPath/with-baseline-shift-and-rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..4a02b42f0fd088ac3a25ea422fc690b07c559ea3 GIT binary patch literal 4507 zcmchbcR1VY`^OV|OA(G8vno_uvyD9twTlorR8-X-wMvROcD1Tnt5w8^5kZWUQl)0? z9knW`O{qgwP+vXg`#aa~-`_vK`?{XzeLt^f{_)(`=W{=gEX@tsSp--B008?V#Ah*WiZcq3sDni8Fr8f+8ZC zfiM9M>US-8eG@imR*WU9YsyuVQ@`(9lxPRg6E@5S-`YfUSZPGkYSr+*uDGSm9U;Ey zKu8L9WTP!k}cr!B`dMsIRI7!kZ|4V7u@dt$MdW{_1?|Uq+(2ffduNWxSX7K+}4%cIv7ymJKJrS6JfTrln zrh<}MDsxCZBK#Rs&}y;`&AJt6o^lcz^H*aQsqFly@c|wcM!G-p4M5<$&D0!tdmA!P zOFrhK!>9$mI~L~@l8|GZNk-Bj=`K(Yxyl(z(ynpNx3-AiurD{eoZ!!|pIW&9*9!M5 zP0@B*R%Rm`YqIB;7>)}IZMU~wQ;;gj-df`P-H3T3PGYxflridZq$NUOjxn3ZQ$kPY z(tM`aKEsI6pS+=A`iMq4YMVa0(bjB@1dnJ~j5`dH9Du44<+Noug-Oz%)`UAnf1@#N zT$tpdl!~%vq#wAs7fTg?OW4%~J<#^EXqnM-6J^VYHs0+wjQ=tS^>qVkjsT^*zBdI&@hbmF~x% zA#Qi=&4~Q)R&IzPC9UsE0Mn_9zT(TDeL3DH)8Xs8U8Rf{^p+Yp(&hNd= z^^@atkh;#em2bN55>cI8(~3FLTVuUrb-A~~bLJc*!G3UJn3{D62$}gSaw(+!K<1Mp z3|%WpXTLS6e*T_30hgEiAc14;Ob6Z8axw8yU>V`fMp1FCV8X%vU0$*$5KEM(Iyrl& z?>M&3-fqPhS9f#utyv}s4xy4^qhq<$|12uy-RJ7yaYiGv$=SXZjb2J9HCvasD)~UUHyah+o*NSU@&T;5HA?kU|#JRRR~_zW)Z* z(-*TYlztQqLPvN!?DhG;<>dj%mV@9GnDY5TYTg#u5YjE;Rq=%<(IBdc^+#0(6N2*e zs}d)m>Om)aG$L^JH@RwCHsbN8sX5?!X6!KQyXcA!&pECFDW8CKo+536bl;4cuOs$U zB1YTmqCpn3;)%>QGtsWM`}THU=e&{jvO5?zsA=dCq#H4AY5*h9DKbZU0YM`Aib7O> zH3i6bv>tKmf_qLMP#{J0y=3CqmZ(srP=+toPEVP=$LE3E$zF@8%_?8`K^+ode$P%MliVEk@lb8-3% zgB*Q_D(gax5*TsNJ#KdUU@v2i>TIB#CL%fuNkp1aBsIDx+G@t^cX=%9Sr@>Zt>5pK zZ?pf=#aHs@UcA`5J33m0V_tFTX7d0#OI79tQe?8&ZKxb;5x3hdbH9y29VH5R`rf){ zxOt7lj*gjb=qh9*xNUTZ(X!Z(x5(R2Nbg4E&qIy^q!b~O!+z{~ zs|u8H8MxsP!DAOx)ilX~hV3x#2N>wLw+k9=aFAVg2v!h6w`Wf8}Tl>79e43*K$EYUP@)?*F&ZP7o{}wZ5B7<6l`Tf z>O;B_8Qi2s#S=cVTI}J@g@MYgsN&i6;8stupJY%HCc?{X?k`ys{29iHNrSUfh#%@m zE62Fz$C`gJ(GWXeeNaqb9A`oCLryb5RE^hWDmPb$EAnM3q<6SB#`)S{4At4_ONtXKK!*2$JRSiLsPA+3?JP?{kQL3m^5^PQ1^0Ng3o>vCsV8aC_ip*zf5`|tBe_( z2X}>k7>ay`C8BMiCC|=RNA!gNG_>6`me=a(tK;v!p$T_G z+>xKtaZV^3DLmxISc6HZeEvOQd z!WZSJ$CRlfRHiag-)c2HV%|%*0~UMz@P-Hf_>EIXYbAM0vl{~YvbqhSmc6dm_~5lMVrmU)NLq`Ssk5P=rp_^5HsE>IQm z*ATa?yB$~CeUPFiJZJubElufFf~UNgP}q#)34;xL$6?MTpYGtMnDfX3(~TSiXjghb zM1A2fqpvJb;Ov@m+Fg3F{ryBkPmQwR@f_46lF{9sGNcKU!Z9o-`Ko7cQ=2g$L>i6W z#@25#=c_9XbvQ9lMTlD|Il=@f{JvbQ7wclUuo^>fAcBeme%kzi4C5SMKMAY6ocLE* z>OKc?@#%}FF(lKw>9-vy)Mz!)^`@EjY1)Xdo)DNl^qXlv;ZkC)%k^MJRbR^CaMQQ9 zK|bZ`$s4btvpz&NIyW@S6WGwOu!X)*2gGkSn;ItFycwIf4(-mKHyVO>sZHm?g>;{%@1vky1WFD^i1S!619HeWwc}H1Z zFsfK?tf}=ms8TEO>~s>7X3f2d|4QR^D#mllKXU5qBN7F)12 z|C2h237EuSra8UZ#op<0(2LX_3E==hI)z9nX3yGUgPhEz)&a6HZ1BB zz&t1)&J1Q^*XVnAz)ZSqE0@4S>`e9$0yssIwn|#?~?hj7IZS1h;<45 zyi4R-98QmMpyBkfQ~#Ih=B?cAUYAl?Y}orcu*2o%1gUac!BX+J6W6!Cy1rwRKntJU zuj)Q4aQK)c_@gLihi%MITG)|Z(N^m?bnuAtXa7YJeK$;ZMv^?5)kO z?4-@q5;-&2`fnMI#OK^&MQ(N0pJ@6ZDsYXorSyLDKIskJGJ@#4i=zX5)5eU}fH_}( zB%@FK$w^jkpfz5xyc8&Z#<6fHrCtjJ}oi_cs%vKW@5q~5A(Y}10)T8 z=vPIpInw&ybH!$ui^qhIyX}*E;)$V)qe6K1v?0%slZUe@f&lsk(g(CJg*HXR+}#Tz z(4LeqDX4u7tQQjh;_jU+J1nViO~pk$wTTI8fS8H=g5#PF?(}c9?9}tJUNh>GiR zGb7(TexakTG+;l@WoEOXwDu5Sx=J!>Ghy%dXx>?ybU zwl+5@k;PpuSrbFMbzhBRNLL=Ls~J(=$IL3ZwY~;j4sb%6zU4r8a%%e)<(o6Y8hX5P z+6V1kutM3lFOeQ~7zMAYNNbJ_=1=yu`|%2~syW=qpCmA3$O5TbK?blQ&mpmlCoF>x zE4$hy{+(s~QX!zJyGFY5dyZ=v590 z15c=#YRHuC9}9~9;cm`F9azEIN1es<9Ob~$JI<<8zMj|=n@dN5d??_ZBB3PTlglkD zUpj-(p+495k^~T?m9<m*>i4WPXJ!4x`4g-jk1N-La6wmVoA#7CoLpwe&gaM{A)}Ktub_N@e%LC z<6AYPk{+ftuU3K^S!ZI2S#rnCI&FVpl9)c|FB`a6D6Fmcb^RJ(Q2A9r+~Y#7S$whk z^M(GeaVr+^BdA9!`b>PeEcNz@xiqAf>nG5l}XbPS(jooza96rXNZs+1VmGbVx z;ga07(wlz}8-n0h$E`~%c23K^M|dt;I_*}6N-^v%CeC=Cf8%7GxCk=5y!(Vs+oH!U zJbdADJ>KU(#k*Qv19CO^FAp3adh@9mpBUU02^n!HqoQqr8RIQL+fRAFGH{*0Q}BN> zai0Il$p3$EcEZ74P+atFO_XC91XtH+r9(XfsO_s0i?AwrZTVHn#?rf=CIYeQx%$uh2 zB$M9^)9Euat7{**mWM!~<2xv%j>X*%--eZ#jxg~Y0fJqCHDDilCV*BOj?`^XS9)p~ z|3r#$jOz^)me1PoN;eB`-Eg!2zdK^rvUJVjb}eaODcI_rE#|6z;Go<4a6#6tM=M?+ z(3D*G_k;cVyC%h^eLkmtM|>o!IHV6Umka{au4Hs>-H^tzw;R~BFy?$M$nhZ#+{7%O zf2bTQHFSETP?l+p+{^`d1m-lT4WamofO;S$tq%=?f(z9Hjy5tPu+0a8v|tuw0)A5ICd6(ernZqpXu-^eso5HYJg`4+Z( zZj3eIoND`IxV3MLZtEbdwnf?*$RejDkMS6b=i1dji*JHp=eR*wg%h@o*gBexZ|xvl zor&xx1aIj`Ukp!=wF* zA}M7W<=U`J0IPsX@E8yH@snlth)oqiV9pQG9PQLTRhPo%%d|ahP@JiN?Z@6L^quk= z?~TH;`k2+q*S+hCzp>sUary%AS?4hb)b_m=vle9%mC?o5*AokD<2A*QllDftoBB05 zngFYEs-!1g5z!Q3K4N{1lDE z-P;2wJYipk&?LfiW@e+BpxYhm+i}BeoWE`xxW`$rG&;wmV6WSsdzyDc5<^~NQM^Q5 zV=MK4=(ETd26JK=q65`<^6`6-l;zrMdeqy<(-b+ZfEXr}PW7{DA~ z?16!-1oE1k8_SXCqE)>yV51j%6YIMDZ2fnmHE1;m>b&W&s!V4qJt7D2%`)_2jojAQGrdhR8qegR25^E8r@z02}u zA*AvJijf94`$-SlJ)<3*8fRlk1NS0<}jXy6K5@$~I zp@wNJsUk8~I%)Yr5HzuGkAJk{_t82o(G-}=eD_~=GEq5lrR3`M6SdwCIo-GGXhGp7 zXw|F8^2h~o0YQv$-OuX|T<p<94>qb%D3d%z56t^LP3(KkIpF$(WmYheGj+m_R68q z4O%X&w<*&|eh?2M0_c#C29j6fxC$3RATDlp8a&ptWT0>|n0X?&Kg(&zdPtjr~UNrm? zZR0$cvBLR4fV{IXj&A*ouE_+BI#qAdE zf1t(-Elg!LzP8hqC}qN&#Ff9r=c$06byB6nK(8%yA6bjmG&ckOSa5Q_djMXfA4wI0 zNJnJSA2B80dJFIc&AE{(t>2?6gN&={uO;0}nns+$2s)pu8c5ypeQD(OT>k~`9gB8$ zL|`kBcO@=z^g!?qFXKY~kU!gQmoBcK(TEEAxid0Wv>Isq3*=q`co@97zq(nz$m{mK zbNYuaE@16ulDC4BwlY%K2L>KE8Va6&fb9|wjT%dchK{Yh36~07e@tOJoNov1e>U z&AK^E8hSpSB`Fsu?C0UVhOQ%nmBN_)?8M=|ZCyWng8;SXn~&p?-8KEsYTGmv3A9zD z)V^2o{IEqA)6h2Igg?fMewbPnKNGB5amLmb)7?GK<0^gG_MnK0b_J>4>p9Up)NztS zLA>O(pVB?O%P|_%l$V323y)%k#qgnx!0zIQwcY1W)@2-zZSrZJEhT#h-*D!~+;5-1 z@*wZ1M3Zx8P)soJ}i*iR3N`|w)ier?_KI(OJs zWiy}x_Kd7a5jCl^So8;HpStD*EqYoY)Q-ZQu)Bc}(PbjdLC0FNu>JA4iNJQn86$HCik0R=PoyCN|EsxN${|y=5k2?0Bm%@A8ZGy@}d`vad`tUxuh5p+EQ(Ubd9_ zS)BUo3Zk`= z?A15h)<%F4hkWfOO1aTj&u(CaMA`^yyP>`8a5&Z_n<6xcS(|*q57n)+w6}ZN(E$Y< z8TwRbLk2a3k6u>=r9Vw>shg#AUlbffW=16FWWnGH*BZTBb?Kb)H;slZF zGbQ+ISo6s#%G!>SLCYXik>@E>+TEQ}pg0#(=t~-fo-(FFkcrx7brKL@*mZ+Xt(H3l zYI_MGT*$HGUvCx47;3KWd>}2Y<+~wD9>k&3$9&gUd*{1CE-i4r4wF{Y@?4T~|IE&S z1qF?KX&&w9G(&n7r-_4t_Zk3`pv|snddo8iGn6rKqh|n^-lAaK9O4U=i=arQs z!yo%@KA7k+hFCglfDH2PjV>cE^#e%6LgI9e9J>2#V%rRzo4JOzV&DpLQv?t2J$+?V z##z5giFNVF7mzA>-Eo!SOnv3l1yOA#=M7gYGT0tuu3Wq;fkQ!FiRyI$@oA>>^aRwf zGTffZjO51(5iFk(4wq`C4i;)CdwTe3!*N3cY;qjR(U}LccsLMjf1aWZWiQ1s!=ixr zY}2q-3@#HnmhBXf#s3u-;XjQQBWy1l*beZedl3BI7q~99wYqrs@)C6(T1e z<_>x*GeCza5Wh#{9I+HvScnm*3#}0uXWfqpFy7zYN>L$h3pq{!%<`YhZGQgVIJ1C` zj;YdMbz@7^8qC@3)y+#;jdl*1d%X+Z4l9V9agTD|9e8x#bq**L)J0L=_wb(pCcG`1 z8-*_4#wktdj@O(mOXu}dy#jRhU4a|dr9;!MmMmZRbX}I!Tg$)o`<5$&Xn_ zQv>=A@&ler5{!P|7s#r75GQSgfIs@;?-8V2f?N7JcrnpAHkm!qrRPZfKM#ss+s8+Kw4Usd?sF9Ic_D>IM@pBK-3{TVEcYJQFZGqQ<($mUdm8 zXJrOKHA~u*Zj#3eD=nCop;C6Ny9$PuyqV?RzRD^#jS~~?t^xLQDzxoQIwoL|jMjoj z497EWD@i{KZ4on^$w`&U=4!Ig6(wxp3S+)zCj=hH>7Rl?)pbCyT$mkHmdzYT`~7k8 z31N|2=m*q?A7sAGbMGI;s2+T(y!hVibFR7l5b&vg>bO%-I=Bl0_XgYQ36j7u?4Mhs z4q~Bfmp(^$_?v~k=&|R8pCaB&l~9~tGT9esqV1q%9a%YAk=wqT!%g%E+g1i&0g95bILg z5gdQr3kYZBOTn>`M>$WzvA~hP)e-zBcBJtAt&z|_apY0Mzm+rVPkfm6kN$6==D$kv i1Re)tan(y4<_?0j{yq&(c-o)u29%x&vQF1A@_ztZ#Ts(} 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..e8db2236bb9db815d1a3b58e2e4fde18b52d237d GIT binary patch literal 2099 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 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..43c9c03a44a0528a11df03076d941d60504603f4 GIT binary patch literal 3435 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 StE%&_Z@LZA-hya`x&4164m@4} 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..a5bdf49797fbdc96c2aa3ad4f4ce2b21e258a95b GIT binary patch literal 3573 zcmc&%XHZk?*4`oX&=lz?NN%X134%Z*L3%YHEp#|^IMSsYFcI64B25CQU_?QbfDk%L z5d@JSJwZg8hzLmUAmnbpGxxjS%y(z*++TOiy!(CD^E_+4Ywta?XZ9Vel`%J`C?@~_ z+@>Z5HUI!Y{#xu%kghJFl0xT9A6B7f1YuBzB8ykZlG&EF9OiV>Zg_oB%Dk{pw#pT?& zbB>OVAt51LTwJG4osyTA=i}pJW@c7WQetIg1#L`BOi(BktTHz@S5#CK78X`kR)#czflZS@~96(i7)z8n*!omU$ zhl7KGels&Ourt^V3_U$Pu#bj@26zg1ryLv{U^$2}7>tL9$G?5x|KGqH7sUdysgX8T zmjFJ3qz7p=w4(nJ9>YgsJn|r@NMcu4TGOXm`uamB@$MCjGzKFCJ@S&V!8m+7$6&1O z9JJJLm+vpU-SSP7dN-f+n3(XDGhavtuk`fG9zd!?^ajl{`m9H&VQ;k%d-{f2*+0 zDY)eugJOke2uiP|U`to=P`gnI{muh7Qw+`HdO=0?%L9}%1xe%o=%p1ng>5z(_<26# z!Ny{h3l832-a9YaySu|fb*=E4$n)(~Ydr4FojHVAf(Ei|MvS$a^5!SWgjDnaK@f@) zxvyk*MC4$C$rwfQteWs{1#(|gszRx7bef8TdT!#;c}^YQ;LovR=Hk3 zNeQ304>^$Y6&;zZ(so)DrE^v!`W>=F+FI+7v`p5wF-VXWh553b^|f34sBte#l-=*K z-em-NV>(m6=pBF5D>pS>c;wmouM4h888u9#jTWb+uUjSqtwi}UUD3>wFR1v*wq3gp)h9QLRB(Y- z`sTDy=06sw2aY6-(e3LGD+Hy@g9V)wLV4C7^c@kFbP;g@M*>={+0y2|yB)o_P^}li z*1IQ;v&a`zkJY=yE`w1%;&L<|6g+>nr#G6lBEk ztxB-V0lf}?1Aj_)YM~}*M6@Fo!PKu|MXYp`GUDlxc}YcBEjMjZ-G}`?2*rsZlFfrK z@@>1*yb}zXLvwr;?K$l}(Pvb>qZV0;D~)op>CSIgPB_;3)OG@in~u#o(fd$*$xKei znWlX{F)peUKKsELzce4M(TGr9crJ?*gu+hPjzS9s`aEW0m58BeDxr4 z%sDE~Y{7Yq;##R;LOheu991-{KA-2Wt=JIcV?`txXR#4@T_?&1Ic@7^?`Esw5*+X; z@B3WPo^}cgf!?M>$ZlGEv5{eIphj7WYtVZ$xDLhO7$)yjH^Pp#(5U2NC^#m{?o?Q* zaPmRHgIn-uvAlFdBh(^~xf)Y79%v(_?!4s7>dnIca0nsrN=k>@?9a{u^2dN2fnCgL zN!4vZt9RH02fD0YV0c|YAZ~%4n30@+w?W=n5RpU+bhoTQ>f>UMvjEL{m*m$!7T>5$ z^Fe%|NLSWi`GMs=m!%=mk2%?!-JC)i`Y>RM^F^0@+07SZZzJMec1BB3SjUHWL6rw2102=E~#hb`< zL0Fugl{v}#49NNh5hhJ~uJQq78xr<^&GWFal%wSLYXu}%`(+t>2VaNg^CM^)vp z_%CJ&^xl_tg0$Jx$nL^;o(SCp%0*;Q6E7}{R$YGYe(oC0L1!UjCu%TYGveryO$KusfM*~J998Q%q8n&=3LFzF#PcG?LVVK?C0C2 z2hEI#orgAUGX`k;BJv`lF{ZvcGb7tUd+oI3@lrBsAhBGtbQ6Njrp=}M*qPj;jr7~a zsa(%|bHfN0zg-AR4kOQ{+hwD79$#^m^nKXB;Pd^;MraOtTD@3&>CmESr;xP?&_%QY z#}G+j{g2hVDQ?!z;TKi?zUiA0n2J9Ot+~l%Q%W`pD3f00o@UhFZkh@!lWn^x%W{eh zthuJQPi!&KX(O~Y@LlfL**J+#AtY?n=PSzxZF9z#vGP7)0jYxCEVDK{DfW`Kx5ai; z-wAZ4N3H!p7g4@1pWHJ0?%#+Nnoe`*3SBoOOKhr_bb9UBL z1eLyVMaD^cMYo;x5VoRLvl|@8jT}6)Px2X{&ze}oI$=BV6x77i!U+oY&HSh2MIxjL zNAW^GWYCt;o8Klh@hKwh{pgF!{V>9-^(8ZhaZdF&A&t8;i<3_xsW0lTE}d>WkpL8j z*Sb4zeYyPFT`|$QDt|H_JxeK(-_f_EE~@)FsBL~$yBLcq?^J1yE14sxu5dkb6+B7Z zf2||V>197^&%1YX=nJLm;ZcK9n%p5}_n|4F{v>yo*!Yx)c~Bdhl#o{pio#pF#MLEb zZtokO1luB=|BXWKJq?3>x^7}`NSA|Bb{$```X}$42GTY!<5#OslfID^mF1zlm)qqj zM!572V`XDZeLoODaOk{ex)Wer3@;3e7chq&!B2MIK-Olb*%5OAL;hn0nl5hbzxDRM zZ8s{0Z!vDSjyZ^T-$K@I$&e(_i~x()G16nr#qWvX4WDT(SECtH6cZ~PJQ zjOW*PXdmWLlFZ7IUpEq)vaq03eD8v8NvlO-QAR*IbSfu`vm02}!om8Yt->ysGE2$~ zzkP`UB!qb&bcm!we>GG6*|dvsn^L_EOWw+;$p$VG-l$LqqQX@|;*!3w`Z}ypdvlKPnL0_%Z?$!oGKcNYwUH2paqbH}G;OQ;;ILNJX_xYm3!{A$U zD=qt;Jt{2Lq~fB$?)Frm&w+WC@be1?e`jFbc9m#>`{W<9@B#-FW;E7XE;2VT{pNbe z8$cGBW&!7!bvyrRdapJ!X-cjv5#Z~DUO|P?6>?a0rKDk{T=z4F)5lli5dwPL_9vlQ zMUh0DXkNIDKCyj6OW^UFgfwj<#geK{sockYfitV8scWf8pM!!iF-OE;iBGT37WcfM z-Bttq_f%pctA{3iephST5bK4y;$68^>?M?9e&m}S)QqfXrKWQ9g+!JE>@yMtqW#p= zU45;`d0MUJq{g%7k%jX;hdEi)e4(SX#I~Jluz$9<xeSy?71U6BvBieH767^;ckOXk}1-!6WhSsUe7R 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..14c2c9990a2b00cc2ff0433bcda9494c021797d0 GIT binary patch literal 3015 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/with-path-and-xlink-href.png b/crates/resvg/tests-hinted/tests/text/textPath/with-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-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..47916929c7a32924738635cba022f078099464ad GIT binary patch literal 3115 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 ZVeoXL={@wR)X!goi6O?I?4oPje*oUxU0MJD 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..53d5dab0259381b66dd1f363408c2004acbc1969 GIT binary patch literal 3312 zcmcguc{r47AAU!6rjVIPq~zEJqq1ZRk!74QwlQPLq?s&($Pys7|YC9 z582lcDr8MZ$yN-~$jE$CUDtPgf1L08^SiI>xu5&F@89!2zvubujYlEP!Gebc0RRA7 zTA11a00{PD@bBX|$j3L#Ig>zu1vUr(_ILgmpe&XBQk;srC~F5ZPWZnO^%Eo#>6iFN z=A^&ypT+-n!otFEI2>o`<>eI+5WvI3^DBbG;hvtJ{QUfSdU|qlaymLX2n52wz<^V) zpr8;O94sy_&ixZeBoYh;hlYlpIdkUFp+lTvS6A1I7cX*gammQYL`O$oxpIZ$MH3Sfj?X#H($dn`*Vo?OUhpS4J#auI z5`~0>IA4H3Ap7?1Q&v`%mzU>s%h4QgHva0t*w|P=KtNYlS5{UQgTbKDXg)qZ&Y?Co zHYgNIOiYZ!oC{i5SQr@@aeDjT&->rfgYiAnoGdQb4rveIMBohBp|qBOd=Vpdt1Jlz zPeU;RTGob!-$fP7=2O}1D{S_+)Jpcoo<4)U!erFdd}S7GeVfbZ=vnCBykWDxGR|JV zwPWzYr?QBBX=<(6M{To(z1Fie6};6FH$ML*XW@0nP$hfl%Pu3bY?kfLW}mf5b+5b< zMIC-Oiy{@YuAOBYeeKke0{}rEOH*Tqu*pxu8log45pL@JHKb0NpMCUUaan5ZJ88>GA3U} zLCG*&r^_55>a3&^+eqqgfqLxPjd>ed7kLTe@W~2tt!jk4N6q(z)4{?#qVdPzY6P

n*e2~0R`lS`F^oBh<3zlB*(rT z{^e^V!JKQc3thHKE8@#d6T*tt0k+yG=(g}5Yg}&&Wxao!3I$WGuur|T+&YC7i!vfZ zFnwaQ^1_0<%Oa05LlPin_+(%)JMH!RNJ~-43M;H1q;#EJ7S2!Y3Fal2rTDxg;&~K~ zWYPx<3ek@z)bWeUfHJx46iVfk(~jw_8aKXfa+z=L{S)ULW2EdFGqYagmL34yHXaI~ z$j{(A&e4RB(IJqVh}_1rv66OGDs1_CQjXcC`@qRW)s?R{uOX2D3MrvjTQ=zLoPF;; zED#ldEpKc+5fZu;;V`N{04Hb=UWS%}%jZLgJ$&yEIiOhr1@cIBVD{+|ksJq+)6-0*s#FiU7@(gR1^q#L`U}>bF>!4chgeI6e zlu0HN_l6ZRkT{A6{cx$AwDj;ysj=ojv4u1Id(cz8YkMRHDLPJn<&%aJwz}z|?-5`| zaxw8};%}sjqfFIiy^QV$IfUrM1qry&G0Nk^mQDvnA<(2lt|ecVEv;}U-jd#M(qBV8 z+Xg*n`bwE&6Ip6DJ`~U4b`cr#Q9k$?_v~B1+9JyIha2+#g0rDn|oeW%upD+Pz>9DCmkz_g=&k@bxq^IM&jqtPUTdU zY#wI`v>o)!L|$uz>ba3r0lxw{qo*Fdk7{><`XG*^zfGn>6YILmeMHPzQp=znseyy?yEwgL|8!F_km8at=6 zBdE=X9YLi|K=Q*3+a!Us%$v9PZ&ap#GL=8S?!q)253g=+F1$R=4!Fkbn5|fgsDXgp zSa6qY(Q<{QlqdRlTl4ZKu4cmFvCkiN+^Ln0O%l*Cf<_g?ZKVMu^KFBmmzL9H-uX`F z#u_o5CW)EEQc(dPkXP@EeQ%Klu?9WJIzVwA3q$NKMr z!a~jc%FAjM6a78sYiNAxBJJddw~yXdK7i+H*02Erpp} zXJ7HBLE}lOGpqdTyPY!O@2Ru-3B$+@r_?q|Z~IHou0L}y8I8}PTe2q6QhHlng%Fb5 z_e^NXCdTa{Y}qhUWxmfe?n1J;o&5S1Y=s&FRI2YD#7>`LEJiLQ>otW&e!ZNhX7RX0 zYft=Usd5|!I_2T?Mm^EbfMs<{B`Ms&`zhg@jEApx;O4?;7jaC&_o1^FuLRD5@i=x4693`mIM9NvbI6n?;eB=_yqV)^=DU>U=1 zY4TGMe*G^G7euDnR#8JvfSK0ul=dx#Fm^xOy4yl(z`P&8)r>h-b+LA2a4!kozLdOh z?DQcYU!oGdUazUELKv9Da|59c&9CYDM!&JXN4F7_)okjg-is=-v@i@paV7WP8L&iF z`*1cb0xQ1zq}MSMVtiVrv%m3iChYm%<+E5*Lc%wphY`^Rq#Ck9Cum-wj}^e2#^g zL|AE*!Bx#Qlb~}DkgHc@E0Wz7!;SEpc2EgPkOaxyw!c;r5V>uh>b7)}$riKP1KWgN z#xlej^N!_Z->in^cA{76M$oYm-Y^frKNze1UJSV{ps~rOI%d1f;N4z5km=YBp+`z>y{nnAEmXxO6%NL z{;0^WdF7Uj2Y>X3W~v;-jVF7dwCi>KL9@5d~tTyl$xfN_-ye(^;1iwT{?b zysg@xrQ7tv26QK;*Tao@l*@?RayAP~_u?L>Ax`N|C5LQ%Y*cMPHZ(br+{CeEE9`5t zCKj6Z*++{{w|hcxCl+Jx`{+5x{dK`5ALL_}-qoPXj$pR{vdI3qsW;#ENwrR`O;4g+ zq@B4a#vh1}jObyJ%)J@)nW_Fvv)mL(^;OE-&%CO)YgqZP^Z8j#&6JUkd9#UMh(FHgPqhlvJMO=zQ`;vcD~XMq?N* z&dkg(_gOYwu9~^vSM3$g0GFWC2^w4HjS@GWuv$V_=Un||6WR+}CTc4J?&hQfj@_dE zE_&p3$IdxL+F>od>nc6vL?M-mS#6AW$49xcdYUdKu!k6%H8#qx;$I?(cAlEP*p;l= zYDEl*rv*>ci6hP>Yh>>blgJfC5{Rd6N#v3SafDwGCv54)Opc{_co!>mzgm*Hv_wy( zogRJQQ8KF4{fd@Kt9D2t`_+ge+(M|h??XKoN#w(qV1C&Wh{yv%V{9)aOrRVLLw(qI z{XqX~5hx6Eg}%bo?|z&8a=dLP8P^uWBLs#0V$4sCp>lH^3>7EvliS38=(ZU7pUi{! zp?QR||8e76;;(ev~&E_xQk3zw$cjCn`@@t16AhBU1(!NvRwh^O)9 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..8ebf154cdf41721e5cc55c37255b67fb33c4827a GIT binary patch literal 3281 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 A+5i9m 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..e4800431c0cf6cc09020413884fd16a2f8986b45 GIT binary patch literal 4008 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

mZ+L zW7PIyb(>y@_BYmi(5S;1_xJNfN;`p|i3o`w5lfHKAO>x}hEk2fR^$8RO@D`*iLP-h zl6&XSOnCs9#hD)otR715f52VmR`vj@CE+`L`WanIxXx{n6cNZZe`!M?Wm9~>(2hA#ajh=Okg)wIdYqT7TNXov>I;%snp(;y=F!opPP5+><#Ts{ z1w9O({Y(0@1L_iRx@}uU^w&pg`;^#HhPW46w?UYT;Y+pCPn$>&VvF4b7MFk<+$*-` z9W`EcA5v7Jh8|}*+h%si^*+LUw#=J8lt#4porhd|BIMzgn}V0tG?pAu8ZB#URf(*x z2>sQB@2(|`Co?GH%sUQxY;$z!x%w@>dthSPM`JSkE%faTe@u35H<;V`l;2s#OVI@JPir) z>R@;+9pTE#I#(DmW&6YUjgYn^XXe{`jD9+}?JMeiBTo5mUOU&W-SU8MqU9bIoVf zlh;j(D%n+E~n6 z)GSm`_mk4Xu4X@PKN@3l3_aRt%0F%|MhQQ4=Sj|}I-{5cO@P((fz^125j~_|NvZfM zjb{S`1HVwI5A*KIh1JYC8e$NAH5UGwLd@N8+>4)vG7&w)qN6(idq<3ir)Sx>@@$!e zCJze6f7Bzz~SML67!)oW4@$$1ABBd&jTQ zQr9tf-qFHhML4G YFx$wY!nyE?$)8ycVSt3!>SG`M2ce8SC;$Ke literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/textPath/writing-mode=tb.png b/crates/resvg/tests-hinted/tests/text/textPath/writing-mode=tb.png new file mode 100644 index 0000000000000000000000000000000000000000..0e7fb7b5d3395636a5bee49aaf4c260219751853 GIT binary patch literal 3841 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 MrWg~75i#+<08b067ytkO literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tref/link-to-a-complex-text.png b/crates/resvg/tests-hinted/tests/text/tref/link-to-a-complex-text.png new file mode 100644 index 0000000000000000000000000000000000000000..af62719f385d052882f217b9c0ae80dc5d365c43 GIT binary patch literal 1957 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 GW&Z`KE3;Gp 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..5404704b2d494a7fdf2ca2586f24ea768c2b8005 GIT binary patch literal 1706 zcmd5+X*An;6pc}8-^Ec|rP~}yTdAcIshvor(NWT5N~KYQ5=^7CwS*!h8MTZmLhaq6 zOuaZB3~|tBSD>CJVT2HUZ#ii2EkBh?z;qXRh=XNAgfItAAo;hJ* zOG-+!T3S7Dc#pZcf50cQL~d+^_nr*dDYRmjw4?>QkXtEwf61nt?_xyy!^4Z zK?py98DNILa!8kBgE?J2{t1e|g45-ooCRjr`z6{5fmx5MG5+evqxi9w5dY>3doAdb z{x&YzcG`8Foga`f&}aJKPX&{Q)Y5VCFO0z0;;KzC7+PE#pnbaNEbWA>8If?WKZY8q z<1vIDqgtD^G@0M6BoS*1R*wn1eu#%yFYd*zg37tq&SE@(-xiR)_fUPwj)vff)TRnT zc#P3tEw&AVc~*{Z?AsBVj3~Bx1!8qumJDJpV~+qux2OP%W(#0%n0VS5HdakU?s{bvMH&6Qhq3I@S4Y9s$qGLp4}d zb^dTRMTZ5}MvnO9vL=D^a5xHIDBg)aqf$ng&NC(>NP*B>9bNm?l`AFze%DP@lNfkkPXSrDMRvC?YjcxJGbOAT9H!f- zL!X@C5C-R*M_GKOF}hVqp(*3pIQj)Jzhv|>Ae9VfcTEx$(aU>8aclOKX%Vd-BfU$w z`woMZ(<}iE7UDko04u z2^o(6mF9n&_`$?2w>U*iBs%V1P~}b^Jaap4|3=VVPqv_ZWSZi2MbG1LYF@+}AxVs(lM4c8aN4V))<%`+)<(fdSNh!W%4|nHWkg+6D3|9qBXoQ8 z!fF?yX>DrJc4-4LYm5>&4fIyyKGOBehK%#-8ZTCde~JA(#G^WKy_<5$a>Kl-g29qw z=Ozg5go8B;Ox-UP*X@gkDE-_^u)Rh4_o&G&T${v9n#XI4gy1RTmzD}`AQihe+Wh>` zMczyMnub~bxVuzrl7>QDdP>q2=05yt{HHKv*1R5g>0R$q8Bv3$BQ3`Pb zv||9p012RuNMjO-j;Mevp#>GeF+s!#7K={CqpgR*pq=3egb57B1Ynbf2DBeCT0JgsIOKX5fG}tT02_cr0I&cU0}%X= z212n{UM~dLqyTatphd*nC>OdaS%afX<29FfxzgIkisLP=D5{JWPPF&RHi(^8TLnIIJc*htFs)_)eZ= zCSn9j4F{?%3ap7dOh|L|qj}4fy9{OUFL-m|Z$TMq->UMzG+p2HMOCf(kQF@*`XRS5 zlfxm2HAr)9TD=F#(arJ7Nco-LmdDcKmT?<2`>v`!67sBzBVe=nc1lOmazYh~)5hl< zIy{FLw*9P4;m9Ntr#s;{b`DD>x^cpJtg%4-85%`tD+Xj)7QD2*=o}$`@PL|4zvF_v zpLnFps-Vb0RC~FhC1yZ(#MJFt%-PwFGFwYMn^J1bYVe-gUmQsn?J{5yf_=a8D;G}0M zH7%mb(MQn9p{nAww5q4uH1|`cJ3gi!IP+O_89C0Zx_R4ofHW?*#ZO?&;r6+SbfTQ=lUAahsUVr)Md7I53CmMa|K+*YkXM z=m2`We8WJ1^<(%A0a4UEEib!6XqL#zPSs~QDNJ1`Bu8a9h2$c)W{3)Z9Bqf!<+W#guesAD|45`E<`QYqi}vMWez-#f}}M^cR24`YLZbV6H=mr$vgRsgUohE-b3X}3yd%BMRJ}tb@Tys11*1s z9!zG!+~*%8tBX-0wyI4uGk2@_`k?VEmswexI9-LHRn#4`w%>bJb7YwQEOv(9JQ10KhQT2zJG?;;wr1$l8Zf~lr7TeXB$46UH z$DJ1*^qPm>ZBCh+darM*9jAJQM$~KfRrc2^h=~M@Z4^P#FYa!@sqto*QKBO+vvF%! zeW}~LlA0f9)cDq(@_M0hlX`G$9s411Cj9J0!=?MO?50%GiCa2TsucB*Fbk=BO?*lylkyAM_{NznlxL> z;Q!X}zNY$`?Q25K)tq_=fkou6K~em3EP+#C%j{6`g+l}|7Q?}tvQUdFpD)RW?A=JD GW&Z`KE3;Gp 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^P6xVuzrl7>QDdP>q2=05yt{HHKv*1R5g>0R$q8Bv3$BQ3`Pb zv||9p012RuNMjO-j;Mevp#>GeF+s!#7K={CqpgR*pq=3egb57B1Ynbf2DBeCT0JgsIOKX5fG}tT02_cr0I&cU0}%X= z212n{UM~dLqyTatphd*nC>OdaS%afX<29FfxzgIkisLP=D5{JWPPF&RHi(^8TLnIIJc*htFs)_)eZ= zCSn9j4F{?%3ap7dOh|L|qj}4fy9{OUFL-m|Z$TMq->UMzG+p2HMOCf(kQF@*`XRS5 zlfxm2HAr)9TD=F#(arJ7Nco-LmdDcKmT?<2`>v`!67sBzBVe=nc1lOmazYh~)5hl< zIy{FLw*9P4;m9Ntr#s;{b`DD>x^cpJtg%4-85%`tD+Xj)7QD2*=o}$`@PL|4zvF_v zpLnFps-Vb0RC~FhC1yZ(#MJFt%-PwFGFwYMn^J1bYVe-gUmQsn?J{5yf_=a8D;G}0M zH7%mb(MQn9p{nAww5q4uH1|`cJ3gi!IP+O_89C0Zx_R4ofHW?*#ZO?&;r6+SbfTQ=lUAahsUVr)Md7I53CmMa|K+*YkXM z=m2`We8WJ1^<(%A0a4UEEib!6XqL#zPSs~QDNJ1`Bu8a9h2$c)W{3)Z9Bqf!<+W#guesAD|45`E<`QYqi}vMWez-#f}}M^cR24`YLZbV6H=mr$vgRsgUohE-b3X}3yd%BMRJ}tb@Tys11*1s z9!zG!+~*%8tBX-0wyI4uGk2@_`k?VEmswexI9-LHRn#4`w%>bJb7YwQEOv(9JQ10KhQT2zJG?;;wr1$l8Zf~lr7TeXB$46UH z$DJ1*^qPm>ZBCh+darM*9jAJQM$~KfRrc2^h=~M@Z4^P#FYa!@sqto*QKBO+vvF%! zeW}~LlA0f9)cDq(@_M0hlX`G$9s411Cj9J0!=?MO?50%GiCa2TsucB*Fbk=BO?*lylkyAM_{NznlxL> z;Q!X}zNY$`?Q25K)tq_=fkou6K~em3EP+#C%j{6`g+l}|7Q?}tvQUdFpD)RW?A=JD GW&Z`KE3;Gp 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..c8cbe94799cb06baf2ee11bb29a9f2a07dd66883 GIT binary patch literal 1621 zcmd5+Sx}Q#7`-9vltq>xVuzrl7>QDdP>q2=05yt{HHKv*1R5g>0R$q8Bv3$BQ3`Pb zv||9p012RuNMjO-j;Mevp#>GeF+s!#7K={CqpgR*pq=3egb57B1Ynbf2DBeCT0JgsIOKX5fG}tT02_cr0I&cU0}%X= z212n{UM~dLqyTatphd*nC>OdaS%afX<29FfxzgIkisLP=D5{JWPPF&RHi(^8TLnIIJc*htFs)_)eZ= zCSn9j4F{?%3ap7dOh|L|qj}4fy9{OUFL-m|Z$TMq->UMzG+p2HMOCf(kQF@*`XRS5 zlfxm2HAr)9TD=F#(arJ7Nco-LmdDcKmT?<2`>v`!67sBzBVe=nc1lOmazYh~)5hl< zIy{FLw*9P4;m9Ntr#s;{b`DD>x^cpJtg%4-85%`tD+Xj)7QD2*=o}$`@PL|4zvF_v zpLnFps-Vb0RC~FhC1yZ(#MJFt%-PwFGFwYMn^J1bYVe-gUmQsn?J{5yf_=a8D;G}0M zH7%mb(MQn9p{nAww5q4uH1|`cJ3gi!IP+O_89C0Zx_R4ofHW?*#ZO?&;r6+SbfTQ=lUAahsUVr)Md7I53CmMa|K+*YkXM z=m2`We8WJ1^<(%A0a4UEEib!6XqL#zPSs~QDNJ1`Bu8a9h2$c)W{3)Z9Bqf!<+W#guesAD|45`E<`QYqi}vMWez-#f}}M^cR24`YLZbV6H=mr$vgRsgUohE-b3X}3yd%BMRJ}tb@Tys11*1s z9!zG!+~*%8tBX-0wyI4uGk2@_`k?VEmswexI9-LHRn#4`w%>bJb7YwQEOv(9JQ10KhQT2zJG?;;wr1$l8Zf~lr7TeXB$46UH z$DJ1*^qPm>ZBCh+darM*9jAJQM$~KfRrc2^h=~M@Z4^P#FYa!@sqto*QKBO+vvF%! zeW}~LlA0f9)cDq(@_M0hlX`G$9s411Cj9J0!=?MO?50%GiCa2TsucB*Fbk=BO?*lylkyAM_{NznlxL> z;Q!X}zNY$`?Q25K)tq_=fkou6K~em3EP+#C%j{6`g+l}|7Q?}tvQUdFpD)RW?A=JD GW&Z`KE3;Gp 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..494403eb610cf84632c149a202d7c4813e58d27d GIT binary patch literal 2014 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 t^*rN;2>Hzwurrn!W^Qb0REfjK{0nA6xi0_! 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..afec95d0c1906fe2c135181a8332cee555510581 GIT binary patch literal 1846 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 Z`(t>iOCK*_VAA{NJs=Ut_$C}J?{8wlC)5A{ 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..a855dac4d4cd03c7486d58c31fc2bdc436a032c9 GIT binary patch literal 1825 zcmd5-do&Yz9RJPCo8=kFBT;5MB^ni7@5jhQVw*ZP%WK8hT1afTZ8^H3led(s#T9FX zgXDVE>Xzp)_b88>s79mfQKY%+xcATd?>+Z>&i8yizwhV!{r*1xeY1{Zz0_59r~m-e zG2ZTh06k@#K3#@{t;bvf``b$AUa$$Ye5EELJQ4p#a2s z1Hb|&PXd{+GXbQy0NY65hX?Q^K=TBN?!fXa2*(0P67V<;qI^MU06<4U>7fYOo}DxZ z6>o|OQ%nxCBM>y=Fo1;9ku_VMlXE7+=mZ3lM%?=A2Qmzv3?XP}&=Cldjt)XjE?PDY zfykD`0T7_7N;Nf=@o)ezii&Uu1Pz5I+u6yUrvPvSfChl2tRH|V08#+(10WFqH~=RB zu$7Jd6ANMiQ^qmp1FwQ;MyJG zi*tB0)|Ui&VtzluJTp!_u%gsn-5V0^#lS3XU-xm)9q;b%+=L?yltq+txGV-vTKPKF zN7KNNE9hPF?rkx!?r%KOxh{RSkoF}F1F53C4bCkPN7n2YBddyq6%Hty@(_UsudPJz z)Hm*uer@3{3EKZ&RNl!=C&*N`rCVJvU+K9kB^GPJtGuBqw^u~Dh=?@A$Be-AY$b(! z7K+QgV$dXqEUyddK>OU;V|J~3z7)GQwE8c$Ui7L{E`1~^+&~%;8?DQ2 zrn^a(otKYC-{=r2li55pm2D8W^!+}^lDweojW$P=364yzv)ZzU+%h~T1G zDF4F6KTH)mC}c-Xa;Hi*yQV!WQ_7ES4nv&2e=o(Tgx{w}Oqjky48mni{X9PZncbN5 z9M29e=*q2u4^@+j1{7vFYDJ&@7Ud&)Nm1LV(XJWJH3s!vceKwWBON`0)30r7yL(WY`-z3-YKQWF z^r9-<$$2a>uOkHr2`E3@27^Q3OZd;5`|A}itv<4Cf@YVj^l%@P4%}EX^GhCzQO`Du zqwgcdM(rJooy~3#<_S|1aS0C7+BR`8y_;+DHS6qU`1}=im+rc4EGa82sQREWF5P0I^(*$G)R|gkucN2^&v!4}1~2B%P!3 zDB^o_iIZYObkJyEdz!^e|IFg*vs;1E<=)eV2zzGg@E50*>u+{EnTagoI3HS&o6FuD zYb5Ug&iWw3MXlCIoIVw%DGwWe^xC(1Ermc|e#@|CcVxg+^-wrIvGe~%w6;Wp{ zfGB8SfLJl9$~m6_7$PM>e!&b5|Lq){7GXU{2k_&Rfa?b-hMnXlLHumA9V z!vckb2?6&n7@R*K;Lz|tK0)Nzhf53$%v(HN978H@y}4{C*kB;wa`84ZXXYc$KerRv zSi_f9#2=b{H)?v@S}*=!t-XsKe;@bC46yP|yw{sBPkPrv2+}#d34&50r=^0CDojLY z?#?yOx2{ocX5|*siO6EvkZ`bx_4Nc0=?!LcPXn=mk`OWi%#PT=0#d#qffGy~6auji zHmQP1(l!2?VZB<{a-l-kypwkhCEn51dz|<7?up!0pa1U{@?X)joB8)cseR(@q4_E` zUR|#ns)R%|(%D0(bc*dM!vPyKW5qIV3pvQW>yi6NBq9jsgJF7@Mop80o za!tET_JU*D417C!)8_79k~wShnnbQO+Zk^*NbZm`aN3tHCB`e!rq#ZtHjg=@ko&^a zRc@2B8FsNAxlmHe|Di^TQAUcP%|k}=X=h@y^GlO(#x0fc>54iY(+a2TO`Lg9>FI>t zqLW#l4lWExb!d_(mS#Pew!_VhJV{9iaVoiG(q&F<+Fh!k=O(wMuZ z>N^LoLQ)_1!-+PeVcu!_)-%SV>>slE<2_VOq`26P3)}aOkQ)3*FgU3Zt2x$s-tJ`<&FDe zfB*5>HFr;mRr@Do?ktbLcj5QqgNL5`yL?`M{rdF`$7jV~{BBh);@?~SStT;QJ25lz z7E{HfHAxdBruEgoz2GRwpuoXkaDhwa@8YU-Cb@rilzgV?L~cqsIZ4%f&@tAi1KrgM uaULr5RS@FlY}YSx3-WIWNKSRW!Z>}az4ET$L@!{;z~JfX=d#Wzp$PyN11S;! 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..b4ebe0cd5a9a385be9460c1a80c8005ada4b00c5 GIT binary patch literal 1887 zcmd5-X;70_6nzj0B#{6CK0v857*rJ5QCz4If&_sORzDVp1eKy}sURYbY3E=5RK6ckfHEhvNF0*VA#v}}T=u{e(7O#gQJ=H7eGJNLdj=ikewQ9ZP= z3$OqHZBGi>9{@G0FR6u6Db$N;9xA{vDItjf;2XcB+NqWJg(`8D<{jv+!tc&!0F?j4 z98uM8ic0^+zmXq?m3aJ^>NyHEqpERnC+9Z%BEBpZ3qcS|%MK&N2#+6Ctui%zWoOrl zMo$q4?*JPBd7O=qAP$@rfmGXo5 z{dH~_0V*>pOWj6oR{#KkN&eITKvHf*lroa7ZqDCETju7IupjlyO;?F z&lVInbnA|z!5T`P^C z1AxY5Px7X~l&+yR4>iPA7l;?S4qmjENg)Ae<^+W@6cz0OxlQl5vV(pw#01qRy|&|C zu7wx$Z?KLUGS?DV{TF1-fvC!UX9BrBeEA((cydFs@%8j5=(SS$U^(@p#Lem2{N2r& zowQW{-=WDy!>7^kAiQ+MNMOOgGmTcnWQ}VFPg^^x`r}LM%N)z^#o7m*++V=cAR5@j$CiI!XcPPIrj_aV zSzWj1@LEYmVFGuLSg$56_)hL@=)gP7VrWInr?W>T+$KbbQV49jZ>7#;V&n9o6}3GR zuCW1DkEo+z^*I;i1I$0j-7i0S1axQ$JW3VIs+=!{y=UoVg}S;i`nBg@XhZUOh9wCr zQ|qoF?6**&p4~yNoCE{=$Qt4#&CJ}Vw`xH1Fj{eX9Mov8 zT#8>$d7>%sbzB5z8cWi7HwkBO<*RnS;_^cjYKM1+ojIY2@yQ5EuCMn&5oeiVu}n|s zAPTQ*NfQsRV=$`BTa#d~_Tzz;-OZEdtjcHpG`zFMBsepbh%0s&*1<_!CjFc2KFy2B z?s#s|G2eWGJs#M3pnU=Tc-7Ls9%M-3Ii#soijAD`XNE3x_U0R0fycgaw?sy^<p~qwBhoQ*PcpRT=pqD>NM7S~-4s+^e;FGk8xD3e<6= zht?Q&Qr?=y+16Zl)4s$kZk2|fiReH8{RMmT(dn~&?ryGI?BdLVn3L*okG79IrtYPq zMG=Yox$Ch3{Jc;gMIH;c2iak!n;>mjc}&mA`-~&Mrt*k+Ioq7vL}Ns!CQ~@FhBaHj zXZbw(Y5pSuRpX)VScH4Xv8``!Z_t6rMa1+?xfE<(jt-qOk*s8o=(|QW-dL|(4#`$j zW-Qxn{c@-*Vc$8-Jau>xu@5zsLdr5$_cG|;TzO;iLF72g-g3lc` 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..3efa66a7b51cf42caf9c98497e0e9f73e7ec6604 GIT binary patch literal 1632 zcmbVNe>l^59RF@3nkL7yIh(TP!Od2o+asl0Lb3@bcJt%O_b>|KiLwftx|2fAvWfiY z%JOUFJExq(TBDN~`8EA8l2l0K*Aa4)yXXG6=X!eX{XFmI{eHba@1M`>kIy-GS0@w_ ziv$1w<-E_q0{~#;71czjBCgjGoK$9Q)IRTM0MKq&Q5c`3jZ+2BySsQgsw{`Y;c~eu z=M$o>t&Kz?2?T3PujBsHIDX;|SYFUGP<}R4Se=}EIaeMZGZUHa#_@l61!{}xw|FMyQkQop zN9$4mKz)z1gPkY)$s6S>-t!$gN#DyWbGdSxFE%)ie%Kn>`Ste9rx-J%#X63)#Z;!_ zTJQTwt%;kg@)7oZ>@Bv);<>aT6!QLZI>c2cgPTB@7E=nxKsq0x3TS?Wys@{w0#=Q3 z)sXMzbx9HVcU$?)`L#s#l5W<;eKW{fM321_a z<)0P?zhmZ`gjHfeXMr#jQ|4zY7@WYQA5&wnQL9Idwu)O~m}fK;Mhyf|juF2|L`!m6 z^EKf3i~TyOQR6-t(AQn+C7 za@Yz-s|>yLRxTDST*d#*(+X+-y#9w<;SU>4GPdTTJyqw?K=mvO=(I14RI3NcQWDX* zA)vax3K=r*nyeE&y!{w1{wj~EIXlu(yuKu&CWIU~&nwvZ*mS>7DJvj5S;%W)I`>k= zkCEL3ad9v)XX6izvxYPG0rsL$ii<@n#WjId}GJm zb(1N1nLaE$L+Oox3J2$Qw>Y)lT7&5hBwr9-gee|zQ!ZxM?UQ0Tq_$LtYO7_q;Bb=L z{tI2%yC7aARcGmu2*%`%<<+>EQ27igcDO4(t(a<_C~P${LE@RG*R`foS`5pDjv4%M-S2Lx|N zU(3<4W$-?IL7eOGxu?192tkWcrfSt`$Jm2yAdED48x5I?4P(#if%`$PUXpdF^eS(` zajzB=C+MhF5~LO6Zs*ee!ZnHsMqOS$6(9vR9SfOMhpq>s&JNJEhdT1vUR0J(fLS#CTST#){S80;tvu-5N{YPkfQ|cf5&Y7ui80tKDT&w;l zxw|lYt!TRFRC(5qUgBVn*Oy-yODcVIG5q(3I{$d-Be@;nL}|T11O7Tzm zMfoAFZ(PE9GmdK>sR^&)V9lNs#MDHS&lgdx3c6UGgOiXIE9;0f_LM8V-h4ZFClzid zuYk-YL1~OaPF15qOLo=v*#WH$)AMF%RBWlSY@2rxVYIj8aL)Y`GDP^h%6_ADhT|oA(2>P@`!hcTIXXgAh>tE)U-RdSIxGNk+vJGX^ a2+Wi_O}78?it4KX0B1*6hnsuA(|-cNpTgGw 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..8da17fb045037c4713431e948c4b2da73a91f028 GIT binary patch literal 4161 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/nested-whitespaces.png b/crates/resvg/tests-hinted/tests/text/tspan/nested-whitespaces.png new file mode 100644 index 0000000000000000000000000000000000000000..67859112b2db0a7cd4c016132499900109ca47e0 GIT binary patch literal 1690 zcmd5+Yc!N;93RG1?o2Kvml~JQt7fu=iHISCGcGavjvQuAZ5I&-bKJsc-I*9^%F>QY z?i26WX+ulIpfQsB7IGb@T-t4-!{)NDZ9nXn?ZbZB=luWw-|zYTZ_lSE-Gg*iQBF$^ zfj}q{oe5qDgcPvjdyud~Dvdu2gKVfXB^-fJ>ez9qJ4cibz+#z)o3|s32?+@d1_LHv zKf%Gla6wQ|keuAkE)x?IZEbBN5=kHsVB+rXj=^AXIGm=YCOi#=LgDdvcrvW``T3DZ zB)Hze!2xbWqtS4sl9JNb*ZniQTQu_ve7A`3BAr7}15~h~eL0ga>o@@kSKR}rv&$M+ zQ=8)I3fc?SScQcV@#SeDz0l|s^(j>JyT@+_8LhV4cFn6{o(KdABofYeN4;Je5vWU_ zQA4z?GEt-X8|LkelGE3R4-Hji#^|`wS?91~9dZG(%7!YoPn0Ck+HRucHGnS>{ELH- z46J|p_pYx7E2s?!Xd4Zy682_)PafT3HzAyF-a<<+y&nkV;v>cinDwl z3x7&B&M4I~E{daryJN=P<$Zj(LE%GUYJRWDTBM$W=@HOd#>|QcR3DaSQ3q#t|N5-N z@@;x^YZw#6&l-rRXnC@W?=fgxHfygV78yoINNHaNc6D#M6rT1#6}0{cwvJs*W(`_=b4$_+>SD`I_+S)xnb10S$u;=#vu< z+de3I=IR8F+bYarvI;%9&Gk@@+sGlPA>j%!exRQsz>|W^!*X@OS(e{MsqbwHSHq|L z!8BPO+~~KCn5yPyh!0m7`}a?_Ed(CzFt(cj$Pcbl(ryXHyl-Jd-GD~9#}f*-v;%$0 z|4Q`bpE8sC*9%eXCB2;P{hb-@GaXri{hdW@-m?s6;A&B%q6P4Zk6{jmx7%+Q1>h#2 zi+bg{qH!qCAu{6UPrMhLKd8>Cb46I*W(pB zm(~v67|92^yncKseFOKwW|PdD!)*)-K(&DT_~n(YwvY8=rfloxBZcgGRWLnF>a?4+ zf!@>;3J{&88?fmVz?ZB8@3lIOJhE1MaS8`I!zx;>HcV@hge5w*BBzHjEJA)$ddij^qSoKq 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..8089e577a6dbd2350fd550c1e87b36fce08e5c81 GIT binary patch literal 1687 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 YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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^P6`qsJU+_les=bm@Zx%Zv( z_w&%#Md(5x5PdIC_dp0_9d>Q3hk}S-`L`aR*>J>@!h}E!I@iX!LX5#?5ajs#1QS6E zJ}ee1EiLW+^rH%eLbot@+3jn@Gs7;|#xK@_+4XI?X%u{ly4!eI4t_t;f$x3+|h> z5#G7kl(;%VAle)+_dUU>qjSZxNt4ZRQlkq$zA|~Wf1k#k^3EzXt97&6Y}&OK3(Zcl zvX!9(8Sg-0`}#QZ7!Tp54QBh#XfiT109U!LIE~%KCsKs(g$U}l@4r|2O=+LP=zVQ8Xh|_eE*>kjl5KgV<=3&l5C*!6X3t+t(`=$n}+JAF{sqt|xT_uM_?2Y^(3%;{cRVQz> zacm#t9nKl+gkzv{-Y5umjF_x+siP@}I z!;$fxCQ?%dEN*>qDfb}9<7vJH#O?tLhQ`#SoxErnB@QN!=f( z5Gt7oz?~IaiXzms8*y~w;p^CLqn~$qvxKljud~eN8o_#6c%)$HHNtIr*emAk^Visg z)+$L|#(%pFhmg{HYtco(xUnn`S5$ptTH8uk$57-vK`c|K3ac#@HcD`JlJoW&0sBzQz$ZA*rpRDH#PUMZ82jxYm~q1YcAs#piOqX^rNR2ys%n@r_4pr8t0`g+ugdT>J-@)UJ1O zr<87A5k!Ma>8lI4Fnire**$pfnfWPGfH-*bvMY#mKVpC{ox*p)b6*wL+ku&~5-&+X z6K)>MCA}tPiExOQ_=;YTbaRoRxE!96i9`H|c^cAsA4ZG+sa7dIw5Aj{qqrnh_L@sd zU;Y@dy?Ot{Q42>Y{Yzz3HXB!DXq1Zu>3~w)lrFK-zd=GSZP95ZoLwv#j7 zEUlR0@dU`5`DxX?cdP2bl#ZZOA?2Yq>!w+hPqMq1*$&LyV z(E?hWr1aXz^Ok;In|t7WHVKy2JGO+`XNPC=>|?o=9L(qY`{8{i*2JmrdVP&lF9bfB zk=#3_l9SW0?+%z$bhy~LwAfDs4w=+u9*eFk+d(T9&}`cfI#}8c`Eo-gR;PO)sEg7- zWLCH6hS@U|V3lXi%|pSBe>m^O26t^J0<8Ep^N?ESdSbMLqyMucEh&9`A?11-um7$Y zLy@|C`R6Ai;tTwcd$#B5iFTINsSUPZsI9JWj1@zHrVb(H93YjFOS6-W8G39XIg<68_i)ilCPxE~Xynz{Au#1BzZlf(l zC11OPv=hK9@D_EPqKk+Z3>>y7#V-b{6>CX`T=>2n?)&#>cBh;S_TvrdzS0xLF1!g! zXy^7Cb;|fup-Dg_kbf&(-Rf(*&>DO7F>C&Qx)#JnPqPh`<`X!=Y8}{6B0l19`!3(o zTZE+m)c;LRSp7fpN6tr(e@FQ H8+qnm#2Rzw 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..3143cfea52475693e850f70a5ff3697ff55858e3 GIT binary patch literal 1392 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCo z0(?STfizao(9i%BudlC1lXY=%frtPV0A&pg4Ix}5B_$vOLdwX$0sD@7t}Yj_fMETXU_Zu>(_7Cuyg-`^B3+vc>h5#^!o<}29{z^ z7srr_TW>BnGCDAbux?;yNO~bJsPdycx@D=XM%Lub9X65f8W#K3n6N&HkKB}Ua*`@H zF6!)R9f*|oH1ZjD-^_VF?Y4q|8)wGjL${9Ho*nS_-haX1=Q=wUDaIcDJA2pn4x{T& z#ZMWXzug}?(Ui9}{|f(Y?bwv11r_Nl%2%&edd;-nVuAH;z3w$^?Q>$MyNaDF-T>rq zaUR;GvuVpMn<}3LKX>W%=0vtc?zk?N*;Z9vs~RJ=aLs4sOF3O@GGf)_j6zdfbqWMy zQ(P?s%+GzdNYSYdJEP6(A|I<3cbDb&W>Gb{SZ!T*vZZc|@ZB?Gv%Mcm)bp1ijZB@sBis!R3_ID(j zMo0d9>d*gh*FqbmEYn~h=e(j`!Z!B<=YqrPej49+FJg5fJAD_=Xa2*#GBixq|7e`G za?PK_=OMWPy0)30rySLK^PYWQ6Y%fHb+*Fyr5sQD zt-TI$Oa`hHb-F01&fW4nUb^Mvqv`uyzc?}_Zu;?bJ$HC1h(6!gAf(o9|K^3_7a0)$ zy&y}EL*&9gh3!s_o1A_=j+Z`iGHI%PcR`8Ql%tyUyST+8CT_Cf__x(@g3iAUi`xVC zxtw}5Wxuq*;)$Bwf&WYny`KuAbvoj>rykX)_pR8Faw=(xJuj2n3Y}w#D-Ok&ct@UA zneVViwf?nm$MP%h_w0@SCtK%r&FZ9W$L}ZkwTvGp{hGVI{Plk3c(Lx;J%=xJ{=T7K ze`BS?9gnF%2Pm-V28-2pU)%EOdQ*jnR(C*KsOQ?4$UnS%yOp{>YBuiD+9VXgG7p$? z?~2WOz3RlSBS|hU@hQIlmpoi_V%DFFmhs=#sN9;kZqdwv?I{PJ}5b6Mw<&;$UhzEfTR 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..76a4839f6f50d740831355d577b9aa60ef79c3b8 GIT binary patch literal 2054 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 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..1389199052ed5df45628c628989e4b3b61f82a17 GIT binary patch literal 1706 zcmd5+do+}39R94x{eC%ei*9?&R3?|qnA{nYX|!VcW+NI|#9$k--Zqx=!&M*3UjDLD_9tr=u1c_3E5{`}bA|3+*{MTRy^VylG zfTPcPN`LF;@D}SHq|p+K(zA0C&b$_~g+-xLo{{XRNPo3V`x2zoA=8)+b zUJn2=-gp;B?;nQV_i&{g9Mk}FbES|Z5wx!-dF3bdoJB?BMRJX?I*z0n-{VWpPH=df zv&$n7Ne<2a0`*z{22%Eu3#RKE^`|>GR{sMb`FytS+IVd%UMhQUt>_|^ug6r6@SN+n z^m!m|1$pNh9wEk}r^gAZwIj&W%EL1q2R?PAFnzS@>>sVRCFHg6@<(0;qy4zdKr_<$ zecIJF_~SLB?-8W)MD1#fe%KuYtJV*Uq8XPP(qL z^8+*bdrfZtA!mGtRys=gnGqCMT(u_FK@`^oY922-2_2C(BZD{lVrfxY9)q|MnzeCj zv-yq60CHWy@*#oOcL}D}^E(O4Kso2)NxTR5*EvkjO>A$nqk&FjYI6k`5oMc1FUY#k^%e=gah27t28bPGU7(K4h0K$7~0Ag^B6zcA(Ux8WDI5E zV@xR+Y9z;e1Am*#uo7DAsg|uF(qm?0$h7n}$8SEf-XF!LYO!=Q zF(SWQ);RYx3WX&VinroUD3yVec}5g;KoH_;N7rsu#fot*zv~J%TKOz@iHD5~Fu7vj zjm+yENAbH>(!NS(x`xf)81P0esM_rAKE}-=&a=Cz z#zNo1?SZmbR;O05tnpPv5y{PQ!86cs5;1nT^fI%m$MjHI>S5mS{l2Ue%4=UvoQk5K zbK>Kn+ov-0ADtZ-j*~?wR~83lE~smb#&9|PZv)XfJo=nbb1Y)!P7pHufiVR|`UUd8 zMt*DTmRp=6CX*ev&na^z_nx>Gzx#9W4Ntb9Tr^4bI{&;n`Nftgeu2xda9p=zA63`m zUTR+COJRT*Pp1?FO%XMhSK6ACV%nMnqOSCrp{41L2C7JPrBEi%Z%XKP_leaubo0lF zdE150rqf1Pfm44^4e=dauWZmLufFMQO~j|T4}(0K6UVzbmm)L7nD{Cyw{mRYOvvMfMPkT=(Njygc0kGQr6xZ=Y@YYjzP54N zfAK0?n;&bVP_sN(_~x!z;;>U=F1FhDWawCesJfG?KQ$-3B^FZSU-|mk*|kKBUSCls zE#INr?XRz9VrS9>vz610v-7;w6*{J5rajo=LSK;=$O&k>D5I!@{NItkQf=ADCclwT xVNVp1uBO<6Vg^wN3#S{{*gv>8=0( literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-1.png b/crates/resvg/tests-hinted/tests/text/tspan/text-shaping-across-multiple-tspan-1.png new file mode 100644 index 0000000000000000000000000000000000000000..621763ecca27de1701f67428f39347c17199348f GIT binary patch literal 1626 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCM z2l#}z0_pnt`i6!EAOi~O85kO1Y#%9`2{m1#0yLaaQMIB!1@CM4GQlQ7VMvYe#3==4-*0&+^^5?pY5Od zdVT!5IqT2P_Fr)QVe$H}*YoXnChU)IuRnj`fq{a-`wtEG3+(?puvD+w$H2gH!PCVt zq~g|_ON?wyjxt9suGQTYEO6^v{eR)9tab?@E2{Q0^UTZqE4J)jmev}%h{Yl%VqvDN zqB;>95)L+fjX&7L$}Of70UV zV@6$34?o6k+Oxg(zxpdz<5Ly6>{`>7&sXr7|Hpm*!;OMU*s{`@3o#o=+xaOD%G{;Y4^(8mqu_Arcmz2 z(pL_g`BQwAov)>=(K#kOjdiPW$Cr7r6I5PLE;34wyzo?EmZDCO=cYEUn_re6w&-iG zb={L3nVHBw(JA8b+ArrBv)QD6sA>m#)UzDP@br`^EbUmMaLKyN;rRDg8xACzGWMF@ znzd2qMS#Fr0k%mgyjxEgiX3f8W&K?y;5<#;?Ha>cowIFS<^G=2zVYq7wpKvp%WIT z@>Dw}nL4T`H1p>~iiw|}<+Ou2a#LHx#skaz`(JEYapJjc4)08ZNbgdqXfe^sMQn+i ze!a4JyiI3EdU)&vwd{p@2`3gQ`CpBlq4Rb9rlzJ8*Mh)n^^u|{Pc1n$>zKM>YAbKx z$?k{MQ%b+S^SdI$dGzEWv(mL|6!K?yEL(GQ>!zw7dV8XjHym7juyj+_ETJItS^>50 zX)cdfr!18?boXMEuBVv(r&!h3tzOLjLdJoc7M!=-qq2I5K-T0V;sQH@R<%t}OLT6txuZPT#ztve5my)cGuzWmh7H)69IeG1?pVwc%eq6l%@l2hF{3*iILT5jh%8h2Uu;4Iv&DyRC3jm^!i?LdN&$t9Bum)beCS2%9b(oVdX%r(*2b@Q2! zaDI(d%U36QHcr;$(mB@1$n}aj<>QOCPZ#fgZzy|lfQdnZjVa-z$IXSC{<|y{wh`DN z{V?U^BvtQeI+2?O9YYb~EF9Feps@Q4e>XdwS;-m5f2)4i0mij=SAa@XPgg&ebxsLQ E0HX62i133|599P$5cC(lA9Vgi#q}h?mjahgcB^JekD@Gzth*AS#m) z6$>~J;EG}kR)GWymI~NNkRbw!Od*9*C=UwcUCQcO{qz33U+-J%d}rTp@9&&_?>Rqi zu8)^1PDxh@0DyCMqxk}WA#M#tS+wHyO}Z;OeG=yu7!QC-$JW3Uo2%?X6?Q&H{hd(~ zjm^Jh>7RJJxLwc8%*@Eh*sjOK#6(9&qwMx$XlUrRhDM{Iz}D6lrEF|$&=yNeOSEg7 zB@hUx9?d9=QYa2U(O-)sCMHg6ZN;^yDAcWnhQ?h8LN#`O)1X}oDk>JJe-#y!iUD8` z0P24e^jTQol#~WcP5-T+proLHYLfqAW&Q+z$jYVxfU+nx55On@y#TZV&;YQTCm0MyoFaD76%Oad?b{6qg0!O1*2d@aJ3C+XqS4nkfX3+P=)2Le zu@CR3#FF{>`GsE>mRJ5rK29G6KvCjO`@%nEXs)jk*Fgeu?T?P?oiB@Wi}|IM<+iuY z_S093##dMU29G9{UzsZ=)M=T2tZ=)jPbZ~PR;c9crO93Q zE?@qXzFNyLKhiLXd&=2Y&Ajn+ae!HNkZHEj+dljB{*9UJ)!LEeSg$E%p&q3td^K6{ zTHCr}HXbp%d+@YvptPiOQ<65ROrQB7)uQnchCW%-7|jn#@_VVvkf^1KN5gtliR%d~ zAKhfR9iG(&#BLtPU6yNfR)20v2A|$i+SshdoApYAh7gaDI74ohXX^cT;WrsG@xT3A z&n369a;R8(VNW(9ocP7{xM{f&)a;kKr*s$NwG)#iG7Ueca&O?X zk+y!6=(t=6`%ZtQD3=RKrub*Wq^b13A`(ooFRp(x=-dmK{hED3y#?vYL)!KRHt9 zR+^|e{&NZp)7EA>J*=8@nL+$JIr1>M)&na2_|UQ0KdsDFwbmd1;MQ_omkRIw!@V3v zfM-tZCH4C*siEihh5VpWdjS*ank=~JteR%XEf5U0<%H9Q#=9T#SmgP2_n|(K6`ZA~ zL2pk6L@GhFU@EC_i2NttBP5jVC4H>#EL6? zt6S|0`@D5bxe+@96VHaN>!QaCw>!2Suvn~3yx*UzAq39!ifdw5UA#Tfp6EM=DbZ)& z=~7Z)ZD_;QURr@;UCeWeN5t32TqV32gjbJCa8E$Sbgxu$gveX)yFGWI10#&!lLIm% z)OlusCuc_9h+QxC%NAP_Q48s`AHzF+qju_ZRq}{dm$l2xpryD8)Bw-d=$LRvdW&+8 zdK;nOOYhBiLYG4T#S>a0iC8awE6G9L;Ae^#%+psULVHnptpGVn=M)`a>On0H% za8(|TJ{i=Z1!u~u?g&OmK4J4RsP!ivcpWY~O7q0KC};^8Vr7}wni8YgLpC~CV&2J4 zN`aG@Zx@W5h1{UGgr=)5^0o6r9S!;zJay!ed=$W9x*K$wx^LcN1k?wtuc=eF`Sl{kU+sf z3vsCt~n-s<6~_HT&lYCmb>jy z($&1y7$pnbbPloS7f&;a6LC$9TMnb1x8|?w)vxQ|38f?gj<4gTBaezME2EcD8YRR~lS7EZ%u0{X-9WC=0vd(6^c+nwO_evw=K)5x0BmS6L(vvJ^Q(2F_P zSW|e2yQhW2{9qUri=IcQa#GWSLH>`3&&j*JD^I9_E1&5JS~xc~iNvr_N*-4zN?<~#_lIq4iW0Dpc~XJUt0FYAJie(}IyRhS zGvRICMOjXKmQfwS?AMf5YTC6b31{c8wGPJ~O8M?Zj#O`T@h+uxz2fKj;YwL7U>GPe zI-M}vox6W)~hqtRo}RgHMeL_L18%+#%D P>+j0l*^5^1$YA{k(lEaj 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..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..fe98f5ec37491687f431f0045c4495eaa1d45fc9 GIT binary patch literal 3790 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 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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 YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..b5ebae5979bd462d5245b54b17285ba6abf3eb5f GIT binary patch literal 1625 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDD z0(?STfpmR+eM3V7kbxh#xVUg}aq;o-$;ikE2?<$QS>@*Dvazu_J39k4DuIExxHymv zG0@-NAHRWUvgZm@egK8^N`m}?84}_J>J29Be{g=m`U~;x53lb$J2CThNB{Z_hyCZw zuFapHu;KoPg7*Om2O8}EJA|2RP-kFZwf1yz45_&F=7KpRgQ5tlL6_LF$3Lf+`yRaS zsj}qk>W-V6G`&v8X(s%Q%oK5%rW3g-<)l?Nn3~jzLAgy=^@gaKLc;LXVg#coI>YFA5np5|J-`ft_# zl!UJ_0&80?%$a+mZAr>awv6(}-{cOsJLbIEu~*XBLTJ+8#(0LclQVfAEK<;0_E>(e zXY90KsUA_sV1ed0wcL}p=m-Y6Z)TS&7CXYaVN2vSt{e0A$Ia5{sEgrNtBmx!v!Zo@ zpYQ3ZEe5HPMq-A)%-674aVAdtDiinrLI3ZlX-}W0aN52QICuKgCYeIL&1;UuENHs? z(|Ov}(-w#OCi+e*m3qGaa_NC8o}_7^S%S~kG-N++JeL-k#<}J!kK6*8`&$enuRU_& z^JdVOfAzKe#+8)L39o`UTr;14Q4MU`lZ^F-N`I{Cb=9V1MR~ITb7w z#*VivQyMN~6e)0Hu^Y^TMGgEnn{~`@1 zuB-3AJ?b%kt(3O;5FM zs1lF)aQ*#P!^4?3jvVEh|AzmMRL1Yi8)m#r{->8_B4kQ99R>f6-I{HNDkr*LFD{ z47+;3k88TwX{Lf-rLQU?UhdUTjkLXRN``?R}los~4?z@%Mj!Odu`N^!&p6 zbzF(lw(eK)Zd&0yBQ-NbN3|vL+E;^L#z}(OQxEM)UwhU@?&|R~n^NXvn{Pd^yYSp{ zzPUSN3~jC+*tABsVQ-9~%x!hE)0>Kt3RWg%l*$L6OS!yf!m+>pM+2H9PTpFsv3h#j z!yFFw5`n!wD^D72z2hyGrzLxcku&MbsohUfI@v42W#(ARbnz~5UXh&;{Bh2!2X7v( z^>(^eb9jP9i__ZQGlUg&BQJ?x+0@ihu&;mS44s8BTR48NmAzvkbm)2W4Sh+?`qaqV zGwn}uCzjW!vRr)LpCNeo^=^+3-z?Z>|6gwMf931_Z!a{mG8pi%9GK*2gTe~ HDWM4f{651} 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..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..732312903e7c93f62e71bd42aa4e9101f07a5157 GIT binary patch literal 1852 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCE z2Ka=y0%>9ZA0Ho3S!`^ql9CcLGqaG85E~ntxVX5XpZuA~`2A>)!DzhDN3|Mm?B5-#j7xWC}R_4UQ; zzn*=4cy{K)+KD@t?%FVC&g}O7`TqIw8_rJ%_)!1eKtUirAt{=78v_Fym#2$kNX4x; z7Ys!k3?!--Yo944KjIpa#m)-zDP;lC-IS+Qcg}%<;F$L zoxa8&tipSm4nz&T8QHF3;aAVjt6Z_Yi#bq&@5Glc^P=yr(7O4(eurs>Lkq)6v6|WE zbq^&ik^Fn+#G}o>tq%oFxZ2w5(oFuv(T7n(?IDEXd>GY{S~=Q=c|{-4?v%(#BVT zHSU+^l!jHFzY@2Br!nV3aB*j3kDgT99d-$AMm^&L*?C->6^_|3tPYIe|GvU~%G^d? zmOXO9v!}AIJ?;C8OYHNjf6cQR_sr{Hym3XoctPS?i#_{RMhJ*0-~W63HG8W|zKu9eDlj;<{72s`}g#MDGf*EZpcTVyIDGvrZ{Y?Kl&Yv+(A3%T_yjEl|kjui-e&pso_6zsiI! z$ClIBHh6=@r+Y3U&I`LgWNgrRI&Ckn1^bjp1LMdm%NiopLnp02+9((yBc6)rh}kgM z!=5RO!(ZGxYv1p#@&rwWBEGP^O=>PH-4Y{JD_$oscuOVc&p5JZW9jWrA*T;dTJ`cK`m*hIHQpL8=AY%C}|5 z9b=BrEO=%Sy;4~A_1?#C%;)SAW9l-Oo~6gOS~z&hJ-ID5iF=v5EG`m6lgeX4v7Ech2|u+pDJU*3Y}$&ndKP z7sHEJ)*t5T$D8lmthc6L{CQP% z!ixuT^MoD<+{hM)2DIEU(wgFV2tuKhbi+AOF7p4f2tU-@kN! zVGm_E$a#%@D&r%T?67V7!%J7!C~SRJ+Qi!MyN+$a6!nPDlX(7azQK8I&y?65?_Rwx zdohE9L4b`ZqB`Sc-2YcQoDcf@bhdm6J9!FNG}61gBT(A5LW*Hrl>Fvr0yCz&uE?H! ZA#RHh=S0618+U{18BbR~mvv4FO#tYwA?W}B literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/with-x-and-y.png b/crates/resvg/tests-hinted/tests/text/tspan/with-x-and-y.png new file mode 100644 index 0000000000000000000000000000000000000000..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..b8263e2813bd9a3376cec863093d7ac109b34f59 GIT binary patch literal 1680 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpBJ z1^9%x0_pnt`i6!EAOjCzW@c7WQj(F85f>MCadGkU^NWp*H8eDIc6QFm$+5Dsvb3}W z8Uhp%5)v{nFaVmFo14qV#s)Og-`}5$3*h>EaktaqG>st)fg0A`Ff(RtKLh`G2V(=-%<%Z7rSKE}rAMmUm@Q zLTUTf6hIM~GcdVdoux0p`E1{N@xzzJd}925eQQN9o*5DB1KG8nO1 zQ&+z}1k$?Zck|R`yQ?-h>7HKq<>36#^Lj7e&fluH;gD*?$6Xr^ZRK85P#p2`*oH^E ziLKG%5f8;SJSwf{Up;sGo7*oZEmja7>i8^9>uk#HQsP&WhNtak%1@ZTjb5$D18hS+#df;M~4EBI^-%;f(Hp z$MOnXt9g7%M7-bfF|YMHY+-QXh!(RnzsTwS_D0*_mZ?IWu4|4}X(j6{pZ>f-f)=GVR=|qdkS|%)K{$u?f%;65FXE zyn2?l`boAme!>S21<#GNHPW2oqhtJhYGU16lY>nK`@_yJ7VG+YNO!A)rl#1h_Qa(e z-@R1CgkGnXMl6B9_+k^#Twbv{yGJ%*dSYf%*B`uOv1k$vu%*7f(Nd3^o{D8FU7bKXmsDN(M`HUDPXrRAsU+pP9R>g?*hw{~yGzXWH6 z2($F00(0~I7TcGHr-`|4A@$%_jk@+Gu`cdts3)46ixjkGln+@9L>|oH}^pdIR zNM-Y)14&CH1wbd^!vb zi3$wU&P?Le`n^8P>L7FDZb83kI+2@FPEJzw9&8LTh_f)MC?$wnzw%zN*FG|5mcUnr YIU@Iud_1O73o5cbUHx3vIVCg!0EAS&ApigX 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..9699c7609e9050367f7089fe34b31a78977500e6 GIT binary patch literal 1585 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfpmR+eM3V7kbw*E@$qqSammQYxVX4jSy|=g=CZM|`TP5ei;D{h2{AK+ECQMU zGzXUn_{Fo29J>Tmp;Hp%7tD|lFQD+DV8Vt42NJG7+}S=c^L6dvvtRvZ&zaw!AAe!} zgY)<64FcZpZ?OOGFx{`pnt_2;+SA1`q~g|_3x-?`1_CY@GZYr6UwrfTeR|HDmbW6c z^2_AoR#qEb6|$X~l(02mQCU*2YS15UZZVyR4GElJ@}LlieXvOtOtN|d*|XFkY>2Xh zO{_FxOx+GO`Rnd$>Ki`gCmj4GaII{s%$b=t&plS)Y1N%*`+c+jHRHnw(;Dp8+Wfk15qJ31inN`kYv#UZ$$lJt zcvU{@={wTbinJp>uT6YgqaGoh-WK}j!mP;G^SR2ke&2hyzsR6CIr_qzR>6j)PNp9I zPxmKXE!ikl8FAFyO-4Jf?3aTg5 zpueR`Kxby9ic7y&a$-dEgx;SE-6BnAE%JJ8bl6IE^}4re%ik+2Yt5K2Z`q{h|65zn z@Sb%(yU51I_KMDoci%Tk8AiO=vF1+Y^X1E%!=~(Yl5S%DQ=}PitvcqnTgde*OLZ<~ zxg@a4?lxS|ASfAC9x~HJC;4j5J~KO8<-Y6Twoltb8JJZnPp(-Is=Gs*$J_Srt4Qr_ zF8-Xe4OO1Bg)U6i-^$JERw6ksge}7Mn9}=S3odl5`*p=S;cT7jO7gM$tIZ_=8k1{oVF&&+Q~75WtL%V43+8r!vOCeph!*D$R-!>GNMjhpk` zeU9vfE*UyjMF(ERo7!yZU0lJx=C7;2=x&M6y^#unE*Zgd<;CF}z_VpCbMvu78?jq{#K}2Gjd@ zpEhh*@G$UaS7?Tl&)ial^-~*MOP9E<-0+R&9=Kc4#+Qs}!IMgZ7C|JF1W6$b&XY1QoO}pc^ z#_5^fh~es%>vix|-@n_qKtlb?g0~sfOQ+txt7#V`oSW>oPcYl<#9^gWuWySq172$U z&X^y(m1%=OTGy3?cJn_MDz^M%UK5{mh~bZdv0*E#OJzl)kdsXfQ&R$?fxkdxr-sLJ zgF7;IathPKSu`3rRa9nvU_7)=(6N~Jgr1?u^$(3DpAJ_X3b?)^NGPI*nOQ}J{lue- zS5GbW-p%;-LL)1K0T0W8Nv4||Qvd(;Qm;@bFh6v1lB)MKoybiogO1?@aTX40&C)gd h7=NX=&IlG>B=^~Rc4_uk#_ym4*wfX|Wt~$(69BFFi=hAj literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/tspan/xml-space-2.png b/crates/resvg/tests-hinted/tests/text/tspan/xml-space-2.png new file mode 100644 index 0000000000000000000000000000000000000000..9699c7609e9050367f7089fe34b31a78977500e6 GIT binary patch literal 1585 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpC2 z0(?STfpmR+eM3V7kbw*E@$qqSammQYxVX4jSy|=g=CZM|`TP5ei;D{h2{AK+ECQMU zGzXUn_{Fo29J>Tmp;Hp%7tD|lFQD+DV8Vt42NJG7+}S=c^L6dvvtRvZ&zaw!AAe!} zgY)<64FcZpZ?OOGFx{`pnt_2;+SA1`q~g|_3x-?`1_CY@GZYr6UwrfTeR|HDmbW6c z^2_AoR#qEb6|$X~l(02mQCU*2YS15UZZVyR4GElJ@}LlieXvOtOtN|d*|XFkY>2Xh zO{_FxOx+GO`Rnd$>Ki`gCmj4GaII{s%$b=t&plS)Y1N%*`+c+jHRHnw(;Dp8+Wfk15qJ31inN`kYv#UZ$$lJt zcvU{@={wTbinJp>uT6YgqaGoh-WK}j!mP;G^SR2ke&2hyzsR6CIr_qzR>6j)PNp9I zPxmKXE!ikl8FAFyO-4Jf?3aTg5 zpueR`Kxby9ic7y&a$-dEgx;SE-6BnAE%JJ8bl6IE^}4re%ik+2Yt5K2Z`q{h|65zn z@Sb%(yU51I_KMDoci%Tk8AiO=vF1+Y^X1E%!=~(Yl5S%DQ=}PitvcqnTgde*OLZ<~ zxg@a4?lxS|ASfAC9x~HJC;4j5J~KO8<-Y6Twoltb8JJZnPp(-Is=Gs*$J_Srt4Qr_ zF8-Xe4OO1Bg)U6i-^$JERw6ksge}7Mn9}=S3odl5`*p=S;cT7jO7gM$tIZ_=8k1{oVF&&+Q~75WtL%V43+8r!vOCeph!*D$R-!>GNMjhpk` zeU9vfE*UyjMF(ERo7!yZU0lJx=C7;2=x&M6y^#unE*Zgd<;CF}z_VpCbMvu78?jq{#K}2Gjd@ zpEhh*@G$UaS7?Tl&)ial^-~*MOP9E<-0+R&9=Kc4#+Qs}!IMgZ7C|JF1W6$b&XY1QoO}pc^ z#_5^fh~es%>vix|-@n_qKtlb?g0~sfOQ+txt7#V`oSW>oPcYl<#9^gWuWySq172$U z&X^y(m1%=OTGy3?cJn_MDz^M%UK5{mh~bZdv0*E#OJzl)kdsXfQ&R$?fxkdxr-sLJ zgF7;IathPKSu`3rRa9nvU_7)=(6N~Jgr1?u^$(3DpAJ_X3b?)^NGPI*nOQ}J{lue- zS5GbW-p%;-LL)1K0T0W8Nv4||Qvd(;Qm;@bFh6v1lB)MKoybiogO1?@aTX40&C)gd h7=NX=&IlG>B=^~Rc4_uk#_ym4*wfX|Wt~$(69BFFi=hAj literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/unicode-bidi/bidi-override.png b/crates/resvg/tests-hinted/tests/text/unicode-bidi/bidi-override.png new file mode 100644 index 0000000000000000000000000000000000000000..ced894d213e6bd6a26225e32a5391679ed389755 GIT binary patch literal 1793 zcmd6oc`(~)9L9fSV>NN6RJBo7U2$tmB-ILuy9pClQ&(uLQbDT+nw6lYwANbcsJM?t zE67G2RVxg#j#5=u(YkG`N)N4|WYe+#c4zZ25Cj5&!C*>CN;n+O$H&Ln+1cCMJ2W&Dfk3FMt7EZP6bdB*im-BW zaymLXqMS;l5(oqlU&KM9(cfD1&v`_Wdc5cb>JpLQ3XuKejMd2Rrl)w}Z7CQaUqldFXC%>@Ru0I{OvYJfRPy6|Hh2T3r~HLQL5392Ee-4GuUfx2W;u z0V^>Kpa3>jlbilzBmtuZd0jW%_Qg%j>!@EH$rE2h>fyyUJhSvkTuQg~x5P)!Y4<8! z^FJ``a7y>T1+(AJ)>}mEA1>C3DGy?%yMHN=Xk3aB>TSj3?zhf)8I-Egz=*tT?3^M1 zJ{;`f3N%uZp0->ZSs^{QVH$J@5Zp_CTYHju8SI!x$S}SStpjvbv6*a}a3U+(0Z_X% zF0W_n89IJfRZs64v>mNw@q==>rs`fgmh`Z<&d@ug&!;Z%k>0>`Vpmj}J2rmMllthU z;*UjTR9#hs(^1NJ%XD(*TooKfcO`WOWATf#AAJHMrW*r2RZkMB)KVlyc_3#=yNlbw z%~-he-Xk@cSFTSAOx{{^R7$y1e7oXpdNF(RNW*JZm$mG=es7=DYWAlWkmjDv$GrNg zR(=T;ahg=Ja)X~|X_J*GX=Zy+$Fi7BE8XW9+2oE{@jpP_8`<(I@Xxfc6+vNdrM?QZ z&un{4+_^ab1V3E#8$aiUe46XKtLJ8E>pQEaCTTTm@3*=fs}0e;4#*r93r%_X1@k;F zbZDsGvmFeu3-v1x1@R?FX!gKPW)Vl`4i#z5g` zu8X~a{I&jsU>3sl9!6H}c2&g*O5zdcr8hCWDT4xz#$iSRoBZJIc6E`^a}l5Ao{>BD z?vHNqr4DX3_@H@!v&O0}M+QUCxCSlr>8wfUfk8W?bYBpfUU!j@?T3z^ux`S83?FFe zhVehgnF)1BL{q!*?m?(lz>`zNCs`G>wX0F$A>Nieh4zdu8#O#qj?j>jR5#LmJkOJR z)O_GG2aY5qM`bObCr%DDyGKvew6cox*;W8QpG{#XaM~yBm#SV}mZLoFUo!N%Nf<@z z{+@wdj9b1{A;_MeRsEQJB~$TS#7ewc?JLb{%`0odj3AjLX`I#mFl|DC;&44vxTAfG zdY-pXYnoAM5nG_q;ydC_I>w-o%lWdSgce?bm1}G+QFk4ADhcnA2nlGtC(9~k?jy!2qCgo1Izv2y^o>A}yTUZe@hxlkxWLXXo{=)k58J9* zw->Cd7J3oU>NH1wt}?;ambfWIh6m>VEE%1vEjTr&lG&5nz^2$X4TNuR2vXCePHv#q zjp5yHTE2ekXXWp+1*;#%^N;zuzPAs)%Ao~zPSJ%W$2LszJqq$qjX}4I`-}Tz!FUwcb h!JqiVF$+^jC0NS6VkEEz!}$7BIM@(y)z;+rzX0a-30?pI 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..ce94fc28ad9af8e143736e4116bfae5974836966 GIT binary patch literal 1704 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpB} z1o(uw0%@$Ep`igNUSD4iBy)3fA!=e{WBvX8A#4{H7a+sR$_hwYT3Q0t8yXry)B{B{ zH8qu#lprc)WMm+w0lB56rQ+h^LPA0j5fKnspn*VHK0dy@ygV~AGoT`H4 z{sV^(pFMy6!sYAN@7%xt@WJc%AHHTipS6R5fi>CF#WAGf)|(5BtOpDjSPuAWgr;=p zP5f)FJ@)~lZn<*Iv%n;^-7b^%1|{r`lw|#MRwr^(ilX;4T-3Xd=Fe3j(kCYk6k|=h zt#M+}WwyfxLPaOqOlOB~d-7pttK5ZMsj?HF|Np;v)2}WcTe)ktXHDv!JN=4_?LW8C z|5Q+&?1nRc{?*x8AFgSgYSLk*U%7rmP{#CYdC{l351g_%y-io0;kC8<+P~pKu`FSw zVmfC<68>^rROSCMV{^jN$qiqHUo7^l(U3V>d&hZ$*3AcI-{YoYJ1JE{>Y`M%Fd+%}=2`87|J zx+$MFn`)PA>7tTbK{mg$xK3_K)Ke>z-emDWYeL-1Np4jqucc2>5ahmObm`5!w}~dx z!mh>gZQK#1yDi~E?@L?v4b$GFdNf^icxJwEmVnOGZ4RZ2`E0*>{StM)V(eAj{ViEL zv_ahMafH{pypu=geBbtpzwHahG(O$yNgH=quo`PdXl>KI;8Nsr!TkW62z$lc*bkOD z53*BC6xFmh^1RkJkd^qt5H_PZAZUT;r4ua)rI#{$b!5Enx_^7JDfdvq6pv%49VYfH zV}G7nsGcBuN$UXDM+L^@hA3a|X&RY|e4C}zBC0CQ)|kxTEBF!^HJ964bb_xySjEjJ zCbe$OvhAs%7dod-4Q>xgU$^FQyT*erB8i^Q+hf~uWWwsWu6>+Y%5r*6n`jr?$<+(f zj6)+<%KJz?yV`T`)}<8-9^Bq+Q(DI!!G0{z;K*SncF`-J>Ly&eIwc{MY56qvEtf=> zN;RuC+qR|tuHCWV>hc8L!l($Ah)#)Z4@+f!DZgje?A>RxCf@vC`u>|tk-}`NW?tLO zbw)#HYwKAb?Y~(QWoxSXt3`jmT4Tkkz05enRy*V9#UNL&08zG5t4M zbN%tJ)V;rX;>+&e|7uzOI(B;8eXp#ues=c`W()55ZTtGSy4CAfc`tVV-SPX-yN_=R zSC;-S{l4Sz%I?FrmfPDMyllSj#VYMnm-*%Q{$6`S{^{$ozmjF=b!&f^SS{Gk`ugmS zy1HV`gTMEOygR)7;)nmA)*BqYd3WEx{D=#ywAU26Uab++Hq}<$j6YUFO5gz{6~4(0j%3&&x2aru&=bDBgL)eEKy5x0p`EhJ=GntW;sFrHU~u z5VvqboF)Wupen?f-lu`|+0Y9$I<29lnrq}|g+*$t*kQO6RDyfD`njxgN@xNAa_Gyv 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..b0970e86a23402d2bfb41325209a2b60f8db0b33 GIT binary patch literal 1723 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDf z1^9%x0%@!uCntxCi%VQwJT^8KqQKwZAFE0~TUtfE{;Jw2B`1Jt`3O*$4KYaf3&g*yX-=ENMV8e!W zb7uFqPn>;rY3761U$3u^PuOKOe<}k5Yp$n@V@SoVHy5@twm2{_Y}ov6YjvXFje3JM z?p8XIiVL4i)lghEwWIc$`MLw;XSxzu7wJT9N_jgOM4p_~iiKKr=;D=Lh`6fvH5g+W zy%|eI&d>e2&tC3(U+m|AJW|@oq5kYYGi_KJd#>$>5#V*EnXK|0)q} zjtPISyv!?zFjPON)z{?Y`kmMuvByhz_XeXoD@@dlcy-F9gP;8PB{ZW= zC~A@4dEH$WN*;F`TwHt{E?K-SlZslku*~^b?(WWMiCSs5Le}1IbJNL)KAZgfN_|tR z(y3*suF;L9eN4UqPbBpZ%rXk^|NX`Jgo_Z9q|h`G%Ln$J(X)cN5}S_&yNS$dDm)u< z>Co$grxfnF`ZAx+V9Hca+$TTnrl^p?Reu{j1sSnvN6gsMtZFlEZ`0*!-5z@9L&t{Q z{|?#dsNSq=xO$Fp+vI?E?N2rDmSs3RnrEq_BN)u$@bCu9qFKRK?)S2tD=%=Z=U=@j zPc~9M?D)3diIHWOt_X0XWJLI7@)h20`L;N9E^l_j=Eqc{KB@G5yj$s8|#UdGAc z%&P@B7v9)=;)B4NSvOB_;Oek`T`oV3_3{l*{%L$BfA!53CkPm|KIP}q&VIo1V;%S7 z;FF3GayP^iXU^#~KFqP3Kdi^f=GTUx!c|{4+|fKQbd*=;48w-H`8(o&_Z~C2YI|H> z()g324TpEujGmqus|&Y%XR(*_tP!0!yLLm$tG+`IYp0Yac=o;T?7UlOwu|5O(DEbM zY76JdZ`Dblo|il1X{SW<#d)l6=~TdK5b>;s?B<9a>|bv`0c*= zizSNnb$Yoy@1M;Z_Q_w%e|?o{+Unc8->=&JH7j}je$#8SLW@5NnlRd}di^cU`pas* zw`}s}2air)|0-_dJ=GUipX+x&RolnbyW%%no?Y(xeYLT=51*ZWo-1l&_AvgzTeEF( z2fXC(T)f}(wI*V}9se5hJ9Eq*{N3IB@c-BOhq6|kzR&BQ*YJkvb;qlZS3Okr_0O2i zy+(Oez}bGW`bN>TP=?Q^W}W_T74z@;rdnoVM=b_{zu-W7zb@g1r-1d^32u`njxgN@xNA DYWC~T literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/word-spacing/10.png b/crates/resvg/tests-hinted/tests/text/word-spacing/10.png new file mode 100644 index 0000000000000000000000000000000000000000..8e0af36dc2dd67aa526a59875eda39e23681a005 GIT binary patch literal 1720 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/word-spacing/5percent.png b/crates/resvg/tests-hinted/tests/text/word-spacing/5percent.png new file mode 100644 index 0000000000000000000000000000000000000000..8e0af36dc2dd67aa526a59875eda39e23681a005 GIT binary patch literal 1720 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 DYWC~T literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/arabic-with-rl.png b/crates/resvg/tests-hinted/tests/text/writing-mode/arabic-with-rl.png new file mode 100644 index 0000000000000000000000000000000000000000..000ca6f9f5ebe9318293f1b6f57de7344225ea65 GIT binary patch literal 1696 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 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..7919401b683944a4ae4026737267a542fe745c29 GIT binary patch literal 1714 zcmah}4>*%~9G`ZQiK1IwLoPyCDobLeE2I!k?0F3tOWm5K%zw^IB!8kKufwt&axrX* zj&6lm{?wE*jB=@QYiV6sYZ&)RcTZ2(^W67&exJ|h{eFMn@9%w|_xXL&J>8u(5hw%< z2GcyS-_Z*OQ$a7RWpF6tUY6(#k^0H~zEl`Yt9@aqU%`VO}8+bz32JOcv>1k&-a zlhg=WQrg*^pU&qN7c&^lOBHo>Y<5%gt(JSe_a6?7KK(=bTBaA2;Rb`L#vX9o;~gWM z97zu!+qW|5srW%mQ+;Qq-Z77}zS}o$1hrquX$^Wt*k5)GJM$Iu&hIl`^!e|g1!etC zb>T6nMOcRm&S=vkopjaJ0D-QG!+#X3zr@O?^XoLw?3N|}1qROr%1c!LXj=w_C z#Ko1zjfGgS{cB8*+gY-oxXauc;MJ3F+K2fngBquuZcEQQNH!!g}Cx;nRq7{Nb)mDuhR_U2P=@+ ziYDHP-k>J@(CO&Q0ctk=cLceX(3#QB9LuEx4N*-gobtZGg4;m6DA!65e@+>CyXZhO zaIu@KUj2qd?7|a`;5f1IDV7}N$LJ6~ADPtl9P;MzyI1MF!Q8NHL5FWRUXTmbSi_zZcM< zEUeC9&Rjm>Eo+?5;4UM-w~=#siHe=ure4+V8j0zc%bTxBSo1uz%tX9OtYyJhHU1gswO;=RmteYP;6gbdDb&UCAW?Z=4h}^ zU6n^7wJ5{O04bQp-!L0Wi(khwcqNZkyz5N_*8Y z)g&50?CzdYAY7M?cw44&Yrh_Ovi%HFm*U04$HXGQBkHsZ*>g;fKVul`&|OUxNkf9w z(eifM{UxrLt!e_dyYz~}pW$Sa@s>WfmgX3Y?PKrZ@%0o|PjS9|Y1}lgGDB23Jq12H zZ-@iLZ>uWd%x`c%Oev70ppYmF_BaBxt|Sy%v|3Hbdb>wL!p#e&(<8#9ZKDrbib%uU zHEfoV)0*1bkY+tWh=_tW4# z_Sasafzm9l#~KSNEuuq-w!Hd@qkLvO|Npql81k;nkB;*>Thx3kkQ4Tt;b~`P*-q%M beS1q~l5b_;Vsva^!PE~pxjWYGB_#h1cuoI# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/invalid-value.png b/crates/resvg/tests-hinted/tests/text/writing-mode/invalid-value.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..b0c289dd882da9c392f75a590b808e8886b3c9ab GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCw z1AIbUfixy)XlSUfuSXMiadANwQBqO@av>zLI3FJ$G8f497TJ{tq!dbm{DK`A1QZPH z1L6}B@(b!4+WRNWU$B1th7J15$V_;x$^mK6yskrs_ZhO%!FOi1C zO4SXV*Y^e`eft~#Ni5~vMnS35xii-6v$vf&Eq~47RpFUN21{3+l8Oiot&HRK_^caN zYNQalA>m*XEBCb>KtfC>Vgn19OyC5u6AlUiNx$<6Z=sT4r4Shuku{(HJUw^%095SU z?_GQC-)C=$m>-!AG8>Bqu;ERtum1u~{2Cs=ef!@3A!5_GouL-IhRWm73Xv3ebzOmiGTd$W*y}9Io*X%uS*{(f&X;)plq@=9i*x{%* zElk>VyBogls?1w`Kk4dSN&eNHb7z}Jd=%u&4v*Tdvj4JO*srMS!%0=+EpOdybdZS5{IXhVX&?*~VS+=3$>@cAKPXQRe(hWJ(k3VllY+P1Yw1HiF*C~Bp_fApymeY#UJ@p1TfBX-$wE`EH5*P{J^udg%A$;3hS!^Z z-}vny(k-VBbFH2cKL5Ctr@8FfNgH1ET}|J3D=zcu z(L`PAu=z(`W$AVwp4E2sdqV5AEqi8uy|D4sPR7ES+jXn+^xtIIikNMF^x@PWYx$-^ zx%SFa2fChZeE-LEO@`Q?r3tN05w(KaTjp`a9yCw<8oK5}me&!fdFmdKI;Vst0FB=?jQ{`u 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..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..58d6e8561071bed1444b76eb0f2e73665de7e353 GIT binary patch literal 1594 zcmbtUdrZ?;6mE+YZAVK4+YJg6=Ef>TK>;bR>3CM9MQFRr2HN7P2w0wFgoH;W0);4| z0yEGss7R12{HQ3FDU>NP1)PH5W`_>3q87_z0s}$zLzqhz|5&!0-1~j!-1FUga&qsH z1+o2&3FZV024l<$@Cn9Xu#CmI(g5|a73uyctcnW=O~hbG*A^$X$c|)zI?IE0a(z+! zm&3-!295Ob@mV4ohsO3M1 z05iWqO>6E=Q~Xru@+oC*v)njA zyoH|E)P$8f_tntBJg5j-U$q_wu7H{dTNR*#G@yE10E$j#Nh~|5c_X=^LISy;2d|L2 zD__Q?`K^dP*R=(B^_oL5tU38rmPmFov+t;+=ak2<7H8yN3Yc`yhXJu}Q*Hw7VbUPY zj>dIGHZ-hu<{S63YE`Cf%}9^?g#%J8hhGA0?aBQg6dxp2%%66mxg=WwFW_EmNT%!` z6G$iR_s-0GM5d6lGYu&~AYEGe$%l*9Q97WmI=B{T zMjAKjE^3sowOlMkBj+5FIk{y z6|;BlqGEWXxRw3kVae~zUPXS!{N(f$Z+>Vdzf_wrqr0pxspg1V!XEY=bS<zLP}5U`KSg)>c7kPX|J{2Cjh+BLPullKF!kPfX>M5KFMQz9(1 z(82gW27$~;)iEImZ&z~9zV1l99P&)voGogY+BY>4Xf3KS(yiy`D$`W%+dpn|GpMae z5YId=b$pbIXCQNt9z=m8f~UAM@$8Z~TrYu<_t5kRmYt89S!RK9T_w)0D5B$A=arp1 zi0DnR{<72t^#m4H0AW+2zp}R>t2NJ%zfSZ`j?+Tjq$Wg1g3sfoOLkCurpQPgY3#<9 zO9R5#l@yTvG9^r(*U@hU2FFu);wJ6xC>PlY0_4N9$0+0Do;|We{n^#Poi6M$zr1Cq zG32NU@tv)c-475l5jIs<=Wl9H0|I9bHLwc9UpV;w=sB?>?desV-3T|k*UfGeWra$C zp$=Mu;;&^qcs^Sg8X4-wRg8CK^|cJJ8j1ce%E_YDo@klh7S*w-+)B@;DN{^+H*}Xd zOC_O28yAw+?4{UNp|9IhXgPdUqO$9^g2~Xqyw9)p1%KN95dpP4jtuRrZ;CJT+oktX z%N&W&)e*@y`uh+3Kel37{w_?rwcKo?T`IBNY~bXuzwM6thYTcSwsYH+!Lh|I%kpLW J)O{{E^d|)2h*m>dia-!5380`L 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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..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..9d3532cb6081a537d1d047858a49be876cdd45ee GIT binary patch literal 1651 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpDv z2l#}z0_pnt`i6!EAOjcR0XXC~F9K>aEeY}qW=Mz^Feo@b;lhUX53X;> z{Cf6qM{QPJ$(-4*m(8BDzI|u^(ueu}^Xuai_Aj{qA>h42!vXvM4o@CV3}Ikkwe)mx z45_&F=GxIlCI<$VgVu9A3hth@H=XnUL71%5-e2o?@&$ihKh5B(Y}jtLm9+;})jO`* z-^$7@rW3J&1xzMzg4hWMg}`K!Dv)jZFY#a#L`?#@4AC&X^@kvam~WSO+bnuj@Ati* zo5RwlU#}074~uIQ4NrVp3PcGtpVJjg4IGfx8cvp1ALEDys0jDc`DuO4oUzp_88f{+r(#YH}-~*5^%Z=ux3* z?ScPixNq3@Y{j%&xx!*k_db2~xzT-E|HgxBvbWez5prJ27Iyu1=+lOy`Vq34e%F52 zB`&zc)NS-S$f-EuN>`^xg7G89l7ov5>=Lz^EB+%-%qm9l@B$982+yh?cg}<`FP_ly zc7cFcx@hZT6W_-b<$dcj>uS1uiq#V{OAc8{w3XQ;EZlVTy`pjQITsh9V{MsN9&WDj z*_$R9lDwq&jLm|tMbjqvML56r(PECWwOl84?!}{^$rm}f9h_dinJAcdeS=Eg8>lU%w%AfnlDQtqdgh7`{mRbGjSZChn35;lF|7xs6$uhAO%>A<6| z3GF^|+W&S0Qd2SSL2^y-uV+0w=4!qmbJYF|lPAq?Rw)CA;{<=2Oe~#N1Ljmx=yk{M4Hi(P$gl zc*U75;OvGsl0p&%*9)3eXNA4f%iGYhbX)S#lIEkeGZKKjip#RI)-hjucd1u#X6uF9 zyADnY>kB9n-7xEP0`K0qV6C1wHtw}-IxB7GZm0;3Y*S^vQF-TicAUrUPfQUCSNPIG z?k-AX-DSt;{V#-H{r<{UR}Xo?X>X*Gu5n)BdMzL@na7*s)U;={N4#{`1ipIfxuI=d z^1YS+Ma(*^FSA5k{iK|&9h-IJL0RI=h!s&xIx4X)kJSIFuE{*SLG84&OOxvR3rs(J zcAVeg8S#hV_rsJ3kq;|3Ppf%;?Dhq>#EtJ_pS6URT+)lq5HdR%{o$^b&NVmwu=oGI z6y_f1N9VPzzf}JJ_{tZVu)Oymldj`quZ|@us-@1Wm1AZ%r>?ML zoF-!(@FZvUG3j>JpKl8z&X~3wzqjt6QA6ngBj+5}rFS3Iip$;&zh7;%R`(E-Ub>#$ zyOw%O&h0#Y91qSficBz^$XJoEPRU7k{uTxMUFlPvJXJX&sP*7e*Nj_+q9>D2ozz-5 zW8I1Nei`<@%la03zopr0Elm~YybcN 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..9509f1a8dd4b0730726befc0a93cd5e236997177 GIT binary patch literal 1690 zcmZ`(X;c$e6b?&3q5|R}$P!Rbr4_=_xKY7k*+f7SA&bK%BM4Yb*og?Gkbr2BfK`Ya z0u`x1wxKjEDlk-o)gX&PsGuO$umuVPf~O$b3Gq+Qv2)J5-@V_wcjvvi@4G)9A$qOF zSYS{n)LQR@9{wnl7G6D8=^zZT{0A=t4B`$3B%)A;57k4f$llNrA-P8mQ9Kd+?30<9 ziSQX28Hi;t7<4*aGc6<}Bse&jL?UTI4-XG_cXy4CEJ5ZI2n0>IdGlt((O4@hD-CI8 zW@chyqVWw44G{-}QSV$&PftVY=%}~d1vflFfRN-*B!7!C-ne}~=}2fO2!0nG8<&`r zo{@R(e8I&V#l@v%A`t{Nw!jabc6Rj*4Zl`Q njC4bx&v%6|<<~>?hFD|qkMlH2`ybSF;a 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 beS1q~l5b_;Vsva^!PE~pxjWYGB_#h1cuoI# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-alignment.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-alignment.png new file mode 100644 index 0000000000000000000000000000000000000000..c0f2a3d36e0cb78af01066dd860f383e74d4c88d GIT binary patch literal 1727 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 E3Fj8X?*IS* 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..4b8b605f6cbc66f33347ee49b9ed0e07fe07c731 GIT binary patch literal 1460 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAjMhW5n0T@z;^_M8K-LVNdpCo z0(?STfizao(9i%BudlC%%f`mW!r4FuPyt+4Q&SUJ3c}{&+Rjd;#poI4G(R(H8ZDpHF zEm)Nsn{OAr^MsUmM3VjWs(ZH|m~yYV?zeu+#O?!LQG4UE56ntTovZgv>+*r9%oR?@ z4tVVfOuIj2=`JbTtxVZRve>5@ZJwNXO2qx^(gfa!=&!kNYd&pxpD%laecD%ry*tg8 z&5nzejF8KIx;AKMo9fJ6SsQG^O!s!2-`KWYc!NyXqIGW5Hca|wV%IQr^=X|X&&P37 z6D-#piu|&vCv=XVT*T7NE0`jFW>zq)E);WR$o?j@MrMtMPU+144ON|-YyOlpvS+{7 z*~Ad`w4T}J2$)Ztt9=rhM@YlkS#;bA>I_t7biI_x8&5-`fvv zdUZ-~!z;hq$D-Ui_SRF1*JSSeap044y7&Pp#e-f~rs^hs-8qNpw13o9rfYT+Jrh)q zmGZ9E@AYBMo_9QJ)}|9FauMZx!0kNnv9^iq)b-g-<>q z5wS1So=>n${KkR%@~?l|)&4d6_vh(xg)g6%@B9Av^ym36;}iGZS-$@Mvi1A^U)o$( zTmLioFYD?3CF|GiSS>pHlG49Q#fWXP8?v+y0&RD$5M;czV`mYoxM0HB{?HEvjiz#| z7oYrf;UUxMId{!&XBD1iomMNGKl^#P{rWJq##FxP%^8;tip;@TiLBq=Y-7r96OA%V`76S`rdF$QQrZ!w)f4zn z9jrQTCG~Sd3IDXitJWN0yEd1Jdrivbn<_%05zn^O?_*!RSx7u$yR7a8t4=1vglgtlKklYe45rGlB5g#L_F4j2Eb?DT= zU4>2gK*pq1nX?3@nd)t*IKc(X%&7T}M%>bBkijsku+v{HB3`R^W&D-yRx&;&)ph0{ Yv*IVK{v%ZrOhIL!r>mdKI;Vst00HAtd;kCd literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dy-on-second-tspan.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-dy-on-second-tspan.png new file mode 100644 index 0000000000000000000000000000000000000000..712c22a4be12e634955b0c233ec5ec5dfa3d95a8 GIT binary patch literal 2146 zcmb_ddpMQZ8vohalc;23E4mn|rrDcrOh*!m+Pf~}{Zqq!HqT2KI^~`ymbIzRq&ij1pUGI7?zx8|9`krTN6_k{;W-Y2`B*jfDgdez%i=4h|)cP zF3<@q0~P|M^722syZ3C^z@^c402)9B@FlPU2&d6VokC@jG)TbDfo#A9AiK>3)&e0E z=5jzESOpvceg+bOZGav?wzn5(0?Gj{)s7{whDt63tby-?TL&0RjT$C9HZ@2eN~PjsZG%z%4R_*e2j5BGRdxiVOQWZx`^NomKXCJ%8wn_w zoh$h1Z@sfgBQrN=L#H2%-=6B^RLr<_5LdigUQQ=@izbi1tWB70c{nwEySMYHWGW(} zBj$R1d|zr-c1}*tq~JA2nCfNyR8k}%3`J7wCke0ZW2 z={uS45fL}@zNvTk#Kj%X(eb@|mQQJ2POZppbWO=ySXx2ow=5YI(G*xh5shEw=n46a>do3F$fNi&LFI|XC3z7dRB3}KCU>t zX$?+dYF5i(Kf$4b4EBTLEJgv9_aEwQwNq?ib#d7hg!RAk?+JZrd#_8WtrES@VRqO^?PJesJu*WtTuE5QvA?B}hW;X4)xAIQS+*f2}&E_PV z3WB>QYaC^{=3CN>h69Dx&E3aXbn#|A$^5o}{qMEt%y)7TQKY$=KXzH$PbbqR0UCZzSD9N#DC8CBpb>>Zk{PeUI(75LN+N8eE?dy@l&e0Md9g84&CW>+)Wi7%{qQng_^1i^G?oSX|=ynvN-Xa3gPi&scWg@ z{!M-B;!H(n|JlCyG+&&^^A~ulj(%v&tlQ={xN|wTEl*7{uAOr2y4#J++K(=kV^f8z zO3Qt^#)=1rb_cxK=2Os98}Lo%b5k&#&wS`_16c{1sN5Q&JE@B1Ph6|?hZP0>X(rS z8Ky$duksvGwG1W#)%uVXCTej9z5t)qOYY4`4yh%JGJv zXCfMweMaNt!E5e?+xA8W<%vCiajEobIltB_o%Me(!q)#6&Z$qhe>zPklEJX0&$7&l cdX#hZnVwc!^YZ1$_mX_t%xq1|c5z~U2hehKnE(I) literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-rotate-and-underline.png b/crates/resvg/tests-hinted/tests/text/writing-mode/tb-with-rotate-and-underline.png new file mode 100644 index 0000000000000000000000000000000000000000..5556ba4f6aea13c6729bb091605234f69d62031e GIT binary patch literal 2549 zcmb7Gd011&7EeGiiLw}8fLh#G#Fzw&5|KqgS&a~QAh(wUgs6ZJ)*vE5z$FMGn_yCe zDn2Z@B!OEL{ELZQjpj?qOp^vhY^$b?Pu2}wbr41UsfG@oSfHNw0f;Je2YnZLB` z?CfL5j(s7&02~fyYHAu67Z)ENudA!;@9%H-ccatk1_lOrJl@gKkw_%EySrOhSm^2L zA)|+f2cj7k78V*Biosya&CM59LtLz1zkUIK@nvOYg+`+hrjwJ?7pMOh;BozKAqG1S z1=5315#Ja^gg;#qko2;C7%+wg{(#0VgM+L#T0_c`9uBT~Sju-SbtOW8p*@%*O;4niK zY%KylTn2K37xgyb1$) zsS#cw=Mr@HU#u{{SOCpPfW#+_2@~nphvRB*rksTs454DRx-n2brq2IX0mo`$HA?_C zF!%2m`B?hxM~|^W#nk*K)7~U}x_H>W?9bUd=uNH4e1o^N&0Tyn6vf-fSl*8j%El?E zG4dxetI?qz$0FK8f zoHJ*qW+*l+YS_Ku7*gAV51kZ@Lsm`6w~{ex7`k8>m>2i8&|=v$0{a;5Wx%!VXl zigg?^$9Uu%MO{kIo9!h>B^cV|*A4kNdLd-nf6_BLs-qi4+-*s&x;9Ry1aVRWH?%AV ziUrMFwW+rR9`D_xQW2bfIAAHtU<`L3ZS|AmgiIOJ?%r1muF7@NJ(W+P?jhg=XI*sOI&}5qzS4_Q2{ArWb3ax+Ik1GvYH#s z%1%QG`FoG9t4&I7d|AT82%AqWdOUs3#7OCuu_Y-vj}O>?Gdq?12lpwBwBiY&Z7C$r zzdv2%n?ty&DQdS7F?w!Q6knaz*Od-duX|tw1Hkkr9*TXe-U7a1@F$Kmf4V-*tvvS9S>63*H z(IQ<9@H~k*`g2+E@pcKZqjKw0T4i9w_7`tQ!mkQ?@7+nFXrqDa<=8bXVd*0eg*}XW zIt3ajAprzSd4$^&CcqJRW);|#&`3}co%14naO!g6<+bEJZ{B3X4VGT+U?Ez2?@heI zU+GFOMt$%AcQCqY!TZQ&1Q!bGZb$WB2?eL6wZ8Qb%?rLEcY4kWV4odRj#%CX?Toz~dB~E^m}RlD2N6`BrLo z#|C%>`Fz>4Z8aM+;0vK~74HUUpuS<+k4AP#`s5#J$wi(#sz|lnE*F9&d&M{m$yX*C zb_Xvo92x!GCO7cLGwExg*_DUxwxVH9)I%4=iCE13Snd?$B7u~5?6z+3oBEY*=~Ppn6-?( zHU`y_4)OI`Qna@Q_^Hnbs22?R84iylDTJn!cKzW1s}_@%1K$A#1)X|#D{`FopWn4s zRD?&xoZN3re+(Xm_kf=ZZKs{geJn+Dfm5T)*$EC&VCP{Yh zp2~OF$o0FrSkqNzl^={FEy>}}{v);ND*jDCj7Tfn18!sZ1Wr}=qb8Z<|4s|z~IiNya6dl`6GPX}sk+r-?p5F5#oj7&vqLt?rqDX7PINI%Az^BrOd|MQZ}k@^@BJuS#rlod+zCbLKN-}~`v?Rj#_C#2#1Zz@3^$yS;@mkW2n5Z$t4m2p*VM;BiJ$iY7o6i?W@ctq zR@Nu+Z%Ir{jGCHSbaXV4NYvES^!4>+v)OujdOA8f1_lPf!NJbX&c?>ZEEX#$Ce?eeTcA ze&}fC?VFKfQE&UwGg><8Pw;OF5*lVE-CT4!vuClvL2uQaG)sLt!cdB6)$HAf_W)RX(e@@>#|A@LjCkYSn1f zWMv+vBK@p>9pIJwDG@5@k>bSv8Q+5mQ6*~~E2v1g$|^40>jk#8U#23b!)mo)x+x13RNjQ@nDvb z7Ml327w9pw{CiVRAs!j9gH+rEY*4GFA-Vgy<{kB!rKX`sF&aOoRRIe#xBR*v*s23e zx=Vy;cNg=#5EY2pJV6gxI2E~exKan`w&alLksA?MD4itJAu2Q0LX1b9`b43pI>05X zeiYW-eM*QT0G2lrTgKsI`W0~E1~9o;h+1v}7kAL1J8J~X0b#b#m8qt%n)lzgS(|#y zi})hhL{w$h7=+n^m2(--q`&nUWR_dBZ6A*b9aFm7baN)P@fqK-yC{6F@}WKYT$`q z+8pVkVNVdCL-~OuiCq{@>9Lb;$Z*{`8oKEDyGN=jlW)=H<02QCv$kmu&F^Q| zpgG0V61%|anPh#QO;AT7hKa7V#$hzh-ElUs2FkCQ7#f9!&)`RoJYEk5Jr1QZe(>46 zO`$^<4>rQ6cgo-ePoD0B=e)zTq!$ry8ov^CM2&t2aS)^1gn!A{;1j^St2@aF^5LWy zpzY23z;R%9WJG)ryb4$iwZvnT>afJSG?2vYr#(#0^tRjswg62IVfV80QCGyTdYRW# znU7H_v!~(R0p*U8>IK=%qGrn5NoGohSh4V-7_G_-(A#-? zB*jH=GbA`%k-f4YI@&%hzj}~f)>|S7rZNKMQ#nD+CG6KD%_3AgFqUU?Q2vrXdgyD_ zRQ!K8x6R57$+bc1+-n*Gy;k!yY*I<6xl} zjb;fD-rQ3*d}#ZxJxbbKVpO|nVV4FV_!yPxYb&8p?%Y^O(c&!2f!$g^KOgfbv)G6i(aPTO_Ie@kz)~bDBU8E zB>S-f)+KJ*3*KKo?+rGL@zIqlUmhn|S5HEzg(upSYhe`uHJT)QTjU8E)x!Sv8AIx_ z13?`n5vU2$KYV{V_iZD&H%=ee71r?*wgF9s*GrD%Vid%<&kf13!4Y5b#5M$kzd_C^ z4}8P|9z%Bd9`n=G+3N#)z^gVU+cF7r(N|ILB_J?EJi{jDw9^F*C(0|Af4X_(738zP z(ZsVJR}aJ*%&g> zF$Qa(md;j2#ajFb7~U8m{({->H(80;^FG6*I zp>tPUOJcJ5X!(5lKjz&UzALKNNZ=dZ@SEPAD6 z9X(GJ{TYE#ez|T;c*t@Ly~n~^yic%c3Doaa=i0etJa~7k*a)MTrG_?kST*ZeoiRnu zo=$N4IR)>r0GIfcw@+HvNuDchR^vL;3t#Y&a^mkx^&5J@CezZ!=agJ=&VVb;o={k@ z?WC*%~9G`ZQiK1IwLoPyCDobLeE2I!k?0F3tOWm5K%zw^IB!8kKufwt&axrX* zj&6lm{?wE*jB=@QYiV6sYZ&)RcTZ2(^W67&exJ|h{eFMn@9%w|_xXL&J>8u(5hw%< z2GcyS-_Z*OQ$a7RWpF6tUY6(#k^0H~zEl`Yt9@aqU%`VO}8+bz32JOcv>1k&-a zlhg=WQrg*^pU&qN7c&^lOBHo>Y<5%gt(JSe_a6?7KK(=bTBaA2;Rb`L#vX9o;~gWM z97zu!+qW|5srW%mQ+;Qq-Z77}zS}o$1hrquX$^Wt*k5)GJM$Iu&hIl`^!e|g1!etC zb>T6nMOcRm&S=vkopjaJ0D-QG!+#X3zr@O?^XoLw?3N|}1qROr%1c!LXj=w_C z#Ko1zjfGgS{cB8*+gY-oxXauc;MJ3F+K2fngBquuZcEQQNH!!g}Cx;nRq7{Nb)mDuhR_U2P=@+ ziYDHP-k>J@(CO&Q0ctk=cLceX(3#QB9LuEx4N*-gobtZGg4;m6DA!65e@+>CyXZhO zaIu@KUj2qd?7|a`;5f1IDV7}N$LJ6~ADPtl9P;MzyI1MF!Q8NHL5FWRUXTmbSi_zZcM< zEUeC9&Rjm>Eo+?5;4UM-w~=#siHe=ure4+V8j0zc%bTxBSo1uz%tX9OtYyJhHU1gswO;=RmteYP;6gbdDb&UCAW?Z=4h}^ zU6n^7wJ5{O04bQp-!L0Wi(khwcqNZkyz5N_*8Y z)g&50?CzdYAY7M?cw44&Yrh_Ovi%HFm*U04$HXGQBkHsZ*>g;fKVul`&|OUxNkf9w z(eifM{UxrLt!e_dyYz~}pW$Sa@s>WfmgX3Y?PKrZ@%0o|PjS9|Y1}lgGDB23Jq12H zZ-@iLZ>uWd%x`c%Oev70ppYmF_BaBxt|Sy%v|3Hbdb>wL!p#e&(<8#9ZKDrbib%uU zHEfoV)0*1bkY+tWh=_tW4# z_Sasafzm9l#~KSNEuuq-w!Hd@qkLvO|Npql81k;nkB;*>Thx3kkQ4Tt;b~`P*-q%M beS1q~l5b_;Vsva^!PE~pxjWYGB_#h1cuoI# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/vertical-lr.png b/crates/resvg/tests-hinted/tests/text/writing-mode/vertical-lr.png new file mode 100644 index 0000000000000000000000000000000000000000..7919401b683944a4ae4026737267a542fe745c29 GIT binary patch literal 1714 zcmah}4>*%~9G`ZQiK1IwLoPyCDobLeE2I!k?0F3tOWm5K%zw^IB!8kKufwt&axrX* zj&6lm{?wE*jB=@QYiV6sYZ&)RcTZ2(^W67&exJ|h{eFMn@9%w|_xXL&J>8u(5hw%< z2GcyS-_Z*OQ$a7RWpF6tUY6(#k^0H~zEl`Yt9@aqU%`VO}8+bz32JOcv>1k&-a zlhg=WQrg*^pU&qN7c&^lOBHo>Y<5%gt(JSe_a6?7KK(=bTBaA2;Rb`L#vX9o;~gWM z97zu!+qW|5srW%mQ+;Qq-Z77}zS}o$1hrquX$^Wt*k5)GJM$Iu&hIl`^!e|g1!etC zb>T6nMOcRm&S=vkopjaJ0D-QG!+#X3zr@O?^XoLw?3N|}1qROr%1c!LXj=w_C z#Ko1zjfGgS{cB8*+gY-oxXauc;MJ3F+K2fngBquuZcEQQNH!!g}Cx;nRq7{Nb)mDuhR_U2P=@+ ziYDHP-k>J@(CO&Q0ctk=cLceX(3#QB9LuEx4N*-gobtZGg4;m6DA!65e@+>CyXZhO zaIu@KUj2qd?7|a`;5f1IDV7}N$LJ6~ADPtl9P;MzyI1MF!Q8NHL5FWRUXTmbSi_zZcM< zEUeC9&Rjm>Eo+?5;4UM-w~=#siHe=ure4+V8j0zc%bTxBSo1uz%tX9OtYyJhHU1gswO;=RmteYP;6gbdDb&UCAW?Z=4h}^ zU6n^7wJ5{O04bQp-!L0Wi(khwcqNZkyz5N_*8Y z)g&50?CzdYAY7M?cw44&Yrh_Ovi%HFm*U04$HXGQBkHsZ*>g;fKVul`&|OUxNkf9w z(eifM{UxrLt!e_dyYz~}pW$Sa@s>WfmgX3Y?PKrZ@%0o|PjS9|Y1}lgGDB23Jq12H zZ-@iLZ>uWd%x`c%Oev70ppYmF_BaBxt|Sy%v|3Hbdb>wL!p#e&(<8#9ZKDrbib%uU zHEfoV)0*1bkY+tWh=_tW4# z_Sasafzm9l#~KSNEuuq-w!Hd@qkLvO|Npql81k;nkB;*>Thx3kkQ4Tt;b~`P*-q%M beS1q~l5b_;Vsva^!PE~pxjWYGB_#h1cuoI# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/tests/text/writing-mode/vertical-rl.png b/crates/resvg/tests-hinted/tests/text/writing-mode/vertical-rl.png new file mode 100644 index 0000000000000000000000000000000000000000..7919401b683944a4ae4026737267a542fe745c29 GIT binary patch literal 1714 zcmah}4>*%~9G`ZQiK1IwLoPyCDobLeE2I!k?0F3tOWm5K%zw^IB!8kKufwt&axrX* zj&6lm{?wE*jB=@QYiV6sYZ&)RcTZ2(^W67&exJ|h{eFMn@9%w|_xXL&J>8u(5hw%< z2GcyS-_Z*OQ$a7RWpF6tUY6(#k^0H~zEl`Yt9@aqU%`VO}8+bz32JOcv>1k&-a zlhg=WQrg*^pU&qN7c&^lOBHo>Y<5%gt(JSe_a6?7KK(=bTBaA2;Rb`L#vX9o;~gWM z97zu!+qW|5srW%mQ+;Qq-Z77}zS}o$1hrquX$^Wt*k5)GJM$Iu&hIl`^!e|g1!etC zb>T6nMOcRm&S=vkopjaJ0D-QG!+#X3zr@O?^XoLw?3N|}1qROr%1c!LXj=w_C z#Ko1zjfGgS{cB8*+gY-oxXauc;MJ3F+K2fngBquuZcEQQNH!!g}Cx;nRq7{Nb)mDuhR_U2P=@+ ziYDHP-k>J@(CO&Q0ctk=cLceX(3#QB9LuEx4N*-gobtZGg4;m6DA!65e@+>CyXZhO zaIu@KUj2qd?7|a`;5f1IDV7}N$LJ6~ADPtl9P;MzyI1MF!Q8NHL5FWRUXTmbSi_zZcM< zEUeC9&Rjm>Eo+?5;4UM-w~=#siHe=ure4+V8j0zc%bTxBSo1uz%tX9OtYyJhHU1gswO;=RmteYP;6gbdDb&UCAW?Z=4h}^ zU6n^7wJ5{O04bQp-!L0Wi(khwcqNZkyz5N_*8Y z)g&50?CzdYAY7M?cw44&Yrh_Ovi%HFm*U04$HXGQBkHsZ*>g;fKVul`&|OUxNkf9w z(eifM{UxrLt!e_dyYz~}pW$Sa@s>WfmgX3Y?PKrZ@%0o|PjS9|Y1}lgGDB23Jq12H zZ-@iLZ>uWd%x`c%Oev70ppYmF_BaBxt|Sy%v|3Hbdb>wL!p#e&(<8#9ZKDrbib%uU zHEfoV)0*1bkY+tWh=_tW4# z_Sasafzm9l#~KSNEuuq-w!Hd@qkLvO|Npql81k;nkB;*>Thx3kkQ4Tt;b~`P*-q%M beS1q~l5b_;Vsva^!PE~pxjWYGB_#h1cuoI# literal 0 HcmV?d00001 diff --git a/crates/resvg/tests-hinted/text/color-font/cbdt.png b/crates/resvg/tests-hinted/text/color-font/cbdt.png new file mode 100644 index 0000000000000000000000000000000000000000..adcdfa237b234dc940ec9ed5487f3f11bb0c1324 GIT binary patch literal 10675 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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 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 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/Inter-LICENSE-OFL.txt b/crates/resvg/tests/fonts/Inter-LICENSE-OFL.txt new file mode 100644 index 000000000..9b2ca37b3 --- /dev/null +++ b/crates/resvg/tests/fonts/Inter-LICENSE-OFL.txt @@ -0,0 +1,92 @@ +Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter) + +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 AND 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/Inter-Regular.ttf b/crates/resvg/tests/fonts/Inter-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c544be478444438df928caee58266d18729e589a GIT binary patch literal 407056 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

lx3cCsK6I>F`lR@PS(3-Z@xUE{#{;L#rZq0f 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 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 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%0D)47q+RUNGfist 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⪼#*7HRT!Q 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/gen-tests.py b/crates/resvg/tests/gen-tests.py index a0b8bd0ba..8a8f12930 100755 --- a/crates/resvg/tests/gen-tests.py +++ b/crates/resvg/tests/gen-tests.py @@ -1,6 +1,17 @@ #!/usr/bin/env python3 -import os +"""Generate integration test files for resvg. + +This script generates two test files: +- render.rs: Tests for all SVG files (unhinted rendering) +- render_hinted.rs: Tests for text SVG files (hinted rendering) + +Usage: + python3 gen-tests.py # Uses default output paths + python3 gen-tests.py -o custom/render.rs --output-hinted custom/render_hinted.rs +""" + +import argparse from pathlib import Path IGNORE = [ @@ -14,28 +25,89 @@ 'tests/paint-servers/radialGradient/focal-point-correction', ] -print('// Copyright 2020 the Resvg Authors') -print('// SPDX-License-Identifier: Apache-2.0 OR MIT') -print() -print('// This file is auto-generated by gen-tests.py') -print() -print('#![allow(non_snake_case)]') -print() -print('use crate::render;') -print() - -files = sorted(list(Path('tests').rglob('*.svg'))) -for file in files: - file = str(file).replace('.svg', '') - - if file in IGNORE: - continue - fn_name = file.replace('tests/', '') +def make_fn_name(file_path): + """Convert a file path to a valid Rust function name.""" + fn_name = file_path.replace('tests/', '') fn_name = fn_name.replace('/', '_') fn_name = fn_name.replace('-', '_') fn_name = fn_name.replace('=', '_eq_') fn_name = fn_name.replace('.', '_') fn_name = fn_name.replace('#', '') + return fn_name + + +def generate_render_rs(output_file): + """Generate render.rs with unhinted tests for all SVG files.""" + with open(output_file, 'w') as f: + f.write('// Copyright 2020 the Resvg Authors\n') + f.write('// SPDX-License-Identifier: Apache-2.0 OR MIT\n') + f.write('\n') + f.write('// This file is auto-generated by gen-tests.py\n') + f.write('\n') + f.write('#![allow(non_snake_case)]\n') + f.write('\n') + f.write('use crate::render;\n') + f.write('\n') + + files = sorted(list(Path('tests').rglob('*.svg'))) + for file in files: + file_str = str(file).replace('.svg', '') + + if file_str in IGNORE: + continue + + fn_name = make_fn_name(file_str) + f.write(f'#[test] fn {fn_name}() {{ assert_eq!(render("{file_str}"), 0); }}\n') + + +def generate_render_hinted_rs(output_file): + """Generate render_hinted.rs with hinted tests for text SVG files.""" + with open(output_file, 'w') as f: + f.write('// Copyright 2020 the Resvg Authors\n') + f.write('// SPDX-License-Identifier: Apache-2.0 OR MIT\n') + f.write('\n') + f.write('// This file is auto-generated by gen-tests.py\n') + f.write('\n') + f.write('#![allow(non_snake_case)]\n') + f.write('\n') + f.write('use crate::render_hinted;\n') + f.write('\n') + + # Only generate hinted tests for text-related tests + text_files = sorted(list(Path('tests/text').rglob('*.svg'))) + for file in text_files: + file_str = str(file).replace('.svg', '') + + if file_str in IGNORE: + continue + + fn_name = 'hinted_' + make_fn_name(file_str) + f.write(f'#[test] fn {fn_name}() {{ assert_eq!(render_hinted("{file_str}"), 0); }}\n') + + +def main(): + parser = argparse.ArgumentParser( + description='Generate integration test files for resvg' + ) + parser.add_argument( + '--output', '-o', + default='integration/render.rs', + help='Output file for unhinted tests (default: integration/render.rs)' + ) + parser.add_argument( + '--output-hinted', + default='integration/render_hinted.rs', + help='Output file for hinted tests (default: integration/render_hinted.rs)' + ) + args = parser.parse_args() + + generate_render_rs(args.output) + print(f'Generated {args.output}') + + generate_render_hinted_rs(args.output_hinted) + print(f'Generated {args.output_hinted}') + - print(f'#[test] fn {fn_name}() {{ assert_eq!(render("{file}"), 0); }}') +if __name__ == '__main__': + main() diff --git a/crates/resvg/tests/integration/hinting.rs b/crates/resvg/tests/integration/hinting.rs new file mode 100644 index 000000000..1b9024c9f --- /dev/null +++ b/crates/resvg/tests/integration/hinting.rs @@ -0,0 +1,293 @@ +// Copyright 2025 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Tests for font hinting functionality. +//! +//! These tests verify that: +//! 1. Hinting produces visibly different output than non-hinted rendering +//! 2. The `text-rendering` CSS property correctly controls hinting behavior +//! 3. Hinting works correctly at various font sizes + +use crate::GLOBAL_FONTDB; + +/// Renders an SVG with the specified hinting settings and returns the pixel data. +fn render_with_hinting(svg_data: &[u8], hinting_enabled: bool) -> 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 DPI option is accepted and doesn't cause errors. +/// Note: Different DPI values affect the ppem used for hinting calculations, +/// but when rendering to the same canvas size at the same nominal font size, +/// the pixel output may be identical because hinting aligns glyphs to the +/// same target pixel grid. +#[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 affect ppem calculation for 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 + ); + + // Verify that rendering at different DPIs doesn't crash and produces valid output. + // The actual pixel differences depend on the font's hinting instructions and + // may be zero when rendering to the same canvas size. + assert!( + !at_72dpi.is_empty(), + "72 DPI rendering should produce output" + ); + assert!( + !at_96dpi.is_empty(), + "96 DPI rendering should produce output" + ); + assert!( + !at_144dpi.is_empty(), + "144 DPI rendering should produce output" + ); +} + +/// 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 7590c60cf..799607dc7 100644 --- a/crates/resvg/tests/integration/main.rs +++ b/crates/resvg/tests/integration/main.rs @@ -11,11 +11,24 @@ use std::process::Command; use std::sync::Arc; use usvg::fontdb; +/// Save a tiny_skia::Pixmap as PNG with 96 DPI metadata. +fn save_pixmap_png_with_dpi( + pixmap: &tiny_skia::Pixmap, + path: &str, +) -> Result<(), png::EncodingError> { + resvg::save_png_with_dpi(pixmap, std::path::Path::new(path), 96) +} + #[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 +47,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 +63,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 +106,8 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { .unwrap() .to_owned(), ), + #[cfg(feature = "text")] + hinting: hinting_options, ..usvg::Options::default() }; @@ -110,7 +156,13 @@ pub fn render_inner(name: &str, test_mode: TestMode) -> usize { }; let make_ref_fn = || -> ! { - pixmap.save_png(&png_path).unwrap(); + // 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); + } + } + save_pixmap_png_with_dpi(&pixmap, &png_path).unwrap(); Command::new("oxipng") .args([ "-o".to_owned(), @@ -129,7 +181,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 +189,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 +201,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..4a597e10a 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); } @@ -1471,6 +1485,23 @@ use crate::render; #[test] fn text_font_weight_normal() { assert_eq!(render("tests/text/font-weight/normal"), 0); } #[test] fn text_glyph_orientation_horizontal_simple_case() { assert_eq!(render("tests/text/glyph-orientation-horizontal/simple-case"), 0); } #[test] fn text_glyph_orientation_vertical_simple_case() { assert_eq!(render("tests/text/glyph-orientation-vertical/simple-case"), 0); } +#[test] fn text_hinting_options_all_options_comparison() { assert_eq!(render("tests/text/hinting-options/all-options-comparison"), 0); } +#[test] fn text_hinting_options_css_style_syntax() { assert_eq!(render("tests/text/hinting-options/css-style-syntax"), 0); } +#[test] fn text_hinting_options_eink_mono_clarity() { assert_eq!(render("tests/text/hinting-options/eink-mono-clarity"), 0); } +#[test] fn text_hinting_options_eink_mono_engine() { assert_eq!(render("tests/text/hinting-options/eink-mono-engine"), 0); } +#[test] fn text_hinting_options_eink_mono_target() { assert_eq!(render("tests/text/hinting-options/eink-mono-target"), 0); } +#[test] fn text_hinting_options_engine_auto() { assert_eq!(render("tests/text/hinting-options/engine-auto"), 0); } +#[test] fn text_hinting_options_engine_native() { assert_eq!(render("tests/text/hinting-options/engine-native"), 0); } +#[test] fn text_hinting_options_mode_lcd() { assert_eq!(render("tests/text/hinting-options/mode-lcd"), 0); } +#[test] fn text_hinting_options_mode_light() { assert_eq!(render("tests/text/hinting-options/mode-light"), 0); } +#[test] fn text_hinting_options_mode_vertical_lcd() { assert_eq!(render("tests/text/hinting-options/mode-vertical-lcd"), 0); } +#[test] fn text_hinting_options_mono_hinted_vs_unhinted() { assert_eq!(render("tests/text/hinting-options/mono-hinted-vs-unhinted"), 0); } +#[test] fn text_hinting_options_preserve_linear_metrics() { assert_eq!(render("tests/text/hinting-options/preserve-linear-metrics"), 0); } +#[test] fn text_hinting_options_symmetric_false() { assert_eq!(render("tests/text/hinting-options/symmetric-false"), 0); } +#[test] fn text_hinting_options_target_mono_1x() { assert_eq!(render("tests/text/hinting-options/target-mono-1x"), 0); } +#[test] fn text_hinting_options_target_mono() { assert_eq!(render("tests/text/hinting-options/target-mono"), 0); } +#[test] fn text_hinting_options_terminus_mono_clarity() { assert_eq!(render("tests/text/hinting-options/terminus-mono-clarity"), 0); } +#[test] fn text_hinting_options_terminus_mono_target() { assert_eq!(render("tests/text/hinting-options/terminus-mono-target"), 0); } #[test] fn text_kerning_0() { assert_eq!(render("tests/text/kerning/0"), 0); } #[test] fn text_kerning_10percent() { assert_eq!(render("tests/text/kerning/10percent"), 0); } #[test] fn text_lengthAdjust_spacingAndGlyphs() { assert_eq!(render("tests/text/lengthAdjust/spacingAndGlyphs"), 0); } @@ -1568,6 +1599,7 @@ use crate::render; #[test] fn text_text_decoration_underline() { assert_eq!(render("tests/text/text-decoration/underline"), 0); } #[test] fn text_text_decoration_with_textLength_on_a_single_character() { assert_eq!(render("tests/text/text-decoration/with-textLength-on-a-single-character"), 0); } #[test] fn text_text_rendering_geometricPrecision() { assert_eq!(render("tests/text/text-rendering/geometricPrecision"), 0); } +#[test] fn text_text_rendering_hinting_comparison() { assert_eq!(render("tests/text/text-rendering/hinting-comparison"), 0); } #[test] fn text_text_rendering_on_tspan() { assert_eq!(render("tests/text/text-rendering/on-tspan"), 0); } #[test] fn text_text_rendering_optimizeLegibility() { assert_eq!(render("tests/text/text-rendering/optimizeLegibility"), 0); } #[test] fn text_text_rendering_optimizeSpeed() { assert_eq!(render("tests/text/text-rendering/optimizeSpeed"), 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..0340b9c81 --- /dev/null +++ b/crates/resvg/tests/integration/render_hinted.rs @@ -0,0 +1,405 @@ +// 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_hinting_options_all_options_comparison() { assert_eq!(render_hinted("tests/text/hinting-options/all-options-comparison"), 0); } +#[test] fn hinted_text_hinting_options_css_style_syntax() { assert_eq!(render_hinted("tests/text/hinting-options/css-style-syntax"), 0); } +#[test] fn hinted_text_hinting_options_eink_mono_clarity() { assert_eq!(render_hinted("tests/text/hinting-options/eink-mono-clarity"), 0); } +#[test] fn hinted_text_hinting_options_eink_mono_engine() { assert_eq!(render_hinted("tests/text/hinting-options/eink-mono-engine"), 0); } +#[test] fn hinted_text_hinting_options_eink_mono_target() { assert_eq!(render_hinted("tests/text/hinting-options/eink-mono-target"), 0); } +#[test] fn hinted_text_hinting_options_engine_auto() { assert_eq!(render_hinted("tests/text/hinting-options/engine-auto"), 0); } +#[test] fn hinted_text_hinting_options_engine_native() { assert_eq!(render_hinted("tests/text/hinting-options/engine-native"), 0); } +#[test] fn hinted_text_hinting_options_mode_lcd() { assert_eq!(render_hinted("tests/text/hinting-options/mode-lcd"), 0); } +#[test] fn hinted_text_hinting_options_mode_light() { assert_eq!(render_hinted("tests/text/hinting-options/mode-light"), 0); } +#[test] fn hinted_text_hinting_options_mode_vertical_lcd() { assert_eq!(render_hinted("tests/text/hinting-options/mode-vertical-lcd"), 0); } +#[test] fn hinted_text_hinting_options_mono_hinted_vs_unhinted() { assert_eq!(render_hinted("tests/text/hinting-options/mono-hinted-vs-unhinted"), 0); } +#[test] fn hinted_text_hinting_options_preserve_linear_metrics() { assert_eq!(render_hinted("tests/text/hinting-options/preserve-linear-metrics"), 0); } +#[test] fn hinted_text_hinting_options_symmetric_false() { assert_eq!(render_hinted("tests/text/hinting-options/symmetric-false"), 0); } +#[test] fn hinted_text_hinting_options_target_mono_1x() { assert_eq!(render_hinted("tests/text/hinting-options/target-mono-1x"), 0); } +#[test] fn hinted_text_hinting_options_target_mono() { assert_eq!(render_hinted("tests/text/hinting-options/target-mono"), 0); } +#[test] fn hinted_text_hinting_options_terminus_mono_clarity() { assert_eq!(render_hinted("tests/text/hinting-options/terminus-mono-clarity"), 0); } +#[test] fn hinted_text_hinting_options_terminus_mono_target() { assert_eq!(render_hinted("tests/text/hinting-options/terminus-mono-target"), 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_hinting_comparison() { assert_eq!(render_hinted("tests/text/text-rendering/hinting-comparison"), 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/hinting-options/all-options-comparison.png b/crates/resvg/tests/tests/text/hinting-options/all-options-comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..2dc89f481f519484f5667ecbf52c9f517eb823f8 GIT binary patch literal 3807 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/all-options-comparison.svg b/crates/resvg/tests/tests/text/hinting-options/all-options-comparison.svg new file mode 100644 index 000000000..aa1aedd46 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/all-options-comparison.svg @@ -0,0 +1,26 @@ + + + target:smooth + target:mono + unhinted + + mode:normal + mode:light + mode:lcd + + engine:auto + engine:native + engine:fallback + + symmetric:true + symmetric:false + + linear:false + linear:true + + mode:vertical-lcd + + Combined: mono + native engine + All hinting options demonstration + + diff --git a/crates/resvg/tests/tests/text/hinting-options/css-style-syntax.png b/crates/resvg/tests/tests/text/hinting-options/css-style-syntax.png new file mode 100644 index 0000000000000000000000000000000000000000..fe553ecaff79d37b7de04fe55226a650a34efab5 GIT binary patch literal 2952 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 F_zyXBca#7C literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/css-style-syntax.svg b/crates/resvg/tests/tests/text/hinting-options/css-style-syntax.svg new file mode 100644 index 000000000..f25344c55 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/css-style-syntax.svg @@ -0,0 +1,17 @@ + + Hinting options via CSS style attribute + + + XML attr: Hamburgefonstiv 0O Il1 + + + CSS style: Hamburgefonstiv 0O Il1 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + XML vs CSS syntax (should match) + diff --git a/crates/resvg/tests/tests/text/hinting-options/eink-mono-clarity.png b/crates/resvg/tests/tests/text/hinting-options/eink-mono-clarity.png new file mode 100644 index 0000000000000000000000000000000000000000..3663c503c14c2c5d19ded9011dc5340952437016 GIT binary patch literal 948 zcmV;l155mgP)nq)X!rmS|t zFTRfA*I_wsgZH$2xshDzF_+(9YYp&`ByaRRV916P#zJuq00-S;-SUekiefQL-JAt6pJf=j6}}xC zTBwq?@YT8&^VSa3>s#v7Ju}|-&Q{H@U#Totyzvp{Qzl8owNb>2(>X*_4Y=p(UtYNS zsE=GKFF`0=VNxdJ)mf5aIEW1Ne(U45gS!BS>nkft%iOH+Q|3`zg%C(0KbkY51!V&e z5;_OfgGS2Q0EiI42Yf@X&4^s0uqn&yT_8~iXn?5$Zc2ZEb|wERDck+oT?e6tNmNr^ z^kQ&t&<|6_HC}jg$xj){`}afK-0l#D9kvrVoV0(!_V%GYebFRAb|DBuCIjXU%K`+z zof(FIv*Xq*kT=4(XaIzTL8s`L(rjjcvI3O+gxmQrR8ZAGbCmO>0#pFKYdFBz74?=r z?{n0on0|xG1Kwg)kKT3PSal`8QPBFGiq+2^F$wnEV?m_o^L1bKUc5)zPptSvO^YdI zn4>@a2%z0CeSe(_+CNg54e*6%*wGBjKXty@AVgiYk&m>N)`$gZMocxs;*b_-kOq>x z0%E{PCJ-6c0*||a*Z>i|hhx+)WEfB(UWUhgWd$Yh5?|qZU^7hW+DpN$Sp8ud{d`xo z5WQdop8Ih5!wl;zZ-2(`Ve`;7_sy++Ah{m?WKMq`@b|7^WVQstEfEMsSlO@wqW}OJ W?<4PEph!Ca0000 + 12px: The quick brown fox jumps 0123456789 + 14px: The quick brown fox jumps 012345 + 16px: Quick brown fox 012345 + diff --git a/crates/resvg/tests/tests/text/hinting-options/eink-mono-engine.png b/crates/resvg/tests/tests/text/hinting-options/eink-mono-engine.png new file mode 100644 index 0000000000000000000000000000000000000000..bb928bceca06c847380806e0daed5b17c03501b5 GIT binary patch literal 1668 zcmYjR3sBPe76!ePqLS+*ULUDFTuQJqE8j-0_^OmOpg)Idd|x0X_y$ zGbjiIGVt^D3Ic(^C{0h+(biNw#m7Yr=rVnYaUc-v+2;iFkuY@#Wx{-1v7zlby%O+y(BhUP(d=g4~vn8ybNoCUR_*DC4NM}nZ*H55oMnc5*ow3`nd6XCv?RKs zCC*$XwgxHMY-=Z>Mx+q%1${w~lBR18OuJ0u&JD!c1tRuNKDHeGCUuwGYK5 zeF#6!dUz-%3|~chmsik!Tlw%N}qSk;+`tEc&2sZ8ut85QAVQAOdXcF_}yg7sf7)M z<^K#DP^iaB6%~-s%N=%C6!xuOwcz=_YP2*5`EA7aI`TIA$b3Jb`9^#D4{J+NzjGQ! z4sO@ACMn}f+&&VdlO`8Y(L;14uX3>c{pk&WbLKu$5PxK_G%sbg!{7|y9#nF_k}Jdb z2_CIp8lDdqoq*D(E{w+;9(*o+39Q$=J6E2R@9a<`dUYLAO_c@Y6rq&#!Nl zln7@_M@Qdgc01uEP2SJuHi^w~D+QMS6hzUP=OtO%5eZ@{O;2@9zVo)qPM$sy$Efc} zrgC&~J z%PUH&3_bLXCMP2st#je@WLo{qx2$$+b&)J|*zOK_ zJqgsV^{sCX@k}P&|ExG@fx{zyWqb-;>*p0t$fJNpRd;Fj3cihBiy~AO3hP+hlQCviDoTWy^|`vGSf_ + Auto engine: Hamburgefonstiv 0O Il1 + Native engine: Hamburgefonstiv 0O Il1 + Auto-fallback: Hamburgefonstiv 0O Il1 + Engine comparison at 14px mono + diff --git a/crates/resvg/tests/tests/text/hinting-options/eink-mono-target.png b/crates/resvg/tests/tests/text/hinting-options/eink-mono-target.png new file mode 100644 index 0000000000000000000000000000000000000000..30016ed98fd0cade1b0e0f3ebc5b3f325aa6b073 GIT binary patch literal 2614 zcmaKuS5yNfgn$L47;1tN znxF_O2qaR4fPe&qNR!^1+_+qK-8c8zv;S}Zd(F(tJj^|$kuD#%7&ia_;DhVwm;wN7 z5EeUf0a=xYak$2k<34&Ae*gf~`fIUe$%DjMW+~FZ9LCZ=gp-pKYwGRo?dN$mQslD=*TGpV_J#r+eF~M>8gt^Ltj18PJxP_%^OC0Dx;1 zuA^xlGV+6dJb3{s0PCx-s6NV#ELJ*mpCjmVE8I*N?}yNatH$NpizNKc$@#?}c$liBzEGe^#j`BL%y4u}C=!K0;Y{BP0TMewANUs}sz*&_?_PwZN8S$elKW8OK*H=psHHjO=;dm18EoT>S} z6-#2j7y;w18PY|3S99^*>cOg{{(Nb-9%UHwNXN0(-0zr4j*+r4R)W{*X{do>&qLyL zAG%F47pMv>(bQC$Od$oP8slrx8p5*!0~p1xc)*RoW)-{f#?07P-I9p@fhM3OqccoB zP#D;Er;(>X?V=1Ow-FFf7G>RRU>!b;&VHjk_B>@}d@;8u^2Pe#_zSCgkhm-dG+gST z3sewU$VNSYp^QTdNxrWoBWJ^-#TKF3mNx2@Vs!=SZ`&0c@~5XX!_ey{sEszz`DvA{ zx8jSh#HbNARvM@Fb@SQ_vtC6#y{y9!mZ~yJ#;q~;H1cdZD>UK9wRJJp1&%+sH+TR+ zfDR@YrXLGVDWNK3>KI}fXTAX}uM`0(AHskr-c2#LBvCCp-S10rhSEei1>IR_FPx(tifM zHbqU$F^S|PGpQeb8~enQmY5qWQET9e-tLoh8fW3wnlgZwNSKZ#%-O8V^33!WHdDo- z@1Tgn{z~#8Ps1-%*nH?rCmv)$eqN}srJlCI-DWcs`UhnCm~;W`6!ha3SymhX-$?K5 zw<#AsN+A(B9f}#H+iO*%Nb*0_#|tJaZ2g9GWQ<}_Yl~+nnlDG?3TAUFn(9zhO+1vs z=`1ST{d)yV5xJT+e(Y_BoVym8ZIJ=BITq|j+4(Ak+dbnS%*Rx9qCverrmA8z6=za< zpau!`g9B?gWhcuWJkuy4B~fBQXRqsX)VVoDpl{^R+=Y2g+#KZGwa6^ksnr|#LJvHo z6$)?Sc2{L+VXI3r@@i%7oU2>llnj4JL${5GLNlQw<1r)?77;VihUazhHHTt7dD@0@ zkDfv_eEAwBF5i-H^LWjj*T7sV)*^CLbA|l*~Q>_M(oV>RssyU{B zPk;p8NC(|ILY)>`^Bg|@aZVTzSKR5>g4zOarfSYl#art;&y(?bG%9UV)M!guU%$me7xR;^=^EPTR=O(Ya4#s2kct7n zg4B-fFmhZc%;+JpDT%}v9IajjTH`h2$`kb9Orx7OY*1Y$k<(R>WDgOGB8$Qffy*Jm z8Szah30&5}qXES^FwYZz*@j~z{c`4zU}s||LjSOzYROY`N-hVYeC9L#5{av>S7d`z?`j!JDCK*!%3`>gTj%NDgBF~F^a_La zMheuD;=D(L6U8R%YDajDCTOOkPp564Z0kQUa>AX#WpwZE^doT_bH|bpkqrg9 z+$S|cuLZ{%gqlG%yPoeLlO&$J%O$o@)?a;KP1jI`| zT9F8eIi(B8J5^c|#Y0Sax*#VF`BB4}yGM8ACF=1d*yQzpFP(rMMg$;_sy8)nb}NA< xKYjPz&)YpcziV?pQ@{K`5PqP@Ob==}06wg0Z + Mono: Hamburgefonstiv 0O Il1 + Smooth: Hamburgefonstiv 0O Il1 + Unhinted: Hamburgefonstiv 0O Il1 + Target comparison at 14px + diff --git a/crates/resvg/tests/tests/text/hinting-options/engine-auto.png b/crates/resvg/tests/tests/text/hinting-options/engine-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..3c38b738f4912748ccd5a8adc578d312a06baff5 GIT binary patch literal 2934 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/engine-auto.svg b/crates/resvg/tests/tests/text/hinting-options/engine-auto.svg new file mode 100644 index 000000000..67409efd1 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/engine-auto.svg @@ -0,0 +1,17 @@ + + Hinting engine: auto (force autohinter) + + + Auto: Hamburgefonstiv 0O Il1 S5 Z2 + + + Native: Hamburgefonstiv 0O Il1 S5 Z2 + + + Fallback: Hamburgefonstiv 0O Il1 S5 Z2 + + Engine comparison at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/engine-native.png b/crates/resvg/tests/tests/text/hinting-options/engine-native.png new file mode 100644 index 0000000000000000000000000000000000000000..69c448b3034c836d2be7d30f6b8b8bbed7ce2580 GIT binary patch literal 3044 zcma)8XHb*d7X4B%5D=pRDr!U#q=Q^3D$*3B6KRH`!O+AIN+3!nfFM2e5*`p#M2cYK z0#Yssy$6&c5UN)?N~8!+0Mx z0RWKHL2b_oIY91--IW94a@Vo+1OVQqUl)`j$$R=hEJ7KWX&vxCIgXBwPEJm4Zf*zY z;NbA+(W3)A5dYHuD*len&dz^t{r~WR@=yN#`%J(kwa$b0RWB1GQ$T$m5hOQ>if8w@ zl`_;3LL|9fI?8r3-u*3gU+qB4nOF`oW@E@|#$-%R@7v`GI@R4)h{QO&ajgOX;1u0k z8fM-jORPv&mR>4pYTu0ZURRcIJla}%wst=$mb;%YZ6TjQO_`6LfpNd9G6SipW3S3R zQ(JOZKEwO0aq1TZ`Rsiszrp2SXjrr|4-@#CBvf- z|3)Jj)`q&X>Kz61SN;=%J*S6FfYxpv`yOsAU=%2s`lD765(&$?7^~pAwBq$j!c>#z zB@xvgFG74>AdwPi#n<_fT$?a|NSU2K^W~?zp=g>B$%eDLfFZ8Zy7iC(?w&n6y?UIn z_Ts46sfR+Idg~GiV3V}NtU*%$c0AjMa{)8qU#6H5ZboW>;7GdZek4WH4534pl_mO1 zBE5Bv^D|dfMNPr5td28x@=qnzYIxiqDUNp1F{bHF%)?!ccCk4*A(o{#D=||HnE=Pk z)mr#iGI4#_pxtzVMJfrPT#zSL$RLt3~$Smc%Tq%<8dGO)7Z;>lo5qStJD*wW<)H`7!ByF#dw~0)o zYvogZ?3SNYp^L0t!m~G__Jgj-Lc`o^i+*+=ay*1)@sBIfO-*9&Jy;gITTF>G>1*{| zLwlFQJ|k(+YY+o>>w92xchbp1Qe*3M4ShnM82CMiY!0kB6yHcQvGn!jlub}-UBS$j)c(8;!9@po=uCm>%Ys=}HD+_g|pB9%DAP5Os8Z zQK9IY+9()vxpm|}WX*K$bvS~5f&3)HiSY$w^c-6;ZdilvnyyaZsC{F7x~_I|QRG9mU9vC~9r{#UeCkf*-6te|{6iT|8 zc@QnX5f4kbVqdrfE_4@+sniXyR+sM;TFeXncqO<)spP0;Uz>31m2>J>2W0(sO~Ops zu|ZMh&ni#^XQR3+>o1E;EfEFJ#D|qa+$f2`M2HQpwZ?+ zeONxaiWi?iG*YypD7kw^>EGjQivM7?^YM~rZ_k*&1}nX)>uMYlr*JqUFg3Z^Kr5yq zv<}up(zU0)TZ<^q@jsCvws=E8RL*Hm+gruB$t!vwWTMPVn*x|6dDt<{8QD!fA(Gy( zlF*?EyDC6j)7^Xadx@>)Lr`ZqAeeD_^0EFOzT%_L5OsaFjg1sB*aXZ8|;z zGU2lNGAPKYT(c7IxORgSXH-{L_9GW>2)0o(5@HDpAo$(e-r+Now!8HCkE4W#e5+d} zqL)R1susb5CFAB5qgz`UYZ1*C5r;xJKMOIlH~DaU&Yc1GqnJKx7`w1sp?yKg8?7I4 z#VPrq2SH?x2XU3w>7HG{186ECz*>6hNOQ+gHnS7l9!#VFMuiukQ_pB`vxuj$-dU8`>SGW}Yw}I7HxHoteV! zJHcfQ0Lqm%2eV$75xDNpjU+$7p-UwP|sUrD7A4 z*fW7z8ThE|zY_UB!R(eZzUO1;ldVrd5pSqbw-yGSusfpxzS|~DmE_Jm$mZi=il&HR z(q)k97e&u8nM)5<+XJ;Y&do-%-M&Ck+k%o_qZfTnEe0+wHxshc5=qc+JBig5MIL2q z`qU`XdT0q9=DftInsMdN zqPO`hZc*HHJi)YUR$+?<<=Nuv2JQV*MN56Gtwkm3w=+KqToS4?b=pXr@s4wj4U@sO z4MgMP1d{-XWp8#7s-W(?MOHXda@)P^1=3QL9MfNgOHjmF_lj>sCyvabDK!;0TUEf0+Tfg?EBYfZ~uo#_tY z!57fJC!}|K>nD@~jI|7wBc@e&K>9@Cg#=LT>P8i=R0{N*Fm2<&$hLp(coA~~SL0Wl z8o;ISPDAMeuL*P+F2m@*3)fev#iU^BO)={E^W1Z7bVBKPiX+=(5*X#fS6XC}Yq{rTG!VZ?qMIQWeqY ztv)nrCZW(e2ieejXfIY2bmhX2GW0q`Eh5E{tlCN-<>jOM6fFF+SKe%(d&_?cMAw&c z2(1fA`*6euf1;HvhCVS1*pIVVb0TAEa+<4|_r4o&sY&GeMdjUa!C<)p#mmz$rL@l+ zOl>sWyD7LB>0H&k(z{rfsTrefZqZZKT6vhboJR8xp40<<^bgn^{{TNXrYxowIWSO# zv#C%-jCd^YpUuXGJ;+?UnmSx@aW0$|`w1N=_~uYsV}*7TXk<{!jTVm2R3R#vbIROI zVGXE2Jr}8FKKHir(GSqA=aa@NtUz*i+xOOuv+^IeOx@LCkRuyQ5t#-*ov#0H(>U;T z(8wk3Gm#!*@IemMQ=#3E4YjGq7V{1*x$u#|!6dyEIQlbaW`|?V2E^9(95KF|g%JW3 zM?Pti4}k-yT*bYUDd&2}0F(ybRO{2dhL%;ZXyX-jVB6T8;C$-_*`myv(CfaQjAQ7} z(?6h-tuLl{+t=O-&Tm2)zUPKIKb(8FHs_cA^=#C2e+)PV58@H%!o+FIcloe%q+d_I zm`Q$Dt(`SBc^PLxZB*8t<3!=EBS6nLiU*2U0V<0+Sl3yty{K38HDu$V0HukvhHrn) z%K(#zzgG^v$rg*OjFmIzx4l8;d>G#y)>%CcJ}Ch^$K(a-?mw~QjA;A~01x>NIS^0U zabqHY=aC>6k!pSHezwFlH-#<{?>{*Qix8$dOYg!3Vnr_S>6lWe?UJ^Ah|VJpAlNNI zutP*$=doUA?kAeT@veY%yRm)N>4)ku{mm0~QZ3Q$VL#7z=DU1>0$-}Y_UbT~+-`Ss z=u8w5fbuV`D2HpuTyvYcOzO3Ie4}h-C%(K!^9U+&{pQEd>sge#dGWSn}goc8xGxs^sDAA qlhG3zp|W-MyWH + Hinting engine: native interpreter + + + Native: Hamburgefonstiv 0O Il1 S5 Z2 + + + Auto-fallback: Hamburgefonstiv 0O Il1 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Native vs auto-fallback at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/mode-lcd.png b/crates/resvg/tests/tests/text/hinting-options/mode-lcd.png new file mode 100644 index 0000000000000000000000000000000000000000..8955d29aa05f44ca2c6911629fac3e243ea226dd GIT binary patch literal 2545 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/mode-lcd.svg b/crates/resvg/tests/tests/text/hinting-options/mode-lcd.svg new file mode 100644 index 000000000..47b7c9872 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/mode-lcd.svg @@ -0,0 +1,17 @@ + + Hinting mode: lcd subpixel optimization + + + Normal: Hamburgefonstiv 0O Il1 S5 Z2 + + + LCD: Hamburgefonstiv 0O Il1 S5 Z2 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + LCD subpixel mode at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/mode-light.png b/crates/resvg/tests/tests/text/hinting-options/mode-light.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7f6269a428b6ac83e03666d98e4355ab0fc54c GIT binary patch literal 2858 zcmai$XHe7G8pi*D(5paHiX()%h3h~UKV zhhR{NCX`h~A)<&BsSyGeKxrZ@BHZlk+EG#@c z9FNCGMn;m!WPukT2>(Km|J(jo|EGXJAp9r!$K(FLV6++#5u|2um}AF*b}9mw8lB&` zKn`k0Q4Qn~xT@q z7keA8#F6=Ov3Nd90jN{O6)xO6m8pDdA+nB>!qq4A8nR z(^s3E^Q#C!Eq|K>N+UL!Lxi>Z-Z6ZzBUul-RJ^ke28my3osqT#U0a+F_)j z9I80zqFfZ^otnc2T?tQpuqHwVS zI;Mo0>1vP{?v#!psm`S9@#2g|bi_E7mUnZRoww$MBfefvDuVqW(O~pD#LYQm5b8R8AXx z_@)cacj!11`!|+#Vsf{YIl?p{RqYfH2(HuV==wfV`l9&iSmqEBNPHB(Ywcj2O0?n5 zK4Jpp!a|eop=Mvcl)SL`(&7rd{ER62X8<$gHGfM@!?I!NmKjTSg04N$L@#)3gN;D0 zXicwSy+z~h_dY*VG&8P(J)-Tl8TaKu^oKm=RH2i819ny9D98dtaF?&aWRWLtT!}l7 z?RE50ePvpZEAlIbqgmb{61J0yqvoP>*Dc10Il7^CExKz7X{xLupL^LGcxHz<1>2M6 z?zZ`Dh1LM(F?AP`?aEE+UTF>XpM2ah84*w?)xxlMF51}3it#z)J|lL?W%He;3S4(> zG{uV#JsdM@Y`LzjI-?Sf~VTq zlno5FDXL9U4o|q*dmD@oyrI}H=zGiQCea@~!L8xm$wejC`{zT_(D6XyE4(RX`^6?gwP>!IpzLfC6mcxG zyf8_wLEl>N7(3L(IJrRZI>y&|3)bOmhvWzPL_DU&=Hn@5UQXE6-X8T7p6seNQua%g z&`84D0H3Ilyp{5sUX{%mxUlE5p-QLI)7r z$9(jiwweu{BHgwO-%R?y-Zs@v|I}vWG(Eqn^Ebj%YNM%tEL1*`hRLC466bhXj3FBZ zxy1@gQWk^P5P0voZ{F_35WO0=gcfjV063k;@Z|?-s#YzxfV&fK-xp&(4A`y!H&NaM zT*1x$;$Yb;>)qz&9nQ@sv7aKP9(N9Tm(mA~TOamb(RmRYAXL(*W!JRFU!G>IA-i)T;&ZHFATD^os)y1~v%v5m= z2tzRXC-;7A(5zmsPw*n?Wh8;ViMA}-s`+(tbe2cLmM~L+~ zFr{91XXmm6^E=Dm*83LG#@%AC=z}Y+1dZ&ZY=%&BNZ{d(sCR1dSmQZy7zY(`PkKiD zfMx8(y}fODjHygx>i+z@XOo*NyJPz}&xYF5dI;O=Q0&4KUGnkS3eNfPNHz(x{4sp6 zcFx`t60kiS;*@|DBJc1`&0;8X%j1Wq>J&b_ipRFz!2p5y&vsa(peey4W|N8#Wwex#LT!sx33Y$Zr&cX%uhJ^B>T_~DR>Qp%0hxIhtzI(RY|U|95Co^QqDF7 zlFqgBr`j)hR(MnxlqN=>68-3*vKf)L!&-aE=DE>2+3JLcELu@SuG+i>YTIrp>zri6 zrgpGIO4ZExj1#7E(}vE?7^y|@ik8$o2;O7oAO{?u||)7?*}8f86RqLju6(mM^#X4%g7-u7t}H~1jq zc~T0g>XqS0LON;oBgCIo{T6TVw#N}NPu(S+Mpd5AF09clg?buj)oA^8;o4SPw$TTk zBvKoNQVh;hE65LUjF!Q~Nok&1VNhb@LXz}BXmg|P65da~{>0?$$;(=<=Z}EfO;exm z9YvZ%qtbXsgw7F=-|&Gse&y!vIoFM@F8cdD(06 + Hinting mode: light vs normal (default) + + + Normal: Hamburgefonstiv 0O Il1 S5 Z2 + + + Light: Hamburgefonstiv 0O Il1 S5 Z2 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Mode comparison at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.png b/crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.png new file mode 100644 index 0000000000000000000000000000000000000000..20d5202d29ea01f3fe5c48c2622810d09073a7b4 GIT binary patch literal 2973 zcma);c{J4f8^^zc5n~K3gDe+?>}!bZB|BponX!#!vW&G*!q^&gg-L^pgcwUk%vj5{ zm$8IYM9Qv`owAJW=bp~F=iL8(@ALUQ&+FOF^WW!u?jtOXI3fHH001~mjIY`N07&+j zJ=vI#Eyv`+#<61$GDh730NAU4E+|6=CUBf2Bh2j#kNy86FE6hfH*N$524b;TUtiy2 zKF%DokB`qW{|0^ckU7?p|vPiq5RulB^8kmJ%yT&ik7>cIxR1FmM$zSLU)*FN52`zDLjnb zPfGreq6vPxT(eqjUAhRuHC$-Np!a+}UnybGxP#+G)SzB?(-&bdFs9ZH%)5Y6^!sTGK%fS3tO?^r8MqwKSo{d$D0=X{ll{64^WwYjtSRgKJ{#|`o+}j znNKyS%U~M%-CMVFUkBvI{0bZIb-5!m`KErF!rO+$phTr`UN)?t32Hyf#j81_AhoV=JxCpM9zXfE1D*O@sJV_ z%c!9oiY1p);8R4T3$3kxS3_)D4S1{Jz?%tf8y@tuexszI_}q2zPic`My&%%iff#OM zuCXsYG99Tc{sj9v?hQtH>>}!3hO+b`qCf=x6ZT0P3&)&!K#*3HV+U?04!NaxxgMTJ zkz?|u+MGePcxpxchPz0jlC*Bm&ET@+$hFwpZeQO0k7>dJQHdU&*Pf8 z1mGG?0$cEmu*FOq_Ez~HLU-h%Nu;0*L9`CmbhFw6CPQzw<#!Kb@iry#^hBaw=&eD5&o6F;4~Q#1EuV0u;& z%36L=E`U$a!hUW)EA%c&`(7SF+DPKVhCxL4sW5TbPqdK{wFAs(3yzX0@xDJtB`Wy#q%;0HlE)#+yin|l-E6Pydrp2QF-(DP zU#3NqpRThV9uT>dig|t-pmiRFdX9XdvbRd=I?-Xhj|(-foa1C}Q_d_EI(vF2GF_Ep z>@oHin76v?TqTpfWb@P81qG14+l{5A6s8AfZFAzoQ6Ps^k_%B%L@8Rbj|rDZP;RVe zZ+!zF*{NTr&zED&jl5B!{ZW&mt6Z?MyXkdZg<)PODd?>P&jignh%#55ZSSc>qBX&0 zuSLcRr2&hIBU{GHooj7b&9A@8FSiJ? zCb2}K2SwE0L89rG*TP!aqq)z=jI{RkKDkg4DZ9wWaHN?}U$F=E2$C8ZQq$yNcTm>)S$v34e5t`@^xOwA|k+OLIx+8kVHE)pfHKz*PW z+G=c?h9}6{Vg^3IZ9YxDkrS%yP!UQw%R@*QE7!ACrs6{UmE&|h!Jp2cgW>y0d=6Qe zwb{@|UIRcKXL+h%>e~se_s-{qdugfxU`JfaA=_Ho9&dM!OLp1FfrbCP^xKAz50U%* zccE91wQ;p(VVCcAKhq;M7au4-U{$)fj8yEu&lN97b2734{AoXJQJmu`z|LVU`>pPM zeTnHyE&Jt^gE%YCN@x8+8Wi#I5yd2jGM{9Kj6EcRbs9@$zrJ&fQH^DB;u2BG@Aloi zqEu_K1AlJ3ZLn}~B;L1aZd4j3ue$e0)^XI4m-W8$l#F!!oTiE+ zW+l3V(w%b$bHy73Wq{I;x@r@fo-e-qeUb%IXXmgJptzx8QMb-ESCbhpP_<~VzlMId zpfNk-f)xO7a}VRBm8Hh!zgRQ%_Ol@_p4C3$R2`gwtYU>r)0JF41#@^aML{ zK~mZ}42n!|Q#(mc^(>H%De7+3Kd455~2L~qr64vqkF-8*Fe=_GW++j{6UF=-NEy5KeVow%&e3NQtg0z zr$H*uY?3NuDo(PjF+Li^i~6h$T78}M(V-H)QqWP)cb%l-hZkFiSbg^4ofpL6b=|c| zwD-tk{)|4U&{dgQj>1#AJoV+C02#t&*%o5g~Rr|=X3_w)$cD?);Pxbad#NH`l0{) OSxpQruRb@x#QhKCUTgLM literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.svg b/crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.svg new file mode 100644 index 000000000..974dbc3f9 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/mode-vertical-lcd.svg @@ -0,0 +1,17 @@ + + Hinting mode: vertical-lcd (for rotated displays) + + + Normal: Hamburgefonstiv 0O Il1 S5 Z2 + + + Vert-LCD: Hamburgefonstiv 0O Il1 S5 Z2 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Vertical LCD mode at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.png b/crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.png new file mode 100644 index 0000000000000000000000000000000000000000..4a7e8a52a5478032049d6cd9f0d9d3f8b410d5d0 GIT binary patch literal 1783 zcmcIl`8OMg7EV%22;vzd8ZFh9R+D1ds=d@QZLBFlLRukc@lvsirIuQXK7vRrEoO`$ zF*J77KB?Lc+VmN*7NJAmSW>&F?eWh07v4SR-tV6K!#&@3?sv{jM?2h+m4-_L003Fk zT`MO50Ej&9eZZ%VD`e(i{TQUkcX6QrfLzx}0`n1aD#t@Nv>nF!82=w3$H*fc?>!Ud ztvUwoL#)LKS6o8xu9LTnJ>T{3IhD zPHj6fgiHz1Yr*AI@!?eoZf?ziU{}Hp(;=mvEN=l;Pv+*4&`0V5qb4p^DFGM{s~aqm z-E`y*NnBp2*R-|~I8J;ZUsC)UkK2PleA@`ZfHmpoiBGU5#lM#MTS4sUSBJLs0cF># z_7)flCeON6V?x^hst@HrZuKPh7KPTc>pyE&}Tcq>yGU>%&LW?R=!j z7^{_>iaJLh{-t{NP6xLVWjzxec5&eVXv3u*{Z#yEdCl}Vk{oR$<1^mEbAh=4lsII% zi+POGYhwycsaM}Wcou#l;=fAdt)x{+do1;(aZufag!Ab4ufzP@rg_Ve+5FkDktZJE z@0aTdfu1Stp?lP=TTY42KWBceM)X#*?cFIF1GITd*SF?d+GZ=wzenJhTg^z_F;gEs zX5`rnQ;HjX1SkOu+@SJn-&a0ta4!E$ z-48~n^q?rozNo%*oGA1YB_bkQ)E))|N21(#HThSZBtBnlFtS|)F=y!Sek*JXp=xKr zPG14{=)?CeD)lVT{`oAN9ZUi_&r5v}G^aSF>JArn`){@yK)+$G)~<;Ty8@%c{VEW= zpyYKtKyiK-#{Kp#5*qZHmYT6s9~;{{hliu12Rk>BBUAn0oAC)VKkPqBW}jMJM~9IE z3pV+;Tr=o6Od*c7o2OOtr4V*nXOQNs_h1q;PzHB~BUUY67QM^ET(Y#xpUA=qi-s>J zJP!+UHZ6G;=aA!F<3LQh!5oh4K>@j928I}2)YL5{6YrO)+>08$J>lur&THqrmTe?2 zTWCN@od{jeBKSh43>u_E%=IX9v_%?LZM@cR2dBJHIWKlvOw$^At|2_J%8__)DZu&oP~v5e&jl=OVz(kKJpogxvmDty9q-%97aBNYq)tXl zXJfW+h%NmV(B-fg8z_^se>3K<#xS0~=KU>~8s8VB6joduVqa%<)K4w*5cE~m8%7^h zapZLc)SAcbtU@LrwCH{K5T3jPw|nT=nkD=LnVLt<4>RIf^kbK+OShO{%7QM<5GzEc7(R6NWuG6sQ>CsJacj#IL)ibyN53r1OFzGDkf0e z;S^EVw`WK@AN<26MbKwWFCJ+n30?Z17E5lJR=PK3XGxpg*LGDO;g$A;P+F6> z3YL_b?fd42+tm~h4R}SynxX3lqep}*1MBC#p;4z_W%|zaf&#<*<`#utG-Zf_%I<5; zSbrG8o?f`@z0&M;7^@<5P*dDKaY(#7e{giW5PLfdrGD=3oTL#H5wx1&*)?%3W_L5)AVF(+kQVkbEd5-}cHE3Z5t;^(R;VRXiJm=di%0{F9LCn=_*!pPp@t_;o64SLY ix*t3ketgIy&m-~29bFY^d6Qlzp9*E|U{z~DNcs;{qA~FR literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.svg b/crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.svg new file mode 100644 index 000000000..55f368df4 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/mono-hinted-vs-unhinted.svg @@ -0,0 +1,6 @@ + + Mono hinted: 0O Il1 S5 Z2 + Mono unhinted: 0O Il1 S5 Z2 + Smooth hinted: 0O Il1 S5 Z2 + Unhinted: 0O Il1 S5 Z2 + diff --git a/crates/resvg/tests/tests/text/hinting-options/preserve-linear-metrics.png b/crates/resvg/tests/tests/text/hinting-options/preserve-linear-metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..28bb513a81d05338fa7214339ca9222cc8d65e1d GIT binary patch literal 2106 zcmbtVcT^JU8-^TdCZeg8W}=qnYC6)&l^LetNEC8qVK>Dq5R&V5#jNYdk(Qd002!S8YL$si3%fYixQH@LXmg?0M!1y0ke%kni8|x-PP-ag#RNhUcC6r4@ks6 z2>t=d%s-uwkdU7OgTY8@B}qw?I6tGL8yXt=&)A>h|99n<)Ym3)ts*>OX8?B3&h@*G z?*9ad!`#Bw22$slC2qEHZkWm z)WJMg{o6liQs9;OZR}X{^B5v;L5E?{eQMNPLn(>B`~2r5e2^~YoT=t#;cMWkRYnK| zI)F$8oE)QU17g**@0&g~HkK=$jHR(ON!Gxsp(Mi8smM%pS;zTj$a2bLedvvnylY;lk%PH9P@3Vc)$T0|G_A*^O1Gh z#79Cvn1fz!q!_@nJe_R;3Yf$vK!btGrGi#bCm497jZm%}R>9Qmk+W`WaKC%j2QfY# z_VK{P{nV{wbEi!29OVs+#}t31$OwK7nMY^eJM%`dqRdz|@7qgPfjoQ(#p&q}384sA zRlLUeptEx2XmsC0c8u@d6cSbM1;||{@PPuL)izUxX@CZzYh{|g;Cf8LDzoIkx2!f$ z0C`VTR3;Z{)pw=wAUZ5a0a<0*w6awLyG5nc7b5FcS&H4PMnvvAkVBH*zezeq2GYsg zV^y6iXvi z_gt^F#_{(Qn7kPW`{hMAS9nr>{|PS{Dg8@UGM7 z{mfB$vc=?S^(OYQ?v&%?V|IhrREOm4WY^(H_(z@dI~XvUg;&*v2xo6;{UflR0&+>n$pKf+;=;9+1X#UljSdG)@b*JIt)?KOoN6+{_2TPEXTakfJ)yVFQ!gmv zmJwABY9{i&efkc;tfSNPgM%OS(c&mZ;vtkxf>(Q$o^X4+s?)#Er+%H76|>Swe>BCS z=XMUuYc}sCA4wwTzMc8gWuk`I_@S|O4noVh8B-LK=4AgOT|ofSMW=YmB7#3Qea}!L z8C}Depm+ADtA^-|8w7()LQhc_yQ{W`MZeui=fi%p>Z|FxVZN2;hrkE*{_AGwM{pCx4GTf5fY|l%! z35NBWerKz+z4bl)ve}_CuUHNBjA;^`z+E(;lf;*OOxFYO9f5HR&^K8KdTi$@!^f zSw^W0F1$CAPWn<>U5?X^gpauSVTHYxL2&O?$O#QPWKs(`BV&QozQUc)qmcGBliqpG zfv4i=p~*$Iv!ok#v)rx2qMejWZkdOhS5Q{{Tfl~Njz!=MX+q#%AIpaKMG8o-0@?Rh zW>#87y(>aWlFMCL{;$ZYh>kMGu6|NsiZ_!3?-4gw=SbEFy<5?GzU{CkGkXFeC=h%4 z^uDL$H;4Z3eUi{BRf}ea*V>qHu1NQQBJ!1z?vW?ru`BN}dD=?w{&%deqY0a87n76b zUvtEG$k^_2fTlQCBy^jotGwpAYMKo5+d-~O+-i*8-5m{1YTM2Ff^z3`q#oHnw8dM= zH&8vs|8)FX7gS+WtdV$VX~U68Q4^J0=dHt=`rzvK$0?aF(VxM<@kfgUHM`z;xyTl# zqc=F(gBCti$j+WNMeRaV`8BGy&NOivH zfvn5^gB8RCeRsZcZ3}xrwsGfpE@22|33a<#Q+ztvzZ9eyKKgv+H?JEozpWFZZ&D|y z)6(Hlu%~9oP2sa7qb~09R9iv9fB*?s+-UAz^E>B4`g~nNfGYfSXOvGyeY&d!E?+Rc zYU1*Yk5$0hlEfa~Z?`N3q+xIFJChSk++NP?j!Aunq21LhG6WPS2|dC(?AZ-~lTNQV zH{YkqzKq%|hV!&O#NFZg-_!e```5vJH_$J?_#j + Preserve linear metrics: prevents horizontal adjustment + + + Linear=false: Hamburgefonstiv 0O Il1 + + + Linear=true: Hamburgefonstiv 0O Il1 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Linear metrics preservation at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/symmetric-false.png b/crates/resvg/tests/tests/text/hinting-options/symmetric-false.png new file mode 100644 index 0000000000000000000000000000000000000000..d2a0f8de466ba0dcd72acff0b09a771930fe32a6 GIT binary patch literal 3003 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 Cl#h1+ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/symmetric-false.svg b/crates/resvg/tests/tests/text/hinting-options/symmetric-false.svg new file mode 100644 index 000000000..347281b37 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/symmetric-false.svg @@ -0,0 +1,17 @@ + + Symmetric rendering: false (ClearType-style narrower stems) + + + Symmetric: Hamburgefonstiv 0O Il1 + + + Asymmetric: Hamburgefonstiv 0O Il1 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Symmetric stem rendering at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/target-mono-1x.png b/crates/resvg/tests/tests/text/hinting-options/target-mono-1x.png new file mode 100644 index 0000000000000000000000000000000000000000..91824b2636dd984a4d0ebdf46b1e85b7b456027f GIT binary patch literal 3337 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/target-mono-1x.svg b/crates/resvg/tests/tests/text/hinting-options/target-mono-1x.svg new file mode 100644 index 000000000..522004205 --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/target-mono-1x.svg @@ -0,0 +1,6 @@ + + Mono 16px: Hamburgefonstiv 0O Il1 + Smooth 16px: Hamburgefonstiv 0O Il1 + Unhinted 16px: Hamburgefonstiv 0O Il1 + Target comparison at 16px + diff --git a/crates/resvg/tests/tests/text/hinting-options/target-mono.png b/crates/resvg/tests/tests/text/hinting-options/target-mono.png new file mode 100644 index 0000000000000000000000000000000000000000..2b190e78e3016e67168433ed6360c8e7788659e9 GIT binary patch literal 2531 zcmaJ@c{CgN7EVw!Y8z`K1fAB9C^c=LrM1(bmJ&;%RMgU>V;il~6rp3QmUKw$wToA= ztCE?PXeo(7t<@k&?R!e6s)U!GIdA@X=gmF$_ucRJednHg?teGU#p#kH2n+%M0FrhH zYgYgO2p8}GabW>Uu=!hpax@%)iUa_pUVnQ)5==@(AlA5CM%oDKKSxkdP;hW?U|^sC z!@|OFIGlh8M1dl}{|$kQ#bW=~|LXnwDJ zDjp}h|GsaA!M=VZ&U}9g?mUwc^Z3wZO*}>uempoBM_za}9pxp&`xzz+A~57#c5B01 zk4U%%$VOsc3~A1rj!e|YxV&y1q_ z{YY*0$WF%KTZZHcptbAJjWkG4$=?MOv~ly#OJwW%44iEZfuUI!r9S=Iniy*47tDIg zH}cW#FpE;WosqdbR}23)z&4%)mz|*q<#`5-<#rBUnZ9det&-xglvrANe}sx4QChcz zXT6Ft(%4X+%=;@*w$EXmF($%$q{@mGh1&JP+Nr*##o4;)x^CYc|FPAo5~+8e8Dk&I z%Y0&Ri+e54MugBA>eH=ZpYa{qD(!@6z=9AxOQgZV$e@7Qmv6GIxdUY+b9X4mR0;6w zz9ZQa;>@`!xz}UeGq_sUTTixHIyoBw*wHpZ-qh#>B-lYx)9MaYAAi!AtUZB>sL48_ z^pxnSw3yf*F}ONDFmE7w<=Aym&xD2R3}p$KH{K|{Q?wc3%MG=(8QUrn5|$=|p;E^>SA~yX|*tME|TtkL9|!syPGNhvOG` z624lqbmJOCx<5a7?TPZl!=DGCrwND?y_V9XC+q z5dYgon)V&hQ9V;?Hol-X`b!v7n1TSZ_N-Q*%b;Mg=@)NQ8!=hx9-^55{S{9R+^U85 zm_Ay4L2Wx-lVq$HVHm(&I9vOmHWqv@Yks0K^8%9*i&l;D`S4b|p_#1=QMU?P;p*je zv-`k~`C1N3Zr%^_i|#^x=^%I22V7CxhYWB;)%M{%G^ZzG(rOo?c^vxv|B|pW`Gbg` zj=1bZeVVW_HJ>Z5t-mo(X`_y90S7+Xw_i0TgoTvQ%2^B5ph8meiz=o73B#__cg2x7(49LncA!2 zU|mHhXi=e=nR`S8vOuF7F-~aY^FPY?fiQ>-Z5^K2F~i*QW|h%mO+=renM|a|Gk1os zw$$1TJ2Ys7|4F4mYtN&NOs-l{Edk9Pr5!c%>im6OSuz$sw1v5)>qkc3l)MBp) zNNq$W^;yUVNtg3}!6G>>O~Yqtl%P`lV+BJrV!Gy*1WrBE&ygPO_1i^A^&9dE4_E^7 z%biOdy%R_>4kNqXEHVLu*S0@q5}ygVXNq~Via@!uP8}7a5)1rI)I|2vDW}wy$;V14 zh1_SP3TNz@>X>0)g-F9?%V8x{s3vGILUb3Yn2p6yRySXY$MW_wsJgeTSGAhntK3tE zIV-m31QPN$18SX{Y@Rf75g-=Abz(ya(gCV`IylOI|HM^UXGPYX z;=UDgCqm#K?`(L}MesD@Ot0(O)#~Fcs6vlKp-$XszXJHWE;yPTsKI!AN zaQCnA#6%v@OGvNiv(Y`iU-oe?k%y@Nf+M`M#_Hsldp&0pq30@MR zNxpCljLdJ#w(3a?H~79&%7(bQi=13mQ@fh%I(ae3kbbK7VAdWv0pPbkwZBH&cDCYZ zk7uTWaxpnQ8rN+aapF9Hf^R?kWw#L0JUB{Um<~duZnH=~ptGI}Rq4bg7#3W3b2lUj zblLVD^UU=$|71Xc7N}Y1r=f|2js!>NMzE=wPnwW!k7x}(^W>AD)V + Hinting target: mono (aliased) vs smooth (default) + + + Mono: Hamburgefonstiv 0O Il1 S5 Z2 + + + Smooth: Hamburgefonstiv 0O Il1 S5 Z2 + + + Unhinted: Hamburgefonstiv 0O Il1 S5 Z2 + + Target comparison at 12px + diff --git a/crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.png b/crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.png new file mode 100644 index 0000000000000000000000000000000000000000..79d45972d24f3c5449d8db0b2b622262c5b61ded GIT binary patch literal 1618 zcmZ8hc~H^`6b4Dn12SAoh)lZ`H8oK~P0d@}&`kW?XQLx<5A1BL$9#V?fzP3v)K#=gUMuS zkxr*;@o%BkG#X8d|10fKTN;f@bYt%ZdEt1PrNTE^j%V&I;Y_{XbU~fkmu8f)%V1PZih^ zg_aYZeSPf|+i4_)d+v`#iWiyzDaf(wmvDuWs~}AzJ578yxwCC}3-I8wj1~*8Ny%P{ z7NXNILSS+!$c1LWVpfDa9(M;r8Q0-K&n0=E2HW*wU6eZbIo3B1()K#_k;zqeixlin z$eQkdOwA06It37x*FItHeMnT!k78{Q21-BY=sF@hyjtIOj6iM4{FOIMDEU{5O?q}( z_1lx^vtTMHA2Ydr+L!Atj zP)N)tM*zyyP1iq_h@+_6tdNX6D0AwS=hy@hpPb4lt|TVdy^jY_t>|euKod@rtU!d= z&DdxhOjReiEx%sM0YfA@HSq?Fctle<)M6bgFG>ISZh(ViRcX`w$3L^-hG&&;yO7J+oK%`ACm7GTDYv ztIzSsC^5XDo*x$;9g8qJ#YJT9C_q5!vFku?aYvsN>Kxm_M?;(!rC*O^X#V6 zQg7r>=EGN2y|#Db*QCi;)osCJvbv)Cgq!~GjM*< zmhGBWfr~SLflZ=Yzl-LUzs8%=JWG%38Ucb6D;~()R-RM#`#6;{?5mz%sgs(U{lYzr z@mPSDRCihQ-#-~nMq5{0Xp-TPF{3uk5l_FMG77=_v8_sLKrj~iBh8?!#fE$~nX-Ez zdb2M6t<8a|w23Mxw|-`T)Bmcz?hy&#r3r2(PZcYjU!Dbha4r!4Cv3&D+WE?%`qZTm z?{dK+*>H>W=<#MieGS_a`EQ*01GSu~y%2T2F=QA*w}EopXTOjoRAr8CpM2QOoX;YR&w$Mqj}W)I!tHMa!Yf-& zHi>O|puAPkV}1j@L0WGv@NP_J9OlVvp)U356-yQ+X) z3&+0SWTlK!yJV~1T-N{VQZ?5|dhX9#9E_*S_t6zP#+o^=@z~vh+&&{YGe2lHe#lp5 zJQ&lTS&0_;kFoM9;kE)3(~xC@mpn{@P7o(|oUN3@zZP&XYwnp|@qQT)^Pw}zg@b~| z`yX)k=80wzjj+X+cZD}?TJ7A7GP*Y6f6%fHhV<>?b|?ZC%&MR1%+D=PecW;315l#7 zg%mBDyK`${|1bWDFRDR5m~uG=UbtL*J$r4OrApN&B>pTgR`1~*mU*uY+vp;WVvGFB zPNgD N!TwwQYPV3c{sb(>17!dJ literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.svg b/crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.svg new file mode 100644 index 000000000..c8a3b48bf --- /dev/null +++ b/crates/resvg/tests/tests/text/hinting-options/terminus-mono-clarity.svg @@ -0,0 +1,18 @@ + + + + 12: The quick brown fox 0123456789 + 14: The quick brown fox 0123456789 + + 13: The quick brown fox 0123456789 + 15: The quick brown fox 0123456789 + + Clarity: 0O Q9 Il1 S5 Z2 B8 rn/m + 12,14=bitmap 13,15=outline + diff --git a/crates/resvg/tests/tests/text/hinting-options/terminus-mono-target.png b/crates/resvg/tests/tests/text/hinting-options/terminus-mono-target.png new file mode 100644 index 0000000000000000000000000000000000000000..5c748d3376018fbfa9d73d291a93ea97efc11303 GIT binary patch literal 1354 zcmX|BeKeB`7=O35u(7$rCQKhL3nP_2lx&G2=}4>>x7&8KrnwBYQrL%&R*OCyadp)4 zvE1_Fy^eFkZCP8V%bjqus9m?FsLT?&@)ho?bNij&^Zb72dCqgr^ZfIii`cu%3gdtQ z0Kh6VBq$O95LA;-H%FPWP(ve_#3Cgm<`@9r9()eO6;GU_sYr|16BTSyHk-})f+JsG zvR}>D%;j>wRd_t!x7Om~qG?t;$d;PK=6K}Z{eXzR;!*@pm;&GMVYYTz%j%W=YoNyf zu%s|FXnRz;&R8n0GiqW67 z5ux=R^Jk^uXnfWdsxbN;dMaAd0tDCOHWUi!s6o9fEBKOgbAh^soRa&P7e>^aliS1RF zINS5y(m}BuIP+xXmqSdqnES$7ubNaH_P3FCoOb7na~>S?`SL%$=R7ND31Wh$hL*ZoOLDu<7x{*p=R9ZcTHN=1#383Na9lkr3w5QGH= z{peIi+fb0G;aPQgnP6ZkDk{8&B0rLT*%>9GmQd5ODAEe{e2;gGtB+;&+Ub&(J5w}c zo2q|EJ~6O_;%I`5)tUXQ+CEaP!$jD0uh>6h+cB1lg#hwI{wRDmDe#Qjx?WLpQ|O6= ziiZIm`tvMAr>NyHNA3_VPw==}ei1nqi0O;!_j8eR%T5H4kXkgY_@F;A@Ya=`h@zF# z+6$cZqcmb}-Miyfox7*O6v + + + 12px bitmap: 0O Il1 S5 Z2 + 14px bitmap: 0O Il1 S5 Z2 + 16px bitmap: 0O Il1 S5 Z2 + + 13px outline: 0O Il1 S5 Z2 + 15px outline: 0O Il1 S5 Z2 + bitmap vs outline + diff --git a/crates/resvg/tests/tests/text/text-rendering/hinting-comparison.png b/crates/resvg/tests/tests/text/text-rendering/hinting-comparison.png new file mode 100644 index 0000000000000000000000000000000000000000..383268545bf5a4e2441df5f86e537505d5e58622 GIT binary patch literal 4223 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 literal 0 HcmV?d00001 diff --git a/crates/resvg/tests/tests/text/text-rendering/hinting-comparison.svg b/crates/resvg/tests/tests/text/text-rendering/hinting-comparison.svg new file mode 100644 index 000000000..29ddc3e93 --- /dev/null +++ b/crates/resvg/tests/tests/text/text-rendering/hinting-comparison.svg @@ -0,0 +1,39 @@ + + Hinting comparison at small sizes + + + HINTED + 8px: Hinting + 10px: Hinting + 12px: Hinting + 14px: Hint + + + UNHINTED + 8px: Hinting + 10px: Hinting + 12px: Hinting + 14px: Hint + + + + + + Confusables: + 0O Il1 rnm + 0O Il1 rnm + + + Quick fox + Quick fox + + Bold 10px + Bold 10px + + Italic 9px + Italic 9px + + + + 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 zcmbW3dpOf?AIHBN$yst}mg12^wkc#Z5&DtC!czEZs^%SghWS0DB~~1_qBzGDDJAUL@35kO6^%wqNJ#i=`nOg%kB?tzjzXab1cHi+%E~fD zMa94E|G&&O7dP@swmsa#Z69E}Y(qNCGoJiL7=+&CA5OlPd-LK@7!)2zKmLF(E{+?$ znahlAzy8WS?Otf-iE9O2+NAh3vc%dIMqbdE1mH^5Fa1X2UFc=rahZ)uPP6oW7Us^ye^i<7me(WhEghhk z$g(dk`hzeuDG~0~Ap09uu?YVGn%bWZO%2-hJHl|k6nd^=83kiV>=XmwK8?FYCRY(0 z<&u>lp?IUMDkO}UJF=L7fF55T%~zICmuazYKzbi>G*8-ng);zG*KpENGdKqqrX*Mo z@27QZPtA@86u}wm-BUKWAiekuDOR>F;brN}Q)w+|W8jT*MoM6aRmkyUNHLnGL&B9| zhWxHsX6}#%-IR5&yO7<^Pb`H-(vQM&Z3p1Tdi*5r%7c{$R4NXky z>jiWOTUC78w&lx0lpo%@#lwVV-<9(=9-bmM=Uy;_sDNMlrtzdiU@?(WCH2vtC)acs zBSm}&$<%~H(p{NUNyxBUcJS$JSLI8>mWAf`mnmc%M@Oo1Nz!K7%Yz7H^FT?} z<6pGL*jogJ^Jli9+<{~99J4i!AH8P0GLPUcYu)$$K0mC5lVO**(@~9|mDPiipLtu@ zT>gAi)Or|0?q~Tg&PXVqjCP}Boe>-HiulUULWlZ|SEp=lIe>A*?+jA&PT~%AW?o5= zTAXH@=X8g?kgphtdSn-~eFDFgV?M|J-ccmaOodqya)$iJ(U|*%=(wy@X&)V*2M&_$ zFOb=?;IFQAu1V2v(<*X;i4cvOX2KXw=Ncy^MeDg$%hL0L2J3@X;l>M7uD0}NXXP9G zkm~v{l>Sh@6wiw}wbYwE-+SAaqCalHcp!}j)>xbuOWNk8iKWeEP+t7q*h6H_L8*e` zO3rp5c6!n8gPxZxiTL6thy@}yf%3-opDBi-kw^%IEJ2iP=_th;pOnPIkAXEV%$8a_GTTZxn zwu?*)=T&4Z_mKNS&PB{Vzg-qDwf`>E;mpe9E%B4BeiGWh)#&L^!UHhX8HmnckuR2Y}Wyp`OlPVDutW0GcdPpq zPX0S11*V4hLCnO?*GStxHd2@q-S4f)Rp+^8vq#TQvWjoOt6M3UPaQ5rxJS!5t1ubB z(-I}SZC2}A%W!iDbj}V_Gg_3@+fMRc>z}VWjr~GeETE`?_!mUhsoDCiq7(XrH1Nq< zsM%0_i99@fI0oAD;gFDs*(f2RCYAAr{B7KH&8hNc?Qr$LaO(lN_j5`nT{9rRv!$*? zftnXNf_iqCrRkO$EYC+WGojKJDCr91M7gP-#(54`&xm@q*<~H4vaNyfuK7MzxMD`xK@G=mgERu5`ds8FrW5$%biu#air z{eiU+P1ED9NBrH-J=QPmYpjHKm5w%(+3R!pa6(n6`7gPm)#20<%owS+BYdAh)E<28 zS*6mN!l3Pq-Ytl?xBIrV9N+FrUu+}R3l6v;EpW-q7nY5$Qtxca&JLMy@A#PN%;x&d z7_3{$+FKmcL>^DKTxfRyKVQkRq%4s*{PNoXAwR8I=UC1cF3wJZZ2=<9k7m5L$B6YM zhB@Cn%)F(vJ@QBy$<*6x8)h+>DFnY*t^ESF`MDCNSNnQ0&$+XS4E3H1cqw(SWU&wN zexY3hyk3wfx#NI>?pV_9)mQJ{DhzvJ+{(KZ-`xk^X*Hs4x0b`7t^KZaEmNLZ2AeV3 z^G$8Gd7)4yFPj2}nntRDYi;QgPkZ#h@EfwVvKZlDVmVCpYiGlIrIiQA7p9&z=T%h@ zfny{Yb*ID#zOs>a2Tfs-24oYO^<_e4LN>p=$MfbpG-bxSb|7oU30QzNpu;GgRl0K;HbMjWAdKEKB-QE9@ka0XOS2D^UESEElG|C?KCL z_eH^aZoucwFmTiR{)?wg3-oIcv}vt2z*%qp<&MF$tgmJm1yw4sp*l#5OiNdB3>~o+ z4$0PNt@kLfQov(HnHFt$B|X5-+pKY0@jUOM7>w=LHlgo-L&~j8T+fN9HTTT~)~Z25 zPq-l)O_FKhGm5?mbC-jX6)^zqh&EvU&<(i1e4MFbi^66 vEBb#S@!uQ#t%$F$gwZM^xeld5)!Voc8v{t~>Z+%|zt+wUZuWO~kZEN=V8!k?avAJCU-C%oIwB z!HfxsG6oab-x47a(eNqX_5Jn!`Q6v`ocliaInTMy_5AfD;B3r=1rdS(00>*0FtG&y z2=e#Y!L#Mqlth|u(PP|6d($ocS6sh-eak12NL!IeB>MaNZ@1y`co!EJ91e%YVz(WW zKiJkrf3S56g+fI|MQz1xUtL{YQBiSAZ$~*fxouxcN@~xZJ>ufx+v%=9*w%u70E5A{ zQy!k*n@@?C%5ITiu&s?9uzTMDV+7dP|oa-Kv*T3)Ar3g{ql(lbnvlH zHy;0Ey~}i-Rr6dfYkfV6D!N~2-@bu2D$bj8XR0@}W8~BP-5Yv3q%3YYs#qvwY6>#2 zVES>*bcm)aADJXcfwH6ikfYjvb4Qxsc413^_kVZ5Kh(affU-r=(iBH!1mHk(x)*KD zPhNJ?69H$|1Tdl$_T}%LYdk2|i2H0~MHq72c9EoqWEA*|Da*Lm^C1u7Ovo1u_{fqx zVOnJvlUJ+E)CM^r@IrCY2YABZDO z(JRbw39svij?n@&isC^#p)Z%er?x|m?ktraRN6&OUDgLK(GbeYN0gQ3JtD5ONFQ~P z$;6n>2wjmgsM2sf#ZyMoOB_*2U1@*YoLG|y@!S2Oq%wW%aqD3!qPm<^>jEi4wcRP1 z%99C8GUFv56YVi!wdwBr>IOLg@xyUsL=ah|T6^Dv3UxX^l27E4mLs#D79l9-57Xcj z_Bkkf%^mQeIc2jF+rTKP3>Z1Kg;$=kQPr+wu{Tlx6i=|+ef!Jsbua4y(qXwuoRBRB zYvp=vgh11{ZUliHz9r$W;cD%hLN=<(;X|s11e0G#PBTeU4_qr5-odNN$R{?=^-gZ; z{s#q$CZ|^Qpu;d1IOXO!HEF7tPuA$^2hyU{cqqF*f}5taHR#9w1n(YZfU%#-B_NpQ zBw0x^<0CsTNGgJ0KGw!uK3Vi!A!ZikC|D#a9)BhE*<4}` zj8!+nH>Z=C7p8s@vM+?PqsJMBA3gEWo$7l*Yd3nrz3=t(tS?aB1g^jJ)q{^Lz8(wrk@EEgsHrn_vj-uBTyll(vY#N)e;tnweqAsRL5&t8KgkG{(U zJSPp|Bkwxu@G_Rb&_(1`U_%!~9GKM0BoQybWQ57HW7r}NVLmpPkDjd3OF75$vdK38 z)9EC}Kjyw?Q`_FlHl1DJA`Oi_;U&ZVvP|9XGa6KsLczd;CeS_PWU{%VlH1#sFR$*h zL@`r3a0oy8%I*-y4^*|VkI5PcfI~nEv-s-ej4FxX+wr(Bte1^H&23y}zGW!+Ei408 zDqIOIddH{h_B7tYJN6kF`)j zqB-VlD2l)CHcD;+9+%7t#U(IeXN# zR5B7C6soR@^|X#(a+TZwa!bDX}9wS}yY=u?@P# z9Xb^?&HqiwkOlvV=yR~o+bWFBOsAB8^BPokEzKI4QFqIwiA^}$7N_1#jZ&Cj`o&Dlgax5vO7r77 zsBu$`1~lL`m+9WA6PDH7k$xFSo5@zlUYf}xupi~L&O=UdtswjvW z>f#@NjHy;9BS;0Ui7wf1yMvHt4_6!A&SxEj`*X$)JY~u@@RDPK=1zS!%5nKn=W!Vi zWQIJvxr12$;FF`Pp?LPo*R41j+^{<(C3Izw!keaDFv^H^LwQLjv*NMZf63$+BF8%D z6jUMg2XO06{y)r6-M@WI@!EwA-DnPXDgEw01-;a-$-oYt~blCYPu z*RJ`-^ROhnl5+dz^J|}u>!J7T^^mkPzX`*wFxRD#9cG*Bl520K7GRlW4cKc*lGw(T z*x7F0S<$DUY@JcDc4WYXjpYls%r2|WXl0f`X0LDuI>*i#+t9CA2;Z673HPZPjv7@u zI@FIDbXzudo}Uk?Y4}j0r4mIAG_ZJLv80(@&|18cYiUSRNO8;gtL>mJC^4bcs+Pkj zmbf_Of5Y@t%(I;MjWAF@cU{g#zM(suyZL!-Ms=M)fIh!E_ciH7Blqi+W>ZuB&mE&H zxn~I*ODp%V#^G0=R#}6DUt#M@t)B=-BPJq$F$>M*SHJY?6mC|pcgO?3P-{#2KYE8n zI0G8w&G3oC9#3SWD~c#WIS?&3r9O2e6d!d&K*Kv~Nh{2H5&g+WLlG-+K|HWAQ1S zO|kq~Ww%ZP>xaT0vFlG!^q=>1DS|e-m+C>-p~XZq{_Ax|N`l@Wc+-?0#TW$X=ifze&Ntt`2G$TNs}k5g_g-F|E-^MySqEwb@eTweKSY}*+0#s2+vl|HVWYGS zIdHrY*0Uf)6I;%Z?D8Yh-&6E*ZqI}H4(;XEdbAA_q`+%0QD5BycA$Dgym+{8a%600 zN`g)6IL5NhyhzdugN}6=iCsTar|4@D+>aN2%1nTm{6lfLy$MDW>4^XWG<@I`g2^9b_`3wEb6Ol%6RJn(RiNbr!9{c2TNj%kImU%2lpCe>c}nwFi`yKkftHhI=EU%K}9-`c{| L#^mvF*XaKMVMUGX diff --git a/crates/usvg/Cargo.toml b/crates/usvg/Cargo.toml index 26f42924f..66dec3457 100644 --- a/crates/usvg/Cargo.toml +++ b/crates/usvg/Cargo.toml @@ -37,19 +37,25 @@ 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 } + +# PNG encoding for embedded bitmap fonts +png = { version = "0.18", optional = true } + [dev-dependencies] once_cell = "1.21" [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", "png", "skrifa", "unicode-bidi", "unicode-script", "unicode-vo"] # Enables system fonts loading. system-fonts = ["fontdb/fs", "fontdb/fontconfig"] # Enables font files memmaping for faster loading. diff --git a/crates/usvg/codegen/attributes.txt b/crates/usvg/codegen/attributes.txt index 32cac0622..4667ca88a 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 @@ -133,6 +135,11 @@ refY requiredExtensions requiredFeatures result +resvg:hinting-engine +resvg:hinting-mode +resvg:hinting-preserve-linear-metrics +resvg:hinting-symmetric +resvg:hinting-target rotate rx ry diff --git a/crates/usvg/codegen/main.rs b/crates/usvg/codegen/main.rs index 60d657e8b..2bc901e07 100644 --- a/crates/usvg/codegen/main.rs +++ b/crates/usvg/codegen/main.rs @@ -106,10 +106,25 @@ fn gen_map( let joined_names = names.iter().map(|n| to_enum_name(n)).join(",\n "); + // Collect CSS-style aliases for resvg: namespaced attributes + // resvg:hinting-target -> -resvg-hinting-target (for CSS style attribute) + let css_aliases: Vec<(String, String)> = names + .iter() + .filter(|n| n.starts_with("resvg:")) + .map(|n| { + let css_name = format!("-resvg-{}", &n[6..]); + let enum_variant = format!("{}::{}", enum_name, to_enum_name(n)); + (css_name, enum_variant) + }) + .collect(); + let mut map = phf_codegen::Map::new(); for name in &names { map.entry(*name, &format!("{}::{}", enum_name, to_enum_name(name))); } + for (css_name, enum_variant) in &css_aliases { + map.entry(css_name, enum_variant); + } let mut map_data = Vec::new(); map.build(&mut map_data)?; @@ -172,19 +187,26 @@ fn gen_map( // some-string -> SomeString // some_string -> SomeString // some:string -> SomeString +// -resvg-foo -> ResvgFoo (leading dash is skipped) // 100 -> N100 fn to_enum_name(name: &str) -> String { let mut change_case = false; + let mut is_first_alpha = true; let mut s = String::with_capacity(name.len()); - for (idx, c) in name.chars().enumerate() { - if idx == 0 { + for c in name.chars() { + // Skip leading dashes/underscores/colons + if is_first_alpha && (c == '-' || c == '_' || c == ':') { + continue; + } + + if is_first_alpha { + is_first_alpha = false; if c.is_digit(10) { s.push('N'); s.push(c); } else { s.push(c.to_uppercase().next().unwrap()); } - continue; } diff --git a/crates/usvg/src/lib.rs b/crates/usvg/src/lib.rs index b60831980..12312472c 100644 --- a/crates/usvg/src/lib.rs +++ b/crates/usvg/src/lib.rs @@ -35,6 +35,42 @@ and can focus just on the rendering part. - All filters are supported. Including filter functions, like `filter="contrast(50%)"` - Recursive elements will be detected and removed - `objectBoundingBox` will be replaced with `userSpaceOnUse` +- Variable fonts are supported via `font-variation-settings` CSS property and automatic + mapping of `font-weight`, `font-stretch`, and `font-style` to variation axes +- Font hinting is supported and controlled by the `text-rendering` property: + `geometricPrecision` disables hinting, `optimizeLegibility`/`optimizeSpeed` enable it +- `font-optical-sizing` is supported for automatic optical size axis adjustment + +## Resvg Extensions + +usvg supports custom properties for fine-grained control over font hinting. +These can be specified as SVG attributes (using the `resvg:` namespace) or as +CSS properties (using the `-resvg-` vendor prefix). + +### Hinting Properties + +| Property | Values | Default | Description | +|----------|--------|---------|-------------| +| `resvg:hinting-target` | `smooth`, `mono` | `smooth` | Target rasterization type | +| `resvg:hinting-mode` | `normal`, `light`, `lcd`, `vertical-lcd` | `normal` | Hinting strength | +| `resvg:hinting-engine` | `auto`, `native`, `auto-fallback` | `auto-fallback` | Hinting engine | +| `resvg:hinting-symmetric` | `true`, `false` | `true` | Symmetric rendering | +| `resvg:hinting-preserve-linear-metrics` | `true`, `false` | `false` | Preserve glyph spacing | + +### Example + +```xml + + + Crisp text + + + Crisp text + +``` + +See [`HintingSettings`] for detailed documentation of each property. ## Limitations diff --git a/crates/usvg/src/main.rs b/crates/usvg/src/main.rs index 8dcaca08f..5b2bbc106 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 c2d13256c..55b3e962b 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; @@ -56,7 +56,7 @@ pub struct Cache { #[cfg(feature = "text")] cache_svg: HashMap<(ID, GlyphId), Option>, #[cfg(feature = "text")] - cache_raster: HashMap<(ID, GlyphId), Option>, + cache_raster: HashMap<(ID, GlyphId, u16), Option>, pub clip_paths: HashMap>, pub masks: HashMap>, @@ -203,7 +203,26 @@ impl Cache { font_lookup!(fontdb_outline, cache_outline, outline, tiny_skia_path::Path); font_lookup!(fontdb_colr, cache_colr, colr, Tree); font_lookup!(fontdb_svg, cache_svg, svg, Node); - font_lookup!(fontdb_raster, cache_raster, raster, BitmapImage); + + #[cfg(feature = "text")] + pub(crate) fn fontdb_raster( + &mut self, + font: ID, + glyph: GlyphId, + font_size: f32, + ) -> Option { + // Round font_size to u16 for cache key (sub-pixel precision not needed for strike selection) + let size_key = font_size.round() as u16; + let key = (font, glyph, size_key); + match self.cache_raster.get(&key) { + Some(cache_hit) => cache_hit.clone(), + None => { + let lookup = self.fontdb.raster(font, glyph, font_size); + self.cache_raster.insert(key, lookup.clone()); + lookup + } + } + } } // TODO: is there a simpler way? 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..fc9d47aeb 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, + + /// Deprecated: This field is no longer used. + /// + /// In SVG, font-size is specified in user units (pixels), so ppem equals + /// font_size directly. Hinting is applied at the source coordinate scale. + /// For pixel-perfect output, render at 1:1 scale or integer zoom factors. + /// + /// This field is kept for API compatibility but has no effect. + pub dpi: Option, +} + +#[cfg(feature = "text")] +impl Default for HintingOptions { + fn default() -> Self { + Self { + // 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 a48b732d5..970f04e12 100644 --- a/crates/usvg/src/parser/svgtree/mod.rs +++ b/crates/usvg/src/parser/svgtree/mod.rs @@ -706,12 +706,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 @@ -727,6 +729,11 @@ impl AId { | AId::Opacity | AId::Overflow | AId::PaintOrder + | AId::ResvgHintingEngine // resvg extension + | AId::ResvgHintingMode // resvg extension + | AId::ResvgHintingPreserveLinearMetrics // resvg extension + | AId::ResvgHintingSymmetric // resvg extension + | AId::ResvgHintingTarget // resvg extension | AId::ShapeRendering | AId::StopColor | AId::StopOpacity @@ -782,6 +789,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..6b1118799 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, @@ -298,6 +300,11 @@ pub enum AId { RequiredExtensions, RequiredFeatures, Result, + ResvgHintingEngine, + ResvgHintingMode, + ResvgHintingPreserveLinearMetrics, + ResvgHintingSymmetric, + ResvgHintingTarget, Rotate, Rx, Ry, @@ -375,261 +382,276 @@ pub enum AId { } static ATTRIBUTES: Map = Map { - key: 3347381344252206323, + key: 3213172566270843353, disps: &[ - (0, 111), (0, 2), - (0, 45), - (0, 5), - (0, 1), - (2, 56), - (0, 5), - (2, 99), - (13, 198), - (0, 61), - (0, 52), - (1, 29), + (0, 50), + (0, 112), + (4, 61), + (0, 12), + (0, 199), (0, 21), - (0, 70), - (0, 164), - (2, 60), - (3, 52), - (0, 1), - (0, 86), - (0, 10), + (0, 2), + (1, 23), + (0, 76), (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, 216), + (0, 37), + (1, 138), + (0, 55), (1, 1), + (0, 5), + (0, 90), + (3, 104), + (0, 104), + (1, 115), + (1, 194), + (2, 129), + (4, 53), + (0, 112), + (0, 30), + (1, 3), + (1, 46), + (0, 1), + (0, 20), + (0, 54), + (6, 7), + (1, 129), + (0, 2), + (1, 3), + (1, 167), + (7, 106), + (0, 59), + (0, 15), + (1, 5), + (12, 201), + (16, 157), + (0, 47), + (0, 6), + (4, 38), ], 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), + ("href", AId::Href), + ("in", AId::In), + ("font-feature-settings", AId::FontFeatureSettings), + ("stroke-miterlimit", AId::StrokeMiterlimit), + ("clipPathUnits", AId::ClipPathUnits), + ("targetY", AId::TargetY), + ("-resvg-hinting-mode", AId::ResvgHintingMode), ("scale", AId::Scale), - ("x2", AId::X2), - ("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), - ("gradientUnits", AId::GradientUnits), - ("exponent", AId::Exponent), - ("text-decoration-color", AId::TextDecorationColor), - ("refX", AId::RefX), - ("enable-background", AId::EnableBackground), + ("patternContentUnits", AId::PatternContentUnits), + ("clip-path", AId::ClipPath), + ("white-space", AId::WhiteSpace), + ("pointsAtY", AId::PointsAtY), + ("in2", AId::In2), + ("fy", AId::Fy), + ("color-interpolation", AId::ColorInterpolation), + ("color", AId::Color), ("mask-border-width", AId::MaskBorderWidth), - ("numOctaves", AId::NumOctaves), - ("kerning", AId::Kerning), + ("mask-border", AId::MaskBorder), + ("inline-size", AId::InlineSize), + ("mask-border-outset", AId::MaskBorderOutset), + ("textLength", AId::TextLength), + ("x1", AId::X1), + ("mask-composite", AId::MaskComposite), + ("width", AId::Width), + ("line-height", AId::LineHeight), + ("text-decoration-line", AId::TextDecorationLine), + ("ry", AId::Ry), ("mix-blend-mode", AId::MixBlendMode), - ("mask-clip", AId::MaskClip), - ("mask-mode", AId::MaskMode), - ("type", AId::Type), - ("class", AId::Class), - ("font", AId::Font), - ("mask-border-repeat", AId::MaskBorderRepeat), - ("stroke-miterlimit", AId::StrokeMiterlimit), - ("text-decoration-stroke", AId::TextDecorationStroke), - ("z", AId::Z), - ("dx", AId::Dx), - ("clip-path", AId::ClipPath), - ("markerHeight", AId::MarkerHeight), - ("text-underline-position", AId::TextUnderlinePosition), - ("stdDeviation", AId::StdDeviation), - ("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), - ("direction", AId::Direction), - ("font-variant-numeric", AId::FontVariantNumeric), - ("startOffset", AId::StartOffset), + ("x2", AId::X2), + ("stitchTiles", AId::StitchTiles), + ("fr", AId::Fr), ("maskUnits", AId::MaskUnits), - ("font-variant", AId::FontVariant), - ("text-orientation", AId::TextOrientation), - ("amplitude", AId::Amplitude), + ("k2", AId::K2), + ("visibility", AId::Visibility), + ("preserveAspectRatio", AId::PreserveAspectRatio), ("rx", AId::Rx), - ("mask-type", AId::MaskType), - ("filter", AId::Filter), - ("in", AId::In), - ("display", AId::Display), - ("seed", AId::Seed), + ("surfaceScale", AId::SurfaceScale), + ("text-decoration", AId::TextDecoration), + ("maskContentUnits", AId::MaskContentUnits), + ("letter-spacing", AId::LetterSpacing), + ("flood-opacity", AId::FloodOpacity), + ("background-color", AId::BackgroundColor), ("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), + ("requiredExtensions", AId::RequiredExtensions), + ("font-weight", AId::FontWeight), + ("stdDeviation", AId::StdDeviation), + ("intercept", AId::Intercept), + ("direction", AId::Direction), + ("azimuth", AId::Azimuth), ("isolation", AId::Isolation), - ("gradientTransform", AId::GradientTransform), - ("transform-box", AId::TransformBox), - ("pointsAtY", AId::PointsAtY), - ("text-decoration-line", AId::TextDecorationLine), - ("requiredFeatures", AId::RequiredFeatures), - ("patternContentUnits", AId::PatternContentUnits), + ("baseFrequency", AId::BaseFrequency), ("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), - ("k4", AId::K4), - ("systemLanguage", AId::SystemLanguage), - ("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), + ("writing-mode", AId::WritingMode), + ("id", AId::Id), + ("font-variant-numeric", AId::FontVariantNumeric), + ("marker-end", AId::MarkerEnd), + ("font-optical-sizing", AId::FontOpticalSizing), ("cx", AId::Cx), - ("alignment-baseline", AId::AlignmentBaseline), - ("font-kerning", AId::FontKerning), - ("requiredExtensions", AId::RequiredExtensions), - ("clip-rule", AId::ClipRule), - ("mask-border-outset", AId::MaskBorderOutset), - ("primitiveUnits", AId::PrimitiveUnits), - ("textLength", AId::TextLength), - ("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), + ("amplitude", AId::Amplitude), + ("fill", AId::Fill), + ("stroke-dasharray", AId::StrokeDasharray), + ("result", AId::Result), ("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), - ("clip", AId::Clip), - ("fx", AId::Fx), - ("visibility", AId::Visibility), - ("shape-margin", AId::ShapeMargin), - ("font-style", AId::FontStyle), - ("y2", AId::Y2), - ("dy", AId::Dy), - ("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), + ("mask-border-mode", AId::MaskBorderMode), + ("mask-type", AId::MaskType), + ("stroke-linecap", AId::StrokeLinecap), + ("baseline-shift", AId::BaselineShift), + ("gradientUnits", AId::GradientUnits), + ("clip-rule", AId::ClipRule), + ("font-variant-east-asian", AId::FontVariantEastAsian), + ("mask-border-source", AId::MaskBorderSource), + ("text-align", AId::TextAlign), ("shape-image-threshold", AId::ShapeImageThreshold), - ("image-rendering", AId::ImageRendering), - ("marker-mid", AId::MarkerMid), - ("filterUnits", AId::FilterUnits), - ("bias", AId::Bias), + ("stroke-linejoin", AId::StrokeLinejoin), + ("transform", AId::Transform), + ("type", AId::Type), + ("mask-position", AId::MaskPosition), ("mask-border-slice", AId::MaskBorderSlice), - ("pointsAtX", AId::PointsAtX), + ("resvg:hinting-symmetric", AId::ResvgHintingSymmetric), + ("font", AId::Font), + ("color-interpolation-filters", AId::ColorInterpolationFilters), ("kernelMatrix", AId::KernelMatrix), - ("color-interpolation", AId::ColorInterpolation), + ("resvg:hinting-engine", AId::ResvgHintingEngine), + ("text-decoration-color", AId::TextDecorationColor), + ("unicode-bidi", AId::UnicodeBidi), + ("preserveAlpha", AId::PreserveAlpha), + ("slope", AId::Slope), + ("font-size-adjust", AId::FontSizeAdjust), + ("radius", AId::Radius), + ("d", AId::D), + ("dx", AId::Dx), + ("mask-mode", AId::MaskMode), + ("viewBox", AId::ViewBox), + ("mode", AId::Mode), + ("font-variation-settings", AId::FontVariationSettings), + ("y2", AId::Y2), + ("pointsAtZ", AId::PointsAtZ), + ("mask-clip", AId::MaskClip), + ("markerWidth", AId::MarkerWidth), + ("font-variant-ligatures", AId::FontVariantLigatures), + ("exponent", AId::Exponent), + ("fx", AId::Fx), + ("enable-background", AId::EnableBackground), + ("font-variant", AId::FontVariant), + ("startOffset", AId::StartOffset), + ("markerUnits", AId::MarkerUnits), + ("systemLanguage", AId::SystemLanguage), + ("opacity", AId::Opacity), + ("text-decoration-style", AId::TextDecorationStyle), + ("font-size", AId::FontSize), + ("stop-opacity", AId::StopOpacity), ("glyph-orientation-vertical", AId::GlyphOrientationVertical), - ("color", AId::Color), + ("mask-origin", AId::MaskOrigin), + ("x", AId::X), + ("shape-margin", AId::ShapeMargin), + ("shape-rendering", AId::ShapeRendering), + ("height", AId::Height), ("patternTransform", AId::PatternTransform), - ("kernelUnitLength", AId::KernelUnitLength), - ("markerUnits", AId::MarkerUnits), - ("font-weight", AId::FontWeight), - ("overflow", AId::Overflow), - ("stop-color", AId::StopColor), - ("r", AId::R), - ("k2", AId::K2), + ("-resvg-hinting-symmetric", AId::ResvgHintingSymmetric), + ("vector-effect", AId::VectorEffect), + ("offset", AId::Offset), ("text-anchor", AId::TextAnchor), - ("inline-size", AId::InlineSize), - ("unicode-bidi", AId::UnicodeBidi), - ("font-family", AId::FontFamily), - ("color-interpolation-filters", AId::ColorInterpolationFilters), - ("slope", AId::Slope), - ("baseFrequency", AId::BaseFrequency), - ("transform", AId::Transform), + ("text-indent", AId::TextIndent), + ("font-synthesis", AId::FontSynthesis), + ("r", AId::R), + ("font-variant-caps", AId::FontVariantCaps), + ("kerning", AId::Kerning), + ("paint-order", AId::PaintOrder), + ("stroke-width", AId::StrokeWidth), + ("mask", AId::Mask), + ("text-decoration-fill", AId::TextDecorationFill), + ("-resvg-hinting-target", AId::ResvgHintingTarget), + ("-resvg-hinting-engine", AId::ResvgHintingEngine), + ("dominant-baseline", AId::DominantBaseline), + ("primitiveUnits", AId::PrimitiveUnits), + ("word-spacing", AId::WordSpacing), + ("kernelUnitLength", AId::KernelUnitLength), + ("style", AId::Style), + ("stroke", AId::Stroke), ("text-rendering", AId::TextRendering), - ("divisor", AId::Divisor), + ("color-rendering", AId::ColorRendering), ("edgeMode", AId::EdgeMode), - ("letter-spacing", AId::LetterSpacing), - ("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), + ("clip", AId::Clip), + ("elevation", AId::Elevation), + ("mask-size", AId::MaskSize), + ("resvg:hinting-target", AId::ResvgHintingTarget), + ("refX", AId::RefX), + ("y1", AId::Y1), + ("dy", AId::Dy), ("pathLength", AId::PathLength), - ("lighting-color", AId::LightingColor), - ("mask-position", AId::MaskPosition), - ("stroke-dasharray", AId::StrokeDasharray), - ("text-decoration", AId::TextDecoration), + ("spreadMethod", AId::SpreadMethod), + ("z", AId::Z), + ("font-stretch", AId::FontStretch), + ("transform-box", AId::TransformBox), + ("text-align-last", AId::TextAlignLast), + ("class", AId::Class), + ("requiredFeatures", AId::RequiredFeatures), + ("divisor", AId::Divisor), + ("tableValues", AId::TableValues), + ("k3", AId::K3), + ("path", AId::Path), + ("text-orientation", AId::TextOrientation), + ("transform-origin", AId::TransformOrigin), + ("color-profile", AId::ColorProfile), + ("rotate", AId::Rotate), + ("alignment-baseline", AId::AlignmentBaseline), + ("marker-mid", AId::MarkerMid), + ("glyph-orientation-horizontal", AId::GlyphOrientationHorizontal), ("stroke-opacity", AId::StrokeOpacity), - ("targetY", AId::TargetY), - ("flood-opacity", AId::FloodOpacity), + ("shape-inside", AId::ShapeInside), + ("filter", AId::Filter), + ("resvg:hinting-mode", AId::ResvgHintingMode), + ("pointsAtX", AId::PointsAtX), + ("stop-color", AId::StopColor), + ("targetX", AId::TargetX), + ("markerHeight", AId::MarkerHeight), + ("filterUnits", AId::FilterUnits), + ("refY", AId::RefY), + ("order", AId::Order), + ("fill-rule", AId::FillRule), ("diffuseConstant", AId::DiffuseConstant), + ("mask-border-repeat", AId::MaskBorderRepeat), + ("display", AId::Display), + ("specularExponent", AId::SpecularExponent), + ("orient", AId::Orient), + ("font-kerning", AId::FontKerning), + ("k4", AId::K4), + ("bias", AId::Bias), + ("text-underline-position", AId::TextUnderlinePosition), + ("marker-start", AId::MarkerStart), + ("text-overflow", AId::TextOverflow), + ("image-rendering", AId::ImageRendering), + ("font-variant-position", AId::FontVariantPosition), + ("specularConstant", AId::SpecularConstant), + ("values", AId::Values), + ("font-family", AId::FontFamily), + ("-resvg-hinting-preserve-linear-metrics", AId::ResvgHintingPreserveLinearMetrics), + ("limitingConeAngle", AId::LimitingConeAngle), + ("overflow", AId::Overflow), + ("flood-color", AId::FloodColor), + ("operator", AId::Operator), + ("seed", AId::Seed), + ("resvg:hinting-preserve-linear-metrics", AId::ResvgHintingPreserveLinearMetrics), + ("stroke-dashoffset", AId::StrokeDashoffset), + ("shape-subtract", AId::ShapeSubtract), + ("xChannelSelector", AId::XChannelSelector), + ("font-style", AId::FontStyle), + ("yChannelSelector", AId::YChannelSelector), + ("lighting-color", AId::LightingColor), + ("gradientTransform", AId::GradientTransform), + ("lengthAdjust", AId::LengthAdjust), + ("numOctaves", AId::NumOctaves), + ("fill-opacity", AId::FillOpacity), + ("k1", AId::K1), + ("text-decoration-stroke", AId::TextDecorationStroke), + ("side", AId::Side), + ("cy", AId::Cy), + ("y", AId::Y), + ("patternUnits", AId::PatternUnits), ], }; diff --git a/crates/usvg/src/parser/svgtree/parse.rs b/crates/usvg/src/parser/svgtree/parse.rs index 2eae321b6..4510c004c 100644 --- a/crates/usvg/src/parser/svgtree/parse.rs +++ b/crates/usvg/src/parser/svgtree/parse.rs @@ -12,6 +12,7 @@ use super::{AId, Attribute, Document, EId, NodeData, NodeId, NodeKind, ShortRang const SVG_NS: &str = "http://www.w3.org/2000/svg"; const XLINK_NS: &str = "http://www.w3.org/1999/xlink"; const XML_NAMESPACE_NS: &str = "http://www.w3.org/XML/1998/namespace"; +const RESVG_NS: &str = "https://resvg.io/ns"; impl<'input> Document<'input> { /// Parses a [`Document`] from a [`roxmltree::Document`]. @@ -232,11 +233,19 @@ pub(crate) fn parse_svg_element<'input>( // Copy presentational attributes first. for attr in xml_node.attributes() { match attr.namespace() { - None | Some(SVG_NS) | Some(XLINK_NS) | Some(XML_NAMESPACE_NS) => {} + None | Some(SVG_NS) | Some(XLINK_NS) | Some(XML_NAMESPACE_NS) | Some(RESVG_NS) => {} _ => continue, } - let aid = match AId::from_str(attr.name()) { + // For resvg namespace attributes, we need to use the prefixed name for lookup + // because the AId enum uses names like "resvg:hinting-target" + let attr_name = if attr.namespace() == Some(RESVG_NS) { + format!("resvg:{}", attr.name()) + } else { + attr.name().to_string() + }; + + let aid = match AId::from_str(&attr_name) { Some(v) => v, None => continue, }; diff --git a/crates/usvg/src/parser/text.rs b/crates/usvg/src/parser/text.rs index eed3aab40..2be4d1526 100644 --- a/crates/usvg/src/parser/text.rs +++ b/crates/usvg/src/parser/text.rs @@ -140,7 +140,13 @@ 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 }) + } else { + None + }; + + if text::convert(&mut text, &state.opt.font_resolver, cache, hinting_ctx).is_none() { return; } @@ -263,6 +269,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 +296,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 +405,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)) { @@ -416,12 +472,141 @@ fn convert_font(node: SvgNode, state: &converter::State) -> Font { families.push(FontFamily::Named(state.opt.font_family.clone())); } + let hinting = parse_hinting_settings(node); + Font { families, style, stretch, weight, + variations, + hinting, + } +} + +/// Parses all `resvg:hinting-*` CSS properties (also available as `-resvg-hinting-*` in CSS style). +fn parse_hinting_settings(node: SvgNode) -> HintingSettings { + let target = node + .find_attribute::<&str>(AId::ResvgHintingTarget) + .and_then(|s| s.parse().ok()) + .unwrap_or_default(); + + let mode = node + .find_attribute::<&str>(AId::ResvgHintingMode) + .and_then(|s| s.parse().ok()) + .unwrap_or_default(); + + let engine = node + .find_attribute::<&str>(AId::ResvgHintingEngine) + .and_then(|s| s.parse().ok()) + .unwrap_or_default(); + + let symmetric_rendering = node + .find_attribute::<&str>(AId::ResvgHintingSymmetric) + .map(|s| s == "true") + .unwrap_or(true); // default is true + + let preserve_linear_metrics = node + .find_attribute::<&str>(AId::ResvgHintingPreserveLinearMetrics) + .map(|s| s == "true") + .unwrap_or(false); // default is false + + HintingSettings { + target, + mode, + engine, + symmetric_rendering, + preserve_linear_metrics, + } +} + +/// 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 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..a1bccbd33 100644 --- a/crates/usvg/src/text/flatten.rs +++ b/crates/usvg/src/text/flatten.rs @@ -5,14 +5,153 @@ 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::{ + FontRef, GlyphId, MetadataProvider, + bitmap::{BitmapData, MaskData}, + instance::{LocationRef, Size as SkrifaSize}, + outline::{ + DrawSettings, Engine, HintingInstance, HintingOptions, OutlinePen, SmoothMode, Target, + pen::ControlBoundsPen, + }, + raw::TableProvider, + setting::VariationSetting, +}; use tiny_skia_path::{NonZeroRect, Size, Transform}; -use xmlwriter::XmlWriter; -use crate::text::colr::GlyphPainter; use crate::*; +/// Encode raw image data as PNG. +fn encode_png(data: &[u8], width: u32, height: u32, color_type: png::ColorType) -> Option> { + let mut png_data = Vec::new(); + { + let mut encoder = png::Encoder::new(&mut png_data, width, height); + encoder.set_color(color_type); + encoder.set_depth(png::BitDepth::Eight); + let mut writer = encoder.write_header().ok()?; + writer.write_image_data(data).ok()?; + } + Some(png_data) +} + +/// Extract a single pixel from bitmap mask data. +/// Returns grayscale value (0x00 = black, 0xFF = white). +fn extract_mask_pixel(data: &[u8], x: u32, y: u32, width: u32, bpp: u8, is_packed: bool) -> u8 { + match bpp { + 1 => { + let (byte_idx, bit_idx) = if is_packed { + // Packed: bits flow continuously across row boundaries + let bit_pos = (y as usize) * (width as usize) + (x as usize); + (bit_pos / 8, 7 - (bit_pos % 8)) + } else { + // Not packed: each row is byte-aligned + let row_bytes = ((width + 7) / 8) as usize; + let idx = (y as usize) * row_bytes + (x as usize) / 8; + (idx, 7 - ((x as usize) % 8)) + }; + if byte_idx < data.len() { + let bit = (data[byte_idx] >> bit_idx) & 1; + // 1 = black (0x00), 0 = white (0xFF) + if bit == 1 { 0x00 } else { 0xFF } + } else { + 0xFF + } + } + 2 => { + // 2 bpp: each byte contains 4 pixels + let row_bytes = ((width + 3) / 4) as usize; + let byte_idx = (y as usize) * row_bytes + (x as usize) / 4; + let shift = 6 - (((x as usize) % 4) * 2); + if byte_idx < data.len() { + let val = (data[byte_idx] >> shift) & 0x03; + // Scale 0-3 to 0-255 (inverted: 3 = black) + 255 - (val * 85) + } else { + 0xFF + } + } + 4 => { + // 4 bpp: each byte contains 2 pixels + let row_bytes = ((width + 1) / 2) as usize; + let byte_idx = (y as usize) * row_bytes + (x as usize) / 2; + let shift = if x % 2 == 0 { 4 } else { 0 }; + if byte_idx < data.len() { + let val = (data[byte_idx] >> shift) & 0x0F; + // Scale 0-15 to 0-255 (inverted: 15 = black) + 255 - (val * 17) + } else { + 0xFF + } + } + 8 => { + // 8 bpp: one byte per pixel + let idx = (y as usize) * (width as usize) + (x as usize); + if idx < data.len() { + // Invert: 255 = black, 0 = white + 255 - data[idx] + } else { + 0xFF + } + } + _ => 0xFF, + } +} + +/// Convert a monochrome/grayscale bitmap mask to PNG format. +/// Supports 1, 2, 4, and 8 bits per pixel. +fn mask_to_png(mask: &MaskData, width: u32, height: u32) -> Option> { + if width == 0 || height == 0 { + return None; + } + + // Check for overflow: width * height must fit in usize + let capacity = (width as usize).checked_mul(height as usize)?; + + // Decode mask data to 8-bit grayscale + let mut grayscale = Vec::with_capacity(capacity); + + for y in 0..height { + for x in 0..width { + grayscale.push(extract_mask_pixel( + mask.data, + x, + y, + width, + mask.bpp, + mask.is_packed, + )); + } + } + + encode_png(&grayscale, width, height, png::ColorType::Grayscale) +} + +/// Convert BGRA bitmap data to PNG format. +fn bgra_to_png(data: &[u8], width: u32, height: u32) -> Option> { + if width == 0 || height == 0 { + return None; + } + + // Check for overflow: width * height * 4 must fit in usize + let expected_len = (width as usize) + .checked_mul(height as usize)? + .checked_mul(4)?; + if data.len() < expected_len { + return None; + } + + // Convert BGRA to RGBA + let mut rgba = Vec::with_capacity(expected_len); + for chunk in data[..expected_len].chunks(4) { + rgba.push(chunk[2]); // R + rgba.push(chunk[1]); // G + rgba.push(chunk[0]); // B + rgba.push(chunk[3]); // A + } + + encode_png(&rgba, width, height, png::ColorType::Rgba) +} + fn resolve_rendering_mode(text: &Text) -> ShapeRendering { match text.rendering_mode { TextRendering::OptimizeSpeed => ShapeRendering::CrispEdges, @@ -45,10 +184,51 @@ fn push_outline_paths( } } -pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZeroRect)> { +/// Hinting context for controlling font hinting behavior. +/// +/// Note: Hinting is applied at the SVG's source coordinate scale, not the final +/// output scale. For pixel-perfect mono rendering, the output should be rendered +/// at 1:1 scale (no zoom/fit), or use a zoom factor that's an integer multiple +/// (2x, 3x, etc.) to maintain pixel alignment. +#[derive(Clone, Copy, Debug)] +pub(crate) struct HintingContext { + /// Whether hinting is enabled globally. + pub(crate) enabled: bool, +} + +impl HintingContext { + /// Calculate pixels per em from font size. + /// + /// In SVG, font-size is specified in user units (pixels), not points. + /// So ppem equals font_size directly when rendering at 1:1 scale. + pub(crate) fn ppem(&self, font_size: f32) -> f32 { + font_size + } +} + +/// 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() { @@ -69,9 +249,33 @@ pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZ // span to we push the actual outline paths into new_children. This way, we don't need // to create a new path for every glyph if we have many consecutive glyphs // with just outlines (which is the most common case). + // + // We also track rendering mode per-glyph: if a glyph uses Mono hinting target, + // it needs CrispEdges rendering (no anti-aliasing), so we flush the builder + // when the rendering mode changes. let mut span_builder = tiny_skia_path::PathBuilder::new(); + let mut current_glyph_rendering_mode = rendering_mode; for glyph in &span.positioned_glyphs { + // Determine rendering mode for this glyph based on hinting target + // Mono target always disables anti-aliasing (CrispEdges), regardless of whether + // hinting is enabled. This allows comparing hinted vs unhinted mono rendering. + let glyph_rendering_mode = if glyph.hinting().target == crate::HintingTarget::Mono { + ShapeRendering::CrispEdges // No anti-aliasing for mono target + } else { + rendering_mode + }; + + // If rendering mode changed, flush the current path segment + if glyph_rendering_mode != current_glyph_rendering_mode { + push_outline_paths( + span, + &mut span_builder, + &mut new_children, + current_glyph_rendering_mode, + ); + current_glyph_rendering_mode = glyph_rendering_mode; + } // A (best-effort conversion of a) COLR glyph. if let Some(tree) = cache.fontdb_colr(glyph.font, glyph.id) { let mut group = Group { @@ -99,25 +303,20 @@ pub(crate) fn flatten(text: &mut Text, cache: &mut Cache) -> Option<(Group, NonZ new_children.push(Node::Group(Box::new(group))); } // A bitmap glyph. - else if let Some(img) = cache.fontdb_raster(glyph.font, glyph.id) { + else if let Some(img) = cache.fontdb_raster(glyph.font, glyph.id, glyph.font_size()) { push_outline_paths(span, &mut span_builder, &mut new_children, rendering_mode); 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,15 +327,51 @@ 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, + glyph.hinting(), + ) + } 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); + } } } - push_outline_paths(span, &mut span_builder, &mut new_children, rendering_mode); + push_outline_paths( + span, + &mut span_builder, + &mut new_children, + current_glyph_rendering_mode, + ); if let Some(path) = span.line_through.as_ref() { let mut path = path.clone(); @@ -159,11 +394,203 @@ 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_settings: crate::HintingSettings, +) -> 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) = ppem { + let size = SkrifaSize::new(ppem_val); + + // Convert HintingSettings to skrifa's Target + let hinting_target = match hinting_settings.target { + crate::HintingTarget::Mono => Target::Mono, + crate::HintingTarget::Smooth => { + // Convert HintingMode to skrifa's SmoothMode + let smooth_mode = match hinting_settings.mode { + crate::HintingMode::Normal => SmoothMode::Normal, + crate::HintingMode::Light => SmoothMode::Light, + crate::HintingMode::Lcd => SmoothMode::Lcd, + crate::HintingMode::VerticalLcd => SmoothMode::VerticalLcd, + }; + Target::Smooth { + mode: smooth_mode, + symmetric_rendering: hinting_settings.symmetric_rendering, + preserve_linear_metrics: hinting_settings.preserve_linear_metrics, + } + } + }; + + // Convert HintingEngine to skrifa's Engine + let engine = match hinting_settings.engine { + crate::HintingEngine::Auto => Engine::Auto(None), + crate::HintingEngine::Native => Engine::Interpreter, + crate::HintingEngine::AutoFallback => Engine::AutoFallback, + }; + + // Build HintingOptions with both engine and target + let hinting_options = HintingOptions { + engine, + target: hinting_target, + }; + + // Create hinting instance with the configured options. + // Note: HintingInstance is created per-glyph. For performance optimization, + // consider caching instances keyed by (font_id, ppem, location, settings) if profiling + // shows this is a bottleneck. + 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 +599,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 +612,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 raster(&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, font_size: f32) -> 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,119 +671,373 @@ 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 mut builder = PathBuilder { - builder: tiny_skia_path::PathBuilder::new(), - }; + let font = FontRef::from_index(data, face_index).ok()?; + let outlines = font.outline_glyphs(); + let glyph = outlines.get(glyph_id)?; - font.outline_glyph(glyph_id, &mut builder)?; - builder.builder.finish() + let mut pen = SkrifaPen::new(); + let settings = DrawSettings::unhinted(SkrifaSize::unscaled(), LocationRef::default()); + 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)?; - - 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)?, - rendering_mode: ImageRendering::OptimizeQuality, - kind: ImageKind::PNG(Arc::new(image.data.into())), - abs_transform: Transform::default(), - abs_bounding_box: NonZeroRect::from_xywh( - 0.0, - 0.0, - image.width as f32, - image.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(), - }; + #[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(); - return Some(bitmap_image); + // 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)); + } + } } - None + // 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 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. + fn raster(&self, id: ID, glyph_id: GlyphId, font_size: f32) -> Option { + self.with_face_data(id, |data, face_index| -> Option { + let font = FontRef::from_index(data, face_index).ok()?; - // 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. - 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)) + // Try to get bitmap strikes + let strikes = font.bitmap_strikes(); + + // Get the largest available strike first to check bitmap type + let largest_strike = strikes + .iter() + .max_by(|a, b| a.ppem().partial_cmp(&b.ppem()).unwrap_or(std::cmp::Ordering::Equal))?; + + let bitmap_glyph = largest_strike.get(glyph_id)?; + let bitmap_data = bitmap_glyph.data; + + // Check if this is a color bitmap (PNG/BGRA) or monochrome (Mask) + let is_color_bitmap = matches!(bitmap_data, BitmapData::Png(_) | BitmapData::Bgra(_)); + + // Strike selection strategy: + // - Color bitmaps (PNG/BGRA): use largest strike (original behavior) + // - Monochrome bitmaps (Mask): only use if exact size match OR no outline exists + let strike = if is_color_bitmap { + // Color bitmap: use largest strike (original behavior) + largest_strike } 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); + // Monochrome bitmap: prefer exact match for pixel-perfect rendering + let has_outline = font.outline_glyphs().get(glyph_id).is_some(); + let exact_match = strikes + .iter() + .find(|s| (s.ppem() - font_size).abs() < 0.01); + + if let Some(strike) = exact_match { + strike + } else if !has_outline { + // No outline fallback, use best available strike + strikes + .iter() + .filter(|s| s.ppem() >= font_size) + .min_by(|a, b| a.ppem().partial_cmp(&b.ppem()).unwrap_or(std::cmp::Ordering::Equal)) + .unwrap_or(largest_strike) + } else { + // Has outline and no exact match - caller will use outline + return None; + } + }; + + // Re-get bitmap_glyph for the selected strike (may differ for monochrome) + let bitmap_glyph = strike.get(glyph_id)?; + let bitmap_data = bitmap_glyph.data; + + // Handle different bitmap formats + let (png_data, width, height): (Vec, u32, u32) = match bitmap_data { + BitmapData::Png(data) => { + // Get PNG dimensions using imagesize + let (w, h) = if let Ok(size) = imagesize::blob_size(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) + }; + (data.to_vec(), w, h) + } + BitmapData::Mask(mask) => { + // Convert monochrome/grayscale mask to PNG + let w = bitmap_glyph.width; + let h = bitmap_glyph.height; + match mask_to_png(&mask, w, h) { + Some(png) => (png, w, h), + None => return None, + } + } + BitmapData::Bgra(data) => { + // Convert BGRA to PNG + let w = bitmap_glyph.width; + let h = bitmap_glyph.height; + match bgra_to_png(data, w, h) { + Some(png) => (png, w, h), + None => return None, + } + } + }; + + // 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 { + // Clamp to i16 range to prevent truncation issues with large glyph bounds + x_min: bb.x_min.clamp(i16::MIN as f32, i16::MAX as f32) as i16, + y_min: bb.y_min.clamp(i16::MIN as f32, i16::MAX as f32) as i16, + x_max: bb.x_max.clamp(i16::MIN as f32, i16::MAX as f32) as i16, + y_max: bb.y_max.clamp(i16::MIN as f32, i16::MAX as f32) as i16, }) - .cloned()? + }) + }; + + // Detect SBIX format by checking if the font has an sbix table. + let is_sbix = font.table_data(Tag::new(b"sbix")).is_some(); + + log::trace!( + "Bitmap glyph: bearing=({}, {}), inner_bearing=({}, {}), ppem={}, bbox={:?}, is_sbix={}, size={}x{}", + bitmap_glyph.bearing_x, bitmap_glyph.bearing_y, + bitmap_glyph.inner_bearing_x, bitmap_glyph.inner_bearing_y, + strike.ppem(), glyph_bbox, is_sbix, width, 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); + + // Choose rendering mode based on bitmap type: + // - Color bitmaps: smooth scaling for better quality when resized + // - Monochrome bitmaps: nearest-neighbor for pixel-perfect rendering + let rendering_mode = if is_color_bitmap { + ImageRendering::OptimizeQuality + } else { + ImageRendering::OptimizeSpeed + }; + + let bitmap_image = BitmapImage { + image: Image { + id: String::new(), + visible: true, + size: Size::from_wh(width as f32, height as f32)?, + rendering_mode, + kind: ImageKind::PNG(Arc::new(png_data)), + abs_transform: Transform::default(), + abs_bounding_box: NonZeroRect::from_xywh(0.0, 0.0, width as f32, height as f32)?, + }, + x, + y, + pixels_per_em: strike.ppem(), + glyph_bbox, + is_sbix, }; - Some(node) + Some(bitmap_image) })? } - 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()], - }; + fn svg(&self, id: ID, glyph_id: GlyphId) -> Option { + // 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 = 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; + } + + // 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; + } - face.paint_color_glyph( - glyph_id, - 0, - RgbaColor::new(0, 0, 0, 255), - &mut glyph_painter, - )?; - svg.end_element(); + 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; - Tree::from_data(svg.end_document().as_bytes(), &Options::default()).ok() + 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 { + // 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 + } +} + +#[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..2aa4ce5b5 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,30 @@ 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, + /// Font hinting settings. + pub hinting: crate::HintingSettings, } 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 hinting settings for this glyph. + pub fn hinting(&self) -> crate::HintingSettings { + self.hinting + } + /// Returns the transform of glyph. pub fn transform(&self) -> Transform { let sx = self.font_size / self.units_per_em as f32; @@ -66,18 +87,32 @@ 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 { + // Bitmap glyphs are in pixel units, not font units. + // self.transform() includes scale = font_size / units_per_em (for outline glyphs). + // We need to counteract that and apply the correct bitmap scaling. + // Total scale should be: font_size / pixels_per_em + // So we need: (font_size / units_per_em) * scale = font_size / pixels_per_em + // Therefore: scale = units_per_em / pixels_per_em + // + // When font_size == pixels_per_em, total scale = 1.0 (pixel-perfect rendering). + // Use a tolerance to snap to exactly 1.0 and avoid floating point precision issues. + let bitmap_scale = self.units_per_em as f32 / pixels_per_em; + let total_scale = (self.font_size / self.units_per_em as f32) * bitmap_scale; + let scale = if (total_scale - 1.0).abs() < 0.00001 { + // Snap to exactly 1.0 for pixel-perfect rendering + self.units_per_em as f32 / self.font_size + } else { + bitmap_scale + }; + 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) + .pre_concat(Transform::from_scale(scale, scale)) + // 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 +934,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 +991,26 @@ 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, + span.font.hinting, )); } } @@ -1127,7 +1181,14 @@ 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, + hinting: crate::HintingSettings, +) -> GlyphCluster { debug_assert!(!glyphs.is_empty()); let mut width = 0.0; @@ -1157,6 +1218,9 @@ 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, + hinting, }); x += glyph.width as f32; @@ -1189,89 +1253,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 +1277,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 +1322,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 +1382,78 @@ 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 +1469,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 +1518,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 +1633,7 @@ pub(crate) struct Glyph { impl Glyph { fn is_missing(&self) -> bool { - self.id.0 == 0 + self.id.to_u32() == 0 } } @@ -1597,6 +1682,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 +1856,83 @@ 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..d41115957 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_colr; +mod skrifa_metrics; + /// 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..a7e46ce0e --- /dev/null +++ b/crates/usvg/src/text/skrifa_colr.rs @@ -0,0 +1,422 @@ +// 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::{ + FontRef, GlyphId, MetadataProvider, + color::{Brush, ColorGlyphFormat, ColorPainter, CompositeMode}, + instance::LocationRef, + outline::OutlinePen, + raw::types::BoundingBox, +}; +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..61ed90026 --- /dev/null +++ b/crates/usvg/src/text/skrifa_metrics.rs @@ -0,0 +1,104 @@ +// Copyright 2024 the Resvg Authors +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Font metrics extraction using skrifa. +//! +//! This module provides font metrics extraction using skrifa's MetadataProvider trait, +//! replacing the previous ttf-parser based implementation. + +use std::num::NonZeroU16; + +use fontdb::ID; +use skrifa::{ + FontRef, MetadataProvider, instance::LocationRef, instance::Size as SkrifaSize, + raw::TableProvider, +}; + +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..be36fd19f 100644 --- a/crates/usvg/src/tree/text.rs +++ b/crates/usvg/src/tree/text.rs @@ -66,6 +66,221 @@ 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); + } +} + +/// Hinting target specifies the type of rasterization output. +/// +/// Corresponds to `-resvg-hinting-target` CSS property. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)] +pub enum HintingTarget { + /// Strong hinting for aliased, monochromatic rasterization. + /// Best for pixel-perfect rendering without anti-aliasing. + Mono, + /// Hinting suitable for anti-aliased rasterization. + /// This is the default and most common choice. + #[default] + Smooth, +} + +impl std::str::FromStr for HintingTarget { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "mono" => Ok(HintingTarget::Mono), + "smooth" => Ok(HintingTarget::Smooth), + _ => Err("invalid"), + } + } +} + +/// Hinting mode for smooth rendering. +/// +/// Corresponds to `-resvg-hinting-mode` CSS property. +/// Only applies when `HintingTarget::Smooth` is used. +/// +/// **Note:** The `Lcd` and `VerticalLcd` modes only affect how glyph outlines are +/// hinted (optimized for subpixel geometry). They do **not** produce actual LCD +/// subpixel rendering with separate RGB channels, as tiny-skia (the rasterizer) +/// does not support subpixel anti-aliasing. For these modes to produce visible +/// differences from `Normal`, a renderer with LCD subpixel support would be needed. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)] +pub enum HintingMode { + /// Standard smooth hinting. Equivalent to FreeType's `FT_LOAD_TARGET_NORMAL`. + #[default] + Normal, + /// Lighter hinting with fewer horizontal adjustments. + /// Produces results closer to unhinted outlines while still aligning to the pixel grid. + /// Equivalent to FreeType's `FT_LOAD_TARGET_LIGHT`. + Light, + /// Optimized for horizontal RGB subpixel rendering (standard LCD displays). + /// Equivalent to FreeType's `FT_LOAD_TARGET_LCD`. + /// + /// **Note:** This only affects outline hinting. Actual subpixel rendering + /// (RGB channel separation) is not implemented in resvg. + Lcd, + /// Optimized for vertical RGB subpixel rendering (rotated LCD displays). + /// Equivalent to FreeType's `FT_LOAD_TARGET_LCD_V`. + /// + /// **Note:** This only affects outline hinting. Actual subpixel rendering + /// (RGB channel separation) is not implemented in resvg. + VerticalLcd, +} + +impl std::str::FromStr for HintingMode { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "normal" => Ok(HintingMode::Normal), + "light" => Ok(HintingMode::Light), + "lcd" => Ok(HintingMode::Lcd), + "vertical-lcd" => Ok(HintingMode::VerticalLcd), + _ => Err("invalid"), + } + } +} + +/// Hinting engine selection. +/// +/// Corresponds to `-resvg-hinting-engine` CSS property. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)] +pub enum HintingEngine { + /// Use the automatic hinter (autohinting). + /// Generates hinting on-the-fly for fonts without native hinting. + Auto, + /// Use only the native TrueType/PostScript interpreter. + /// Falls back to unhinted if the font has no hinting instructions. + Native, + /// Automatic selection based on font capabilities (default). + /// Uses native interpreter if `fpgm`/`prep` tables exist, otherwise autohints. + /// This matches FreeType's default behavior. + #[default] + AutoFallback, +} + +impl std::str::FromStr for HintingEngine { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "auto" => Ok(HintingEngine::Auto), + "native" => Ok(HintingEngine::Native), + "auto-fallback" => Ok(HintingEngine::AutoFallback), + _ => Err("invalid"), + } + } +} + +/// Complete hinting configuration for text rendering. +/// +/// These options control how font outlines are adjusted for pixel grid alignment. +/// All options can be set via resvg-specific CSS properties or SVG attributes. +/// +/// # Custom Properties +/// +/// These properties are resvg extensions and not part of the SVG or CSS standards. +/// They can be used in two ways: +/// +/// ## As SVG attributes (resvg namespace) +/// +/// ```xml +/// +/// +/// Pixel-perfect text +/// +/// +/// ``` +/// +/// ## As CSS properties (vendor-prefixed) +/// +/// ```xml +/// +/// +/// Pixel-perfect text +/// +/// +/// ``` +/// +/// # Available Properties +/// +/// | Property | Values | Default | Description | +/// |----------|--------|---------|-------------| +/// | `-resvg-hinting-target` | `smooth`, `mono` | `smooth` | Rasterization target | +/// | `-resvg-hinting-mode` | `normal`, `light`, `lcd`, `vertical-lcd` | `normal` | Smooth hinting mode | +/// | `-resvg-hinting-engine` | `auto`, `native`, `auto-fallback` | `auto-fallback` | Hinting engine | +/// | `-resvg-hinting-symmetric` | `true`, `false` | `true` | Symmetric rendering | +/// | `-resvg-hinting-preserve-linear-metrics` | `true`, `false` | `false` | Preserve spacing | +/// +/// These properties inherit and can be set on any text element or ancestor. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub struct HintingSettings { + /// The hinting target (mono or smooth rasterization). + /// CSS: `-resvg-hinting-target` + pub target: HintingTarget, + /// The smooth hinting mode (only used when target is Smooth). + /// CSS: `-resvg-hinting-mode` + pub mode: HintingMode, + /// The hinting engine to use. + /// CSS: `-resvg-hinting-engine` + pub engine: HintingEngine, + /// Allow TrueType bytecode to assume symmetric rendering (vertical supersampling). + /// When true, ClearType-optimized fonts may produce wider horizontal stems. + /// CSS: `-resvg-hinting-symmetric` + pub symmetric_rendering: bool, + /// Preserve linear advance metrics (no horizontal glyph adjustments). + /// When true, inter-glyph spacing remains constant regardless of hinting. + /// Useful for layout consistency without re-evaluating glyph outlines. + /// CSS: `-resvg-hinting-preserve-linear-metrics` + pub preserve_linear_metrics: bool, +} + +impl Default for HintingSettings { + fn default() -> Self { + Self { + target: HintingTarget::default(), + mode: HintingMode::default(), + engine: HintingEngine::default(), + symmetric_rendering: true, + preserve_linear_metrics: false, + } + } +} + /// A font style property. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum FontStyle { @@ -113,6 +328,8 @@ pub struct Font { pub(crate) style: FontStyle, pub(crate) stretch: FontStretch, pub(crate) weight: u16, + pub(crate) variations: Vec, + pub(crate) hinting: HintingSettings, } impl Font { @@ -137,6 +354,18 @@ impl Font { pub fn weight(&self) -> u16 { self.weight } + + /// Font variation settings for variable fonts. + pub fn variations(&self) -> &[FontVariation] { + &self.variations + } + + /// Hinting settings for text rendering. + /// + /// Controlled by `-resvg-hinting-*` CSS properties. + pub fn hinting(&self) -> HintingSettings { + self.hinting + } } /// A dominant baseline property. @@ -218,6 +447,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 +528,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 +594,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 diff --git a/crates/usvg/src/writer.rs b/crates/usvg/src/writer.rs index 93b131052..d97183e7e 100644 --- a/crates/usvg/src/writer.rs +++ b/crates/usvg/src/writer.rs @@ -1529,6 +1529,38 @@ fn write_span( xml.write_attribute("style", "font-kerning:none"); } + // Write hinting settings if they differ from defaults + if span.font.hinting.target != HintingTarget::Smooth { + xml.write_svg_attribute(AId::ResvgHintingTarget, "mono"); + } + + if span.font.hinting.mode != HintingMode::Normal { + let mode = match span.font.hinting.mode { + HintingMode::Normal => unreachable!(), + HintingMode::Light => "light", + HintingMode::Lcd => "lcd", + HintingMode::VerticalLcd => "vertical-lcd", + }; + xml.write_svg_attribute(AId::ResvgHintingMode, mode); + } + + if span.font.hinting.engine != HintingEngine::AutoFallback { + let engine = match span.font.hinting.engine { + HintingEngine::Auto => "auto", + HintingEngine::Native => "native", + HintingEngine::AutoFallback => unreachable!(), + }; + xml.write_svg_attribute(AId::ResvgHintingEngine, engine); + } + + if !span.font.hinting.symmetric_rendering { + xml.write_svg_attribute(AId::ResvgHintingSymmetric, "false"); + } + + if span.font.hinting.preserve_linear_metrics { + xml.write_svg_attribute(AId::ResvgHintingPreserveLinearMetrics, "true"); + } + if span.dominant_baseline != DominantBaseline::Auto { let name = match span.dominant_baseline { DominantBaseline::UseScript => "use-script", diff --git a/crates/usvg/tests/files/clip-path-with-complex-text-expected.svg b/crates/usvg/tests/files/clip-path-with-complex-text-expected.svg index 49f2ea86e..0000eca71 100644 --- a/crates/usvg/tests/files/clip-path-with-complex-text-expected.svg +++ b/crates/usvg/tests/files/clip-path-with-complex-text-expected.svg @@ -2,7 +2,7 @@ - + diff --git a/crates/usvg/tests/files/clip-path-with-text-expected.svg b/crates/usvg/tests/files/clip-path-with-text-expected.svg index 01f09f81c..eb4733c30 100644 --- a/crates/usvg/tests/files/clip-path-with-text-expected.svg +++ b/crates/usvg/tests/files/clip-path-with-text-expected.svg @@ -1,7 +1,7 @@ - + diff --git a/crates/usvg/tests/files/preserve-text-simple-case-expected.svg b/crates/usvg/tests/files/preserve-text-simple-case-expected.svg index 2a97df767..fd3592f52 100644 --- a/crates/usvg/tests/files/preserve-text-simple-case-expected.svg +++ b/crates/usvg/tests/files/preserve-text-simple-case-expected.svg @@ -1,5 +1,5 @@ - + diff --git a/crates/usvg/tests/files/text-simple-case-expected.svg b/crates/usvg/tests/files/text-simple-case-expected.svg index 2a97df767..fd3592f52 100644 --- a/crates/usvg/tests/files/text-simple-case-expected.svg +++ b/crates/usvg/tests/files/text-simple-case-expected.svg @@ -1,5 +1,5 @@ - + diff --git a/crates/usvg/tests/files/text-with-generated-gradients-expected.svg b/crates/usvg/tests/files/text-with-generated-gradients-expected.svg index 8af171f67..5f0ec9eea 100644 --- a/crates/usvg/tests/files/text-with-generated-gradients-expected.svg +++ b/crates/usvg/tests/files/text-with-generated-gradients-expected.svg @@ -6,8 +6,8 @@ - - - + + + From dd72a7a68faef60097896823511118b4563b942a Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 09:55:25 +0100 Subject: [PATCH 2/8] Vendor fontdb 0.23.0 as a workspace crate Copy fontdb 0.23.0 source code into crates/fontdb/ as a first step toward replacing ttf-parser with skrifa for font metadata parsing. Source: https://github.com/RazrFalcon/fontdb (MIT licensed) Co-Authored-By: Claude Opus 4.5 --- Cargo.lock | 34 +- Cargo.toml | 1 + crates/fontdb/Cargo.toml | 38 + crates/fontdb/src/lib.rs | 1381 +++++++++++++++++++++++++ crates/fontdb/tests/add_fonts.rs | 15 + crates/fontdb/tests/fonts/LICENSE.txt | 11 + crates/fontdb/tests/fonts/Tuffy.ttf | Bin 0 -> 172324 bytes 7 files changed, 1479 insertions(+), 1 deletion(-) create mode 100644 crates/fontdb/Cargo.toml create mode 100644 crates/fontdb/src/lib.rs create mode 100644 crates/fontdb/tests/add_fonts.rs create mode 100644 crates/fontdb/tests/fonts/LICENSE.txt create mode 100644 crates/fontdb/tests/fonts/Tuffy.ttf diff --git a/Cargo.lock b/Cargo.lock index f10cb52ba..9b59622c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,25 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "env_filter", + "log", +] + [[package]] name = "euclid" version = "0.22.11" @@ -190,6 +209,19 @@ dependencies = [ "roxmltree 0.20.0", ] +[[package]] +name = "fontdb" +version = "0.23.0" +dependencies = [ + "env_logger", + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + [[package]] name = "fontdb" version = "0.23.0" @@ -750,7 +782,7 @@ dependencies = [ "base64", "data-url", "flate2", - "fontdb", + "fontdb 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", "harfrust", "imagesize", "kurbo", diff --git a/Cargo.toml b/Cargo.toml index 1bfecbc73..17c7baeb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "crates/c-api", + "crates/fontdb", "crates/resvg", "crates/usvg", "crates/usvg/codegen", diff --git a/crates/fontdb/Cargo.toml b/crates/fontdb/Cargo.toml new file mode 100644 index 000000000..29ad19ee8 --- /dev/null +++ b/crates/fontdb/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "fontdb" +version = "0.23.0" +authors = ["Yevhenii Reizner "] +edition = "2021" +description = "A simple, in-memory font database with CSS-like queries." +documentation = "https://docs.rs/fontdb/" +repository = "https://github.com/RazrFalcon/fontdb" +license = "MIT" +keywords = ["font", "db", "css", "truetype", "ttf"] +categories = ["text-processing"] + +[dependencies] +log = "0.4" +memmap2 = { version = "0.9", optional = true } +slotmap = { version = "1.0.6", default-features = false } +tinyvec = { version = "1.6.0", features = ["alloc"] } + +[dependencies.ttf-parser] +version = "0.25" +default-features = false +features = ["opentype-layout", "apple-layout", "variable-fonts", "glyph-names"] + +[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies] +fontconfig-parser = { version = "0.5", optional = true, default-features = false } + +[dev-dependencies] +env_logger = { version = "0.11", default-features = false } + +[features] +default = ["std", "fs", "memmap", "fontconfig"] +std = ["ttf-parser/std"] +# Allows local filesystem interactions. +fs = ["std"] +# Allows font files memory mapping, greatly improves performance. +memmap = ["fs", "memmap2"] +# Enables minimal fontconfig support on Linux. +fontconfig = ["fontconfig-parser", "fs"] diff --git a/crates/fontdb/src/lib.rs b/crates/fontdb/src/lib.rs new file mode 100644 index 000000000..6a788decb --- /dev/null +++ b/crates/fontdb/src/lib.rs @@ -0,0 +1,1381 @@ +/*! +`fontdb` is a simple, in-memory font database with CSS-like queries. + +# Features + +- The database can load fonts from files, directories and raw data (`Vec`). +- The database can match a font using CSS-like queries. See `Database::query`. +- The database can try to load system fonts. + Currently, this is implemented by scanning predefined directories. + The library does not interact with the system API. +- Provides a unique ID for each font face. + +# Non-goals + +- Advanced font properties querying.
+ The database provides only storage and matching capabilities. + For font properties querying you can use [ttf-parser]. + +- A font fallback mechanism.
+ This library can be used to implement a font fallback mechanism, but it doesn't implement one. + +- Application's global database.
+ The database doesn't use `static`, therefore it's up to the caller where it should be stored. + +- Font types support other than TrueType. + +# Font vs Face + +A font is a collection of font faces. Therefore, a font face is a subset of a font. +A simple font (\*.ttf/\*.otf) usually contains a single font face, +but a font collection (\*.ttc) can contain multiple font faces. + +`fontdb` stores and matches font faces, not fonts. +Therefore, after loading a font collection with 5 faces (for example), the database will be populated +with 5 `FaceInfo` objects, all of which will be pointing to the same file or binary data. + +# Performance + +The database performance is largely limited by the storage itself. +We are using [ttf-parser], so the parsing should not be a bottleneck. + +On my machine with Samsung SSD 860 and Gentoo Linux, it takes ~20ms +to load 1906 font faces (most of them are from Google Noto collection) +with a hot disk cache and ~860ms with a cold one. + +On Mac Mini M1 it takes just 9ms to load 898 fonts. + +# Safety + +The library relies on memory-mapped files, which is inherently unsafe. +But since we do not keep the files open it should be perfectly safe. + +If you would like to use a persistent memory mapping of the font files, +then you can use the unsafe [`Database::make_shared_face_data`] function. + +[ttf-parser]: https://github.com/RazrFalcon/ttf-parser +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] +#![warn(missing_debug_implementations)] +#![warn(missing_copy_implementations)] + +extern crate alloc; + +#[cfg(not(feature = "std"))] +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; + +pub use ttf_parser::Language; +pub use ttf_parser::Width as Stretch; + +use slotmap::SlotMap; +use tinyvec::TinyVec; + +/// A unique per database face ID. +/// +/// Since `Database` is not global/unique, we cannot guarantee that a specific ID +/// is actually from the same db instance. This is up to the caller. +/// +/// ID overflow will cause a panic, but it's highly unlikely that someone would +/// load more than 4 billion font faces. +/// +/// Because the internal representation of ID is private, The `Display` trait +/// implementation for this type only promise that unequal IDs will be displayed +/// as different strings, but does not make any guarantees about format or +/// content of the strings. +/// +/// [`KeyData`]: https://docs.rs/slotmap/latest/slotmap/struct.KeyData.html +#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Debug, Default)] +pub struct ID(InnerId); + +slotmap::new_key_type! { + /// Internal ID type. + struct InnerId; +} + +impl ID { + /// Creates a dummy ID. + /// + /// Should be used in tandem with [`Database::push_face_info`]. + #[inline] + pub fn dummy() -> Self { + Self(InnerId::from(slotmap::KeyData::from_ffi(core::u64::MAX))) + } +} + +impl core::fmt::Display for ID { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", (self.0).0.as_ffi()) + } +} + +/// A list of possible font loading errors. +#[derive(Debug)] +enum LoadError { + /// A malformed font. + /// + /// Typically means that [ttf-parser](https://github.com/RazrFalcon/ttf-parser) + /// wasn't able to parse it. + MalformedFont, + /// A valid TrueType font without a valid *Family Name*. + UnnamedFont, + /// A file IO related error. + #[cfg(feature = "std")] + IoError(std::io::Error), +} + +#[cfg(feature = "std")] +impl From for LoadError { + #[inline] + fn from(e: std::io::Error) -> Self { + LoadError::IoError(e) + } +} + +impl core::fmt::Display for LoadError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + LoadError::MalformedFont => write!(f, "malformed font"), + LoadError::UnnamedFont => write!(f, "font doesn't have a family name"), + #[cfg(feature = "std")] + LoadError::IoError(ref e) => write!(f, "{}", e), + } + } +} + +/// A font database. +#[derive(Clone, Debug)] +pub struct Database { + faces: SlotMap, + family_serif: String, + family_sans_serif: String, + family_cursive: String, + family_fantasy: String, + family_monospace: String, +} + +impl Default for Database { + fn default() -> Self { + Self::new() + } +} + +impl Database { + /// Create a new, empty `Database`. + /// + /// Generic font families would be set to: + /// + /// - `serif` - Times New Roman + /// - `sans-serif` - Arial + /// - `cursive` - Comic Sans MS + /// - `fantasy` - Impact (Papyrus on macOS) + /// - `monospace` - Courier New + #[inline] + pub fn new() -> Self { + Database { + faces: SlotMap::with_key(), + family_serif: "Times New Roman".to_string(), + family_sans_serif: "Arial".to_string(), + family_cursive: "Comic Sans MS".to_string(), + #[cfg(not(target_os = "macos"))] + family_fantasy: "Impact".to_string(), + #[cfg(target_os = "macos")] + family_fantasy: "Papyrus".to_string(), + family_monospace: "Courier New".to_string(), + } + } + + /// Loads a font data into the `Database`. + /// + /// Will load all font faces in case of a font collection. + pub fn load_font_data(&mut self, data: Vec) { + self.load_font_source(Source::Binary(alloc::sync::Arc::new(data))); + } + + /// Loads a font from the given source into the `Database` and returns + /// the ID of the loaded font. + /// + /// Will load all font faces in case of a font collection. + pub fn load_font_source(&mut self, source: Source) -> TinyVec<[ID; 8]> { + let ids = source.with_data(|data| { + let n = ttf_parser::fonts_in_collection(data).unwrap_or(1); + let mut ids = TinyVec::with_capacity(n as usize); + + for index in 0..n { + match parse_face_info(source.clone(), data, index) { + Ok(mut info) => { + let id = self.faces.insert_with_key(|k| { + info.id = ID(k); + info + }); + ids.push(ID(id)); + } + Err(e) => log::warn!( + "Failed to load a font face {} from source cause {}.", + index, + e + ), + } + } + + ids + }); + + ids.unwrap_or_default() + } + + /// Backend function used by load_font_file to load font files. + #[cfg(feature = "fs")] + fn load_fonts_from_file(&mut self, path: &std::path::Path, data: &[u8]) { + let source = Source::File(path.into()); + + let n = ttf_parser::fonts_in_collection(data).unwrap_or(1); + for index in 0..n { + match parse_face_info(source.clone(), data, index) { + Ok(info) => { + self.push_face_info(info); + } + Err(e) => { + log::warn!( + "Failed to load a font face {} from '{}' cause {}.", + index, + path.display(), + e + ) + } + } + } + } + + /// Loads a font file into the `Database`. + /// + /// Will load all font faces in case of a font collection. + #[cfg(all(feature = "fs", feature = "memmap"))] + pub fn load_font_file>( + &mut self, + path: P, + ) -> Result<(), std::io::Error> { + self.load_font_file_impl(path.as_ref()) + } + + // A non-generic version. + #[cfg(all(feature = "fs", feature = "memmap"))] + fn load_font_file_impl(&mut self, path: &std::path::Path) -> Result<(), std::io::Error> { + let file = std::fs::File::open(path)?; + let data: &[u8] = unsafe { &memmap2::MmapOptions::new().map(&file)? }; + + self.load_fonts_from_file(path, data); + Ok(()) + } + + /// Loads a font file into the `Database`. + /// + /// Will load all font faces in case of a font collection. + #[cfg(all(feature = "fs", not(feature = "memmap")))] + pub fn load_font_file>( + &mut self, + path: P, + ) -> Result<(), std::io::Error> { + self.load_font_file_impl(path.as_ref()) + } + + // A non-generic version. + #[cfg(all(feature = "fs", not(feature = "memmap")))] + fn load_font_file_impl(&mut self, path: &std::path::Path) -> Result<(), std::io::Error> { + let data = std::fs::read(path)?; + + self.load_fonts_from_file(path, &data); + Ok(()) + } + + /// Loads font files from the selected directory into the `Database`. + /// + /// This method will scan directories recursively. + /// + /// Will load `ttf`, `otf`, `ttc` and `otc` fonts. + /// + /// Unlike other `load_*` methods, this one doesn't return an error. + /// It will simply skip malformed fonts and will print a warning into the log for each of them. + #[cfg(feature = "fs")] + pub fn load_fonts_dir>(&mut self, dir: P) { + self.load_fonts_dir_impl(dir.as_ref(), &mut Default::default()) + } + + #[cfg(feature = "fs")] + fn canonicalize( + &self, + path: std::path::PathBuf, + entry: std::fs::DirEntry, + seen: &mut std::collections::HashSet, + ) -> Option<(std::path::PathBuf, std::fs::FileType)> { + let file_type = entry.file_type().ok()?; + if !file_type.is_symlink() { + if !seen.is_empty() { + if seen.contains(&path) { + return None; + } + seen.insert(path.clone()); + } + + return Some((path, file_type)); + } + + if seen.is_empty() && file_type.is_dir() { + seen.reserve(8192 / std::mem::size_of::()); + + for (_, info) in self.faces.iter() { + let path = match &info.source { + Source::Binary(_) => continue, + Source::File(path) => path.to_path_buf(), + #[cfg(feature = "memmap")] + Source::SharedFile(path, _) => path.to_path_buf(), + }; + seen.insert(path); + } + } + + let stat = std::fs::metadata(&path).ok()?; + if stat.is_symlink() { + return None; + } + + let canon = std::fs::canonicalize(path).ok()?; + if seen.contains(&canon) { + return None; + } + seen.insert(canon.clone()); + Some((canon, stat.file_type())) + } + + // A non-generic version. + #[cfg(feature = "fs")] + fn load_fonts_dir_impl( + &mut self, + dir: &std::path::Path, + seen: &mut std::collections::HashSet, + ) { + let fonts_dir = match std::fs::read_dir(dir) { + Ok(dir) => dir, + Err(_) => return, + }; + + for entry in fonts_dir.flatten() { + let (path, file_type) = match self.canonicalize(entry.path(), entry, seen) { + Some(v) => v, + None => continue, + }; + + if file_type.is_file() { + match path.extension().and_then(|e| e.to_str()) { + #[rustfmt::skip] // keep extensions match as is + Some("ttf") | Some("ttc") | Some("TTF") | Some("TTC") | + Some("otf") | Some("otc") | Some("OTF") | Some("OTC") => { + if let Err(e) = self.load_font_file(&path) { + log::warn!("Failed to load '{}' cause {}.", path.display(), e); + } + }, + _ => {} + } + } else if file_type.is_dir() { + self.load_fonts_dir_impl(&path, seen); + } + } + } + + /// Attempts to load system fonts. + /// + /// Supports Windows, Linux and macOS. + /// + /// System fonts loading is a surprisingly complicated task, + /// mostly unsolvable without interacting with system libraries. + /// And since `fontdb` tries to be small and portable, this method + /// will simply scan some predefined directories. + /// Which means that fonts that are not in those directories must + /// be added manually. + #[cfg(feature = "fs")] + pub fn load_system_fonts(&mut self) { + #[cfg(target_os = "windows")] + { + let mut seen = Default::default(); + if let Some(ref system_root) = std::env::var_os("SYSTEMROOT") { + let system_root_path = std::path::Path::new(system_root); + self.load_fonts_dir_impl(&system_root_path.join("Fonts"), &mut seen); + } else { + self.load_fonts_dir_impl("C:\\Windows\\Fonts\\".as_ref(), &mut seen); + } + + if let Ok(ref home) = std::env::var("USERPROFILE") { + let home_path = std::path::Path::new(home); + self.load_fonts_dir_impl( + &home_path.join("AppData\\Local\\Microsoft\\Windows\\Fonts"), + &mut seen, + ); + self.load_fonts_dir_impl( + &home_path.join("AppData\\Roaming\\Microsoft\\Windows\\Fonts"), + &mut seen, + ); + } + } + + #[cfg(target_os = "macos")] + { + let mut seen = Default::default(); + self.load_fonts_dir_impl("/Library/Fonts".as_ref(), &mut seen); + self.load_fonts_dir_impl("/System/Library/Fonts".as_ref(), &mut seen); + // Downloadable fonts, location varies on major macOS releases + if let Ok(dir) = std::fs::read_dir("/System/Library/AssetsV2") { + for entry in dir { + let entry = match entry { + Ok(entry) => entry, + Err(_) => continue, + }; + if entry + .file_name() + .to_string_lossy() + .starts_with("com_apple_MobileAsset_Font") + { + self.load_fonts_dir_impl(&entry.path(), &mut seen); + } + } + } + self.load_fonts_dir_impl("/Network/Library/Fonts".as_ref(), &mut seen); + + if let Ok(ref home) = std::env::var("HOME") { + let home_path = std::path::Path::new(home); + self.load_fonts_dir_impl(&home_path.join("Library/Fonts"), &mut seen); + } + } + + // Redox OS. + #[cfg(target_os = "redox")] + { + let mut seen = Default::default(); + self.load_fonts_dir_impl("/ui/fonts".as_ref(), &mut seen); + } + + // Linux. + #[cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))] + { + #[cfg(feature = "fontconfig")] + { + if !self.load_fontconfig() { + log::warn!("Fallback to loading from known font dir paths."); + self.load_no_fontconfig(); + } + } + + #[cfg(not(feature = "fontconfig"))] + { + self.load_no_fontconfig(); + } + } + } + + + // Linux. + #[cfg(all( + unix, + feature = "fs", + not(any(target_os = "macos", target_os = "android")) + ))] + fn load_no_fontconfig(&mut self) { + let mut seen = Default::default(); + self.load_fonts_dir_impl("/usr/share/fonts/".as_ref(), &mut seen); + self.load_fonts_dir_impl("/usr/local/share/fonts/".as_ref(), &mut seen); + + if let Ok(ref home) = std::env::var("HOME") { + let home_path = std::path::Path::new(home); + self.load_fonts_dir_impl(&home_path.join(".fonts"), &mut seen); + self.load_fonts_dir_impl(&home_path.join(".local/share/fonts"), &mut seen); + } + } + + // Linux. + #[cfg(all( + unix, + feature = "fontconfig", + not(any(target_os = "macos", target_os = "android")) + ))] + fn load_fontconfig(&mut self) -> bool { + use std::path::Path; + + let mut fontconfig = fontconfig_parser::FontConfig::default(); + let home = std::env::var("HOME"); + + if let Ok(ref config_file) = std::env::var("FONTCONFIG_FILE") { + let _ = fontconfig.merge_config(Path::new(config_file)); + } else { + let xdg_config_home = if let Ok(val) = std::env::var("XDG_CONFIG_HOME") { + Some(val.into()) + } else if let Ok(ref home) = home { + // according to https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + // $XDG_CONFIG_HOME should default to $HOME/.config if not set + Some(Path::new(home).join(".config")) + } else { + None + }; + + let read_global = match xdg_config_home { + Some(p) => fontconfig + .merge_config(&p.join("fontconfig/fonts.conf")) + .is_err(), + None => true, + }; + + if read_global { + let _ = fontconfig.merge_config(Path::new("/etc/fonts/local.conf")); + } + let _ = fontconfig.merge_config(Path::new("/etc/fonts/fonts.conf")); + } + + for fontconfig_parser::Alias { + alias, + default, + prefer, + accept, + } in fontconfig.aliases + { + let name = prefer + .get(0) + .or_else(|| accept.get(0)) + .or_else(|| default.get(0)); + + if let Some(name) = name { + match alias.to_lowercase().as_str() { + "serif" => self.set_serif_family(name), + "sans-serif" => self.set_sans_serif_family(name), + "sans serif" => self.set_sans_serif_family(name), + "monospace" => self.set_monospace_family(name), + "cursive" => self.set_cursive_family(name), + "fantasy" => self.set_fantasy_family(name), + _ => {} + } + } + } + + if fontconfig.dirs.is_empty() { + return false; + } + + let mut seen = Default::default(); + for dir in fontconfig.dirs { + let path = if dir.path.starts_with("~") { + if let Ok(ref home) = home { + Path::new(home).join(dir.path.strip_prefix("~").unwrap()) + } else { + continue; + } + } else { + dir.path + }; + self.load_fonts_dir_impl(&path, &mut seen); + } + + true + } + + /// Pushes a user-provided `FaceInfo` to the database. + /// + /// In some cases, a caller might want to ignore the font's metadata and provide their own. + /// This method doesn't parse the `source` font. + /// + /// The `id` field should be set to [`ID::dummy()`] and will be then overwritten by this method. + pub fn push_face_info(&mut self, mut info: FaceInfo) -> ID { + ID(self.faces.insert_with_key(|k| { + info.id = ID(k); + info + })) + } + + /// Removes a font face by `id` from the database. + /// + /// Returns `false` while attempting to remove a non-existing font face. + /// + /// Useful when you want to ignore some specific font face(s) + /// after loading a large directory with fonts. + /// Or a specific face from a font. + pub fn remove_face(&mut self, id: ID) { + self.faces.remove(id.0); + } + + /// Returns `true` if the `Database` contains no font faces. + #[inline] + pub fn is_empty(&self) -> bool { + self.faces.is_empty() + } + + /// Returns the number of font faces in the `Database`. + /// + /// Note that `Database` stores font faces, not fonts. + /// For example, if a caller will try to load a font collection (`*.ttc`) that contains 5 faces, + /// then the `Database` will load 5 font faces and this method will return 5, not 1. + #[inline] + pub fn len(&self) -> usize { + self.faces.len() + } + + /// Sets the family that will be used by `Family::Serif`. + pub fn set_serif_family>(&mut self, family: S) { + self.family_serif = family.into(); + } + + /// Sets the family that will be used by `Family::SansSerif`. + pub fn set_sans_serif_family>(&mut self, family: S) { + self.family_sans_serif = family.into(); + } + + /// Sets the family that will be used by `Family::Cursive`. + pub fn set_cursive_family>(&mut self, family: S) { + self.family_cursive = family.into(); + } + + /// Sets the family that will be used by `Family::Fantasy`. + pub fn set_fantasy_family>(&mut self, family: S) { + self.family_fantasy = family.into(); + } + + /// Sets the family that will be used by `Family::Monospace`. + pub fn set_monospace_family>(&mut self, family: S) { + self.family_monospace = family.into(); + } + + /// Returns the generic family name or the `Family::Name` itself. + /// + /// Generic family names should be set via `Database::set_*_family` methods. + pub fn family_name<'a>(&'a self, family: &'a Family) -> &'a str { + match family { + Family::Name(name) => name, + Family::Serif => self.family_serif.as_str(), + Family::SansSerif => self.family_sans_serif.as_str(), + Family::Cursive => self.family_cursive.as_str(), + Family::Fantasy => self.family_fantasy.as_str(), + Family::Monospace => self.family_monospace.as_str(), + } + } + + /// Performs a CSS-like query and returns the best matched font face. + pub fn query(&self, query: &Query) -> Option { + for family in query.families { + let name = self.family_name(family); + let candidates: Vec<_> = self + .faces + .iter() + .filter(|(_, face)| face.families.iter().any(|family| family.0 == name)) + .map(|(_, info)| info) + .collect(); + + if !candidates.is_empty() { + if let Some(index) = find_best_match(&candidates, query) { + return Some(candidates[index].id); + } + } + } + + None + } + + /// Returns an iterator over the internal storage. + /// + /// This can be used for manual font matching. + #[inline] + pub fn faces(&self) -> impl Iterator + '_ { + self.faces.iter().map(|(_, info)| info) + } + + /// Selects a `FaceInfo` by `id`. + /// + /// Returns `None` if a face with such ID was already removed, + /// or this ID belong to the other `Database`. + pub fn face(&self, id: ID) -> Option<&FaceInfo> { + self.faces.get(id.0) + } + + /// Returns font face storage and the face index by `ID`. + pub fn face_source(&self, id: ID) -> Option<(Source, u32)> { + self.face(id).map(|info| (info.source.clone(), info.index)) + } + + /// Executes a closure with a font's data. + /// + /// We can't return a reference to a font binary data because of lifetimes. + /// So instead, you can use this method to process font's data. + /// + /// The closure accepts raw font data and font face index. + /// + /// In case of `Source::File`, the font file will be memory mapped. + /// + /// Returns `None` when font file loading failed. + /// + /// # Example + /// + /// ```ignore + /// let is_variable = db.with_face_data(id, |font_data, face_index| { + /// let font = ttf_parser::Face::from_slice(font_data, face_index).unwrap(); + /// font.is_variable() + /// })?; + /// ``` + pub fn with_face_data(&self, id: ID, p: P) -> Option + where + P: FnOnce(&[u8], u32) -> T, + { + let (src, face_index) = self.face_source(id)?; + src.with_data(|data| p(data, face_index)) + } + + /// Makes the font data that backs the specified face id shared so that the application can + /// hold a reference to it. + /// + /// # Safety + /// + /// If the face originates from a file from disk, then the file is mapped from disk. This is unsafe as + /// another process may make changes to the file on disk, which may become visible in this process' + /// mapping and possibly cause crashes. + /// + /// If the underlying font provides multiple faces, then all faces are updated to participate in + /// the data sharing. If the face was previously marked for data sharing, then this function will + /// return a clone of the existing reference. + #[cfg(all(feature = "fs", feature = "memmap"))] + pub unsafe fn make_shared_face_data( + &mut self, + id: ID, + ) -> Option<(std::sync::Arc + Send + Sync>, u32)> { + let face_info = self.faces.get(id.0)?; + let face_index = face_info.index; + + let old_source = face_info.source.clone(); + + let (path, shared_data) = match &old_source { + Source::Binary(data) => { + return Some((data.clone(), face_index)); + } + Source::File(ref path) => { + let file = std::fs::File::open(path).ok()?; + let shared_data = std::sync::Arc::new(memmap2::MmapOptions::new().map(&file).ok()?) + as std::sync::Arc + Send + Sync>; + (path.clone(), shared_data) + } + Source::SharedFile(_, data) => { + return Some((data.clone(), face_index)); + } + }; + + let shared_source = Source::SharedFile(path.clone(), shared_data.clone()); + + self.faces.iter_mut().for_each(|(_, face)| { + if matches!(&face.source, Source::File(old_path) if old_path == &path) { + face.source = shared_source.clone(); + } + }); + + Some((shared_data, face_index)) + } + + /// Transfers ownership of shared font data back to the font database. This is the reverse operation + /// of [`Self::make_shared_face_data`]. If the font data belonging to the specified face is mapped + /// from a file on disk, then that mapping is closed and the data becomes private to the process again. + #[cfg(all(feature = "fs", feature = "memmap"))] + pub fn make_face_data_unshared(&mut self, id: ID) { + let face_info = match self.faces.get(id.0) { + Some(face_info) => face_info, + None => return, + }; + + let old_source = face_info.source.clone(); + + let shared_path = match old_source { + #[cfg(all(feature = "fs", feature = "memmap"))] + Source::SharedFile(path, _) => path, + _ => return, + }; + + let new_source = Source::File(shared_path.clone()); + + self.faces.iter_mut().for_each(|(_, face)| { + if matches!(&face.source, Source::SharedFile(path, ..) if path == &shared_path) { + face.source = new_source.clone(); + } + }); + } +} + +/// A single font face info. +/// +/// A font can have multiple faces. +/// +/// A single item of the `Database`. +#[derive(Clone, Debug)] +pub struct FaceInfo { + /// An unique ID. + pub id: ID, + + /// A font source. + /// + /// Note that multiple `FaceInfo` objects can reference the same data in case of + /// font collections, which means that they'll use the same Source. + pub source: Source, + + /// A face index in the `source`. + pub index: u32, + + /// A list of family names. + /// + /// Contains pairs of Name + Language. Where the first family is always English US, + /// unless it's missing from the font. + /// + /// Corresponds to a *Typographic Family* (ID 16) or a *Font Family* (ID 1) [name ID] + /// in a TrueType font. + /// + /// This is not an *Extended Typographic Family* or a *Full Name*. + /// Meaning it will contain _Arial_ and not _Arial Bold_. + /// + /// [name ID]: https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids + pub families: Vec<(String, Language)>, + + /// A PostScript name. + /// + /// Corresponds to a *PostScript name* (6) [name ID] in a TrueType font. + /// + /// [name ID]: https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids + pub post_script_name: String, + + /// A font face style. + pub style: Style, + + /// A font face weight. + pub weight: Weight, + + /// A font face stretch. + pub stretch: Stretch, + + /// Indicates that the font face is monospaced. + pub monospaced: bool, +} + +/// A font source. +/// +/// Either a raw binary data or a file path. +/// +/// Stores the whole font and not just a single face. +#[derive(Clone)] +pub enum Source { + /// A font's raw data, typically backed by a Vec. + Binary(alloc::sync::Arc + Sync + Send>), + + /// A font's path. + #[cfg(feature = "fs")] + File(std::path::PathBuf), + + /// A font's raw data originating from a shared file mapping. + #[cfg(all(feature = "fs", feature = "memmap"))] + SharedFile( + std::path::PathBuf, + std::sync::Arc + Sync + Send>, + ), +} + +impl core::fmt::Debug for Source { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Binary(arg0) => f + .debug_tuple("SharedBinary") + .field(&arg0.as_ref().as_ref()) + .finish(), + #[cfg(feature = "fs")] + Self::File(arg0) => f.debug_tuple("File").field(arg0).finish(), + #[cfg(all(feature = "fs", feature = "memmap"))] + Self::SharedFile(arg0, arg1) => f + .debug_tuple("SharedFile") + .field(arg0) + .field(&arg1.as_ref().as_ref()) + .finish(), + } + } +} + +impl Source { + fn with_data(&self, p: P) -> Option + where + P: FnOnce(&[u8]) -> T, + { + match &self { + #[cfg(all(feature = "fs", not(feature = "memmap")))] + Source::File(ref path) => { + let data = std::fs::read(path).ok()?; + + Some(p(&data)) + } + #[cfg(all(feature = "fs", feature = "memmap"))] + Source::File(ref path) => { + let file = std::fs::File::open(path).ok()?; + let data = unsafe { &memmap2::MmapOptions::new().map(&file).ok()? }; + + Some(p(data)) + } + Source::Binary(ref data) => Some(p(data.as_ref().as_ref())), + #[cfg(all(feature = "fs", feature = "memmap"))] + Source::SharedFile(_, ref data) => Some(p(data.as_ref().as_ref())), + } + } +} + +/// A database query. +/// +/// Mainly used by `Database::query()`. +#[derive(Clone, Copy, Default, Debug, Eq, PartialEq, Hash)] +pub struct Query<'a> { + /// A prioritized list of font family names or generic family names. + /// + /// [font-family](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#propdef-font-family) in CSS. + pub families: &'a [Family<'a>], + + /// Specifies the weight of glyphs in the font, their degree of blackness or stroke thickness. + /// + /// [font-weight](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-weight-prop) in CSS. + pub weight: Weight, + + /// Selects a normal, condensed, or expanded face from a font family. + /// + /// [font-stretch](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-stretch-prop) in CSS. + pub stretch: Stretch, + + /// Allows italic or oblique faces to be selected. + /// + /// [font-style](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-style-prop) in CSS. + pub style: Style, +} + +// Enum value descriptions are from the CSS spec. +/// A [font family](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#propdef-font-family). +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum Family<'a> { + /// The name of a font family of choice. + /// + /// This must be a *Typographic Family* (ID 16) or a *Family Name* (ID 1) in terms of TrueType. + /// Meaning you have to pass a family without any additional suffixes like _Bold_, _Italic_, + /// _Regular_, etc. + /// + /// Localized names are allowed. + Name(&'a str), + + /// Serif fonts represent the formal text style for a script. + Serif, + + /// Glyphs in sans-serif fonts, as the term is used in CSS, are generally low contrast + /// and have stroke endings that are plain — without any flaring, cross stroke, + /// or other ornamentation. + SansSerif, + + /// Glyphs in cursive fonts generally use a more informal script style, + /// and the result looks more like handwritten pen or brush writing than printed letterwork. + Cursive, + + /// Fantasy fonts are primarily decorative or expressive fonts that + /// contain decorative or expressive representations of characters. + Fantasy, + + /// The sole criterion of a monospace font is that all glyphs have the same fixed width. + Monospace, +} + +/// Specifies the weight of glyphs in the font, their degree of blackness or stroke thickness. +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] +pub struct Weight(pub u16); + +impl Default for Weight { + #[inline] + fn default() -> Weight { + Weight::NORMAL + } +} + +impl Weight { + /// Thin weight (100), the thinnest value. + pub const THIN: Weight = Weight(100); + /// Extra light weight (200). + pub const EXTRA_LIGHT: Weight = Weight(200); + /// Light weight (300). + pub const LIGHT: Weight = Weight(300); + /// Normal (400). + pub const NORMAL: Weight = Weight(400); + /// Medium weight (500, higher than normal). + pub const MEDIUM: Weight = Weight(500); + /// Semibold weight (600). + pub const SEMIBOLD: Weight = Weight(600); + /// Bold weight (700). + pub const BOLD: Weight = Weight(700); + /// Extra-bold weight (800). + pub const EXTRA_BOLD: Weight = Weight(800); + /// Black weight (900), the thickest value. + pub const BLACK: Weight = Weight(900); +} + +/// Allows italic or oblique faces to be selected. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum Style { + /// A face that is neither italic not obliqued. + Normal, + /// A form that is generally cursive in nature. + Italic, + /// A typically-sloped version of the regular face. + Oblique, +} + +impl Default for Style { + #[inline] + fn default() -> Style { + Style::Normal + } +} + +fn parse_face_info(source: Source, data: &[u8], index: u32) -> Result { + let raw_face = ttf_parser::RawFace::parse(data, index).map_err(|_| LoadError::MalformedFont)?; + let (families, post_script_name) = parse_names(&raw_face).ok_or(LoadError::UnnamedFont)?; + let (mut style, weight, stretch) = parse_os2(&raw_face); + let (monospaced, italic) = parse_post(&raw_face); + + if style == Style::Normal && italic { + style = Style::Italic; + } + + Ok(FaceInfo { + id: ID::dummy(), + source, + index, + families, + post_script_name, + style, + weight, + stretch, + monospaced, + }) +} + +fn parse_names(raw_face: &ttf_parser::RawFace) -> Option<(Vec<(String, Language)>, String)> { + const NAME_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"name"); + let name_data = raw_face.table(NAME_TAG)?; + let name_table = ttf_parser::name::Table::parse(name_data)?; + + let mut families = collect_families(ttf_parser::name_id::TYPOGRAPHIC_FAMILY, &name_table.names); + + // We have to fallback to Family Name when no Typographic Family Name was set. + if families.is_empty() { + families = collect_families(ttf_parser::name_id::FAMILY, &name_table.names); + } + + // Make English US the first one. + if families.len() > 1 { + if let Some(index) = families + .iter() + .position(|f| f.1 == Language::English_UnitedStates) + { + if index != 0 { + families.swap(0, index); + } + } + } + + if families.is_empty() { + return None; + } + + let post_script_name = name_table + .names + .into_iter() + .find(|name| { + name.name_id == ttf_parser::name_id::POST_SCRIPT_NAME && name.is_supported_encoding() + }) + .and_then(|name| name_to_unicode(&name))?; + + Some((families, post_script_name)) +} + +fn collect_families(name_id: u16, names: &ttf_parser::name::Names) -> Vec<(String, Language)> { + let mut families = Vec::new(); + for name in names.into_iter() { + if name.name_id == name_id && name.is_unicode() { + if let Some(family) = name_to_unicode(&name) { + families.push((family, name.language())); + } + } + } + + // If no Unicode English US family name was found then look for English MacRoman as well. + if !families + .iter() + .any(|f| f.1 == Language::English_UnitedStates) + { + for name in names.into_iter() { + if name.name_id == name_id && name.is_mac_roman() { + if let Some(family) = name_to_unicode(&name) { + families.push((family, name.language())); + break; + } + } + } + } + + families +} + +fn name_to_unicode(name: &ttf_parser::name::Name) -> Option { + if name.is_unicode() { + let mut raw_data: Vec = Vec::new(); + for c in ttf_parser::LazyArray16::::new(name.name) { + raw_data.push(c); + } + + String::from_utf16(&raw_data).ok() + } else if name.is_mac_roman() { + // We support only MacRoman encoding here, which should be enough in most cases. + let mut raw_data = Vec::with_capacity(name.name.len()); + for b in name.name { + raw_data.push(MAC_ROMAN[*b as usize]); + } + + String::from_utf16(&raw_data).ok() + } else { + None + } +} + +fn parse_os2(raw_face: &ttf_parser::RawFace) -> (Style, Weight, Stretch) { + const OS2_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"OS/2"); + let table = match raw_face + .table(OS2_TAG) + .and_then(ttf_parser::os2::Table::parse) + { + Some(table) => table, + None => return (Style::Normal, Weight::NORMAL, Stretch::Normal), + }; + + let style = match table.style() { + ttf_parser::Style::Normal => Style::Normal, + ttf_parser::Style::Italic => Style::Italic, + ttf_parser::Style::Oblique => Style::Oblique, + }; + + let weight = table.weight(); + let stretch = table.width(); + + (style, Weight(weight.to_number()), stretch) +} + +fn parse_post(raw_face: &ttf_parser::RawFace) -> (bool, bool) { + // We need just a single value from the `post` table, while ttf-parser will parse all. + // Therefore we have a custom parser. + + const POST_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"post"); + let data = match raw_face.table(POST_TAG) { + Some(v) => v, + None => return (false, false), + }; + + // All we care about, it that u32 at offset 12 is non-zero. + let monospaced = data.get(12..16) != Some(&[0, 0, 0, 0]); + + // Italic angle as f16.16. + let italic = data.get(4..8) != Some(&[0, 0, 0, 0]); + + (monospaced, italic) +} + +trait NameExt { + fn is_mac_roman(&self) -> bool; + fn is_supported_encoding(&self) -> bool; +} + +impl NameExt for ttf_parser::name::Name<'_> { + #[inline] + fn is_mac_roman(&self) -> bool { + use ttf_parser::PlatformId::Macintosh; + // https://docs.microsoft.com/en-us/typography/opentype/spec/name#macintosh-encoding-ids-script-manager-codes + const MACINTOSH_ROMAN_ENCODING_ID: u16 = 0; + + self.platform_id == Macintosh && self.encoding_id == MACINTOSH_ROMAN_ENCODING_ID + } + + #[inline] + fn is_supported_encoding(&self) -> bool { + self.is_unicode() || self.is_mac_roman() + } +} + +// https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-style-matching +// Based on https://github.com/servo/font-kit +#[inline(never)] +fn find_best_match(candidates: &[&FaceInfo], query: &Query) -> Option { + debug_assert!(!candidates.is_empty()); + + // Step 4. + let mut matching_set: Vec = (0..candidates.len()).collect(); + + // Step 4a (`font-stretch`). + let matches = matching_set + .iter() + .any(|&index| candidates[index].stretch == query.stretch); + let matching_stretch = if matches { + // Exact match. + query.stretch + } else if query.stretch <= Stretch::Normal { + // Closest stretch, first checking narrower values and then wider values. + let stretch = matching_set + .iter() + .filter(|&&index| candidates[index].stretch < query.stretch) + .min_by_key(|&&index| { + query.stretch.to_number() - candidates[index].stretch.to_number() + }); + + match stretch { + Some(&matching_index) => candidates[matching_index].stretch, + None => { + let matching_index = *matching_set.iter().min_by_key(|&&index| { + candidates[index].stretch.to_number() - query.stretch.to_number() + })?; + + candidates[matching_index].stretch + } + } + } else { + // Closest stretch, first checking wider values and then narrower values. + let stretch = matching_set + .iter() + .filter(|&&index| candidates[index].stretch > query.stretch) + .min_by_key(|&&index| { + candidates[index].stretch.to_number() - query.stretch.to_number() + }); + + match stretch { + Some(&matching_index) => candidates[matching_index].stretch, + None => { + let matching_index = *matching_set.iter().min_by_key(|&&index| { + query.stretch.to_number() - candidates[index].stretch.to_number() + })?; + + candidates[matching_index].stretch + } + } + }; + matching_set.retain(|&index| candidates[index].stretch == matching_stretch); + + // Step 4b (`font-style`). + let style_preference = match query.style { + Style::Italic => [Style::Italic, Style::Oblique, Style::Normal], + Style::Oblique => [Style::Oblique, Style::Italic, Style::Normal], + Style::Normal => [Style::Normal, Style::Oblique, Style::Italic], + }; + let matching_style = *style_preference.iter().find(|&query_style| { + matching_set + .iter() + .any(|&index| candidates[index].style == *query_style) + })?; + + matching_set.retain(|&index| candidates[index].style == matching_style); + + // Step 4c (`font-weight`). + // + // The spec doesn't say what to do if the weight is between 400 and 500 exclusive, so we + // just use 450 as the cutoff. + let weight = query.weight.0; + + let matching_weight = if matching_set + .iter() + .any(|&index| candidates[index].weight.0 == weight) + { + Weight(weight) + } else if (400..450).contains(&weight) + && matching_set + .iter() + .any(|&index| candidates[index].weight.0 == 500) + { + // Check 500 first. + Weight::MEDIUM + } else if (450..=500).contains(&weight) + && matching_set + .iter() + .any(|&index| candidates[index].weight.0 == 400) + { + // Check 400 first. + Weight::NORMAL + } else if weight <= 500 { + // Closest weight, first checking thinner values and then fatter ones. + let idx = matching_set + .iter() + .filter(|&&index| candidates[index].weight.0 <= weight) + .min_by_key(|&&index| weight - candidates[index].weight.0); + + match idx { + Some(&matching_index) => candidates[matching_index].weight, + None => { + let matching_index = *matching_set + .iter() + .min_by_key(|&&index| candidates[index].weight.0 - weight)?; + candidates[matching_index].weight + } + } + } else { + // Closest weight, first checking fatter values and then thinner ones. + let idx = matching_set + .iter() + .filter(|&&index| candidates[index].weight.0 >= weight) + .min_by_key(|&&index| candidates[index].weight.0 - weight); + + match idx { + Some(&matching_index) => candidates[matching_index].weight, + None => { + let matching_index = *matching_set + .iter() + .min_by_key(|&&index| weight - candidates[index].weight.0)?; + candidates[matching_index].weight + } + } + }; + matching_set.retain(|&index| candidates[index].weight == matching_weight); + + // Ignore step 4d (`font-size`). + + // Return the result. + matching_set.into_iter().next() +} + +/// Macintosh Roman to UTF-16 encoding table. +/// +/// https://en.wikipedia.org/wiki/Mac_OS_Roman +#[rustfmt::skip] +const MAC_ROMAN: &[u16; 256] = &[ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x2318, 0x21E7, 0x2325, 0x2303, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, + 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, + 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, + 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, + 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, + 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, + 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, + 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, + 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, + 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, + 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, + 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, + 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, + 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, + 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, + 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7, +]; diff --git a/crates/fontdb/tests/add_fonts.rs b/crates/fontdb/tests/add_fonts.rs new file mode 100644 index 000000000..e9c561a47 --- /dev/null +++ b/crates/fontdb/tests/add_fonts.rs @@ -0,0 +1,15 @@ +const DEMO_TTF: &[u8] = include_bytes!("./fonts/Tuffy.ttf"); +use std::sync::Arc; + +#[test] +fn add_fonts_and_get_ids_back() { + env_logger::init(); + let mut font_db = fontdb::Database::new(); + let ids = font_db.load_font_source(fontdb::Source::Binary(Arc::new(DEMO_TTF))); + + assert_eq!(ids.len(), 1); + let id = ids[0]; + + let font = font_db.face(id).unwrap(); + assert!(font.families.iter().any(|(name, _)| name == "Tuffy")); +} diff --git a/crates/fontdb/tests/fonts/LICENSE.txt b/crates/fontdb/tests/fonts/LICENSE.txt new file mode 100644 index 000000000..defced0c0 --- /dev/null +++ b/crates/fontdb/tests/fonts/LICENSE.txt @@ -0,0 +1,11 @@ +We, the copyright holders of this work, hereby release it into the +public domain. This applies worldwide. + +In case this is not legally possible, + +We grant any entity the right to use this work for any purpose, without +any conditions, unless such conditions are required by law. + +Thatcher Ulrich http://tulrich.com +Karoly Barta bartakarcsi@gmail.com +Michael Evans http://www.evertype.com diff --git a/crates/fontdb/tests/fonts/Tuffy.ttf b/crates/fontdb/tests/fonts/Tuffy.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ade553a60fd1b01e16a00a8ef5ea396541245d37 GIT binary patch literal 172324 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

-!d7L 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 Mp!?<=~~)z#T^vVXvA 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 Date: Mon, 12 Jan 2026 10:16:26 +0100 Subject: [PATCH 3/8] Port fontdb from ttf-parser to skrifa This eliminates the ttf-parser dependency by modifying the vendored fontdb to use skrifa for font parsing. Key changes: - Replace ttf_parser::fonts_in_collection with FileRef::new().len() - Replace ttf_parser::RawFace with FontRef::from_index() - Replace ttf_parser name table parsing with font.localized_strings() - Replace OS/2 table parsing with font.attributes() - Replace post table parsing with font.metrics() and font.post() - Add local Language enum (simplified: EnglishUnitedStates + Unknown) - Add local Stretch enum with to_number() for CSS matching - Add stretch_from_skrifa() for skrifa::attribute::Stretch conversion - Update usvg to use vendored fontdb via path dependency - Update Rust 2024 edition patterns (remove redundant ref bindings) The MAC_ROMAN encoding table is removed as skrifa handles all name table encodings internally via LocalizedString::chars(). Co-Authored-By: Claude Opus 4.5 --- .github/copyright.sh | 3 +- Cargo.lock | 123 +++----- crates/fontdb/Cargo.toml | 44 ++- crates/fontdb/src/lib.rs | 464 +++++++++++++++---------------- crates/fontdb/tests/add_fonts.rs | 5 +- crates/usvg/Cargo.toml | 2 +- crates/usvg/src/text/mod.rs | 4 +- 7 files changed, 290 insertions(+), 355 deletions(-) diff --git a/.github/copyright.sh b/.github/copyright.sh index b2d899024..7bfc8d7cf 100644 --- a/.github/copyright.sh +++ b/.github/copyright.sh @@ -7,7 +7,8 @@ # -g "!src/special_directory" # Check all the standard Rust source files -output=$(rg "^// Copyright (19|20)[\d]{2} (.+ and )?the Resvg Authors( and .+)?$\n^// SPDX-License-Identifier: Apache-2\.0 OR MIT$\n\n" --files-without-match --multiline -g "*.{rs,c,cpp,h}" .) +# Exclude vendored fontdb (has its own copyright from original author) +output=$(rg "^// Copyright (19|20)[\d]{2} (.+ and )?the Resvg Authors( and .+)?$\n^// SPDX-License-Identifier: Apache-2\.0 OR MIT$\n\n" --files-without-match --multiline -g "*.{rs,c,cpp,h}" -g "!crates/fontdb/*" .) if [ -n "$output" ]; then echo -e "The following files lack the correct copyright header:\n" diff --git a/Cargo.lock b/Cargo.lock index 9b59622c1..cc1d31052 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "arrayref" @@ -26,14 +26,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.0", ] [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" @@ -81,9 +81,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cloudabi" @@ -119,43 +119,24 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "data-url" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "either" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" - -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", -] - -[[package]] -name = "env_logger" -version = "0.11.8" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" -dependencies = [ - "env_filter", - "log", -] +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "euclid" @@ -177,9 +158,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -202,9 +183,9 @@ dependencies = [ [[package]] name = "fontconfig-parser" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" dependencies = [ "roxmltree 0.20.0", ] @@ -212,28 +193,13 @@ dependencies = [ [[package]] name = "fontdb" version = "0.23.0" -dependencies = [ - "env_logger", - "fontconfig-parser", - "log", - "memmap2", - "slotmap", - "tinyvec", - "ttf-parser", -] - -[[package]] -name = "fontdb" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" dependencies = [ "fontconfig-parser", "log", "memmap2", + "skrifa", "slotmap", "tinyvec", - "ttf-parser", ] [[package]] @@ -303,21 +269,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.170" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "log" -version = "0.4.26" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" @@ -327,18 +293,18 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -350,7 +316,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.4.0", + "autocfg 1.5.0", ] [[package]] @@ -597,9 +563,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" dependencies = [ "bytemuck", ] @@ -621,9 +587,9 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simplecss" @@ -658,9 +624,9 @@ dependencies = [ [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -729,9 +695,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -742,15 +708,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "ttf-parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" -dependencies = [ - "core_maths", -] - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -765,9 +722,9 @@ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-script" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-vo" @@ -782,7 +739,7 @@ dependencies = [ "base64", "data-url", "flate2", - "fontdb 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fontdb", "harfrust", "imagesize", "kurbo", diff --git a/crates/fontdb/Cargo.toml b/crates/fontdb/Cargo.toml index 29ad19ee8..cbe2ba786 100644 --- a/crates/fontdb/Cargo.toml +++ b/crates/fontdb/Cargo.toml @@ -2,37 +2,33 @@ name = "fontdb" version = "0.23.0" authors = ["Yevhenii Reizner "] -edition = "2021" -description = "A simple, in-memory font database with CSS-like queries." -documentation = "https://docs.rs/fontdb/" -repository = "https://github.com/RazrFalcon/fontdb" +edition = "2024" +rust-version = "1.87.0" license = "MIT" -keywords = ["font", "db", "css", "truetype", "ttf"] +description = "A simple, in-memory font database with CSS-like queries. Vendored for resvg with skrifa backend." +repository = "https://github.com/linebender/resvg" +documentation = "https://docs.rs/fontdb/" +keywords = ["font", "db", "css", "truetype", "opentype"] categories = ["text-processing"] [dependencies] +slotmap = "1.0" +tinyvec = { version = "1.8", features = ["alloc"] } +skrifa = "0.40" log = "0.4" -memmap2 = { version = "0.9", optional = true } -slotmap = { version = "1.0.6", default-features = false } -tinyvec = { version = "1.6.0", features = ["alloc"] } -[dependencies.ttf-parser] -version = "0.25" -default-features = false -features = ["opentype-layout", "apple-layout", "variable-fonts", "glyph-names"] - -[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies] -fontconfig-parser = { version = "0.5", optional = true, default-features = false } - -[dev-dependencies] -env_logger = { version = "0.11", default-features = false } +memmap2 = { version = "0.9", optional = true } +fontconfig-parser = { version = "0.5.8", optional = true } [features] -default = ["std", "fs", "memmap", "fontconfig"] -std = ["ttf-parser/std"] -# Allows local filesystem interactions. +default = ["std", "fs", "system-fonts", "memmap"] +# Enables standard library support (always on for this vendored version). +std = [] +# Enables file system operations (loading fonts from files/directories). fs = ["std"] -# Allows font files memory mapping, greatly improves performance. +# Enables system fonts loading. +system-fonts = ["fs", "fontconfig"] +# Enables fontconfig support on Linux. +fontconfig = ["fontconfig-parser"] +# Enables font files memory mapping for faster loading. memmap = ["fs", "memmap2"] -# Enables minimal fontconfig support on Linux. -fontconfig = ["fontconfig-parser", "fs"] diff --git a/crates/fontdb/src/lib.rs b/crates/fontdb/src/lib.rs index 6a788decb..f88b764ab 100644 --- a/crates/fontdb/src/lib.rs +++ b/crates/fontdb/src/lib.rs @@ -1,79 +1,163 @@ -/*! -`fontdb` is a simple, in-memory font database with CSS-like queries. +// Copyright 2020 Yevhenii Reizner (original fontdb, MIT licensed) +// Copyright 2026 the Resvg Authors (modifications) +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! Vendored and modified version of fontdb 0.23.0 that uses skrifa instead of ttf-parser. +//! +//! Original: (MIT licensed) +//! +//! # Features +//! +//! - The database can load fonts from files, directories and raw data (`Vec`). +//! - The database can match a font using CSS-like queries. See `Database::query`. +//! - The database can try to load system fonts. +//! Currently, this is implemented by scanning predefined directories. +//! The library does not interact with the system API. +//! - Provides a unique ID for each font face. +//! +//! # Font vs Face +//! +//! A font is a collection of font faces. Therefore, a font face is a subset of a font. +//! A simple font (*.ttf/*.otf) usually contains a single font face, +//! but a font collection (*.ttc) can contain multiple font faces. +//! +//! `fontdb` stores and matches font faces, not fonts. +//! Therefore, after loading a font collection with 5 faces (for example), the database will be populated +//! with 5 `FaceInfo` objects, all of which will be pointing to the same file or binary data. +//! +//! # Performance +//! +//! The database performance is largely limited by the storage itself. +//! Font parsing is handled by skrifa. +//! +//! # Safety +//! +//! The library relies on memory-mapped files, which is inherently unsafe. +//! But since we do not keep the files open it should be perfectly safe. +//! +//! If you would like to use a persistent memory mapping of the font files, +//! then you can use the unsafe [`Database::make_shared_face_data`] function. + +// Allow unsafe code for mmap operations (from original fontdb) +#![allow(unsafe_code)] +#![deny(missing_docs)] -# Features - -- The database can load fonts from files, directories and raw data (`Vec`). -- The database can match a font using CSS-like queries. See `Database::query`. -- The database can try to load system fonts. - Currently, this is implemented by scanning predefined directories. - The library does not interact with the system API. -- Provides a unique ID for each font face. - -# Non-goals - -- Advanced font properties querying.
- The database provides only storage and matching capabilities. - For font properties querying you can use [ttf-parser]. - -- A font fallback mechanism.
- This library can be used to implement a font fallback mechanism, but it doesn't implement one. - -- Application's global database.
- The database doesn't use `static`, therefore it's up to the caller where it should be stored. - -- Font types support other than TrueType. - -# Font vs Face - -A font is a collection of font faces. Therefore, a font face is a subset of a font. -A simple font (\*.ttf/\*.otf) usually contains a single font face, -but a font collection (\*.ttc) can contain multiple font faces. - -`fontdb` stores and matches font faces, not fonts. -Therefore, after loading a font collection with 5 faces (for example), the database will be populated -with 5 `FaceInfo` objects, all of which will be pointing to the same file or binary data. - -# Performance - -The database performance is largely limited by the storage itself. -We are using [ttf-parser], so the parsing should not be a bottleneck. - -On my machine with Samsung SSD 860 and Gentoo Linux, it takes ~20ms -to load 1906 font faces (most of them are from Google Noto collection) -with a hot disk cache and ~860ms with a cold one. - -On Mac Mini M1 it takes just 9ms to load 898 fonts. +use slotmap::SlotMap; +use tinyvec::TinyVec; -# Safety +use skrifa::{FontRef, MetadataProvider, raw::FileRef, raw::TableProvider, string::StringId}; -The library relies on memory-mapped files, which is inherently unsafe. -But since we do not keep the files open it should be perfectly safe. +/// A font face language. +/// +/// Simplified version - we only need to distinguish English US for family name prioritization. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)] +pub enum Language { + /// English (United States) + EnglishUnitedStates, + /// Any other language + #[default] + Unknown, +} -If you would like to use a persistent memory mapping of the font files, -then you can use the unsafe [`Database::make_shared_face_data`] function. +impl Language { + /// Returns the primary language tag. + pub fn primary_language(&self) -> &'static str { + match self { + Language::EnglishUnitedStates => "en", + Language::Unknown => "und", + } + } -[ttf-parser]: https://github.com/RazrFalcon/ttf-parser -*/ + /// Returns the region tag. + pub fn region(&self) -> &'static str { + match self { + Language::EnglishUnitedStates => "US", + Language::Unknown => "", + } + } +} -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] -#![warn(missing_debug_implementations)] -#![warn(missing_copy_implementations)] +/// Convert from BCP-47 language tag to our Language enum +fn language_from_bcp47(tag: Option<&str>) -> Language { + match tag { + Some(t) if t.starts_with("en-US") || t == "en" => Language::EnglishUnitedStates, + _ => Language::Unknown, + } +} -extern crate alloc; +/// Selects a normal, condensed, or expanded face from a font family. +#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Hash, Default)] +pub enum Stretch { + /// 50% + UltraCondensed, + /// 62.5% + ExtraCondensed, + /// 75% + Condensed, + /// 87.5% + SemiCondensed, + /// 100% + #[default] + Normal, + /// 112.5% + SemiExpanded, + /// 125% + Expanded, + /// 150% + ExtraExpanded, + /// 200% + UltraExpanded, +} -#[cfg(not(feature = "std"))] -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; +impl Stretch { + /// Convert to a numeric value for CSS matching calculations. + fn to_number(self) -> i32 { + match self { + Stretch::UltraCondensed => 1, + Stretch::ExtraCondensed => 2, + Stretch::Condensed => 3, + Stretch::SemiCondensed => 4, + Stretch::Normal => 5, + Stretch::SemiExpanded => 6, + Stretch::Expanded => 7, + Stretch::ExtraExpanded => 8, + Stretch::UltraExpanded => 9, + } + } +} -pub use ttf_parser::Language; -pub use ttf_parser::Width as Stretch; +/// Convert from skrifa's Stretch percentage to our Stretch enum +fn stretch_from_skrifa(s: skrifa::attribute::Stretch) -> Stretch { + let pct = s.percentage(); + if pct <= 56.25 { + Stretch::UltraCondensed + } else if pct <= 68.75 { + Stretch::ExtraCondensed + } else if pct <= 81.25 { + Stretch::Condensed + } else if pct <= 93.75 { + Stretch::SemiCondensed + } else if pct <= 106.25 { + Stretch::Normal + } else if pct <= 118.75 { + Stretch::SemiExpanded + } else if pct <= 137.5 { + Stretch::Expanded + } else if pct <= 175.0 { + Stretch::ExtraExpanded + } else { + Stretch::UltraExpanded + } +} -use slotmap::SlotMap; -use tinyvec::TinyVec; +/// Get the number of fonts in a font collection (TTC), or 1 for single fonts +fn fonts_in_collection(data: &[u8]) -> u32 { + match FileRef::new(data) { + Ok(FileRef::Collection(c)) => c.len(), + Ok(FileRef::Font(_)) => 1, + Err(_) => 1, + } +} /// A unique per database face ID. /// @@ -118,8 +202,7 @@ impl core::fmt::Display for ID { enum LoadError { /// A malformed font. /// - /// Typically means that [ttf-parser](https://github.com/RazrFalcon/ttf-parser) - /// wasn't able to parse it. + /// Typically means that skrifa wasn't able to parse it. MalformedFont, /// A valid TrueType font without a valid *Family Name*. UnnamedFont, @@ -142,7 +225,7 @@ impl core::fmt::Display for LoadError { LoadError::MalformedFont => write!(f, "malformed font"), LoadError::UnnamedFont => write!(f, "font doesn't have a family name"), #[cfg(feature = "std")] - LoadError::IoError(ref e) => write!(f, "{}", e), + LoadError::IoError(e) => write!(f, "{}", e), } } } @@ -193,7 +276,7 @@ impl Database { /// /// Will load all font faces in case of a font collection. pub fn load_font_data(&mut self, data: Vec) { - self.load_font_source(Source::Binary(alloc::sync::Arc::new(data))); + self.load_font_source(Source::Binary(std::sync::Arc::new(data))); } /// Loads a font from the given source into the `Database` and returns @@ -202,7 +285,7 @@ impl Database { /// Will load all font faces in case of a font collection. pub fn load_font_source(&mut self, source: Source) -> TinyVec<[ID; 8]> { let ids = source.with_data(|data| { - let n = ttf_parser::fonts_in_collection(data).unwrap_or(1); + let n = fonts_in_collection(data); let mut ids = TinyVec::with_capacity(n as usize); for index in 0..n { @@ -233,7 +316,7 @@ impl Database { fn load_fonts_from_file(&mut self, path: &std::path::Path, data: &[u8]) { let source = Source::File(path.into()); - let n = ttf_parser::fonts_in_collection(data).unwrap_or(1); + let n = fonts_in_collection(data); for index in 0..n { match parse_face_info(source.clone(), data, index) { Ok(info) => { @@ -475,7 +558,6 @@ impl Database { } } - // Linux. #[cfg(all( unix, @@ -752,10 +834,12 @@ impl Database { Source::Binary(data) => { return Some((data.clone(), face_index)); } - Source::File(ref path) => { + Source::File(path) => { let file = std::fs::File::open(path).ok()?; - let shared_data = std::sync::Arc::new(memmap2::MmapOptions::new().map(&file).ok()?) - as std::sync::Arc + Send + Sync>; + // SAFETY: We immediately copy data out, not keeping the mmap alive + let shared_data = + std::sync::Arc::new(unsafe { memmap2::MmapOptions::new().map(&file).ok()? }) + as std::sync::Arc + Send + Sync>; (path.clone(), shared_data) } Source::SharedFile(_, data) => { @@ -863,7 +947,7 @@ pub struct FaceInfo { #[derive(Clone)] pub enum Source { /// A font's raw data, typically backed by a Vec. - Binary(alloc::sync::Arc + Sync + Send>), + Binary(std::sync::Arc + Sync + Send>), /// A font's path. #[cfg(feature = "fs")] @@ -903,21 +987,22 @@ impl Source { { match &self { #[cfg(all(feature = "fs", not(feature = "memmap")))] - Source::File(ref path) => { + Source::File(path) => { let data = std::fs::read(path).ok()?; Some(p(&data)) } #[cfg(all(feature = "fs", feature = "memmap"))] - Source::File(ref path) => { + Source::File(path) => { let file = std::fs::File::open(path).ok()?; - let data = unsafe { &memmap2::MmapOptions::new().map(&file).ok()? }; + // SAFETY: Memory mapping is valid for the duration of this function call + let data = unsafe { memmap2::MmapOptions::new().map(&file).ok()? }; - Some(p(data)) + Some(p(&data)) } - Source::Binary(ref data) => Some(p(data.as_ref().as_ref())), + Source::Binary(data) => Some(p(data.as_ref().as_ref())), #[cfg(all(feature = "fs", feature = "memmap"))] - Source::SharedFile(_, ref data) => Some(p(data.as_ref().as_ref())), + Source::SharedFile(_, data) => Some(p(data.as_ref().as_ref())), } } } @@ -1032,10 +1117,10 @@ impl Default for Style { } fn parse_face_info(source: Source, data: &[u8], index: u32) -> Result { - let raw_face = ttf_parser::RawFace::parse(data, index).map_err(|_| LoadError::MalformedFont)?; - let (families, post_script_name) = parse_names(&raw_face).ok_or(LoadError::UnnamedFont)?; - let (mut style, weight, stretch) = parse_os2(&raw_face); - let (monospaced, italic) = parse_post(&raw_face); + let font = FontRef::from_index(data, index).map_err(|_| LoadError::MalformedFont)?; + let (families, post_script_name) = parse_names(&font).ok_or(LoadError::UnnamedFont)?; + let (mut style, weight, stretch) = parse_os2(&font); + let (monospaced, italic) = parse_post(&font); if style == Style::Normal && italic { style = Style::Italic; @@ -1054,23 +1139,34 @@ fn parse_face_info(source: Source, data: &[u8], index: u32) -> Result Option<(Vec<(String, Language)>, String)> { - const NAME_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"name"); - let name_data = raw_face.table(NAME_TAG)?; - let name_table = ttf_parser::name::Table::parse(name_data)?; +fn parse_names(font: &FontRef) -> Option<(Vec<(String, Language)>, String)> { + let mut families = Vec::new(); - let mut families = collect_families(ttf_parser::name_id::TYPOGRAPHIC_FAMILY, &name_table.names); + // Try Typographic Family (ID 16) first + for s in font.localized_strings(StringId::TYPOGRAPHIC_FAMILY_NAME) { + let lang = language_from_bcp47(s.language()); + let name: String = s.chars().collect(); + if !name.is_empty() { + families.push((name, lang)); + } + } - // We have to fallback to Family Name when no Typographic Family Name was set. + // Fallback to Family Name (ID 1) if families.is_empty() { - families = collect_families(ttf_parser::name_id::FAMILY, &name_table.names); + for s in font.localized_strings(StringId::FAMILY_NAME) { + let lang = language_from_bcp47(s.language()); + let name: String = s.chars().collect(); + if !name.is_empty() { + families.push((name, lang)); + } + } } - // Make English US the first one. + // Make English US the first one if families.len() > 1 { if let Some(index) = families .iter() - .position(|f| f.1 == Language::English_UnitedStates) + .position(|f| f.1 == Language::EnglishUnitedStates) { if index != 0 { families.swap(0, index); @@ -1082,128 +1178,49 @@ fn parse_names(raw_face: &ttf_parser::RawFace) -> Option<(Vec<(String, Language) return None; } - let post_script_name = name_table - .names - .into_iter() - .find(|name| { - name.name_id == ttf_parser::name_id::POST_SCRIPT_NAME && name.is_supported_encoding() - }) - .and_then(|name| name_to_unicode(&name))?; + // Get PostScript name + let post_script_name = font + .localized_strings(StringId::POSTSCRIPT_NAME) + .next() + .map(|s| s.chars().collect::()) + .unwrap_or_default(); Some((families, post_script_name)) } -fn collect_families(name_id: u16, names: &ttf_parser::name::Names) -> Vec<(String, Language)> { - let mut families = Vec::new(); - for name in names.into_iter() { - if name.name_id == name_id && name.is_unicode() { - if let Some(family) = name_to_unicode(&name) { - families.push((family, name.language())); - } - } - } - - // If no Unicode English US family name was found then look for English MacRoman as well. - if !families - .iter() - .any(|f| f.1 == Language::English_UnitedStates) - { - for name in names.into_iter() { - if name.name_id == name_id && name.is_mac_roman() { - if let Some(family) = name_to_unicode(&name) { - families.push((family, name.language())); - break; - } - } - } - } - - families -} - -fn name_to_unicode(name: &ttf_parser::name::Name) -> Option { - if name.is_unicode() { - let mut raw_data: Vec = Vec::new(); - for c in ttf_parser::LazyArray16::::new(name.name) { - raw_data.push(c); - } +fn parse_os2(font: &FontRef) -> (Style, Weight, Stretch) { + let attrs = font.attributes(); - String::from_utf16(&raw_data).ok() - } else if name.is_mac_roman() { - // We support only MacRoman encoding here, which should be enough in most cases. - let mut raw_data = Vec::with_capacity(name.name.len()); - for b in name.name { - raw_data.push(MAC_ROMAN[*b as usize]); - } - - String::from_utf16(&raw_data).ok() - } else { - None - } -} - -fn parse_os2(raw_face: &ttf_parser::RawFace) -> (Style, Weight, Stretch) { - const OS2_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"OS/2"); - let table = match raw_face - .table(OS2_TAG) - .and_then(ttf_parser::os2::Table::parse) - { - Some(table) => table, - None => return (Style::Normal, Weight::NORMAL, Stretch::Normal), + let style = match attrs.style { + skrifa::attribute::Style::Normal => Style::Normal, + skrifa::attribute::Style::Italic => Style::Italic, + skrifa::attribute::Style::Oblique(_) => Style::Oblique, }; - let style = match table.style() { - ttf_parser::Style::Normal => Style::Normal, - ttf_parser::Style::Italic => Style::Italic, - ttf_parser::Style::Oblique => Style::Oblique, - }; - - let weight = table.weight(); - let stretch = table.width(); + let weight = Weight(attrs.weight.value() as u16); + let stretch = stretch_from_skrifa(attrs.stretch); - (style, Weight(weight.to_number()), stretch) + (style, weight, stretch) } -fn parse_post(raw_face: &ttf_parser::RawFace) -> (bool, bool) { - // We need just a single value from the `post` table, while ttf-parser will parse all. - // Therefore we have a custom parser. - - const POST_TAG: ttf_parser::Tag = ttf_parser::Tag::from_bytes(b"post"); - let data = match raw_face.table(POST_TAG) { - Some(v) => v, - None => return (false, false), - }; - - // All we care about, it that u32 at offset 12 is non-zero. - let monospaced = data.get(12..16) != Some(&[0, 0, 0, 0]); - - // Italic angle as f16.16. - let italic = data.get(4..8) != Some(&[0, 0, 0, 0]); +fn parse_post(font: &FontRef) -> (bool, bool) { + // Check if monospaced using skrifa's metrics + let monospaced = font + .metrics( + skrifa::instance::Size::unscaled(), + skrifa::instance::LocationRef::default(), + ) + .is_monospace; + + // Check italic angle from post table + let italic = font + .post() + .map(|post| post.italic_angle().to_f64() != 0.0) + .unwrap_or(false); (monospaced, italic) } -trait NameExt { - fn is_mac_roman(&self) -> bool; - fn is_supported_encoding(&self) -> bool; -} - -impl NameExt for ttf_parser::name::Name<'_> { - #[inline] - fn is_mac_roman(&self) -> bool { - use ttf_parser::PlatformId::Macintosh; - // https://docs.microsoft.com/en-us/typography/opentype/spec/name#macintosh-encoding-ids-script-manager-codes - const MACINTOSH_ROMAN_ENCODING_ID: u16 = 0; - - self.platform_id == Macintosh && self.encoding_id == MACINTOSH_ROMAN_ENCODING_ID - } - - #[inline] - fn is_supported_encoding(&self) -> bool { - self.is_unicode() || self.is_mac_roman() - } -} - // https://www.w3.org/TR/2018/REC-css-fonts-3-20180920/#font-style-matching // Based on https://github.com/servo/font-kit #[inline(never)] @@ -1340,42 +1357,3 @@ fn find_best_match(candidates: &[&FaceInfo], query: &Query) -> Option { // Return the result. matching_set.into_iter().next() } - -/// Macintosh Roman to UTF-16 encoding table. -/// -/// https://en.wikipedia.org/wiki/Mac_OS_Roman -#[rustfmt::skip] -const MAC_ROMAN: &[u16; 256] = &[ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, - 0x0010, 0x2318, 0x21E7, 0x2325, 0x2303, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, - 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, - 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, - 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, - 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, - 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, - 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, - 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, - 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, - 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, - 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, - 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, - 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, - 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, - 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, - 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, - 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7, -]; diff --git a/crates/fontdb/tests/add_fonts.rs b/crates/fontdb/tests/add_fonts.rs index e9c561a47..0373f856a 100644 --- a/crates/fontdb/tests/add_fonts.rs +++ b/crates/fontdb/tests/add_fonts.rs @@ -1,9 +1,12 @@ +// Copyright 2020 Yevhenii Reizner (original fontdb, MIT licensed) +// Copyright 2026 the Resvg Authors (modifications) +// SPDX-License-Identifier: Apache-2.0 OR MIT + const DEMO_TTF: &[u8] = include_bytes!("./fonts/Tuffy.ttf"); use std::sync::Arc; #[test] fn add_fonts_and_get_ids_back() { - env_logger::init(); let mut font_db = fontdb::Database::new(); let ids = font_db.load_font_source(fontdb::Source::Binary(Arc::new(DEMO_TTF))); diff --git a/crates/usvg/Cargo.toml b/crates/usvg/Cargo.toml index 66dec3457..5c64c301c 100644 --- a/crates/usvg/Cargo.toml +++ b/crates/usvg/Cargo.toml @@ -36,7 +36,7 @@ simplecss = "0.2" siphasher = "1.0" # perfect hash implementation # text -fontdb = { version = "0.23.0", default-features = false, optional = true } +fontdb = { path = "../fontdb", default-features = false, optional = true } harfrust = { version = "0.5", optional = true } unicode-bidi = { version = "0.3", optional = true } unicode-script = { version = "0.5", optional = true } diff --git a/crates/usvg/src/text/mod.rs b/crates/usvg/src/text/mod.rs index d41115957..15829c69f 100644 --- a/crates/usvg/src/text/mod.rs +++ b/crates/usvg/src/text/mod.rs @@ -174,13 +174,13 @@ impl FontResolver<'_> { let base_family = base_face .families .iter() - .find(|f| f.1 == fontdb::Language::English_UnitedStates) + .find(|f| f.1 == fontdb::Language::EnglishUnitedStates) .unwrap_or(&base_face.families[0]); let new_family = face .families .iter() - .find(|f| f.1 == fontdb::Language::English_UnitedStates) + .find(|f| f.1 == fontdb::Language::EnglishUnitedStates) .unwrap_or(&base_face.families[0]); log::warn!("Fallback from {} to {}.", base_family.0, new_family.0); From 6f556f9d1c62bec7bb12bc9261ba7c3c59ef71aa Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 14:13:14 +0100 Subject: [PATCH 4/8] Apply Rust best practices fixes - Fix incorrect safety comment on mmap (fontdb) - Replace deprecated core::u64::MAX with u64::MAX (fontdb) - Use .first() instead of .get(0) (fontdb) - Fix potential panics on empty slices in font fallback (usvg/text/mod.rs) - Add empty path check in path_length() (usvg/parser/text.rs) - Add ASCII validation for font variation tags (usvg/parser/text.rs) - Use idiomatic .or() instead of .map_or() (usvg/parser/text.rs) - Return &TextFlow instead of clone in text_flow() (usvg/tree/text.rs) - Add logging for checked_sub failure (usvg/text/layout.rs) Co-Authored-By: Claude Opus 4.5 --- crates/fontdb/src/lib.rs | 12 +++++++----- crates/usvg/src/parser/text.rs | 20 +++++++++++++------- crates/usvg/src/text/layout.rs | 5 ++++- crates/usvg/src/text/mod.rs | 6 +++--- crates/usvg/src/tree/text.rs | 4 ++-- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/fontdb/src/lib.rs b/crates/fontdb/src/lib.rs index f88b764ab..837c99d74 100644 --- a/crates/fontdb/src/lib.rs +++ b/crates/fontdb/src/lib.rs @@ -187,7 +187,7 @@ impl ID { /// Should be used in tandem with [`Database::push_face_info`]. #[inline] pub fn dummy() -> Self { - Self(InnerId::from(slotmap::KeyData::from_ffi(core::u64::MAX))) + Self(InnerId::from(slotmap::KeyData::from_ffi(u64::MAX))) } } @@ -622,9 +622,9 @@ impl Database { } in fontconfig.aliases { let name = prefer - .get(0) - .or_else(|| accept.get(0)) - .or_else(|| default.get(0)); + .first() + .or_else(|| accept.first()) + .or_else(|| default.first()); if let Some(name) = name { match alias.to_lowercase().as_str() { @@ -836,7 +836,9 @@ impl Database { } Source::File(path) => { let file = std::fs::File::open(path).ok()?; - // SAFETY: We immediately copy data out, not keeping the mmap alive + // SAFETY: The mmap is kept alive through Arc sharing. While another process + // could modify the underlying file (which is why this function is marked unsafe), + // the mapping remains valid for the lifetime of the Arc. let shared_data = std::sync::Arc::new(unsafe { memmap2::MmapOptions::new().map(&file).ok()? }) as std::sync::Arc + Send + Sync>; diff --git a/crates/usvg/src/parser/text.rs b/crates/usvg/src/parser/text.rs index 2be4d1526..233491dd8 100644 --- a/crates/usvg/src/parser/text.rs +++ b/crates/usvg/src/parser/text.rs @@ -574,10 +574,10 @@ fn parse_font_variation_settings(node: SvgNode) -> Vec { tag_str.push(c); } - // Tag must be exactly 4 characters - if tag_str.len() != 4 { + // Tag must be exactly 4 ASCII characters + if tag_str.len() != 4 || !tag_str.is_ascii() { log::warn!( - "Invalid font-variation-settings tag: '{}' (must be 4 characters)", + "Invalid font-variation-settings tag: '{}' (must be 4 ASCII characters)", tag_str ); continue; @@ -601,6 +601,7 @@ fn parse_font_variation_settings(node: SvgNode) -> Vec { }; let tag_bytes = tag_str.as_bytes(); + // SAFETY: We verified above that tag_str is exactly 4 ASCII bytes let tag = [tag_bytes[0], tag_bytes[1], tag_bytes[2], tag_bytes[3]]; variations.push(FontVariation::new(tag, value)); @@ -853,8 +854,8 @@ fn resolve_decoration( for node in tspan.ancestors() { if find_decoration(node, text_decoration) || node.tag_name() == Some(EId::Text) { - fill_node = fill_node.map_or(Some(node), Some); - stroke_node = stroke_node.map_or(Some(node), Some); + fill_node = fill_node.or(Some(node)); + stroke_node = stroke_node.or(Some(node)); break; } } @@ -956,8 +957,13 @@ fn convert_writing_mode(text_node: SvgNode) -> WritingMode { } fn path_length(path: &tiny_skia_path::Path) -> f64 { - let mut prev_mx = path.points()[0].x; - let mut prev_my = path.points()[0].y; + let points = path.points(); + if points.is_empty() { + return 0.0; + } + + let mut prev_mx = points[0].x; + let mut prev_my = points[0].y; let mut prev_x = prev_mx; let mut prev_y = prev_my; diff --git a/crates/usvg/src/text/layout.rs b/crates/usvg/src/text/layout.rs index 2aa4ce5b5..d2a1a8324 100644 --- a/crates/usvg/src/text/layout.rs +++ b/crates/usvg/src/text/layout.rs @@ -1516,7 +1516,10 @@ fn shape_text_with_font( glyphs.push(Glyph { byte_idx: ByteIndex::new(idx), - cluster_len: end.checked_sub(start).unwrap_or(0), // TODO: can fail? + cluster_len: end.checked_sub(start).unwrap_or_else(|| { + log::warn!("Invalid cluster bounds: end={} < start={}", end, start); + 0 + }), text: sub_text[start..end].to_string(), id: GlyphId::new(info.glyph_id as u32), dx: pos.x_offset, diff --git a/crates/usvg/src/text/mod.rs b/crates/usvg/src/text/mod.rs index 15829c69f..151920575 100644 --- a/crates/usvg/src/text/mod.rs +++ b/crates/usvg/src/text/mod.rs @@ -149,7 +149,7 @@ impl FontResolver<'_> { /// to find a font that has the correct style and supports the character. pub fn default_fallback_selector() -> FallbackSelectionFn<'static> { Box::new(|c, exclude_fonts, fontdb| { - let base_font_id = exclude_fonts[0]; + let base_font_id = *exclude_fonts.first()?; // Iterate over fonts and check if any of them support the specified char. for face in fontdb.faces() { @@ -175,13 +175,13 @@ impl FontResolver<'_> { .families .iter() .find(|f| f.1 == fontdb::Language::EnglishUnitedStates) - .unwrap_or(&base_face.families[0]); + .or_else(|| base_face.families.first())?; let new_family = face .families .iter() .find(|f| f.1 == fontdb::Language::EnglishUnitedStates) - .unwrap_or(&base_face.families[0]); + .or_else(|| face.families.first())?; log::warn!("Fallback from {} to {}.", base_family.0, new_family.0); return Some(face.id); diff --git a/crates/usvg/src/tree/text.rs b/crates/usvg/src/tree/text.rs index be36fd19f..03287ed4c 100644 --- a/crates/usvg/src/tree/text.rs +++ b/crates/usvg/src/tree/text.rs @@ -741,8 +741,8 @@ impl TextChunk { } /// A text chunk flow. - pub fn text_flow(&self) -> TextFlow { - self.text_flow.clone() + pub fn text_flow(&self) -> &TextFlow { + &self.text_flow } /// A text chunk actual text. From 9bdb8df4de6a77c096ae7b7956e27e651c30c69c Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 18:36:06 +0100 Subject: [PATCH 5/8] Move span-uniform fields from PositionedGlyph to Span Move `variations`, `font_optical_sizing`, and `hinting` fields from `PositionedGlyph` to `Span` struct since these values are uniform for all glyphs within a span. Benefits: - Reduces memory by not duplicating Vec per glyph - Cleaner data model: span-level properties at span level - Minor perf improvement: needs_variations check once per span Based on PR #997 review feedback. Co-Authored-By: Claude Opus 4.5 --- crates/usvg/src/text/flatten.rs | 44 ++++++++++-------- crates/usvg/src/text/layout.rs | 81 ++++++++------------------------- 2 files changed, 43 insertions(+), 82 deletions(-) diff --git a/crates/usvg/src/text/flatten.rs b/crates/usvg/src/text/flatten.rs index a1bccbd33..1297004fe 100644 --- a/crates/usvg/src/text/flatten.rs +++ b/crates/usvg/src/text/flatten.rs @@ -254,17 +254,26 @@ fn flatten_impl( // it needs CrispEdges rendering (no anti-aliasing), so we flush the builder // when the rendering mode changes. let mut span_builder = tiny_skia_path::PathBuilder::new(); - let mut current_glyph_rendering_mode = rendering_mode; + + // Determine rendering mode for this span based on hinting target. + // Mono target always disables anti-aliasing (CrispEdges), regardless of whether + // hinting is enabled. This allows comparing hinted vs unhinted mono rendering. + let span_rendering_mode = if span.hinting.target == crate::HintingTarget::Mono { + ShapeRendering::CrispEdges // No anti-aliasing for mono target + } else { + rendering_mode + }; + let mut current_glyph_rendering_mode = span_rendering_mode; + + // Check if we need variations for this span (uniform for all glyphs). + // 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. + let needs_variations = !span.variations.is_empty() + || span.font_optical_sizing == crate::FontOpticalSizing::Auto; for glyph in &span.positioned_glyphs { - // Determine rendering mode for this glyph based on hinting target - // Mono target always disables anti-aliasing (CrispEdges), regardless of whether - // hinting is enabled. This allows comparing hinted vs unhinted mono rendering. - let glyph_rendering_mode = if glyph.hinting().target == crate::HintingTarget::Mono { - ShapeRendering::CrispEdges // No anti-aliasing for mono target - } else { - rendering_mode - }; + // For mono hinting, all glyphs in the span use the same rendering mode + let glyph_rendering_mode = span_rendering_mode; // If rendering mode changed, flush the current path segment if glyph_rendering_mode != current_glyph_rendering_mode { @@ -328,12 +337,7 @@ fn flatten_impl( new_children.push(Node::Group(Box::new(group))); } 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; - + // Use span-level variation settings (uniform for all glyphs in span). let outline = if use_hinting { // Use skrifa for hinted outline extraction let ppem = hinting_ctx.map(|ctx| ctx.ppem(glyph.font_size())); @@ -341,19 +345,19 @@ fn flatten_impl( &cache.fontdb, glyph.font, glyph.id, - &glyph.variations, + &span.variations, glyph.font_size(), - glyph.font_optical_sizing(), + span.font_optical_sizing, ppem, - glyph.hinting(), + span.hinting, ) } else if needs_variations { cache.fontdb.outline_with_variations( glyph.font, glyph.id, - &glyph.variations, + &span.variations, glyph.font_size(), - glyph.font_optical_sizing(), + span.font_optical_sizing, ) } else { cache.fontdb_outline(glyph.font, glyph.id) diff --git a/crates/usvg/src/text/layout.rs b/crates/usvg/src/text/layout.rs index d2a1a8324..86f7e835e 100644 --- a/crates/usvg/src/text/layout.rs +++ b/crates/usvg/src/text/layout.rs @@ -45,12 +45,6 @@ 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, - /// Font hinting settings. - pub hinting: crate::HintingSettings, } impl PositionedGlyph { @@ -59,16 +53,6 @@ impl PositionedGlyph { self.font_size } - /// Returns the font optical sizing mode. - pub fn font_optical_sizing(&self) -> crate::FontOpticalSizing { - self.font_optical_sizing - } - - /// Returns the hinting settings for this glyph. - pub fn hinting(&self) -> crate::HintingSettings { - self.hinting - } - /// Returns the transform of glyph. pub fn transform(&self) -> Transform { let sx = self.font_size / self.units_per_em as f32; @@ -182,6 +166,12 @@ pub struct Span { pub paint_order: PaintOrder, /// The font size of the span. pub font_size: NonZeroPositiveF32, + /// Font variation settings for variable fonts (uniform for all glyphs in span). + pub variations: Vec, + /// Font optical sizing mode for auto-opsz computation. + pub font_optical_sizing: crate::FontOpticalSizing, + /// Font hinting settings. + pub hinting: crate::HintingSettings, /// The visibility of the span. pub visible: bool, /// The glyphs that make up the span. @@ -373,11 +363,23 @@ pub(crate) fn layout_text( }) .collect(); + // Compute effective variations for this span (including auto-opsz). + let effective_variations = compute_effective_variations( + &span.font.variations, + span.font_size.get(), + span.font_optical_sizing, + font.id, + fontdb, + ); + spans.push(Span { fill, stroke: span.stroke.clone(), paint_order: span.paint_order, font_size: span.font_size, + variations: effective_variations, + font_optical_sizing: span.font_optical_sizing, + hinting: span.font.hinting, visible: span.visible, positioned_glyphs, underline, @@ -991,26 +993,10 @@ 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, - span.font.hinting, )); } } @@ -1181,14 +1167,7 @@ fn apply_word_spacing(chunk: &TextChunk, clusters: &mut [GlyphCluster]) { } } -fn form_glyph_clusters( - glyphs: &[Glyph], - text: &str, - font_size: f32, - variations: &[crate::FontVariation], - font_optical_sizing: crate::FontOpticalSizing, - hinting: crate::HintingSettings, -) -> GlyphCluster { +fn form_glyph_clusters(glyphs: &[Glyph], text: &str, font_size: f32) -> GlyphCluster { debug_assert!(!glyphs.is_empty()); let mut width = 0.0; @@ -1218,9 +1197,6 @@ fn form_glyph_clusters( font: glyph.font.id, text: glyph.text.clone(), id: glyph.id, - variations: variations.to_vec(), - font_optical_sizing, - hinting, }); x += glyph.width as f32; @@ -1410,10 +1386,6 @@ fn shape_text_with_font( 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, @@ -1423,21 +1395,6 @@ fn shape_text_with_font( } } - // 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() { From d91c134112c83c70bcd59a22376c824d53272e64 Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 18:54:25 +0100 Subject: [PATCH 6/8] Remove empty --drop-tables flag from README The empty --drop-tables= flag doesn't do anything. Remove it. Co-Authored-By: Claude Opus 4.5 --- crates/resvg/tests/fonts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/resvg/tests/fonts/README.md b/crates/resvg/tests/fonts/README.md index 18d6d1515..d100d9164 100644 --- a/crates/resvg/tests/fonts/README.md +++ b/crates/resvg/tests/fonts/README.md @@ -18,5 +18,5 @@ we can distinguish them from CBDT in tests). 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` +2. Run `pyftsubset RobotoFlex*.ttf --unicodes="U+0020-007E" --layout-features='*' --output-file=RobotoFlex.subset.ttf` 3. Copy OFL license from https://github.com/googlefonts/roboto-flex/blob/main/OFL.txt From 09c3805802c7ea53bf741d06df6dd46419a7bb4d Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 21:20:57 +0100 Subject: [PATCH 7/8] Implement LRU cache for glyph outlines with full parameter support Replace the simple (font_id, glyph_id) HashMap cache with a comprehensive LRU cache that captures all parameters affecting glyph outline shape: - Font ID and glyph ID - PPEM for hinting (stored as f32::to_bits() for exact matching) - Hinting settings (target, mode, engine, symmetric, preserve_linear_metrics) - Variation hash (computed from sorted variations + auto-opsz) Key changes: - Add `lru` crate dependency for bounded cache with LRU eviction - Add OutlineCacheKey struct capturing all outline-affecting parameters - Add CacheStats for tracking hits/misses/evictions - Add compute_variation_hash() for consistent variation hashing - Replace HashMap with LruCache (default capacity: 10,000 entries) - Unify three code paths (simple/variable/hinted) into single cache lookup - Add cache management methods (stats, clear, resize, len, capacity) This ensures that hinted outlines and variable font outlines are now cached, significantly improving performance for text-heavy documents with repeated glyphs at the same settings. Co-Authored-By: Claude Opus 4.5 --- Cargo.lock | 39 +++++++ crates/usvg/Cargo.toml | 3 +- crates/usvg/src/parser/converter.rs | 166 +++++++++++++++++++++++++++- crates/usvg/src/parser/mod.rs | 4 +- crates/usvg/src/text/flatten.rs | 101 +++++++++++++---- 5 files changed, 284 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc1d31052..e9f42746b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "arrayref" version = "0.3.9" @@ -138,6 +144,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "euclid" version = "0.22.11" @@ -172,6 +184,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "font-types" version = "0.11.0" @@ -231,6 +249,17 @@ dependencies = [ "smallvec", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "image-webp" version = "0.2.4" @@ -285,6 +314,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown", +] + [[package]] name = "memchr" version = "2.7.6" @@ -744,6 +782,7 @@ dependencies = [ "imagesize", "kurbo", "log", + "lru", "once_cell", "pico-args", "png 0.18.0", diff --git a/crates/usvg/Cargo.toml b/crates/usvg/Cargo.toml index 5c64c301c..a4d3634e7 100644 --- a/crates/usvg/Cargo.toml +++ b/crates/usvg/Cargo.toml @@ -38,6 +38,7 @@ siphasher = "1.0" # perfect hash implementation # text fontdb = { path = "../fontdb", default-features = false, optional = true } harfrust = { version = "0.5", optional = true } +lru = { version = "0.12", optional = true } unicode-bidi = { version = "0.3", optional = true } unicode-script = { version = "0.5", optional = true } unicode-vo = { version = "0.1", optional = true } @@ -55,7 +56,7 @@ once_cell = "1.21" default = ["text", "system-fonts", "memmap-fonts"] # Enables text-to-path conversion support. # Uses harfrust (HarfBuzz port) for shaping and skrifa for font access. -text = ["fontdb", "harfrust", "png", "skrifa", "unicode-bidi", "unicode-script", "unicode-vo"] +text = ["fontdb", "harfrust", "lru", "png", "skrifa", "unicode-bidi", "unicode-script", "unicode-vo"] # Enables system fonts loading. system-fonts = ["fontdb/fs", "fontdb/fontconfig"] # Enables font files memmaping for faster loading. diff --git a/crates/usvg/src/parser/converter.rs b/crates/usvg/src/parser/converter.rs index 55b3e962b..60902c75a 100644 --- a/crates/usvg/src/parser/converter.rs +++ b/crates/usvg/src/parser/converter.rs @@ -3,6 +3,8 @@ use std::collections::{HashMap, HashSet}; use std::hash::{Hash, Hasher}; +#[cfg(feature = "text")] +use std::num::NonZeroUsize; use std::str::FromStr; use std::sync::Arc; @@ -11,6 +13,8 @@ use fontdb::Database; #[cfg(feature = "text")] use fontdb::ID; #[cfg(feature = "text")] +use lru::LruCache; +#[cfg(feature = "text")] use skrifa::GlyphId; use svgtypes::{Length, LengthUnit as Unit, PaintOrderKind, TransformOrigin}; use tiny_skia_path::PathBuilder; @@ -42,15 +46,91 @@ pub struct State<'a> { pub(crate) opt: &'a Options<'a>, } -#[derive(Clone)] +/// Cache key for glyph outlines that captures all parameters affecting the outline shape. +#[cfg(feature = "text")] +#[derive(Clone, Hash, PartialEq, Eq, Debug)] +pub struct OutlineCacheKey { + /// Font database ID + pub font_id: ID, + /// Glyph ID within the font + pub glyph_id: GlyphId, + /// PPEM for hinting (None = unhinted), stored as f32::to_bits() for exact matching + pub ppem_bits: Option, + /// Hinting target (None = unhinted) + pub hinting_target: Option, + /// Hinting mode (None = unhinted) + pub hinting_mode: Option, + /// Hinting engine (None = unhinted) + pub hinting_engine: Option, + /// Symmetric rendering flag + pub symmetric_rendering: bool, + /// Preserve linear metrics flag + pub preserve_linear_metrics: bool, + /// Hash of variation coordinates (for consistent lookup) + pub variation_hash: u64, +} + +/// Statistics for cache usage tracking. +#[cfg(feature = "text")] +#[derive(Clone, Default, Debug)] +pub struct CacheStats { + /// Number of cache hits + pub outline_hits: usize, + /// Number of cache misses + pub outline_misses: usize, + /// Number of entries evicted due to LRU + pub outline_evictions: usize, +} + +/// Default outline cache capacity (number of entries). +#[cfg(feature = "text")] +pub const DEFAULT_OUTLINE_CACHE_CAPACITY: usize = 10_000; + +/// Computes a hash of variation coordinates for cache key generation. +/// +/// This creates a stable hash from font variations and auto-opsz settings +/// that can be used as part of a cache key. +#[cfg(feature = "text")] +pub fn compute_variation_hash( + variations: &[FontVariation], + font_optical_sizing: FontOpticalSizing, + font_size: f32, + has_opsz_axis: bool, +) -> u64 { + use std::collections::hash_map::DefaultHasher; + + let mut hasher = DefaultHasher::new(); + + // Sort variations by tag for consistent ordering + let mut sorted: Vec<_> = variations.iter().collect(); + sorted.sort_by_key(|v| v.tag); + + for v in sorted { + v.tag.hash(&mut hasher); + v.value.to_bits().hash(&mut hasher); + } + + // Include auto-opsz if applicable + if font_optical_sizing == FontOpticalSizing::Auto && has_opsz_axis { + b"opsz".hash(&mut hasher); + font_size.to_bits().hash(&mut hasher); + } + + hasher.finish() +} + pub struct Cache { /// This fontdb is initialized from [`Options::fontdb`] and then populated /// over the course of conversion. #[cfg(feature = "text")] pub fontdb: Arc, + /// LRU cache for glyph outlines, keyed by all parameters affecting outline shape. + #[cfg(feature = "text")] + cache_outline: LruCache>, + /// Statistics for cache usage tracking. #[cfg(feature = "text")] - cache_outline: HashMap<(ID, GlyphId), Option>, + cache_stats: CacheStats, #[cfg(feature = "text")] cache_colr: HashMap<(ID, GlyphId), Option>, #[cfg(feature = "text")] @@ -92,13 +172,20 @@ macro_rules! font_lookup { } impl Cache { - pub(crate) fn new(#[cfg(feature = "text")] fontdb: Arc) -> Self { + pub(crate) fn new( + #[cfg(feature = "text")] fontdb: Arc, + #[cfg(feature = "text")] outline_cache_capacity: usize, + ) -> Self { Self { #[cfg(feature = "text")] fontdb, #[cfg(feature = "text")] - cache_outline: HashMap::new(), + cache_outline: LruCache::new( + NonZeroUsize::new(outline_cache_capacity).unwrap_or(NonZeroUsize::MIN), + ), + #[cfg(feature = "text")] + cache_stats: CacheStats::default(), #[cfg(feature = "text")] cache_colr: HashMap::new(), #[cfg(feature = "text")] @@ -200,7 +287,39 @@ impl Cache { } } - font_lookup!(fontdb_outline, cache_outline, outline, tiny_skia_path::Path); + /// Get or compute a glyph outline with full caching support. + /// + /// This method handles all outline types (simple, variable, hinted) through a unified + /// cache keyed by all parameters that affect the outline shape. The `compute` closure + /// is only called on cache miss. + #[cfg(feature = "text")] + pub fn get_or_compute_outline( + &mut self, + key: OutlineCacheKey, + compute: F, + ) -> Option + where + F: FnOnce() -> Option, + { + // Check cache first (get() also updates LRU order) + if let Some(cached) = self.cache_outline.get(&key) { + self.cache_stats.outline_hits += 1; + return cached.clone(); + } + + // Compute on miss + self.cache_stats.outline_misses += 1; + let result = compute(); + + // Track evictions (if cache is at capacity, next put will evict) + if self.cache_outline.len() == self.cache_outline.cap().get() { + self.cache_stats.outline_evictions += 1; + } + + self.cache_outline.put(key, result.clone()); + result + } + font_lookup!(fontdb_colr, cache_colr, colr, Tree); font_lookup!(fontdb_svg, cache_svg, svg, Node); @@ -223,6 +342,41 @@ impl Cache { } } } + + /// Returns the current cache statistics. + #[cfg(feature = "text")] + pub fn outline_cache_stats(&self) -> &CacheStats { + &self.cache_stats + } + + /// Clears all cached outlines and resets statistics. + #[cfg(feature = "text")] + pub fn clear_outline_cache(&mut self) { + self.cache_outline.clear(); + self.cache_stats = CacheStats::default(); + } + + /// Resizes the outline cache capacity. + /// + /// If the new capacity is smaller than the current number of entries, + /// the least recently used entries will be evicted. + #[cfg(feature = "text")] + pub fn resize_outline_cache(&mut self, new_capacity: usize) { + self.cache_outline + .resize(NonZeroUsize::new(new_capacity).unwrap_or(NonZeroUsize::MIN)); + } + + /// Returns the current number of cached outline entries. + #[cfg(feature = "text")] + pub fn outline_cache_len(&self) -> usize { + self.cache_outline.len() + } + + /// Returns the current outline cache capacity. + #[cfg(feature = "text")] + pub fn outline_cache_capacity(&self) -> usize { + self.cache_outline.cap().get() + } } // TODO: is there a simpler way? @@ -399,6 +553,8 @@ pub(crate) fn convert_doc(svg_doc: &svgtree::Document, opt: &Options) -> Result< let mut cache = Cache::new( #[cfg(feature = "text")] opt.fontdb.clone(), + #[cfg(feature = "text")] + DEFAULT_OUTLINE_CACHE_CAPACITY, ); for node in svg_doc.descendants() { diff --git a/crates/usvg/src/parser/mod.rs b/crates/usvg/src/parser/mod.rs index ec9d0eac5..de9fbd217 100644 --- a/crates/usvg/src/parser/mod.rs +++ b/crates/usvg/src/parser/mod.rs @@ -19,7 +19,9 @@ mod use_node; #[cfg(feature = "text")] mod text; #[cfg(feature = "text")] -pub(crate) use converter::Cache; +pub(crate) use converter::{ + Cache, CacheStats, OutlineCacheKey, DEFAULT_OUTLINE_CACHE_CAPACITY, compute_variation_hash, +}; pub use image::{ImageHrefDataResolverFn, ImageHrefResolver, ImageHrefStringResolverFn}; #[cfg(feature = "text")] pub use options::HintingOptions; diff --git a/crates/usvg/src/text/flatten.rs b/crates/usvg/src/text/flatten.rs index 1297004fe..d50850fdc 100644 --- a/crates/usvg/src/text/flatten.rs +++ b/crates/usvg/src/text/flatten.rs @@ -338,31 +338,88 @@ fn flatten_impl( new_children.push(Node::Group(Box::new(group))); } else { // Use span-level variation settings (uniform for all glyphs in span). - 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, - &span.variations, - glyph.font_size(), - span.font_optical_sizing, - ppem, - span.hinting, - ) - } else if needs_variations { - cache.fontdb.outline_with_variations( - glyph.font, - glyph.id, - &span.variations, - glyph.font_size(), - span.font_optical_sizing, - ) + // Clone Arc before mutable borrow for the closure + let fontdb = cache.fontdb.clone(); + + // Compute ppem for hinting (if applicable) + let ppem = if use_hinting { + hinting_ctx.map(|ctx| ctx.ppem(glyph.font_size())) } else { - cache.fontdb_outline(glyph.font, glyph.id) + None }; + // For cache key: when auto-opsz is enabled, assume font has opsz axis + // This is a safe approximation that may create slightly more cache entries + // for fonts without opsz, but avoids expensive axis lookup + let has_opsz_axis = span.font_optical_sizing == crate::FontOpticalSizing::Auto; + + // Compute variation hash for cache key + let variation_hash = crate::parser::compute_variation_hash( + &span.variations, + span.font_optical_sizing, + glyph.font_size(), + has_opsz_axis, + ); + + // Build cache key with all parameters affecting outline shape + let cache_key = crate::parser::OutlineCacheKey { + font_id: glyph.font, + glyph_id: glyph.id, + ppem_bits: ppem.map(|p| p.to_bits()), + hinting_target: if use_hinting { + Some(span.hinting.target) + } else { + None + }, + hinting_mode: if use_hinting { + Some(span.hinting.mode) + } else { + None + }, + hinting_engine: if use_hinting { + Some(span.hinting.engine) + } else { + None + }, + symmetric_rendering: span.hinting.symmetric_rendering, + preserve_linear_metrics: span.hinting.preserve_linear_metrics, + variation_hash, + }; + + // Capture values for closure + let variations = &span.variations; + let font_optical_sizing = span.font_optical_sizing; + let hinting_settings = span.hinting; + let font_id = glyph.font; + let glyph_id = glyph.id; + let font_size = glyph.font_size(); + + // Get from cache or compute (unified for all outline types) + let outline = cache.get_or_compute_outline(cache_key, || { + if use_hinting { + extract_outline_skrifa( + &fontdb, + font_id, + glyph_id, + variations, + font_size, + font_optical_sizing, + ppem, + hinting_settings, + ) + } else if needs_variations { + fontdb.outline_with_variations( + font_id, + glyph_id, + variations, + font_size, + font_optical_sizing, + ) + } else { + fontdb.outline(font_id, glyph_id) + } + }); + if let Some(outline) = outline.and_then(|p| p.transform(glyph.outline_transform())) { span_builder.push_path(&outline); From 9d2a8661043961923783b797153a105c10454612 Mon Sep 17 00:00:00 2001 From: Tobias Oetiker Date: Mon, 12 Jan 2026 21:25:41 +0100 Subject: [PATCH 8/8] Update CHANGELOG for skrifa port and outline caching Document all changes from the skrifa branch: - Hinting support with CSS custom properties - Variable font support with avar normalization - LRU outline cache with full parameter support - Port from ttf-parser/rustybuzz to skrifa/harfrust - Vendored fontdb ported to skrifa - Various bug fixes and improvements Co-Authored-By: Claude Opus 4.5 --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ crates/usvg/src/parser/mod.rs | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d259dc62..5c332a74d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,35 @@ This changelog also contains important changes in dependencies. This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API. +### Added + +- Hinting support for text rendering with configurable settings via CSS custom properties + (`-resvg-hinting-target`, `-resvg-hinting-mode`, `-resvg-hinting-engine`, + `-resvg-hinting-symmetric`, `-resvg-hinting-preserve-linear-metrics`). +- Variable font support with avar-aware axis normalization for correct rendering. +- LRU cache for glyph outlines with full parameter support (hinting settings, variations, ppem). + Dramatically improves performance for text-heavy documents with repeated glyphs. +- Cache statistics tracking (`CacheStats`) for monitoring outline cache hits/misses/evictions. +- Cache management methods: `outline_cache_stats()`, `clear_outline_cache()`, + `resize_outline_cache()`, `outline_cache_len()`, `outline_cache_capacity()`. + +### Changed + +- Port text rendering from `ttf-parser`/`rustybuzz` to `skrifa`/`harfrust`. +- Vendor `fontdb` 0.23.0 as a workspace crate, ported from `ttf-parser` to `skrifa`. + This eliminates the `ttf-parser` dependency entirely. +- Move span-uniform fields (`variations`, `font_optical_sizing`, `hinting`) from + `PositionedGlyph` to `Span` for reduced memory usage and better cache efficiency. +- Unify three outline extraction code paths (simple/variable/hinted) into single cached lookup. + +### Fixed + +- Remove empty `--drop-tables` flag from README. +- Fix potential panics on empty slices in font fallback. +- Add empty path check in `path_length()`. +- Add ASCII validation for font variation tags. +- Fix incorrect safety comment on mmap in fontdb. + ## [0.46.0] This release has an MSRV of 1.87.0 for `usvg` and `resvg` and the C API. diff --git a/crates/usvg/src/parser/mod.rs b/crates/usvg/src/parser/mod.rs index de9fbd217..a2098930c 100644 --- a/crates/usvg/src/parser/mod.rs +++ b/crates/usvg/src/parser/mod.rs @@ -20,7 +20,7 @@ mod use_node; mod text; #[cfg(feature = "text")] pub(crate) use converter::{ - Cache, CacheStats, OutlineCacheKey, DEFAULT_OUTLINE_CACHE_CAPACITY, compute_variation_hash, + Cache, CacheStats, DEFAULT_OUTLINE_CACHE_CAPACITY, OutlineCacheKey, compute_variation_hash, }; pub use image::{ImageHrefDataResolverFn, ImageHrefResolver, ImageHrefStringResolverFn}; #[cfg(feature = "text")]