summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2022-12-31 09:27:57 +0000
committerAdrian Johnson <ajohnson@redneon.com>2022-12-31 09:27:57 +0000
commit3a60f6e138942af739b5998c521527e691ffeba4 (patch)
tree69c58de3db015a42e2b813207efa1d74b461195a /test
parent8c983c0d5d26af252dab087482ad71c8f4e35b26 (diff)
parent3e8b9a7cf4417d862917ec3c50fe8f0f58142e46 (diff)
downloadcairo-3a60f6e138942af739b5998c521527e691ffeba4.tar.gz
Merge branch 'ft-svg-fonts' into 'master'
Support SVG fonts in FT backend See merge request cairo/cairo!319
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am3
-rw-r--r--test/Makefile.sources3
-rw-r--r--test/cairo-logo-font.ttx539
-rw-r--r--test/cairo-svg-test-doc.ttx689
-rw-r--r--test/cairo-svg-test-fill.ttx365
-rw-r--r--test/cairo-svg-test-gradient.ttx441
-rw-r--r--test/cairo-svg-test-path.ttx281
-rw-r--r--test/cairo-svg-test-shapes.ttx333
-rw-r--r--test/cairo-svg-test-stroke.ttx608
-rw-r--r--test/cairo-svg-test-transform.ttx403
-rw-r--r--test/cairo-test.c67
-rw-r--r--test/cairo-test.h5
-rw-r--r--test/ft-svg-cairo-logo.c66
-rw-r--r--test/ft-svg-color-font.c146
-rw-r--r--test/ft-svg-render.c159
-rw-r--r--test/meson.build46
-rw-r--r--test/reference/ft-svg-cairo-logo.ref.pngbin0 -> 13204 bytes
-rw-r--r--test/reference/ft-svg-color-font.ref.pngbin0 -> 10973 bytes
-rw-r--r--test/reference/ft-svg-render-doc.ref.pngbin0 -> 11069 bytes
-rw-r--r--test/reference/ft-svg-render-fill.ref.pngbin0 -> 1641 bytes
-rw-r--r--test/reference/ft-svg-render-gradient.ref.pngbin0 -> 9156 bytes
-rw-r--r--test/reference/ft-svg-render-path.ref.pngbin0 -> 2570 bytes
-rw-r--r--test/reference/ft-svg-render-shapes.ref.pngbin0 -> 3073 bytes
-rw-r--r--test/reference/ft-svg-render-stroke.ref.pngbin0 -> 2224 bytes
-rw-r--r--test/reference/ft-svg-render-transform.ref.pngbin0 -> 4248 bytes
-rw-r--r--test/svg/README22
-rwxr-xr-xtest/svg/build_ttx_fonts.py161
-rw-r--r--test/svg/doc.0.viewBox1.svg4
-rw-r--r--test/svg/doc.1.viewBox2.svg4
-rw-r--r--test/svg/doc.2.image.svg121
-rw-r--r--test/svg/doc.3.image-transform.svg122
-rw-r--r--test/svg/doc.4.clip-user.svg9
-rw-r--r--test/svg/doc.5.clip-object.svg10
-rw-r--r--test/svg/doc.6.clip-user2.svg10
-rw-r--r--test/svg/doc.7.clip-object2.svg11
-rw-r--r--test/svg/doc.8.clip-user3.svg15
-rw-r--r--test/svg/doc.9.clip-object3.svg15
-rw-r--r--test/svg/doc.A.g.svg14
-rw-r--r--test/svg/fill.0.name.svg4
-rw-r--r--test/svg/fill.1.hex6.svg4
-rw-r--r--test/svg/fill.2.hex3.svg4
-rw-r--r--test/svg/fill.3.rgb.svg4
-rw-r--r--test/svg/fill.4.current-color.svg4
-rw-r--r--test/svg/fill.5.palette.svg4
-rw-r--r--test/svg/fill.6.opacity.svg4
-rw-r--r--test/svg/fill.7.color.svg5
-rw-r--r--test/svg/fill.8.rule.svg8
-rw-r--r--test/svg/fuzzer/README19
-rw-r--r--test/svg/fuzzer/meson.build14
-rw-r--r--test/svg/fuzzer/svg-render-fuzzer.c57
-rw-r--r--test/svg/gradient.0.lin-pad.svg10
-rw-r--r--test/svg/gradient.1.lin-reflect.svg11
-rw-r--r--test/svg/gradient.2.lin-repeat.svg11
-rw-r--r--test/svg/gradient.3.lin-user.svg11
-rw-r--r--test/svg/gradient.4.lin-transform.svg10
-rw-r--r--test/svg/gradient.5.rad-pad.svg10
-rw-r--r--test/svg/gradient.6.rad-reflect.svg11
-rw-r--r--test/svg/gradient.7.rad-repeat.svg11
-rw-r--r--test/svg/gradient.8.rad-user.svg11
-rw-r--r--test/svg/gradient.9.rad-transform.svg11
-rw-r--r--test/svg/meson.build9
-rw-r--r--test/svg/path.0.line.svg8
-rw-r--r--test/svg/path.1.curve.svg9
-rw-r--r--test/svg/path.2.quad.svg8
-rw-r--r--test/svg/path.3.arc.svg7
-rw-r--r--test/svg/shapes.0.rect.svg3
-rw-r--r--test/svg/shapes.1.rounded-rect.svg3
-rw-r--r--test/svg/shapes.2.circle.svg3
-rw-r--r--test/svg/shapes.3.ellipse.svg3
-rw-r--r--test/svg/shapes.4.line.svg3
-rw-r--r--test/svg/shapes.5.polyline.svg12
-rw-r--r--test/svg/shapes.6.polygon.svg12
-rw-r--r--test/svg/stroke.0.name.svg6
-rw-r--r--test/svg/stroke.1.hex6.svg6
-rw-r--r--test/svg/stroke.2.hex3.svg6
-rw-r--r--test/svg/stroke.3.rgb.svg6
-rw-r--r--test/svg/stroke.4.current-color.svg6
-rw-r--r--test/svg/stroke.5.palette.svg6
-rw-r--r--test/svg/stroke.6.opacity.svg6
-rw-r--r--test/svg/stroke.7.color.svg7
-rw-r--r--test/svg/stroke.8.width.svg14
-rw-r--r--test/svg/stroke.9.cap.svg17
-rw-r--r--test/svg/stroke.A.dash.svg27
-rw-r--r--test/svg/stroke.B.dash-offset.svg31
-rw-r--r--test/svg/stroke.C.miter.svg10
-rw-r--r--test/svg/stroke.D.round.svg10
-rw-r--r--test/svg/stroke.E.bevel.svg10
-rw-r--r--test/svg/stroke.F.miter-limit.svg11
-rw-r--r--test/svg/svg-font-template.ttx190
-rw-r--r--test/svg/svg-render.c308
-rw-r--r--test/svg/transform.0.translate.svg8
-rw-r--r--test/svg/transform.1.scale.svg10
-rw-r--r--test/svg/transform.2.rotate.svg10
-rw-r--r--test/svg/transform.3.skewX.svg10
-rw-r--r--test/svg/transform.4.skewY.svg10
-rw-r--r--test/svg/transform.5.matrix.svg10
-rw-r--r--test/svg/transform.6.multiple.svg16
-rw-r--r--test/svg/transform.7.stroke.svg20
98 files changed, 5760 insertions, 1 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index a74d71a7c..df2d59f44 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -14,6 +14,9 @@ if CAIRO_HAS_FT_FONT
test_sources += $(ft_font_test_sources)
if CAIRO_HAS_FC_FONT
test_sources += $(fc_font_test_sources)
+if HAVE_FT_SVG_DOCUMENT
+test_sources += $(fc_svg_font_test_sources)
+endif
endif
endif
diff --git a/test/Makefile.sources b/test/Makefile.sources
index c01d3ac2a..ab41aac5f 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -425,6 +425,9 @@ fc_font_test_sources = \
ft-text-vertical-layout-type3.c \
ft-text-antialias-none.c
+fc_svg_font_test_sources = \
+ ft-svg-color-font.c
+
gl_surface_test_sources = \
gl-device-release.c \
gl-oversized-surface.c \
diff --git a/test/cairo-logo-font.ttx b/test/cairo-logo-font.ttx
new file mode 100644
index 000000000..9e4b832c0
--- /dev/null
+++ b/test/cairo-logo-font.ttx
@@ -0,0 +1,539 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="A"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x3e7355ef"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000001"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Wed Jun 15 00:00:00 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1000"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="0"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="1"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="1"/>
+ <maxCompositeContours value="1"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="2"/>
+ <maxComponentDepth value="1"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="800"/>
+ <sTypoDescender value="-100"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1000" lsb="0"/>
+ <mtx name="A" width="1000" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="A">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Logo
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Logo Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="310" height="508">
+ <defs id="cairo-artwork_defs">
+ <g id="hacker_emblem">
+ <!-- Note: This is similar though not identical to Keith Packard's SVG version
+ of the hacker emblem (http://www.catb.org/hacker-emblem/glider.svg) -->
+ <g id="hacker_emblem_grid" fill="white" stroke="none">
+ <!-- Outside: Top, Right, Bottom, Left -->
+ <rect x="-2.95" y="-3.05" width="6" height="0.1" />
+ <rect x="2.95" y="-2.95" width="0.1" height="6" />
+ <rect x="-3.05" y="2.95" width="6" height="0.1" />
+ <rect x="-3.05" y="-3.05" width="0.1" height="6" />
+ <!-- Vertical: Left, Right -->
+ <rect x="-1.05" y="-2.95" width="0.1" height="5.9" />
+ <rect x="0.95" y="-2.95" width="0.1" height="5.9" />
+ <!-- Horizontal: TopLeft, TopMiddle, TopRight -->
+ <rect x="-2.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="-0.95" y="-1.05" width="1.9" height="0.1" />
+ <rect x="1.05" y="-1.05" width="1.9" height="0.1" />
+ <!-- Horizontal: BottomLeft, BottomMiddle, BottomRight -->
+ <rect x="-2.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="-0.95" y="0.95" width="1.9" height="0.1" />
+ <rect x="1.05" y="0.95" width="1.9" height="0.1" />
+ </g>
+ <g id="hacker_emblem_dots" fill="white">
+ <circle cx="0" cy="-2" r="0.7" />
+ <circle cx="2" cy="0" r="0.7" />
+ <circle cx="-2" cy="2" r="0.7" />
+ <circle cx="0" cy="2" r="0.7" />
+ <circle cx="2" cy="2" r="0.7" />
+ </g>
+ </g>
+ <g id="scarab" fill="#3B80AE">
+ <g transform="translate(-150, -170)">
+ <path id="scarab_head" d="M205.599,94.567c0-11.668-24.914-21.129-55.628-21.129
+ c-30.723,0-55.624,9.46-55.624,21.129c0,10.203,24.901,7.346,55.624,7.346C180.685,101.913,205.599,104.233,205.599,94.567z"/>
+ <path id="scarab_torso" d="M136.423,161.506c0,0,12.751,12.577,13.547,13.362
+ c2.262-2.232,13.545-13.362,13.545-13.362c7.135-7.036,87.111-6.399,91.066-6.363c-0.469-6.298-1.254-12.472-2.325-18.519
+ c-15.183-19.279-42.811-32.225-74.485-32.225h-55.518c-31.745,0-59.439,13.011-74.598,32.37c-1.054,6-1.829,12.128-2.296,18.374
+ C49.321,155.106,129.288,154.47,136.423,161.506z"/>
+ <path id="scarab_spine" d="M149.97,301.187c2.005-24.729,8.386-103.483,8.405-103.721
+ c-0.09-0.219-6.478-15.578-8.405-20.214c-1.936,4.655-8.316,19.995-8.408,20.214C141.582,197.704,147.965,276.458,149.97,301.187z"/>
+ <path id="scarab_wing_left" d="M140.403,197.149l8.862-21.31l-13.686-13.499
+ c-5.65-5.573-67.074-6.235-90.259-6.019l-0.006-0.622c-0.154,2.144-0.271,4.302-0.35,6.475
+ c-0.076,2.207,10.392,4.706,10.392,6.717c0,2.319-10.457,5.084-10.359,7.631c2.993,73.349,48.53,131.631,104.372,132.048
+ l-9.02-111.29L140.403,197.149z"/>
+ <path id="scarab_wing_right" d="M244.585,168.891c0-2.011,10.467-4.506,10.391-6.715
+ c-0.079-2.174-0.195-4.332-0.351-6.479l-0.004,0.624c-23.186-0.216-84.608,0.445-90.26,6.017l-13.688,13.502l8.915,21.438
+ l-9.017,111.29c55.854-0.417,101.378-58.698,104.373-132.049C255.04,173.976,244.585,171.209,244.585,168.891z"/>
+ <path id="scarab_leg_front_left" d="M44.506,141.12c-4.135-0.856-4.895-1.54-7.935-2.92
+ c-9.59-3.364-10.376-5.481-16.08-11.86c-7.426-8.306-12.661-20.142-17.1-29.463c-3.576-7.525-3.984-16.409-2.86-24.273
+ c0.991-6.935,7.144-12.869,12.074-18.92c5.844-7.191,10.356-14.822,17.924-21.354c7.736-6.682,23.203-9.809,26.168-19.648
+ C57.86,8.819,54.334,1.766,61.482,0c-0.366,4.703,3.639,8.477,2.397,13.575c-1.129,4.627-4.368,5.811-9.611,9.099
+ c-7.564,4.746-18.366,8.779-24.748,13.965c-7.175,5.827-4.369,13.771-10.569,20.057c-2.001,2.03-7.901,4.706-9.137,6.83
+ c-1.861,3.199-0.297,9.572-0.116,13.12c0.425,8.284,5.588,14.244,9.555,22.045c4.152,8.141,6.429,15.409,13.411,22.519
+ c4.183,4.262,11.429,4.802,16.21,10.647l-3.555,4.186L44.506,141.12z"/>
+ <path id="scarab_leg_middle_left" d="M43.94,191.922l-0.809-7.346
+ c-9.506-4.579-10.339-9.772-20.738-12.466c-23.728-6.151-21.361,11.25-15.532,26.373c5.676,14.726,8.237,30.23,14.345,44.795
+ c2.805,6.688,6.919,13.213,14.298,15.127c0.372-8.435-0.917-10.651-6.113-16.919c-4.395-5.293-3.326-12.548-6.072-18.504
+ c-3.581-7.804-4.196-15.646-7.279-23.502c-1.363-3.479-8.33-13.966-6.452-17.861c3.183-6.603,9.178-0.083,12.179,2.077
+ c4.218,3.036,6.467,2.223,11.681,2.898C34.041,186.673,37.005,188.756,43.94,191.922z"/>
+ <path id="scarab_leg_back_left" d="M65.839,257.063l-2.771-4.837
+ c-6.68,8.928-6.993,16.228-10.056,23.347c-5.277,12.263-0.157,28.851,9.854,37.676c6.052,5.375,15.907,9.618,23.122,13.136
+ c10.035,4.892,20.113,11.286,31.336,13.396c2.482,0.466,8.798,1.295,6.693-3.522c-0.975-2.237-8.091-4.591-10.146-5.734
+ c-8.312-4.623-16.377-10.524-24.142-16.176c-9.498-6.862-20.843-11.186-28.311-20.684c-3.054-3.885-3.544-4.922-2.816-9.39
+ c0.693-4.263,1.344-9.174,2.241-13.439C61.855,266.029,63.274,261.378,65.839,257.063z"/>
+ <path id="scarab_leg_front_right" d="M255.487,141.12c4.134-0.856,4.896-1.54,7.936-2.92
+ c9.583-3.364,10.369-5.481,16.071-11.86c7.428-8.306,12.661-20.142,17.115-29.463c3.574-7.525,3.983-16.409,2.86-24.273
+ c-0.992-6.935-7.157-12.869-12.087-18.92c-5.843-7.191-10.356-14.822-17.919-21.354c-7.735-6.682-23.202-9.809-26.167-19.648
+ C242.135,8.819,245.66,1.766,238.511,0c0.366,4.703-3.637,8.477-2.396,13.575c1.131,4.627,4.368,5.811,9.611,9.099
+ c7.563,4.746,18.367,8.779,24.747,13.965c7.17,5.827,4.362,13.771,10.563,20.057c2.001,2.03,7.901,4.706,9.139,6.83
+ c1.859,3.199,0.295,9.572,0.113,13.12c-0.424,8.284-5.588,14.244-9.553,22.045c-4.152,8.141-6.431,15.409-13.404,22.519
+ c-4.184,4.262-11.429,4.802-16.211,10.647l3.556,4.186L255.487,141.12z"/>
+ <path id="scarab_leg_middle_right" d="M256.053,191.922l0.81-7.346
+ c9.507-4.579,10.34-9.772,20.73-12.466c23.741-6.151,21.374,11.25,15.534,26.373c-5.676,14.726-8.238,30.23-14.347,44.795
+ c-2.804,6.688-6.911,13.213-14.291,15.127c-0.371-8.435,0.918-10.651,6.113-16.919c4.39-5.293,3.319-12.548,6.066-18.504
+ c3.58-7.804,4.197-15.646,7.278-23.502c1.363-3.479,8.33-13.966,6.453-17.861c-3.184-6.603-9.179-0.083-12.181,2.077
+ c-4.217,3.036-6.458,2.223-11.672,2.898C265.951,186.673,262.986,188.756,256.053,191.922z"/>
+ <path id="scarab_leg_back_right" d="M234.155,257.063l2.771-4.837
+ c6.679,8.928,6.991,16.228,10.057,23.347c5.274,12.263,0.154,28.851-9.854,37.676c-6.055,5.375-15.903,9.618-23.117,13.136
+ c-10.034,4.892-20.127,11.286-31.351,13.396c-2.481,0.466-8.789,1.295-6.691-3.522c0.976-2.237,8.092-4.591,10.146-5.734
+ c8.312-4.623,16.392-10.524,24.155-16.176c9.498-6.862,20.838-11.186,28.305-20.684c3.055-3.885,3.543-4.922,2.818-9.39
+ c-0.696-4.263-1.346-9.174-2.244-13.439C238.137,266.029,236.718,261.378,234.155,257.063z"/>
+ </g>
+ </g>
+ <radialGradient id="gradient_radial_dung"
+ cx="0" cy="0" r="60"
+ fx="0" fy="0" gradientUnits="userSpaceOnUse"
+ >
+ <stop offset="0" stop-color="#9a9a9a" />
+ <stop offset="0.70" stop-color="#bababa" />
+ <stop offset="0.95" stop-color="#FFFFFF" />
+ </radialGradient>
+ <g id="dung">
+ <circle cx="0" cy="0" r="60" fill="url(#gradient_radial_dung)" />
+ <g transform="translate(-61, -61)">
+ <!-- rough equivalent: <circle cx="0" cy="0" r="60" stroke="#8a8a8a" stroke-width="2" /> -->
+ <path fill="#8a8a8a" d="M0,61c0,33.636,27.364,61,61,61s61-27.364,61-61S94.636,0,61,0S0,27.364,0,61z
+ M2,61C2,28.467,28.467,2,61,2c32.532,0,59,26.467,59,59c0,32.533-26.468,59-59,59C28.467,120,2,93.533,2,61z"/>
+ </g>
+ <use xlink:href="#hacker_emblem" x="0" y="0" transform="scale(9)" />
+ </g>
+
+ <!-- scarab dimensions: 300x340 -->
+ <!-- dung dimensions: 120x120 (radius: 60) -->
+ <!-- scarab and dung dimensions: 300x400 -->
+
+ <g id="cairo_logo">
+ <!-- dimensions: 300x400, centered -->
+ <!-- The logo (scarab and dung), with the center-point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 30)" />
+ </g>
+ <g id="cairo_logo_dung-centered">
+ <!-- The logo (scarab and dung), with the dung at (0,0), the scarab below -->
+ <use xlink:href="#dung" x="0" y="0" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0,170)" />
+ </g>
+ <g id="cairo_logo_scarab-centered">
+ <!-- The logo (scarab and dung), with the scarab's rotational center at (0,0), the dung above -->
+ <!-- The scarab's rotational center in this case is not the center of its bounding box,
+ but is calculated to be the intersection-point of the torso, spine and wings -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -175.85)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -5.85)" />
+ </g>
+ <g id="cairo_logo_top-centered">
+ <!-- The logo (scarab and dung), with the top-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, 230)" /><!-- (0,170+60) -->
+ </g>
+ <g id="cairo_logo_bottom-centered">
+ <!-- The logo (scarab and dung), with the bottom-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(0, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(0, -170)" />
+ </g>
+ <g id="cairo_logo_right-centered">
+ <!-- The logo (scarab and dung), with the right-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 30)" />
+ </g>
+ <g id="cairo_logo_left-centered">
+ <!-- The logo (scarab and dung), with the left-center point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -140)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 30)" />
+ </g>
+ <g id="cairo_logo_topleft-centered">
+ <!-- The logo (scarab and dung), with the top-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, 230)" /><!-- (150, 170+60) -->
+ </g>
+ <g id="cairo_logo_topright-centered">
+ <!-- The logo (scarab and dung), with the top-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, 60)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, 230)" /><!-- (-150,170+60) -->
+ </g>
+ <g id="cairo_logo_bottomleft-centered">
+ <!-- The logo (scarab and dung), with the bottom-left point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(150, -170)" />
+ </g>
+ <g id="cairo_logo_bottomright-centered">
+ <!-- The logo (scarab and dung), with the bottom-right point of the bounding box at (0,0) -->
+ <use xlink:href="#dung" x="0" y="0" transform="translate(-150, -340)" />
+ <use xlink:href="#scarab" x="0" y="0" transform="translate(-150, -170)" />
+ </g>
+
+ <g id="cairo_text" transform="translate(0,-97)">
+ <g transform="scale(0.1484,0.1484)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(65,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(486.75,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1234.25,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1610,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <!-- scaled by 0.72, shifted around to hit pixel boundaries -->
+ <g id="cairo_text_small" transform="translate(0,-71)">
+ <g transform="scale(0.085,0.085)"> <g transform="translate(-1139,-208.5)">
+ <!-- 63 (c), advance 444, 0 horiBearing 38,522 -->
+ <path transform="translate(-151,0)" d="
+ M 412, 433
+ C 385, 422 336, 413 298, 413
+ C 142, 413 38, 525 38, 680
+ C 38, 826 144, 947 298, 947
+ C 332, 947 377, 944 416, 926
+ L 409, 842
+ C 380, 861 340, 871 308, 871
+ C 187, 871 138, 771 138, 680
+ C 138, 583 197, 489 302, 489
+ C 332, 489 368, 496 404, 511
+ L 412, 433 " />
+ <!-- 61 (a), advance 556, 0 horiBearing 46,522 -->
+ <path transform="translate(379.5,0)" d="
+ M 109, 541
+ C 147, 509 204, 489 257, 489
+ C 351, 489 383, 534 383, 622
+ C 346, 620 320, 620 283, 620
+ C 186, 620 46, 660 46, 788
+ C 46, 899 123, 947 233, 947
+ C 319, 947 369, 900 391, 869
+ L 393, 869
+ L 393, 935
+ L 481, 935
+ C 479, 920 477, 893 477, 835
+ L 477, 624
+ C 477, 485 418, 413 272, 413
+ C 207, 413 151, 433 104, 461
+ L 109, 541
+ M 383, 737
+ C 383, 813 334, 871 241, 871
+ C 198, 871 146, 842 146, 788
+ C 146, 698 272, 690 323, 690
+ C 343, 690 363, 692 383, 692
+ L 383, 737 " />
+ <!-- 69 (i), advance 278, 0 horiBearing 86,730 -->
+ <path transform="translate(1000,0)" d="
+ M 92, 935
+ L 186, 935
+ L 186, 425
+ L 92, 425
+ L 92, 935
+ M 88, 261
+ A 51, 51 0 1 1 190,261
+ A 51, 51 0 1 1 88,261" />
+ <!-- 72 (r), advance 389, 0 horiBearing 80,522 -->
+ <path transform="translate(1341.5,0)" d="
+ M 80, 935
+ L 174, 935
+ L 174, 703
+ C 174, 575 229, 495 313, 495
+ C 329, 495 348, 497 365, 504
+ L 365, 420
+ C 345, 416 331, 413 303, 413
+ C 249, 413 195, 451 170, 504
+ L 168, 504
+ L 168, 425
+ L 80, 425
+ L 80, 935 " />
+ <!-- 6f (o), advance 611, 0 horiBearing 46,522 -->
+ <path transform="translate(1826,0)" d="
+ M 46, 680
+ C 46, 826 152, 947 306, 947
+ C 459, 947 565, 826 565, 680
+ C 565, 525 461, 413 306, 413
+ C 150, 413 46, 525 46, 680
+ M 146, 680
+ C 146, 583 205, 489 306, 489
+ C 406, 489 465, 583 465, 680
+ C 465, 771 416, 871 306, 871
+ C 195, 871 146, 771 146, 680 " />
+ <!-- bounds: 38, 205 <-> 2232, 947 -->
+ </g> </g>
+ </g>
+
+ <g id="cairo_logo_with_text">
+ <!-- The logo (scarab and dung), with the text 'cairo' below, the dot of the 'i' positioned between the hind legs of the scarab -->
+ <!-- dimensions: 300x490, centered -->
+ <use xlink:href="#cairo_logo_top-centered" transform="translate(0, -245)" />
+ <use xlink:href="#cairo_text" transform="translate(0, 245)" />
+ </g>
+
+ <g id="cairo_banner">
+ <!-- The logo on the left, the text 'cairo' in the center, and a mirror image of the logo on the right -->
+ <!-- The logos are scaled such that the scarab body nearly matches the height of the text characters (excepting the 'i')
+ and the dung should nearly aligns with the dot of the 'i'. The bottoms of the logos are aligned with the bottom of the text. -->
+ <!-- dimensions: 370x88, centered -->
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(-180, 40), scale(0.1944)" />
+ <use xlink:href="#cairo_text_small" transform="translate(0, 42)" fill="black" />
+ <use xlink:href="#cairo_logo_bottomleft-centered" transform="translate(180, 40), scale(0.1944), scale(-1, 1)" />
+ </g>
+ </defs>
+ <g transform="translate(5, -500)">
+ <use xlink:href="#cairo_logo_with_text" transform="translate(150, 245)" />
+ </g>
+</svg>]]>
+ </svgDoc>
+ <colorPalettes>
+ </colorPalettes>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-doc.ttx b/test/cairo-svg-test-doc.ttx
new file mode 100644
index 000000000..c2cdb2817
--- /dev/null
+++ b/test/cairo-svg-test-doc.ttx
@@ -0,0 +1,689 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ <GlyphID id="8" name="seven"/>
+ <GlyphID id="9" name="eight"/>
+ <GlyphID id="10" name="nine"/>
+ <GlyphID id="11" name="A"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x6d925ed5"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:40 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="12"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="A" width="1100" lsb="0"/>
+ <mtx name="eight" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="nine" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="seven" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
+ <map code="0x38" name="eight"/><!-- DIGIT EIGHT -->
+ <map code="0x39" name="nine"/><!-- DIGIT NINE -->
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="A" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="eight" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="nine" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Doc
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Doc Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+ <rect x="10" y="-90" width="80" height="80"
+ fill="none" stroke="black" stroke-width="10"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg">
+ <rect x="-4" y="-14" width="8" height="8"
+ fill="none" stroke="black" stroke-width="1"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <image x="0" y="-1000" width="1000" height="1000"
+ xlink:href="data:image/png;base64,
+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
+BNcsrHnv+f9Qc51Rfhz5VAAAAABJRU5ErkJggg=="/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <image x="0" y="-1000" width="1000" height="1000"
+ transform="scale(0.5) rotate(-45),translate(800,500)"
+ xlink:href="data:image/png;base64,
+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
+BNcsrHnv+f9Qc51Rfhz5VAAAAABJRU5ErkJggg=="/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ <rect x="100" y="-900" width="800" height="400"/>
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="8" startGlyphID="8">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ <rect x="0" y="0" width="1" height="0.5"/>
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="9" startGlyphID="9">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ </clipPath>
+
+ <clipPath id="clip2" clipPathUnits="userSpaceOnUse" >
+ <rect x="100" y="-900" width="800" height="400"/>
+ </clipPath>
+
+ <g clip-path="url(#clip)">
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip2)" />
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="10" startGlyphID="10">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ </clipPath>
+
+ <clipPath id="clip2" clipPathUnits="objectBoundingBox">
+ <rect x="0" y="0" width="1" height="0.5"/>
+ </clipPath>
+
+ <g clip-path="url(#clip)">
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip2)" />
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="11" startGlyphID="11">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink" >
+ <defs>
+ <circle id="circle"
+ cx="0" cy="0" r="250" />
+ </defs>
+
+ <g opacity="0.5">
+ <use xlink:href="#circle" x="330" y="-500"
+ fill="red" />
+ <use xlink:href="#circle" x="670" y="-500"
+ fill="green" />
+ </g>
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-fill.ttx b/test/cairo-svg-test-fill.ttx
new file mode 100644
index 000000000..b6867ec8f
--- /dev/null
+++ b/test/cairo-svg-test-fill.ttx
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ <GlyphID id="8" name="seven"/>
+ <GlyphID id="9" name="eight"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x71e2812"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:40 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="10"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="56"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="eight" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="seven" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
+ <map code="0x38" name="eight"/><!-- DIGIT EIGHT -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="eight" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Fill
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Fill Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="indigo" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="#AA55AA" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="#A5A" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="rgb (75, 0 , 130)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="currentColor" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="var(--color1, red)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="magenta" fill-opacity="0.5" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="8" startGlyphID="8">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ color="green" >
+ <rect x="100" y="-750" width="800" height="500"
+ fill="currentColor" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="9" startGlyphID="9">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <g transform="scale(5,5) translate(0,-150)">
+ <polygon fill-rule="nonzero"
+ points="50,0 21,90 98,35 2,35 79,90"/>
+ <polygon fill-rule="evenodd"
+ points="150,0 121,90 198,35 102,35 179,90"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-gradient.ttx b/test/cairo-svg-test-gradient.ttx
new file mode 100644
index 000000000..4a7a22175
--- /dev/null
+++ b/test/cairo-svg-test-gradient.ttx
@@ -0,0 +1,441 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ <GlyphID id="8" name="seven"/>
+ <GlyphID id="9" name="eight"/>
+ <GlyphID id="10" name="nine"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x4322c7de"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:39 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="11"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="57"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="eight" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="nine" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="seven" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
+ <map code="0x38" name="eight"/><!-- DIGIT EIGHT -->
+ <map code="0x39" name="nine"/><!-- DIGIT NINE -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="eight" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="nine" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Gradient
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Gradient Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x21="66%">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="0.5" />
+ </linearGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x2="66%"
+ spreadMethod="reflect">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x2="66%"
+ spreadMethod="repeat">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="300" y1="-500" x2="600" y2="-500"
+ gradientUnits="userSpaceOnUse">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" gradientTransform="rotate(45)">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="50%" cy="50%"
+ fx="0.75" fy="0.35" r="0.5">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="75%" cy="25%" r="33%"
+ fx="0.64" fy="0.18" fr="0.17"
+ spreadMethod="reflect" >
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="8" startGlyphID="8">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="75%" cy="25%" r="33%"
+ fx="0.64" fy="0.18" fr="0.17"
+ spreadMethod="repeat" >
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="9" startGlyphID="9">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="450" cy="-550" r="400"
+ fx="600" fy="-400" fr="10"
+ gradientUnits="userSpaceOnUse" >
+ <stop offset="0%" stop-color="red" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="0.5" />
+ </radialGradient>
+ </defs>
+ <rect x="0" y="-1000" width="1000" height="1000" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="10" startGlyphID="10">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="50%" cy="25%"
+ fx="0.75" fy="0.35" r="0.5"
+ gradientTransform="scale(1, 2)">
+ <stop offset="0%" stop-color="red" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-path.ttx b/test/cairo-svg-test-path.ttx
new file mode 100644
index 000000000..9173a537d
--- /dev/null
+++ b/test/cairo-svg-test-path.ttx
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x20ff0b91"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:40 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="5"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="51"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Path
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Path Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M 200 -200
+ L 500 -500
+ H 800
+ V -200
+ " />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M200,-400
+ C200,-200
+ 500,-200
+ 500,-400
+ S800,-600
+ 800,-400" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M200,-300
+ Q400,-50
+ 600,-300
+ T1000,-300"
+ />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M500,-500
+ L 712 -712
+ A300,300 0 1,0 712, -288 z"
+ />
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-shapes.ttx b/test/cairo-svg-test-shapes.ttx
new file mode 100644
index 000000000..15a573a64
--- /dev/null
+++ b/test/cairo-svg-test-shapes.ttx
@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0xa8919a30"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:40 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="8"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="54"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Shapes
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Shapes Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500" rx="100" ry="100"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <circle cx="500" cy="-500" r="400"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <ellipse cx="500" cy="-500" rx="400" ry="200"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="200" y1="-200" x2="800" y2="-800" stroke="black" stroke-width="20"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline fill="none" stroke="black" stroke-width="20"
+ points="100, -100,
+ 300, -100,
+ 300, -300,
+ 500, -300,
+ 500, -500,
+ 700, -500
+ 700, -700
+ 900, -700
+ 900, -900" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">
+<polygon points="350, -75
+ 379, -161
+ 469, -161
+ 397, -215
+ 423, -301
+ 350, -250
+ 277, -301
+ 303, -215
+ 231, -161
+ 321, -161" />
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-stroke.ttx b/test/cairo-svg-test-stroke.ttx
new file mode 100644
index 000000000..a403da928
--- /dev/null
+++ b/test/cairo-svg-test-stroke.ttx
@@ -0,0 +1,608 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ <GlyphID id="8" name="seven"/>
+ <GlyphID id="9" name="eight"/>
+ <GlyphID id="10" name="nine"/>
+ <GlyphID id="11" name="A"/>
+ <GlyphID id="12" name="B"/>
+ <GlyphID id="13" name="C"/>
+ <GlyphID id="14" name="D"/>
+ <GlyphID id="15" name="E"/>
+ <GlyphID id="16" name="F"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x2d1b9ede"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:39 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="17"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="70"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="A" width="1100" lsb="0"/>
+ <mtx name="B" width="1100" lsb="0"/>
+ <mtx name="C" width="1100" lsb="0"/>
+ <mtx name="D" width="1100" lsb="0"/>
+ <mtx name="E" width="1100" lsb="0"/>
+ <mtx name="F" width="1100" lsb="0"/>
+ <mtx name="eight" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="nine" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="seven" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
+ <map code="0x38" name="eight"/><!-- DIGIT EIGHT -->
+ <map code="0x39" name="nine"/><!-- DIGIT NINE -->
+ <map code="0x41" name="A"/><!-- LATIN CAPITAL LETTER A -->
+ <map code="0x42" name="B"/><!-- LATIN CAPITAL LETTER B -->
+ <map code="0x43" name="C"/><!-- LATIN CAPITAL LETTER C -->
+ <map code="0x44" name="D"/><!-- LATIN CAPITAL LETTER D -->
+ <map code="0x45" name="E"/><!-- LATIN CAPITAL LETTER E -->
+ <map code="0x46" name="F"/><!-- LATIN CAPITAL LETTER F -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="A" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="B" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="C" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="D" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="E" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="F" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="eight" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="nine" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Stroke
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Stroke Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="indigo" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="#AA55AA" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="#A5A" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="rgb(75,0,130)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="currentColor" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="var(--color1, red)" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="magenta" stroke-opacity="0.5" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="8" startGlyphID="8">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ color="green" >
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="currentColor" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="9" startGlyphID="9">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-900" x2="900" y2="-900"
+ fill="none"
+ stroke-width="100"
+ stroke="black" />
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="200"
+ stroke="black" />
+ <line x1="100" y1="-100" x2="900" y2="-100"
+ fill="none"
+ stroke-width="300"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="10" startGlyphID="10">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-900" x2="900" y2="-900"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="butt"
+ stroke="black" />
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="round"
+ stroke="black" />
+ <line x1="100" y1="-100" x2="900" y2="-100"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="square"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="11" startGlyphID="11">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-950" x2="900" y2="-950"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="none"
+ stroke="black" />
+ <line x1="100" y1="-750" x2="900" y2="-750"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200"
+ stroke="black" />
+ <line x1="100" y1="-550" x2="900" y2="-550"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50"
+ stroke="black" />
+ <line x1="100" y1="-350" x2="900" y2="-350"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100"
+ stroke="black" />
+ <line x1="100" y1="-150" x2="900" y2="-150"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100 150"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="12" startGlyphID="12">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-950" x2="900" y2="-950"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="none"
+ stroke="black" />
+ <line x1="100" y1="-750" x2="900" y2="-750"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-550" x2="900" y2="-550"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-350" x2="900" y2="-350"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-150" x2="900" y2="-150"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100 150"
+ stroke-dashoffset="100"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="13" startGlyphID="13">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="miter"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="14" startGlyphID="14">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="round"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="15" startGlyphID="15">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="bevel"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="16" startGlyphID="16">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="miter"
+ stroke-miterlimit="2"
+ stroke="black" />
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-svg-test-transform.ttx b/test/cairo-svg-test-transform.ttx
new file mode 100644
index 000000000..1f07c05ad
--- /dev/null
+++ b/test/cairo-svg-test-transform.ttx
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ <GlyphID id="1" name="zero"/>
+ <GlyphID id="2" name="one"/>
+ <GlyphID id="3" name="two"/>
+ <GlyphID id="4" name="three"/>
+ <GlyphID id="5" name="four"/>
+ <GlyphID id="6" name="five"/>
+ <GlyphID id="7" name="six"/>
+ <GlyphID id="8" name="seven"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x970fff1"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000011"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Fri Jul 1 06:21:39 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="100"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="1"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="9"/>
+ <maxPoints value="4"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="0"/>
+ <maxCompositeContours value="0"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="0"/>
+ <maxComponentDepth value="0"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="48"/>
+ <usLastCharIndex value="55"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ <mtx name="five" width="1100" lsb="0"/>
+ <mtx name="four" width="1100" lsb="0"/>
+ <mtx name="one" width="1100" lsb="0"/>
+ <mtx name="seven" width="1100" lsb="0"/>
+ <mtx name="six" width="1100" lsb="0"/>
+ <mtx name="three" width="1100" lsb="0"/>
+ <mtx name="two" width="1100" lsb="0"/>
+ <mtx name="zero" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
+ <map code="0x31" name="one"/><!-- DIGIT ONE -->
+ <map code="0x32" name="two"/><!-- DIGIT TWO -->
+ <map code="0x33" name="three"/><!-- DIGIT THREE -->
+ <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+ <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+ <map code="0x36" name="six"/><!-- DIGIT SIX -->
+ <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
+ <contour>
+ <pt x="0" y="0" on="1"/>
+ <pt x="0" y="1000" on="1"/>
+ <pt x="1000" y="1000" on="1"/>
+ <pt x="1000" y="0" on="1"/>
+ </contour>
+ <instructions/>
+ </TTGlyph>
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Transform
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Svg Test Transform Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="1" startGlyphID="1">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <use xlink:href="#square" transform="translate(600, -400)"/>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="2" startGlyphID="2">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -400)">
+ <use xlink:href="#square" transform="scale(1.5, 0.5)"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="3" startGlyphID="3">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(600, -600)">
+ <use xlink:href="#square" transform="rotate(30)"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="4" startGlyphID="4">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -400)">
+ <use xlink:href="#square" transform="skewX(30)"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="5" startGlyphID="5">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -500)">
+ <use xlink:href="#square" transform="skewY(30)"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="6" startGlyphID="6">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(600, -600)">
+ <use xlink:href="#square" transform="matrix(1, 0.4, -0.6, 1.1, 50, -70)"/>
+ </g>
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="7" startGlyphID="7">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <path id="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" />
+ </defs>
+ <use xlink:href="#heart"
+ transform="translate(10, -650)
+ rotate(-10 50 100)
+ translate(-166 125.5)
+ skewX(40)
+ scale(1 0.5),scale(8, 8)"
+ fill="grey"/>
+ <use xlink:href="#heart"
+ transform="translate(300, -800),scale(6, 6)"
+ fill="none" stroke="red" />
+</svg>]]>
+ </svgDoc>
+ <svgDoc endGlyphID="8" startGlyphID="8">
+ <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="c1"
+ cx="100" cy="100" r="80"
+ fill="none"
+ stroke="black"
+ stroke-width="20" />
+ <circle id="c2"
+ cx="100" cy="100" r="80"
+ fill="none"
+ stroke="black"
+ stroke-width="20"
+ transform="scale(3,3)" />
+ </defs>
+
+ <use xlink:href="#c1" x="100" y="-900"/>
+ <use xlink:href="#c2" x="300" y="-700"/>
+
+</svg>]]>
+ </svgDoc>
+ </SVG>
+
+</ttFont>
diff --git a/test/cairo-test.c b/test/cairo-test.c
index cbd4fb1ab..5a2cf1a74 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1825,3 +1825,70 @@ cairo_test_status_from_status (const cairo_test_context_t *ctx,
return CAIRO_TEST_FAILURE;
}
+
+#if CAIRO_HAS_FT_FONT
+
+#include "cairo-ft.h"
+
+static void
+_free_face (void *face)
+{
+ FT_Done_Face ((FT_Face) face);
+}
+
+static FT_Library ft_library = NULL;
+
+#endif
+
+static const cairo_user_data_key_t ft_font_key;
+
+cairo_test_status_t
+cairo_test_ft_select_font_from_file (cairo_t *cr,
+ const char *filename)
+{
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+#if CAIRO_HAS_FT_FONT
+ FT_Face face;
+ cairo_font_face_t *font_face;
+ char *srcdir_filename = NULL;
+
+ if (access (filename, F_OK) != 0) {
+ if (ctx->srcdir) {
+ xasprintf (&srcdir_filename, "%s/%s", ctx->srcdir, filename);
+ filename = srcdir_filename;
+ }
+ }
+
+ if (access (filename, F_OK) != 0) {
+ cairo_test_log (ctx, "Could not find font file: %s\n", filename);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ if (!ft_library) {
+ if (FT_Init_FreeType (&ft_library))
+ return CAIRO_TEST_FAILURE;
+ }
+
+ if (FT_New_Face (ft_library, filename, 0, &face)) {
+ cairo_test_log (ctx, "FT_New_Face failed loading font file: %s\n", filename);
+ return CAIRO_TEST_FAILURE;
+ }
+
+ free (srcdir_filename);
+ font_face = cairo_ft_font_face_create_for_ft_face (face, 0);
+ if (cairo_font_face_status (font_face))
+ return CAIRO_TEST_FAILURE;
+
+ cairo_font_face_set_user_data (font_face, &ft_font_key, face, _free_face);
+ cairo_set_font_face (cr, font_face);
+ if (cairo_status (cr))
+ return CAIRO_TEST_FAILURE;
+
+ cairo_font_face_destroy (font_face);
+
+ return CAIRO_TEST_SUCCESS;
+#else
+ cairo_test_log (ctx, "cairo_test_ft_select_font_from_file() requires the FreeType backend\n");
+ return CAIRO_TEST_FAILURE;
+#endif
+}
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 6169c5371..adff2583c 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -323,6 +323,11 @@ cairo_t *
cairo_test_create (cairo_surface_t *surface,
const cairo_test_context_t *ctx);
+/* Set font face from a font file in build or src dir, using the FT backend. */
+cairo_test_status_t
+cairo_test_ft_select_font_from_file (cairo_t *cr,
+ const char *filename);
+
CAIRO_END_DECLS
#endif
diff --git a/test/ft-svg-cairo-logo.c b/test/ft-svg-cairo-logo.c
new file mode 100644
index 000000000..22fb25f23
--- /dev/null
+++ b/test/ft-svg-cairo-logo.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2022 Adrian Johnson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Adrian Johnson <ajohnson@redneon.com>
+ */
+
+#include "cairo-test.h"
+#include <cairo-ft.h>
+
+#define FONT_SIZE 200
+#define MARGIN 5
+#define WIDTH (FONT_SIZE + MARGIN*2)
+#define HEIGHT (FONT_SIZE + MARGIN*2)
+
+#define FONT_FILE "cairo-logo-font.ttf"
+
+/* Character code in font of the logo */
+#define CAIRO_LOGO_CHAR "A"
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_test_status_t result;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ result = cairo_test_ft_select_font_from_file (cr, FONT_FILE);
+ if (result)
+ return result;
+
+ cairo_set_font_size (cr, FONT_SIZE);
+ cairo_move_to (cr, MARGIN, FONT_SIZE + MARGIN);
+
+ cairo_show_text (cr, CAIRO_LOGO_CHAR);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (ft_svg_cairo_logo,
+ "Test cairo logo SVG font",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw)
diff --git a/test/ft-svg-color-font.c b/test/ft-svg-color-font.c
new file mode 100644
index 000000000..56510feca
--- /dev/null
+++ b/test/ft-svg-color-font.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2022 Adrian Johnson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Adrian Johnson <ajohnson@redneon.com>
+ */
+
+#include "cairo-test.h"
+#include <cairo-ft.h>
+
+#define FONT_SIZE 50
+#define MARGIN 5
+#define WIDTH (FONT_SIZE*4 + MARGIN*2)
+#define HEIGHT (FONT_SIZE*3 + MARGIN*5)
+
+/* Check the full name to ensure we got an SVG font. */
+#define FONT_FAMILY "Twitter Color Emoji"
+#define FONT_FULLNAME "Twitter Color Emoji SVGinOT"
+
+static const char spade_utf8[] = { 0xe2, 0x99, 0xa0, 0x00 }; /* U+2660 glyph 87 */
+static const char club_utf8[] = { 0xe2, 0x99, 0xa3, 0x00 }; /* U+2663 glyph 88 */
+static const char heart_utf8[] = { 0xe2, 0x99, 0xa5, 0x00 }; /* U+2665 glyph 89 */
+static const char diamond_utf8[] = { 0xe2, 0x99, 0xa6, 0x00 }; /* U+2666 glyph 90 */
+
+static cairo_test_status_t
+set_color_emoji_font (cairo_t *cr)
+{
+ cairo_font_options_t *font_options;
+ cairo_font_face_t *font_face;
+ FcPattern *pattern;
+ FcPattern *resolved;
+ FcChar8 *font_name;
+ FcResult result;
+
+ pattern = FcPatternCreate ();
+ if (pattern == NULL)
+ return CAIRO_TEST_NO_MEMORY;
+
+ FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) FONT_FAMILY);
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+
+ font_options = cairo_font_options_create ();
+ cairo_get_font_options (cr, font_options);
+ cairo_ft_font_options_substitute (font_options, pattern);
+
+ FcDefaultSubstitute (pattern);
+ resolved = FcFontMatch (NULL, pattern, &result);
+ if (resolved == NULL) {
+ FcPatternDestroy (pattern);
+ return CAIRO_TEST_NO_MEMORY;
+ }
+
+ if (FcPatternGetString (resolved, FC_FULLNAME, 0, &font_name) == FcResultMatch) {
+ if (strcmp((char*)font_name, FONT_FULLNAME) != 0) {
+ const cairo_test_context_t *ctx = cairo_test_get_context (cr);
+ cairo_test_log (ctx, "Could not find %s font\n", FONT_FULLNAME);
+ return CAIRO_TEST_UNTESTED;
+ }
+ } else {
+ return CAIRO_TEST_FAILURE;
+ }
+
+ font_face = cairo_ft_font_face_create_for_pattern (resolved);
+ cairo_set_font_face (cr, font_face);
+
+ cairo_font_options_destroy (font_options);
+ cairo_font_face_destroy (font_face);
+ FcPatternDestroy (pattern);
+ FcPatternDestroy (resolved);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_font_options_t *font_options;
+ cairo_test_status_t result;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ result = set_color_emoji_font (cr);
+ if (result != CAIRO_TEST_SUCCESS)
+ return result;
+
+ cairo_set_font_size (cr, FONT_SIZE);
+
+ /* Color glyphs */
+ cairo_move_to (cr, MARGIN, FONT_SIZE + MARGIN);
+ cairo_show_text (cr, diamond_utf8);
+ cairo_show_text (cr, club_utf8);
+ cairo_show_text (cr, heart_utf8);
+ cairo_show_text (cr, spade_utf8);
+
+ /* Non-color glyphs */
+ font_options = cairo_font_options_create ();
+ cairo_font_options_set_color_mode (font_options, CAIRO_COLOR_MODE_NO_COLOR);
+ cairo_set_font_options (cr, font_options);
+ cairo_move_to (cr, MARGIN, FONT_SIZE*2 + MARGIN*2);
+ cairo_show_text (cr, diamond_utf8);
+ cairo_show_text (cr, club_utf8);
+ cairo_show_text (cr, heart_utf8);
+ cairo_show_text (cr, spade_utf8);
+
+ /* Color glyph text path */
+ cairo_font_options_set_color_mode (font_options, CAIRO_COLOR_MODE_COLOR);
+ cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+ cairo_move_to (cr, MARGIN, FONT_SIZE*3 + MARGIN*3);
+ cairo_text_path (cr, diamond_utf8);
+ cairo_text_path (cr, club_utf8);
+ cairo_text_path (cr, heart_utf8);
+ cairo_text_path (cr, spade_utf8);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (ft_svg_color_font,
+ "Test color font",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw)
diff --git a/test/ft-svg-render.c b/test/ft-svg-render.c
new file mode 100644
index 000000000..9b0351b10
--- /dev/null
+++ b/test/ft-svg-render.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright © 2022 Adrian Johnson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Adrian Johnson <ajohnson@redneon.com>
+ */
+
+#include "cairo-test.h"
+#include <cairo-ft.h>
+
+#define GLYPH_SIZE 50
+#define PAD 5
+#define WIDTH (4*(GLYPH_SIZE + PAD) + PAD)
+#define HEIGHT WIDTH
+
+//#define CLIP 1
+#define LOG_EXTENTS 1
+
+static cairo_test_status_t
+draw_font (cairo_t *cr, int width, int height, const char *font_file)
+{
+ cairo_test_status_t result;
+ char buf[10];
+ cairo_text_extents_t extents;
+ cairo_font_options_t *font_options;
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+
+ result = cairo_test_ft_select_font_from_file (cr, font_file);
+ if (result)
+ return result;
+
+ font_options = cairo_font_options_create ();
+ cairo_font_options_set_color_mode (font_options, CAIRO_COLOR_MODE_NO_COLOR);
+// cairo_set_font_options (cr, font_options);
+ cairo_font_options_destroy (font_options);
+
+ cairo_set_font_size (cr, GLYPH_SIZE);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ int x = j * (GLYPH_SIZE + PAD) + PAD;
+ int y = i * (GLYPH_SIZE + PAD) + PAD;
+ int glyph_number = 4*i + j;
+ buf[0] = glyph_number < 10 ? '0' + glyph_number : 'A' + glyph_number - 10;
+ buf[1] = 0;
+ cairo_save (cr);
+ cairo_text_extents (cr, buf, &extents);
+#if LOG_EXTENTS
+ cairo_test_log (cairo_test_get_context (cr),
+ "Char '%c' extents: x_bearing: %f y_bearing: %f width: %f height: %f x_advance: %f y_advance: %f\n",
+ buf[0],
+ extents.x_bearing,
+ extents.y_bearing,
+ extents.width,
+ extents.height,
+ extents.x_advance,
+ extents.y_advance);
+#endif
+#if CLIP
+ cairo_rectangle (cr, x, y, GLYPH_SIZE, GLYPH_SIZE);
+ cairo_clip (cr);
+#endif
+ cairo_move_to (cr, x, y + GLYPH_SIZE);
+ cairo_show_text (cr, buf);
+ cairo_restore (cr);
+ if (cairo_status (cr)) {
+ cairo_test_log (cairo_test_get_context (cr),
+ "cairo_show_text() failed with \"%s\"\n",
+ buf);
+ return CAIRO_TEST_FAILURE;
+ }
+ }
+ }
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+#define DRAW_FUNC(name) \
+static cairo_test_status_t \
+draw_##name (cairo_t *cr, int width, int height) { \
+ return draw_font (cr, width, height, "cairo-svg-test-" #name ".ttf"); \
+}
+
+DRAW_FUNC(doc)
+CAIRO_TEST (ft_svg_render_doc,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_doc)
+
+DRAW_FUNC(fill)
+CAIRO_TEST (ft_svg_render_fill,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_fill)
+
+DRAW_FUNC(gradient)
+CAIRO_TEST (ft_svg_render_gradient,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_gradient)
+
+DRAW_FUNC(path)
+CAIRO_TEST (ft_svg_render_path,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_path)
+
+DRAW_FUNC(shapes)
+CAIRO_TEST (ft_svg_render_shapes,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_shapes)
+
+DRAW_FUNC(stroke)
+CAIRO_TEST (ft_svg_render_stroke,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_stroke)
+
+DRAW_FUNC(transform)
+CAIRO_TEST (ft_svg_render_transform,
+ "Test SVG glyph render",
+ "svgrender", /* keywords */
+ NULL, /* requirements */
+ WIDTH, HEIGHT,
+ NULL, draw_transform)
diff --git a/test/meson.build b/test/meson.build
index f1612e670..4638dcca6 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -427,6 +427,15 @@ test_ft_font_sources = [
'ft-text-antialias-none.c',
]
+test_ft_svg_font_sources = [
+ 'ft-svg-color-font.c',
+]
+
+test_ft_svg_ttx_font_sources = [
+ 'ft-svg-cairo-logo.c',
+ 'ft-svg-render.c'
+]
+
test_gl_sources = [
'gl-device-release.c',
'gl-oversized-surface.c',
@@ -517,6 +526,17 @@ ps2png_sources = [
'ps2png.c',
]
+test_ttx_fonts = [
+ 'cairo-logo-font.ttx',
+ 'cairo-svg-test-doc.ttx',
+ 'cairo-svg-test-fill.ttx',
+ 'cairo-svg-test-gradient.ttx',
+ 'cairo-svg-test-path.ttx',
+ 'cairo-svg-test-shapes.ttx',
+ 'cairo-svg-test-stroke.ttx',
+ 'cairo-svg-test-transform.ttx',
+]
+
build_any2ppm = false
has_multipage_surfaces = false
add_fallback_resolution = false
@@ -527,6 +547,12 @@ endif
if feature_conf.get('CAIRO_HAS_FT_FONT', 0) == 1 and feature_conf.get('CAIRO_HAS_FC_FONT', 0) == 1
test_sources += test_ft_font_sources
+ if conf.get('HAVE_FT_SVG_DOCUMENT', 0) == 1
+ test_sources += test_ft_svg_font_sources
+ if conf.get('CAIRO_CAN_TEST_TTX_FONT', 0) == 1
+ test_sources += test_ft_svg_ttx_font_sources
+ endif
+ endif
endif
if feature_conf.get('CAIRO_HAS_QUARTZ_SURFACE', 0) == 1
@@ -639,10 +665,22 @@ endforeach
if build_machine.system() != 'windows'
run_command('ln', '-sf',
meson.current_source_dir(),
- join_paths(meson.current_build_dir(), 'srcdir'),
+ meson.current_build_dir() / 'srcdir',
check: true)
endif
+if ttx.found()
+ # By default, if the output file exists, ttx creates a new name. We specify the full
+ # output name to make ttx overwrite the existing file instead of creating a new file.
+ foreach ttx_font : test_ttx_fonts
+ custom_target(ttx_font,
+ input: ttx_font,
+ command: [ ttx, '-q', '-o', '@OUTDIR@' / '@BASENAME@.ttf', '@INPUT@' ],
+ output: '@BASENAME@.ttf',
+ build_by_default: true)
+ endforeach
+endif
+
env = environment()
env.set('srcdir', meson.current_source_dir())
@@ -653,3 +691,9 @@ test('cairo', exe,
suite: ['cairo-test-suite', 'slow'],
workdir: meson.current_build_dir(),
depends: test_depends)
+
+# The SVG renderer debug tools can only be built if the _cairo_debug_svg_render()
+# function has been exposed by defining DEBUG_SVG_RENDER
+if conf.get('HAVE_FT_SVG_DOCUMENT', 0) == 1 and cc.get_define('DEBUG_SVG_RENDER') != ''
+ subdir('svg')
+endif
diff --git a/test/reference/ft-svg-cairo-logo.ref.png b/test/reference/ft-svg-cairo-logo.ref.png
new file mode 100644
index 000000000..0c92934d6
--- /dev/null
+++ b/test/reference/ft-svg-cairo-logo.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-color-font.ref.png b/test/reference/ft-svg-color-font.ref.png
new file mode 100644
index 000000000..22bafde03
--- /dev/null
+++ b/test/reference/ft-svg-color-font.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-doc.ref.png b/test/reference/ft-svg-render-doc.ref.png
new file mode 100644
index 000000000..e7ecf7f1a
--- /dev/null
+++ b/test/reference/ft-svg-render-doc.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-fill.ref.png b/test/reference/ft-svg-render-fill.ref.png
new file mode 100644
index 000000000..a72cdd1f2
--- /dev/null
+++ b/test/reference/ft-svg-render-fill.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-gradient.ref.png b/test/reference/ft-svg-render-gradient.ref.png
new file mode 100644
index 000000000..d647dc06a
--- /dev/null
+++ b/test/reference/ft-svg-render-gradient.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-path.ref.png b/test/reference/ft-svg-render-path.ref.png
new file mode 100644
index 000000000..2667059cc
--- /dev/null
+++ b/test/reference/ft-svg-render-path.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-shapes.ref.png b/test/reference/ft-svg-render-shapes.ref.png
new file mode 100644
index 000000000..209e0ddb3
--- /dev/null
+++ b/test/reference/ft-svg-render-shapes.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-stroke.ref.png b/test/reference/ft-svg-render-stroke.ref.png
new file mode 100644
index 000000000..86f1ab9b6
--- /dev/null
+++ b/test/reference/ft-svg-render-stroke.ref.png
Binary files differ
diff --git a/test/reference/ft-svg-render-transform.ref.png b/test/reference/ft-svg-render-transform.ref.png
new file mode 100644
index 000000000..dcc372aac
--- /dev/null
+++ b/test/reference/ft-svg-render-transform.ref.png
Binary files differ
diff --git a/test/svg/README b/test/svg/README
new file mode 100644
index 000000000..c4504dc9b
--- /dev/null
+++ b/test/svg/README
@@ -0,0 +1,22 @@
+build_ttx_fonts.py
+==================
+Is used to create the test/*.ttx files used for testing the SVG glyph renderer.
+
+build_ttx_fonts.py will look for files of the form
+
+<font-name>.<char>.<test-name>.svg
+
+in the input directory, and using svg-font-template.ttx, create <font-name>.ttx
+files that contain one glyph for each svg file. Each <font-name>.ttx will contain
+a glyph for each svg with the matching <font-name> prefix. Each glyphs will be mapped
+to the <char> i nthe svg filename. The <char> must be one of 0-9,A-F.
+
+svg-render.c
+============
+svg-render renders SVG files using both librsvg and cairo-svg-glyph-render.c.
+It is used for testing cairo-svg-glyph-render.c during development.
+
+To use svg-render, cairo must be built with CFLAGS="-DDEBUG_SVG_RENDER" to enable the
+_cairo_debug_svg_render() function.
+
+
diff --git a/test/svg/build_ttx_fonts.py b/test/svg/build_ttx_fonts.py
new file mode 100755
index 000000000..d7e7f5b8f
--- /dev/null
+++ b/test/svg/build_ttx_fonts.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+
+# Build the ttx cairo svg test fonts from svg files
+# The svg files use the naming convention
+# <font-name>.<char>.<test-name>.svg
+# eg "circle.A.cx_cy_r.svg"
+#
+# <font-name> is use to create the name of the ttx font.
+# <char> is a ascii hex character (uppercase) that the font fill map to the SVG description.
+# <test-name> is a descriptive name of the SVG file and is not used to build the font…
+#
+# This script looks for all files matching the above pattern and
+# creates one ttx font for each unique <font-name>. Each font will
+# contain up to 16 characters. The SVG description of each character
+# and the character that maps to the SVG description is obtained from
+# the SVG file beginning with <font-name>.<char>.
+
+import argparse
+import os
+import re
+import sys
+import xml.dom.minidom
+
+TEMPLATE_FILE="svg-font-template.ttx"
+
+glyph_names = {
+ '0': 'zero',
+ '1': 'one',
+ '2': 'two',
+ '3': 'three',
+ '4': 'four',
+ '5': 'five',
+ '6': 'six',
+ '7': 'seven',
+ '8': 'eight',
+ '9': 'nine',
+ 'A': 'A',
+ 'B': 'B',
+ 'C': 'C',
+ 'D': 'D',
+ 'E': 'E',
+ 'F': 'F'
+}
+
+# files is list of (char, filename)
+def build_font(font_name, files, in_dir, out_dir, no_reformat):
+ name = "cairo-svg-test-" + font_name
+ doc = xml.dom.minidom.parse(os.path.join(in_dir, TEMPLATE_FILE))
+ glyph_id = 1
+ text_nl = doc.createTextNode('\n\n')
+ for f in sorted(files):
+ glyph_name = glyph_names[f[0]]
+
+ glyph_order = doc.getElementsByTagName('GlyphOrder')[0]
+ glyph_id_elem = doc.createElement('GlyphID')
+ glyph_id_elem.setAttribute('id', str(glyph_id))
+ glyph_id_elem.setAttribute('name', glyph_name)
+ glyph_order.appendChild(glyph_id_elem)
+ glyph_order.appendChild(text_nl)
+
+ hmtx = doc.getElementsByTagName('hmtx')[0]
+ mtx = doc.createElement('mtx')
+ mtx.setAttribute('name', glyph_name)
+ mtx.setAttribute('width', '1100')
+ mtx.setAttribute('lsb', '0')
+ hmtx.appendChild(mtx)
+
+ cmap_format = doc.getElementsByTagName('cmap_format_4')[0]
+ map = doc.createElement('map')
+ map.setAttribute('code', hex(ord(f[0])))
+ map.setAttribute('name', glyph_name)
+ cmap_format.appendChild(map)
+
+ glyf = doc.getElementsByTagName('glyf')[0]
+ tt_glyph = doc.createElement('TTGlyph')
+ tt_glyph.setAttribute('name', glyph_name)
+ glyf.appendChild(tt_glyph)
+ contour = doc.createElement('contour')
+ tt_glyph.appendChild(contour)
+ pt = doc.createElement('pt')
+ pt.setAttribute('x', "0")
+ pt.setAttribute('y', "0")
+ pt.setAttribute('on', "1")
+ contour.appendChild(pt)
+ pt = doc.createElement('pt')
+ pt.setAttribute('x', "0")
+ pt.setAttribute('y', "1000")
+ pt.setAttribute('on', "1")
+ contour.appendChild(pt)
+ pt = doc.createElement('pt')
+ pt.setAttribute('x', "1000")
+ pt.setAttribute('y', "1000")
+ pt.setAttribute('on', "1")
+ contour.appendChild(pt)
+ pt = doc.createElement('pt')
+ pt.setAttribute('x', "1000")
+ pt.setAttribute('y', "0")
+ pt.setAttribute('on', "1")
+ contour.appendChild(pt)
+ instructions = doc.createElement('instructions')
+ tt_glyph.appendChild(instructions)
+
+ svg = doc.getElementsByTagName('SVG')[0]
+ svgdoc = doc.createElement('svgDoc')
+ svgdoc.setAttribute('startGlyphID', str(glyph_id))
+ svgdoc.setAttribute('endGlyphID', str(glyph_id))
+ with open(os.path.join(in_dir, f[1]), 'r') as svg_file:
+ svg_data = svg_file.read()
+ cdata = doc.createCDATASection(svg_data)
+ svgdoc.appendChild(cdata)
+ svg.appendChild(svgdoc)
+ glyph_id += 1
+
+ name_record = doc.getElementsByTagName('namerecord')[0]
+ name_record.firstChild.replaceWholeText(name.replace("-", " ").title())
+ name_record = doc.getElementsByTagName('namerecord')[2]
+ name_record.firstChild.replaceWholeText(name.replace("-", " ").title() + " Regular")
+
+ ttx_filename = os.path.join(out_dir, name + '.ttx')
+ ttf_filename = os.path.join(out_dir, name + '.ttf')
+ with open(ttx_filename, 'w') as ttx_file:
+ doc.writexml(ttx_file)
+
+ if not no_reformat:
+ # Convert to ttf and back to ttx. This reformats the ttx file
+ # which allows better quality diffs.
+ if os.path.exists(ttf_filename):
+ os.remove(ttf_filename)
+ os.system("ttx " + ttx_filename)
+ os.remove(ttx_filename)
+ os.system("ttx " + ttf_filename)
+ os.remove(ttf_filename)
+
+def build_file_list(in_dir):
+ dict = {}
+ regex_prog = re.compile(r"([^\.]+)\.(.)\.[^\.]+\.svg", re.ASCII)
+ files = os.listdir(in_dir)
+ for f in files:
+ match = regex_prog.fullmatch(f)
+ if match:
+ fontname = match.group(1)
+ character = match.group(2)
+ if (fontname not in dict):
+ dict[fontname] = [(character, f)];
+ else:
+ dict[fontname].append((character, f))
+ return dict
+
+if __name__=='__main__':
+ parser = argparse.ArgumentParser(description='Build ttx fonts.')
+ parser.add_argument("-i", nargs=1, metavar="indir", default=["."], help="Input directory")
+ parser.add_argument("-o", nargs=1, metavar="outdir", default=["."], help="Output directory")
+ parser.add_argument("-n", action='store_true', help="Don't reformat the output.")
+ args = parser.parse_args()
+ in_dir = args.i[0]
+ out_dir = args.o[0]
+ no_reformat = args.n
+ file_list = build_file_list(in_dir)
+ font_name = None
+ for key, value in file_list.items():
+ build_font(key, value, in_dir, out_dir, no_reformat)
diff --git a/test/svg/doc.0.viewBox1.svg b/test/svg/doc.0.viewBox1.svg
new file mode 100644
index 000000000..c1f55a4eb
--- /dev/null
+++ b/test/svg/doc.0.viewBox1.svg
@@ -0,0 +1,4 @@
+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
+ <rect x="10" y="-90" width="80" height="80"
+ fill="none" stroke="black" stroke-width="10"/>
+</svg>
diff --git a/test/svg/doc.1.viewBox2.svg b/test/svg/doc.1.viewBox2.svg
new file mode 100644
index 000000000..b8f976ba9
--- /dev/null
+++ b/test/svg/doc.1.viewBox2.svg
@@ -0,0 +1,4 @@
+<svg viewBox="-5 -5 10 10" xmlns="http://www.w3.org/2000/svg">
+ <rect x="-4" y="-14" width="8" height="8"
+ fill="none" stroke="black" stroke-width="1"/>
+</svg>
diff --git a/test/svg/doc.2.image.svg b/test/svg/doc.2.image.svg
new file mode 100644
index 000000000..1d03842a9
--- /dev/null
+++ b/test/svg/doc.2.image.svg
@@ -0,0 +1,121 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <image x="0" y="-1000" width="1000" height="1000"
+ xlink:href="data:image/png;base64,
+iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAABhWlDQ1BJQ0MgcHJvZmlsZQAAKJF9
+kT1Iw0AYht+m1opUHOwgopChOlkQFXXUKhShQqkVWnUwufQPmjQkKS6OgmvBwZ/FqoOLs64OroIg
++APi6OSk6CIlfpcUWsR4x3EP733vy913gFAvM9XsGANUzTJS8ZiYya6KwVd0YggBmtMSM/W5ZDIB
+z/F1Dx/f76I8y7vuz9Gj5EwG+ETiWaYbFvEG8dSmpXPeJw6zoqQQnxOPGnRB4keuyy6/cS44LPDM
+sJFOzROHicVCG8ttzIqGSjxJHFFUjfKFjMsK5y3OarnKmvfkLwzltJVlrtMaRByLWEISImRUUUIZ
+FqK0a6SYSNF5zMM/4PiT5JLJVQIjxwIqUCE5fvA/+N1bMz8x7iaFYkDgxbY/hoHgLtCo2fb3sW03
+TgD/M3CltfyVOjDzSXqtpUWOgN5t4OK6pcl7wOUO0P+kS4bkSH5aQj4PvJ/RN2WBvluge83tW/Mc
+pw9AmnqVuAEODoGRAmWve7y7q71v/9Y0+/cDaP1yo4gSHTAAAAAGYktHRAD/AP8A/6C9p5MAAAAJ
+cEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfmBh0FBzE5rnzLAAAAGXRFWHRDb21tZW50AENyZWF0
+ZWQgd2l0aCBHSU1QV4EOFwAAF45JREFUaN5NmnmPZOd13n/vdrdau6p6X2cjw5FIarMjAYmDwP7H
+Buz4K/ib8IMFQaAgtiVLoRRSociZIWc4Pb1Xda237vIu+eNWD91AoYHuu9R7luc85zlHfPyzvwxC
+CJRSzUdKpJAIKVBSIZVESoGUGqkkQggIASkE2miMiTGRQWmNkAqlNVobBMDmPgApwVmHrWu894QQ
+CCHgvcMHh6stdVVh6xpra5xzeO/xLry/NtBcj5AIIRFSEbzFe49+OIQQAgDnPSiBbL4KUki0Nmhj
+EFIhmz8jCGhtMFHzP6kNSjbPkVJuDNC88OGLSCnRujlYAELwBB/w3uOURWlFXSlUrTYHCVhrsdbi
+nYMQmpcTCMGDbyxklELnqxVZlhEnMe00RmtNXlT4zT1CiM2XUkitUUo1X5RAYwSNVM0hpJSNR1Tj
+GQDvHMH7H7wYxSitQIBznrquCD6g/A/etNbi6sYrVVUhpaSuKpxrjOGdJwgAj6Ixnp7f3xOcY7uX
+koiSSHq2tmIqJ5nmDgSEjSWEEO89h5CNbRrT/uAJuTm0kCBEY3sB3nmEkGjTeLDxkCd4R+0tbO5H
+GYRonqOsbV4QAhiNEDThJj3Ob8LNe4IQ6LquSSJBMb+DJEbLDqv5HEFgf2vAfSFwm9AQgBQCAc0D
+mtMhnGvCSza5JVXjPSEEMki8dwQNUor3BxZC4JxDSYXXAS003nlq6sZwm+u0VoSgYRMB3nu89yjv
+sbbJI2stuixLYi2JtCB4j/OerNXG2pp8MeNkZ4/7UlA4scmaTXw/eEgqpNKbsFIo80P4KaXe3+G9
+33jQN/GNQAiIohgjIkIIOGubCPAe4SRBBqTSGEBKiXNNoldVSV1VgMOHJo908BatBFpKUAofwPqA
+1IY4Sbi6vODw6JhZrcitINBY6n1ia4UypvGA1Jtc2RxISgQNmDjnmuOH5lCB0ACB0htLO5QySKUJ
+/gHRNogZNO1EESlQQuCQfPXqbYN4zuKcQ7MJF6M1QRkCAakU7U6XVtYijlMuLy94/PgJN+tAXoEy
+5j3SSalQ2qB0hNIKIR5gXDWhhAAhiIxBCEHw7j38eu+xwRMCTV7JxstJ6pBCYG1NL1KIakm5XiDi
+mKJyWA9pnJDna4Jv7tEASkmM1mBiRJSCVAQfEErT7Q+RAi4vLzk9OeWm1NRe8IDDSjfJ+YDryugm
+R4RAbpI2iAYctNIELwnBbzzUWDiEJokfwjGKElItSOqcYrHAC0Wr08V7qOoCrSDa1C4fAjiHbGqC
+IIkNWRqhdESSddAmoi4rAoJWp4fSEefn33O8FZHGGi3VxitgjEZrjRQCfIMkG5gjCFBKNcWMQBAC
+ROO5wMYAQqC1xhiDkpJRS7DFgipfESUt+oMRUZxS1RZb1yhtqF1A6wit9cPHgJBEJiJNIlZWEJuI
+yGjanS7tdpe6LljM5tzf3fP2u1f86NOf8tXFErEpeloJpGxCFATOe0QIiOAJtoFv5wLONcgFzWGt
+d3jvfvCcr9lSBevxFfm6Imv1iJIMtKGoAx5JCJbaB1br4n2RDSGgIxNTWY8yMVJKtjoJ66pExm28
+k2iTEJAcnD4ijiPOv39D+vVXPPvwYy6XnkBjTUkDpw+1QkqBtxYTxzjvCIALHufY5IoHIQk4rHfs
+dWKicsLlu7fErT7HHzwj7XSxtSXPS2qviPMlaE0R9HvkZINoWinF/XxJGhuEaSGATqqxviROeoQQ
+iGNDvfaYTTH7/uKSk0dPuL+eouOMdqeLtTVCgKstaZq8x3wdpyRJRgAm9xOyrIVUEhU30FyVOU92
+2qwuX3F3fU2vNyLt9DFCUeUlJmkTqIi1opUYpG8xWVmUVCA9nuY5WghBWVm8MqRJipMGIQVtbTDU
+xKJiPZ8xn9xxP5kwnU4pqpKXL1+xv3vI9WxJvbQkaUZQEYaAK0ustSzXOXHWwtY1rU6HNElZLleb
+QgrClfzouM/tyy8Zj8cMBiN2Dk+R0lB7CEGwXMyJsERRwBkJnR7VbIzRDe+rbQM6OooilFJcXFxx
+cBhhIkeBwtUOQk2IPMFbnHWUZUlVV3gfuLy+JW31SJUgVoJgK7TSIAVKR9wsl0Qm4ur8Lds7O8zr
+mrqucOucxbrEuprjYZtqUvLq5UtGox2ybg+TtUmzLs5DsVqQhhVSwMpKtDLkziCFRKkG/bRSeEB1
+Or3PlJJ0OxmDwQC3nFBbx83tFdI7itJSV5YgoaprDo+PMUazWq+pqpp22iJKE9I0Y11WGAkhOG5u
+b2lnGb1uC7xltcxZr5cc7QwZdlv0WgnVcsLk8px3Fxc8OjxEKUmcthju7KKlJNaANORlwNclJoq4
+mJcUVUUIDoJAiA2r9iFQWUdZOySO8WxJ4RaUZcVUgI5bmCxj2O3SHu7g6wrrHM55ptN7autpLZc4
+F9je2WXQHTCezEhjTb5eEBvJ6ekJ08USgsOohnvNbs4RtmBrsMUTLSmqnJ7uIao1dr0k6/YpdMTa
+KtK0xlaeiY02sKtwLsKHGuEE4NFFsabVarNcLvAIFkVBXlr29w4Y7WwTxTHWVSgpGN/cYG2FkIok
+a1FaT1Hm6EJTVo502aKqSlpJhNYSay11XXBzfc79dMn29pDx7B5XFWhfo2NDnKT84oMPmU/GCJ2Q
+z2csxzcgFT4I2tqx9BXnF+dcsEUAlIkxG1JceY+UBm1tTVmWFDZjPJujTIJdTFgs7jk6O6XdH7Cc
+jnn93bfkec5ytaSqa7r9PtoYBr0+Uilmy5wojhhu9XF1TUdq4iRBiYaEvru44uZyTRJFrFZLcCW9
+TpvgPOvlmuNnz6nLgmK+YD65Z7UsSA3IakUlYF44fGbQRqG02iBohSkjnKtRaZp99sBiy9rSymKq
+suTkyTP6gyHju1tmiyXOeW5ubwhAK2sgd3s0xDpHu92h1e5SVTVb3TbgWeRrILAzGpDnBWkSs9Vt
+s7e7w93dLVtbA2bTOVoKiqpECkEaa/qDIc7VrGdTyvUauxxj6zU+2yIn2XSfDTnVWiOlIASPare7
+nyVZhlaGTq+D95bKOgajHebzBXd3dzhXM53OqF2g3+txdnKM957T00ebqhozGu3gPThviYxmvV6j
+pWBvMCBqtYmiiEgrdGTYHY3w3lFXFVVVNdcK6G0N6Q62aPeGvLt4y+W7c/Ki4ODpc+5KSWFBbIio
+EHLDrmn6JJMkRElKlCbsbG/T7XTZPzxECFiuc4IUSKVBabZ3dzg+OsQGSZS2yIuSbn9IXVmGwx5P
+Hh1T1Y40S7m5uWY2ueObV9/y5ZdfIkTARDE+NN5vt9t89NGHZO02zjUE9Ysvv+Ty4gohAov5HCEV
+O8enTArPJK9/0BWspSwLrK0b5m4MstPpkmUtojgmzVJMknF0ckbtAsZE5HlBkIr9/X263S5eaNZF
+xf7+EU+fPuN+MmU8mbAzHNLLYqy1dNKMrW6XTq9HnMScHu3x6GiP5WKOdZ4oikizDneTGds7O7R7
+PfJ1gVaal6++ZTqbk3b7YAwrJ3l5s8CHhik4a7GuJnjXkM2HRi6K40ZiAawXDHf2sNbhbM1qtaLT
+6zEajUizlE6nizYR1lqKokAISVXkeG/xdUmxXnJ7e0O+XJKvC+I44c33b3BViatL5vMZL168Ynt3
+j9HuPt2tEVmnx8nJKTpJGe3to6RmOp1ikgQrJPOiJjIxQj60uQ42bLmRsDTKGLSta6q6ot3ukLZb
+dHpdrs/PcR463S7tTgcQZGnGzu4OSimODvaZzqbYOqfMFzw63CXSithEHIz6VFXByeE+OjKkUUwW
+KSIJ88kdKsroDwacX92ymM0xCsqypNVqcXV923AoJNu7e0ynC7q9PlcFSCdxoekilWp0MqObFpsK
+tHOOJIpx1pLECYvplFanRxtPVVbsbO8RfM1oNOLo6AgtYTmd0sliBr0OnVZCGmuKfM79dMwnHz1D
+6ojz80t6/S6nhzsIW6OVRMnAwc4A7xzfvXjBsN+j085wzrNeF3RpxIbZdMZZf8Dh8SnLdUmgBOFR
+SiLUxhNCoFQjFnqt0UI0SBBFjToopcboCGMUjx7v0e20ubg4Zzq+RVRrXr/6LWmy4os/X/Hhk0/4
++PlHDIcj7u6nvP7+nJ9+8hPSNKXX67EzHDRs4eaK1XJBEhsePz4CV/Hk9IDeYEQSRdxcXbHK16Ak
+dW0J3jOe3NHK2lzOVljnUdIgRGi4nFJoJRAhNAVSKdT27t5nAogjw2g0QiIpigJrLVGSkOc5q+k9
+j/e3+OJ3v+Vv/lPCzWSKefZjnjx9gp19QXvwjJNHH/DyxUuGo20CgeFwQDttMZ1O6PW7fPrpx+wP
+O9ze3fL5//0NxfI1l2+vyVpdnPfMZ3MGo22q2tJptdC60bEupjlq0wlKKfEERAhoJTfXNH2QfIAv
+V1u8tUgpKMuCyeSOf/vNv/DqxZ/5+U8/4Wd/8R/Z2TmmOxiSxA3XYfUVx/spn//bb1kUFqTi8uoa
+KTXdThcdR8RxzLOPfkTtIK+/ZpG9pvXjH/PX/+UJP3oy5nf/+hu0EkRJgrUehcRvZM77+YLKBYRq
+FEylFMIHQnCb6GlUmqZTFBJvLSF4rq6vWa6WpGnC3e01MlhOjo/wCFaV5We//Av+9E3Ojz95znH9
+Lfu7I5ZrwcvzObUXdPtbxGlCUa6Z3t/j6oqqsgx3D7k8/4aTk4R8PMZe/G9qVqTdbc4eP+H08WOU
+gHfnbxnfXHH+/Rtm0ynzvMR5j3WNfPSgkTVCh9wIhs3fVK/X/0wpiRABrRSj7R0m41v6vQ5PHj9i
+sViQr5ZU64LHHzxDygFvvr+hnQlurhf8+ncVl1c3fPyTT7k4/55ev4+taiIpMFGE94Hto2P+z7/+
+gZ09wVYn4Xh/i6S1x6//+2v+89/8A8YY0sjQ63RYrXLa7RadTod5aVk7gZCNpEQIKCXRSqE3B7G2
+xvmADsFD8EihKaoSISVFkXN48IgkTWi125y/u+T65o6vX7zi5z/5hJ//4u9YlTV//uYlMvwzs/mM
+u6tLkiQjzws0gdIYTBTT6kjy2ZRvX7/mxZuc58+7BCJqb/nrf/wn4jTi3ZvXVEWJc56j0xMuzs9Z
+LJa4oBGqoSONZB1QUqKVRCIJwRGC+He61kZSCc4RxRFPHp8RxxF7e3sEPLfXl1gXcM7xzavvOH93
+yUcf/5hPfvIxq7ImGR0ymy+5v5/T73fo9PtUtmKd50ghuXz3jmxrl6dnR3z46ackWcLNxQXfvXrF
+1cUllXXsDgc8+w8fkSQR88ktN+N76mxIFBncpv8RG91ZblRO7wJBuAbVet3+Z0IEyrJECMn+4RFn
+Z8csp2PiNGV7e4dBv88f/vA51zfXGK0RSuGC4upmzHg65+76mtV8yt7+AdujEaPBFrvbA9ZFRVVW
+XF9eUaA5e3TG3s6Ir776E19/+Sdurm/QStGKIp48e8bR6Qm2rpHB4XXE3Kn3Cv+DOmm0QiuJ2IjZ
+1jnqukInaUK318X7RiVZTO9ZzLpYH4iNYb1aoaKYf/jH/8YfP/+c8XiMMobHaUpeW6qywkSaODFs
+7++TKEkaa5TUdDpdhFTc3N0xnc1YLNd8/vvPeX1+zv3tDVIKep02R4f7HB4fsVrMqYqCTneLarwm
+ULyfADTyKygpwHmss43M5DzBe1S/3/vMe0ddlmgJVVXQ7/e5H485f/ManOPq6pLF7J7BcMTN7d2G
+ERumk3t6W0Nur67I87zRiyNDN0tot7usiop35++4ur7Z9Cwd2qkh2BKjFc+envH4yRO2Bn20aurG
+anbP/XTBi8tGO5Abyi5EIDbNEOlBuHbObaZeHrV/ePhZbCK0bhqUOIp+GKAEy2q15OzxI7Z3hjx9
++hQhIF/l1NY2Ek8cc3p2wu3NNUJp+r0erazFfD7j5nbMYj7F1o7jsxOkaITtar1CS8FgOKCVRiym
+93zxxy+Yjm9YLuZc3M6ZrJvZoPUO5y1aSiJj0FJhbd2M47x/fyAdRQajDc5BZAxGKxaLBUfHh1y+
+fc3Hz59zdnZGq52hpGRvf588X5NXnjgyPHp8hneOJ49OubtfcPntKxa3V9TWQoBur8tf/vJXKK1Z
+zCYs7u85ODig3+tw+uQxs8kYt7VFVRaslguKouY2t7iHISgerRWYhkI9iN1CiM1wtMkVaXREp9sh
+jhPanTZJHINzWOs4ODjg6xcv+d3vf0++LqitByHobg1ZFyWrPOf25oadnW3OTo+5f/eKePySX23V
+/LJToe6+w5YF7W6HLEtIohjrPL1ej0cffIiR4n3NODl7RJpmZN0t8spuBPJmSqaEBNcMiKT8gcI3
+478GftXJ6elnSknW+Yq6rOj1+qzzFdZ7nK3ZHvRYTO+pqpI46+AC9HoDDvZ2kcEzm004PNhn5/CY
+k8dP+dPXrxFVSStOWe8+47/+3d/T63W5fvuWm5s78vUaISVZq0UUZ6yLNbfv3vLm9UuMifnucsLa
+gVSNOK2UQmvZKIuyGaIGAt55bO3eq5bq8eMnn9m62kyTPHe3N0RRBELSbreROuLs7BGd7oDVaoXz
+8MEHTynWCyKt2R5uoZUhTlNaWYuqrPgfv/4XcpHwq7/9ew729xChJk2a4dDh/jZbo23m8zlVsWI+
+uSafT7BVxar03C1LShcQUv4wVRYCrQ1s2G7wnrq2m6ruEYAOeKRUuFDhnKPVbuGcY2d/n939fYSz
+TOcL3nz7DfvHZ5w83uZufM9gMMTVNdY6TJKwWMwp8jX9wRbBRIyefYi3FdZVYD1vX7/BRDFJp0Or
+04Zqyer+gmpd4p2nN9xneTenqCZIodHGUJZlM3uUBu9BCI9sxi5oJfFaI72nrmt0CAJJM7fwQJRm
+nD56RL5cYmtLGhmyWNLfek6VL1iMr5lNbhlujzBa0e1uka/XBO+ZTWfc3tyg45i6toxvr8niBjK7
+w22wBUorFtNbynyBy+e0sgyRDKhEyvLdmEgrPArBhpV7h4p0M9YDlHgYk0ucD+ACwjnUzu7OZ943
+o6v21hbBB6hrBtu7fP2nP5K1OxweHWNEYDgaUeVLWt0es8mEqizJ12u8h/HknqqquHz7lt3hgKIq
+sSE0CocQ4GuSLGG9mGPLHOMK2qMDkt4eXqcsCsd3r99Q1jUog6dpgR+2JYw2TY5s9i6stbjNFNpa
+i272TmC0vcvt1SXaaOh2eP3i//Hs+SeMhkMWyzXbwz62XLF3csZqsaDXbqG0Il8tGK8WoGOG2/v8
+6q/+CrynnWUgAnVdcXf9PVmkWY0d2/tHFIslRC2K2pFkEeuipKwdelO1MXKjmDSVW0uJ180YPNCI
+ELXzVPUPhVEmSUwcxVycv6VYr6mrmqoseP7JT7Flwbu355R1zbffvUHomLIsieMILQWtWHOwM+J4
+u88gctjVlPl8jtQKExsIjvViiqtKymJN1t3CASbbwqkEGyR5UZF1+iAVi/EYpTVJ2oJN57dpmpol
+hc0GxkPteJjdCwK6KBqpppVlrJYrnK3ZPzri/O05CDg6Pubi7ffs7x9QW0d+e0cnizGy2R+x64Jg
+SzpZRtbrsrawXkwpVjNsXSG8RzbbL1TFGiEVrd4QW1ekWZegYmrrWS3mrNc5cdqC4DcTY0WSpiht
+QP6wnPPweb+AAOj5bEaaxqxWK+LY0N3q8+LrF0Ra8+jJI6aTCe1WxjpfkqZHpFpT5Qv6wz5VndNO
+U0wWEyUt4labWDQvtc7jfcDXFVKAwqG0bnRbExGlbWSUEIKgrNbcXl7Q6XbJPWBrImMgTZteXan3
+7e/Dz4PqGAL4EJp+xDmPNhqtIxbTBd5Zkm6LgODq4pzR7gGtVsY//6//yc9+8ilGSWrv6PSGSKVI
+kpg0zVBJRqpjXAhUdY0gEKxGbQQ1rTVJ1kLHMVIn1M7hPdzfj6mLHCEF1joiqXDOvl9KeL/+sYFe
+ABFoFnLqBr61c5bgJQhDZWvy5ZI0idneO+D1qxfsHx5z/uY7fvqLX9BODJfv3rG3PYTQwkQpcWQQ
+WmPiDGUSlNZY7xuq4z1qM3qWWiHY/JYaKSTW1qzzkuVsSl0WdLp98Ip8k8RShPdKifeBsBEa2Czd
+BNcsrHnv+f9Qc51Rfhz5VAAAAABJRU5ErkJggg=="/>
+</svg>
diff --git a/test/svg/doc.3.image-transform.svg b/test/svg/doc.3.image-transform.svg
new file mode 100644
index 000000000..90e5ecb1a
--- /dev/null
+++ b/test/svg/doc.3.image-transform.svg
@@ -0,0 +1,122 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <image x="0" y="-1000" width="1000" height="1000"
+ transform="scale(0.5) rotate(-45),translate(800,500)"
+ xlink:href="data:image/png;base64,
+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
+BNcsrHnv+f9Qc51Rfhz5VAAAAABJRU5ErkJggg=="/>
+</svg>
diff --git a/test/svg/doc.4.clip-user.svg b/test/svg/doc.4.clip-user.svg
new file mode 100644
index 000000000..26cdd818a
--- /dev/null
+++ b/test/svg/doc.4.clip-user.svg
@@ -0,0 +1,9 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+</svg>
diff --git a/test/svg/doc.5.clip-object.svg b/test/svg/doc.5.clip-object.svg
new file mode 100644
index 000000000..732911590
--- /dev/null
+++ b/test/svg/doc.5.clip-object.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+
+</svg>
diff --git a/test/svg/doc.6.clip-user2.svg b/test/svg/doc.6.clip-user2.svg
new file mode 100644
index 000000000..a68c1c42f
--- /dev/null
+++ b/test/svg/doc.6.clip-user2.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ <rect x="100" y="-900" width="800" height="400"/>
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+</svg>
diff --git a/test/svg/doc.7.clip-object2.svg b/test/svg/doc.7.clip-object2.svg
new file mode 100644
index 000000000..f5c153dd1
--- /dev/null
+++ b/test/svg/doc.7.clip-object2.svg
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ <rect x="0" y="0" width="1" height="0.5"/>
+ </clipPath>
+
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip)" />
+
+</svg>
diff --git a/test/svg/doc.8.clip-user3.svg b/test/svg/doc.8.clip-user3.svg
new file mode 100644
index 000000000..8ff61d593
--- /dev/null
+++ b/test/svg/doc.8.clip-user3.svg
@@ -0,0 +1,15 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="userSpaceOnUse" >
+ <circle cx="500" cy="-500" r="400" />
+ </clipPath>
+
+ <clipPath id="clip2" clipPathUnits="userSpaceOnUse" >
+ <rect x="100" y="-900" width="800" height="400"/>
+ </clipPath>
+
+ <g clip-path="url(#clip)">
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip2)" />
+ </g>
+</svg>
diff --git a/test/svg/doc.9.clip-object3.svg b/test/svg/doc.9.clip-object3.svg
new file mode 100644
index 000000000..b291df79f
--- /dev/null
+++ b/test/svg/doc.9.clip-object3.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
+ <clipPath id="clip" clipPathUnits="objectBoundingBox">
+ <circle cx=".5" cy=".5" r=".5" />
+ </clipPath>
+
+ <clipPath id="clip2" clipPathUnits="objectBoundingBox">
+ <rect x="0" y="0" width="1" height="0.5"/>
+ </clipPath>
+
+ <g clip-path="url(#clip)">
+ <rect x="100" y="-900" width="800" height="800"
+ stroke="green" stroke-width="100"
+ clip-path="url(#clip2)" />
+ </g>
+</svg>
diff --git a/test/svg/doc.A.g.svg b/test/svg/doc.A.g.svg
new file mode 100644
index 000000000..bdaade725
--- /dev/null
+++ b/test/svg/doc.A.g.svg
@@ -0,0 +1,14 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink" >
+ <defs>
+ <circle id="circle"
+ cx="0" cy="0" r="250" />
+ </defs>
+
+ <g opacity="0.5">
+ <use xlink:href="#circle" x="330" y="-500"
+ fill="red" />
+ <use xlink:href="#circle" x="670" y="-500"
+ fill="green" />
+ </g>
+</svg>
diff --git a/test/svg/fill.0.name.svg b/test/svg/fill.0.name.svg
new file mode 100644
index 000000000..e377b8827
--- /dev/null
+++ b/test/svg/fill.0.name.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="indigo" />
+</svg>
diff --git a/test/svg/fill.1.hex6.svg b/test/svg/fill.1.hex6.svg
new file mode 100644
index 000000000..04759d78a
--- /dev/null
+++ b/test/svg/fill.1.hex6.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="#AA55AA" />
+</svg>
diff --git a/test/svg/fill.2.hex3.svg b/test/svg/fill.2.hex3.svg
new file mode 100644
index 000000000..9f9bce580
--- /dev/null
+++ b/test/svg/fill.2.hex3.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="#A5A" />
+</svg>
diff --git a/test/svg/fill.3.rgb.svg b/test/svg/fill.3.rgb.svg
new file mode 100644
index 000000000..c18b03bb5
--- /dev/null
+++ b/test/svg/fill.3.rgb.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="rgb (75, 0 , 130)" />
+</svg>
diff --git a/test/svg/fill.4.current-color.svg b/test/svg/fill.4.current-color.svg
new file mode 100644
index 000000000..cf77d65a6
--- /dev/null
+++ b/test/svg/fill.4.current-color.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="currentColor" />
+</svg>
diff --git a/test/svg/fill.5.palette.svg b/test/svg/fill.5.palette.svg
new file mode 100644
index 000000000..53ea97512
--- /dev/null
+++ b/test/svg/fill.5.palette.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="var(--color1, red)" />
+</svg>
diff --git a/test/svg/fill.6.opacity.svg b/test/svg/fill.6.opacity.svg
new file mode 100644
index 000000000..59b4eb41f
--- /dev/null
+++ b/test/svg/fill.6.opacity.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"
+ fill="magenta" fill-opacity="0.5" />
+</svg>
diff --git a/test/svg/fill.7.color.svg b/test/svg/fill.7.color.svg
new file mode 100644
index 000000000..745b2e881
--- /dev/null
+++ b/test/svg/fill.7.color.svg
@@ -0,0 +1,5 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ color="green" >
+ <rect x="100" y="-750" width="800" height="500"
+ fill="currentColor" />
+</svg>
diff --git a/test/svg/fill.8.rule.svg b/test/svg/fill.8.rule.svg
new file mode 100644
index 000000000..366ff6760
--- /dev/null
+++ b/test/svg/fill.8.rule.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <g transform="scale(5,5) translate(0,-150)">
+ <polygon fill-rule="nonzero"
+ points="50,0 21,90 98,35 2,35 79,90"/>
+ <polygon fill-rule="evenodd"
+ points="150,0 121,90 198,35 102,35 179,90"/>
+ </g>
+</svg>
diff --git a/test/svg/fuzzer/README b/test/svg/fuzzer/README
new file mode 100644
index 000000000..4bb8d9654
--- /dev/null
+++ b/test/svg/fuzzer/README
@@ -0,0 +1,19 @@
+libFuzzer based fuzzing for cairo-svg-glyph-render.c
+====================================================
+
+Build
+-----
+CC=clang CFLAGS="-DDEBUG_SVG_RENDER -g -fsanitize=fuzzer-no-link,address" meson -Db_lundef=false bld-fuzzer
+ninja -C bld-fuzzer
+
+
+Test
+----
+ ./bld-fuzzer/test/svg/fuzzer/svg-render-fuzzer <CORPUS DIR>
+
+where <CORPUS DIR> is a directory containing SVG files.
+
+If the fuzzer crashes, a crash-* file will be written. Run the
+fuzzer with the crash file to reproduce the crash.
+
+ ./bld-fuzzer/test/svg/fuzzer/svg-render-fuzzer <crash-file>
diff --git a/test/svg/fuzzer/meson.build b/test/svg/fuzzer/meson.build
new file mode 100644
index 000000000..37e23a474
--- /dev/null
+++ b/test/svg/fuzzer/meson.build
@@ -0,0 +1,14 @@
+fuzz_targets = [
+ 'svg-render-fuzzer'
+]
+
+fuzz_args = ['-fsanitize=fuzzer,address']
+
+foreach target_name : fuzz_targets
+ exe = executable(target_name, [target_name + '.c'],
+ include_directories: [incbase, incsrc],
+ c_args: [fuzz_args, '-DHAVE_CONFIG_H'],
+ link_with: [libcairo],
+ link_args: [fuzz_args, extra_link_args],
+ dependencies: [deps, test_deps])
+endforeach
diff --git a/test/svg/fuzzer/svg-render-fuzzer.c b/test/svg/fuzzer/svg-render-fuzzer.c
new file mode 100644
index 000000000..08eb79dd8
--- /dev/null
+++ b/test/svg/fuzzer/svg-render-fuzzer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2022 Uli Schlachter
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Uli Schlachter <psychon@znc.in>
+ */
+
+#include <cairo.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+cairo_bool_t
+_cairo_debug_svg_render (cairo_t *cr,
+ const char *svg_document,
+ const char *element,
+ double units_per_em,
+ int debug_level);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ cairo_surface_t *s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ cairo_t *cr = cairo_create(s);
+
+ /* Get us a zero terminated string */
+ const char *svg_document = strndup ((const char *) data, size);
+
+ _cairo_debug_svg_render (cr,
+ svg_document,
+ NULL,
+ 1000,
+ 0);
+ free (svg_document);
+ cairo_destroy (cr);
+ cairo_surface_destroy (s);
+ return 0;
+}
diff --git a/test/svg/gradient.0.lin-pad.svg b/test/svg/gradient.0.lin-pad.svg
new file mode 100644
index 000000000..0ec54092f
--- /dev/null
+++ b/test/svg/gradient.0.lin-pad.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x21="66%">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="0.5" />
+ </linearGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/gradient.1.lin-reflect.svg b/test/svg/gradient.1.lin-reflect.svg
new file mode 100644
index 000000000..9e3e50cb9
--- /dev/null
+++ b/test/svg/gradient.1.lin-reflect.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x2="66%"
+ spreadMethod="reflect">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/gradient.2.lin-repeat.svg b/test/svg/gradient.2.lin-repeat.svg
new file mode 100644
index 000000000..1f023f5e1
--- /dev/null
+++ b/test/svg/gradient.2.lin-repeat.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="33%" x2="66%"
+ spreadMethod="repeat">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/gradient.3.lin-user.svg b/test/svg/gradient.3.lin-user.svg
new file mode 100644
index 000000000..fc90328f0
--- /dev/null
+++ b/test/svg/gradient.3.lin-user.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" x1="300" y1="-500" x2="600" y2="-500"
+ gradientUnits="userSpaceOnUse">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="0" y="-900" width="1000" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/gradient.4.lin-transform.svg b/test/svg/gradient.4.lin-transform.svg
new file mode 100644
index 000000000..bc8f5b622
--- /dev/null
+++ b/test/svg/gradient.4.lin-transform.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <linearGradient id="grad" gradientTransform="rotate(45)">
+ <stop offset="0%" stop-color="blue" stop-opacity="1" />
+ <stop offset="100%" stop-color="red" stop-opacity="1" />
+ </linearGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/gradient.5.rad-pad.svg b/test/svg/gradient.5.rad-pad.svg
new file mode 100644
index 000000000..b631ddc73
--- /dev/null
+++ b/test/svg/gradient.5.rad-pad.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="50%" cy="50%"
+ fx="0.75" fy="0.35" r="0.5">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/gradient.6.rad-reflect.svg b/test/svg/gradient.6.rad-reflect.svg
new file mode 100644
index 000000000..b6fea76be
--- /dev/null
+++ b/test/svg/gradient.6.rad-reflect.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="75%" cy="25%" r="33%"
+ fx="0.64" fy="0.18" fr="0.17"
+ spreadMethod="reflect" >
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/gradient.7.rad-repeat.svg b/test/svg/gradient.7.rad-repeat.svg
new file mode 100644
index 000000000..63d138d2a
--- /dev/null
+++ b/test/svg/gradient.7.rad-repeat.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="75%" cy="25%" r="33%"
+ fx="0.64" fy="0.18" fr="0.17"
+ spreadMethod="repeat" >
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/gradient.8.rad-user.svg b/test/svg/gradient.8.rad-user.svg
new file mode 100644
index 000000000..e1d9c61f0
--- /dev/null
+++ b/test/svg/gradient.8.rad-user.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="450" cy="-550" r="400"
+ fx="600" fy="-400" fr="10"
+ gradientUnits="userSpaceOnUse" >
+ <stop offset="0%" stop-color="red" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="0.5" />
+ </radialGradient>
+ </defs>
+ <rect x="0" y="-1000" width="1000" height="1000" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/gradient.9.rad-transform.svg b/test/svg/gradient.9.rad-transform.svg
new file mode 100644
index 000000000..4b90aaaf6
--- /dev/null
+++ b/test/svg/gradient.9.rad-transform.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <radialGradient id="grad" cx="50%" cy="25%"
+ fx="0.75" fy="0.35" r="0.5"
+ gradientTransform="scale(1, 2)">
+ <stop offset="0%" stop-color="red" stop-opacity="1" />
+ <stop offset="100%" stop-color="green" stop-opacity="1" />
+ </radialGradient>
+ </defs>
+ <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/meson.build b/test/svg/meson.build
new file mode 100644
index 000000000..858e9d9cc
--- /dev/null
+++ b/test/svg/meson.build
@@ -0,0 +1,9 @@
+if librsvg_dep.found()
+ executable('svg-render',
+ 'svg-render.c',
+ dependencies: [libcairo_dep, librsvg_dep])
+endif
+
+if cc.links(files(meson.project_source_root() / 'meson-cc-tests/fuzzer.c'), args: '-fsanitize=fuzzer,address')
+ subdir('fuzzer')
+endif
diff --git a/test/svg/path.0.line.svg b/test/svg/path.0.line.svg
new file mode 100644
index 000000000..19d50914a
--- /dev/null
+++ b/test/svg/path.0.line.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M 200 -200
+ L 500 -500
+ H 800
+ V -200
+ " />
+</svg>
diff --git a/test/svg/path.1.curve.svg b/test/svg/path.1.curve.svg
new file mode 100644
index 000000000..49c252ac8
--- /dev/null
+++ b/test/svg/path.1.curve.svg
@@ -0,0 +1,9 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M200,-400
+ C200,-200
+ 500,-200
+ 500,-400
+ S800,-600
+ 800,-400" />
+</svg>
diff --git a/test/svg/path.2.quad.svg b/test/svg/path.2.quad.svg
new file mode 100644
index 000000000..00a0dde57
--- /dev/null
+++ b/test/svg/path.2.quad.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M200,-300
+ Q400,-50
+ 600,-300
+ T1000,-300"
+ />
+</svg>
diff --git a/test/svg/path.3.arc.svg b/test/svg/path.3.arc.svg
new file mode 100644
index 000000000..f177a72af
--- /dev/null
+++ b/test/svg/path.3.arc.svg
@@ -0,0 +1,7 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <path fill="none" stroke="black" stroke-width="20"
+ d="M500,-500
+ L 712 -712
+ A300,300 0 1,0 712, -288 z"
+ />
+</svg>
diff --git a/test/svg/shapes.0.rect.svg b/test/svg/shapes.0.rect.svg
new file mode 100644
index 000000000..17db34649
--- /dev/null
+++ b/test/svg/shapes.0.rect.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500"/>
+</svg>
diff --git a/test/svg/shapes.1.rounded-rect.svg b/test/svg/shapes.1.rounded-rect.svg
new file mode 100644
index 000000000..717470bee
--- /dev/null
+++ b/test/svg/shapes.1.rounded-rect.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <rect x="100" y="-750" width="800" height="500" rx="100" ry="100"/>
+</svg>
diff --git a/test/svg/shapes.2.circle.svg b/test/svg/shapes.2.circle.svg
new file mode 100644
index 000000000..3c07bad83
--- /dev/null
+++ b/test/svg/shapes.2.circle.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <circle cx="500" cy="-500" r="400"/>
+</svg>
diff --git a/test/svg/shapes.3.ellipse.svg b/test/svg/shapes.3.ellipse.svg
new file mode 100644
index 000000000..67260a404
--- /dev/null
+++ b/test/svg/shapes.3.ellipse.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <ellipse cx="500" cy="-500" rx="400" ry="200"/>
+</svg>
diff --git a/test/svg/shapes.4.line.svg b/test/svg/shapes.4.line.svg
new file mode 100644
index 000000000..58de42947
--- /dev/null
+++ b/test/svg/shapes.4.line.svg
@@ -0,0 +1,3 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="200" y1="-200" x2="800" y2="-800" stroke="black" stroke-width="20"/>
+</svg>
diff --git a/test/svg/shapes.5.polyline.svg b/test/svg/shapes.5.polyline.svg
new file mode 100644
index 000000000..0cc5c383c
--- /dev/null
+++ b/test/svg/shapes.5.polyline.svg
@@ -0,0 +1,12 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline fill="none" stroke="black" stroke-width="20"
+ points="100, -100,
+ 300, -100,
+ 300, -300,
+ 500, -300,
+ 500, -500,
+ 700, -500
+ 700, -700
+ 900, -700
+ 900, -900" />
+</svg>
diff --git a/test/svg/shapes.6.polygon.svg b/test/svg/shapes.6.polygon.svg
new file mode 100644
index 000000000..56bda0705
--- /dev/null
+++ b/test/svg/shapes.6.polygon.svg
@@ -0,0 +1,12 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">
+<polygon points="350, -75
+ 379, -161
+ 469, -161
+ 397, -215
+ 423, -301
+ 350, -250
+ 277, -301
+ 303, -215
+ 231, -161
+ 321, -161" />
+</svg>
diff --git a/test/svg/stroke.0.name.svg b/test/svg/stroke.0.name.svg
new file mode 100644
index 000000000..f2a926475
--- /dev/null
+++ b/test/svg/stroke.0.name.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="indigo" />
+</svg>
diff --git a/test/svg/stroke.1.hex6.svg b/test/svg/stroke.1.hex6.svg
new file mode 100644
index 000000000..89f2b1b38
--- /dev/null
+++ b/test/svg/stroke.1.hex6.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="#AA55AA" />
+</svg>
diff --git a/test/svg/stroke.2.hex3.svg b/test/svg/stroke.2.hex3.svg
new file mode 100644
index 000000000..a8565a7b6
--- /dev/null
+++ b/test/svg/stroke.2.hex3.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="#A5A" />
+</svg>
diff --git a/test/svg/stroke.3.rgb.svg b/test/svg/stroke.3.rgb.svg
new file mode 100644
index 000000000..42e7514e4
--- /dev/null
+++ b/test/svg/stroke.3.rgb.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="rgb(75,0,130)" />
+</svg>
diff --git a/test/svg/stroke.4.current-color.svg b/test/svg/stroke.4.current-color.svg
new file mode 100644
index 000000000..9d645b881
--- /dev/null
+++ b/test/svg/stroke.4.current-color.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="currentColor" />
+</svg>
diff --git a/test/svg/stroke.5.palette.svg b/test/svg/stroke.5.palette.svg
new file mode 100644
index 000000000..1262a7ba0
--- /dev/null
+++ b/test/svg/stroke.5.palette.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="var(--color1, red)" />
+</svg>
diff --git a/test/svg/stroke.6.opacity.svg b/test/svg/stroke.6.opacity.svg
new file mode 100644
index 000000000..b84d1bdc9
--- /dev/null
+++ b/test/svg/stroke.6.opacity.svg
@@ -0,0 +1,6 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="magenta" stroke-opacity="0.5" />
+</svg>
diff --git a/test/svg/stroke.7.color.svg b/test/svg/stroke.7.color.svg
new file mode 100644
index 000000000..952f48261
--- /dev/null
+++ b/test/svg/stroke.7.color.svg
@@ -0,0 +1,7 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ color="green" >
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="100"
+ stroke="currentColor" />
+</svg>
diff --git a/test/svg/stroke.8.width.svg b/test/svg/stroke.8.width.svg
new file mode 100644
index 000000000..bb9edea90
--- /dev/null
+++ b/test/svg/stroke.8.width.svg
@@ -0,0 +1,14 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-900" x2="900" y2="-900"
+ fill="none"
+ stroke-width="100"
+ stroke="black" />
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="200"
+ stroke="black" />
+ <line x1="100" y1="-100" x2="900" y2="-100"
+ fill="none"
+ stroke-width="300"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.9.cap.svg b/test/svg/stroke.9.cap.svg
new file mode 100644
index 000000000..35046446c
--- /dev/null
+++ b/test/svg/stroke.9.cap.svg
@@ -0,0 +1,17 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-900" x2="900" y2="-900"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="butt"
+ stroke="black" />
+ <line x1="100" y1="-500" x2="900" y2="-500"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="round"
+ stroke="black" />
+ <line x1="100" y1="-100" x2="900" y2="-100"
+ fill="none"
+ stroke-width="200"
+ stroke-linecap="square"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.A.dash.svg b/test/svg/stroke.A.dash.svg
new file mode 100644
index 000000000..2be5a1d90
--- /dev/null
+++ b/test/svg/stroke.A.dash.svg
@@ -0,0 +1,27 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-950" x2="900" y2="-950"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="none"
+ stroke="black" />
+ <line x1="100" y1="-750" x2="900" y2="-750"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200"
+ stroke="black" />
+ <line x1="100" y1="-550" x2="900" y2="-550"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50"
+ stroke="black" />
+ <line x1="100" y1="-350" x2="900" y2="-350"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100"
+ stroke="black" />
+ <line x1="100" y1="-150" x2="900" y2="-150"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100 150"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.B.dash-offset.svg b/test/svg/stroke.B.dash-offset.svg
new file mode 100644
index 000000000..f7623ea84
--- /dev/null
+++ b/test/svg/stroke.B.dash-offset.svg
@@ -0,0 +1,31 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <line x1="100" y1="-950" x2="900" y2="-950"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="none"
+ stroke="black" />
+ <line x1="100" y1="-750" x2="900" y2="-750"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-550" x2="900" y2="-550"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-350" x2="900" y2="-350"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100"
+ stroke-dashoffset="100"
+ stroke="black" />
+ <line x1="100" y1="-150" x2="900" y2="-150"
+ fill="none"
+ stroke-width="100"
+ stroke-dasharray="200 50 100 150"
+ stroke-dashoffset="100"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.C.miter.svg b/test/svg/stroke.C.miter.svg
new file mode 100644
index 000000000..1dc4ee6a7
--- /dev/null
+++ b/test/svg/stroke.C.miter.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="miter"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.D.round.svg b/test/svg/stroke.D.round.svg
new file mode 100644
index 000000000..3e4c6236f
--- /dev/null
+++ b/test/svg/stroke.D.round.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="round"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.E.bevel.svg b/test/svg/stroke.E.bevel.svg
new file mode 100644
index 000000000..25d9e3803
--- /dev/null
+++ b/test/svg/stroke.E.bevel.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="bevel"
+ stroke="black" />
+</svg>
diff --git a/test/svg/stroke.F.miter-limit.svg b/test/svg/stroke.F.miter-limit.svg
new file mode 100644
index 000000000..14357f0b4
--- /dev/null
+++ b/test/svg/stroke.F.miter-limit.svg
@@ -0,0 +1,11 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <polyline
+ points="100, -200
+ 900, -400
+ 100, -700"
+ fill="none"
+ stroke-width="200"
+ stroke-linejoin="miter"
+ stroke-miterlimit="2"
+ stroke="black" />
+</svg>
diff --git a/test/svg/svg-font-template.ttx b/test/svg/svg-font-template.ttx
new file mode 100644
index 000000000..715074dda
--- /dev/null
+++ b/test/svg/svg-font-template.ttx
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.19">
+
+ <GlyphOrder>
+ <!-- The 'id' attribute is only for humans; it is ignored when parsed. -->
+ <GlyphID id="0" name=".notdef"/>
+ </GlyphOrder>
+
+ <head>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="1.0"/>
+ <fontRevision value="1.0"/>
+ <checkSumAdjustment value="0x3e7355ef"/>
+ <magicNumber value="0x5f0f3cf5"/>
+ <flags value="00000000 00000001"/>
+ <unitsPerEm value="1000"/>
+ <created value="Wed Jun 15 00:00:00 2022"/>
+ <modified value="Wed Jun 15 00:00:00 2022"/>
+ <xMin value="0"/>
+ <yMin value="0"/>
+ <xMax value="1000"/>
+ <yMax value="1000"/>
+ <macStyle value="00000000 00000000"/>
+ <lowestRecPPEM value="6"/>
+ <fontDirectionHint value="2"/>
+ <indexToLocFormat value="0"/>
+ <glyphDataFormat value="0"/>
+ </head>
+
+ <hhea>
+ <tableVersion value="0x00010000"/>
+ <ascent value="1000"/>
+ <descent value="0"/>
+ <lineGap value="200"/>
+ <advanceWidthMax value="1100"/>
+ <minLeftSideBearing value="0"/>
+ <minRightSideBearing value="0"/>
+ <xMaxExtent value="1000"/>
+ <caretSlopeRise value="1"/>
+ <caretSlopeRun value="0"/>
+ <caretOffset value="0"/>
+ <reserved0 value="0"/>
+ <reserved1 value="0"/>
+ <reserved2 value="0"/>
+ <reserved3 value="0"/>
+ <metricDataFormat value="0"/>
+ <numberOfHMetrics value="2"/>
+ </hhea>
+
+ <maxp>
+ <!-- Most of this table will be recalculated by the compiler -->
+ <tableVersion value="0x10000"/>
+ <numGlyphs value="2"/>
+ <maxPoints value="1"/>
+ <maxContours value="1"/>
+ <maxCompositePoints value="1"/>
+ <maxCompositeContours value="1"/>
+ <maxZones value="1"/>
+ <maxTwilightPoints value="0"/>
+ <maxStorage value="0"/>
+ <maxFunctionDefs value="0"/>
+ <maxInstructionDefs value="0"/>
+ <maxStackElements value="256"/>
+ <maxSizeOfInstructions value="1"/>
+ <maxComponentElements value="2"/>
+ <maxComponentDepth value="1"/>
+ </maxp>
+
+ <OS_2>
+ <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+ will be recalculated by the compiler -->
+ <version value="3"/>
+ <xAvgCharWidth value="1000"/>
+ <usWeightClass value="400"/>
+ <usWidthClass value="5"/>
+ <fsType value="00000000 00000001"/>
+ <ySubscriptXSize value="600"/>
+ <ySubscriptYSize value="600"/>
+ <ySubscriptXOffset value="0"/>
+ <ySubscriptYOffset value="75"/>
+ <ySuperscriptXSize value="600"/>
+ <ySuperscriptYSize value="600"/>
+ <ySuperscriptXOffset value="0"/>
+ <ySuperscriptYOffset value="300"/>
+ <yStrikeoutSize value="0"/>
+ <yStrikeoutPosition value="300"/>
+ <sFamilyClass value="0"/>
+ <panose>
+ <bFamilyType value="0"/>
+ <bSerifStyle value="0"/>
+ <bWeight value="0"/>
+ <bProportion value="0"/>
+ <bContrast value="0"/>
+ <bStrokeVariation value="0"/>
+ <bArmStyle value="0"/>
+ <bLetterForm value="0"/>
+ <bMidline value="0"/>
+ <bXHeight value="0"/>
+ </panose>
+ <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+ <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+ <achVendID value="djr "/>
+ <fsSelection value="00000000 01000000"/>
+ <usFirstCharIndex value="65"/>
+ <usLastCharIndex value="65"/>
+ <sTypoAscender value="1000"/>
+ <sTypoDescender value="0"/>
+ <sTypoLineGap value="200"/>
+ <usWinAscent value="1000"/>
+ <usWinDescent value="300"/>
+ <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+ <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+ <sxHeight value="500"/>
+ <sCapHeight value="720"/>
+ <usDefaultChar value="0"/>
+ <usBreakChar value="32"/>
+ <usMaxContext value="3"/>
+ </OS_2>
+
+ <hmtx>
+ <mtx name=".notdef" width="1100" lsb="0"/>
+ </hmtx>
+
+ <cmap>
+ <tableVersion version="0"/>
+ <cmap_format_4 platformID="0" platEncID="3" language="0">
+ </cmap_format_4>
+ </cmap>
+
+ <loca>
+ <!-- The 'loca' table will be calculated by the compiler -->
+ </loca>
+
+ <glyf>
+
+ <!-- The xMin, yMin, xMax and yMax values
+ will be recalculated by the compiler. -->
+
+ <TTGlyph name=".notdef"/><!-- contains no outline data -->
+
+ </glyf>
+
+ <name>
+ <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+ Cairo Font Template
+ </namerecord>
+ <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+ Regular
+ </namerecord>
+ <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+ Cairo Font Template Regular
+ </namerecord>
+ </name>
+
+ <post>
+ <formatType value="3.0"/>
+ <italicAngle value="0.0"/>
+ <underlinePosition value="0"/>
+ <underlineThickness value="0"/>
+ <isFixedPitch value="0"/>
+ <minMemType42 value="0"/>
+ <maxMemType42 value="0"/>
+ <minMemType1 value="0"/>
+ <maxMemType1 value="0"/>
+ </post>
+
+ <CPAL>
+ <version value="0"/>
+ <numPaletteEntries value="2"/>
+ <palette index="0">
+ <color index="0" value="#C5A1D7FF"/>
+ <color index="1" value="#80DFC8FF"/>
+ </palette>
+ <palette index="1">
+ <color index="0" value="#6392A9FF"/>
+ <color index="1" value="#7896B3FF"/>
+ </palette>
+ </CPAL>
+
+ <SVG>
+ <svgDoc endGlyphID="0" startGlyphID="0">
+ <![CDATA[<svg xmlns="http://www.w3.org/2000/svg"></svg>]]>
+ </svgDoc>
+ <colorPalettes>
+ </colorPalettes>
+ </SVG>
+
+</ttFont>
diff --git a/test/svg/svg-render.c b/test/svg/svg-render.c
new file mode 100644
index 000000000..8f67ebdc2
--- /dev/null
+++ b/test/svg/svg-render.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright © 2016 Adrian Johnson
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Adrian Johnson <ajohnson@redneon.com>
+ */
+
+/* Compilation:
+ * Build cairo with -DDEBUG_SVG_RENDER
+ * gcc -o svg-render svg-render.c `pkg-config --cflags --libs cairo librsvg`
+ */
+
+/* svg-render - render SVG files using both the cairo glyph renderer and librsvg.
+ *
+ * This allows testing the cairo SVG test cases before assembling them into an SVG font.
+ * Usage:
+ * svg-render [-b] [-s] [-g <id>] [-e <em_size> ] input.svg
+ *
+ * Output is written to input.cairo.png and input.rsvg.png.
+ *
+ * -b print bounding box.
+ * -s Use standard SVG viewport. See below.
+ * -g render glyph with id <id>
+ * -e set the EM size. The default is 1000.
+ *
+ * SVG Glyphs are assumed to be wholely within the view port.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <cairo.h>
+#include <librsvg/rsvg.h>
+
+typedef enum { CAIRO_SVG, LIBRSVG } svg_renderer_t;
+
+/* output image size */
+#define WIDTH 1000
+#define HEIGHT 1000
+
+static cairo_bool_t bbox = FALSE;
+static cairo_bool_t standard_svg = FALSE;
+static const char *glyph_id = NULL;
+static int em_size = 1000;
+
+cairo_bool_t
+_cairo_debug_svg_render (cairo_t *cr,
+ const char *svg_document,
+ const char *element,
+ double units_per_em,
+ int debug_level);
+
+static void
+cairo_render (const char *svg_document, cairo_t *cr)
+{
+ if (!_cairo_debug_svg_render (cr, svg_document, glyph_id, em_size, 2))
+ printf("_cairo_debug_svg_render() failed\n");
+}
+
+static void
+librsvg_render (const char *svg_document, cairo_t *cr)
+{
+ gboolean has_width;
+ gboolean has_height;
+ gboolean has_viewbox;
+ RsvgLength svg_width;
+ RsvgLength svg_height;
+ RsvgRectangle svg_viewbox;
+ RsvgRectangle viewport;
+ double width, height;
+ GError *error = NULL;
+
+ RsvgHandle *handle = rsvg_handle_new_from_data ((guint8 *)svg_document,
+ strlen(svg_document),
+ &error);
+ if (!handle) {
+ printf ("Could not load: %s", error->message);
+ return;
+ }
+
+ /* Default width if not specified is EM Square */
+ width = em_size;
+ height = em_size;
+
+ /* Get width/height if specified. */
+ rsvg_handle_get_intrinsic_dimensions(handle,
+ &has_width,
+ &svg_width,
+ &has_height,
+ &svg_height,
+ &has_viewbox,
+ &svg_viewbox);
+ if (has_width)
+ width = svg_width.length;
+
+ if (has_height)
+ height = svg_height.length;
+
+ /* We set the viewport for the call rsvg_handle_render_layer() to
+ * width/height. That way if either dimension is not specified in
+ * the SVG it will be inherited from the viewport we provide.
+ *
+ * As this scales up the rendered dimensions by width/height we
+ * need to undo this scaling to get a unit square scale that
+ * matches the cairo SVG renderer scale. The OpenType SVG spec
+ * does not say what to do if width != height. In this case we
+ * will just use a uniform scale that ensures the viewport fits in
+ * the unit square and also center it.
+ */
+
+ if (width > height) {
+ cairo_scale (cr, 1.0/width, 1.0/width);
+ cairo_translate (cr, 0, (width - height)/2.0);
+ } else {
+ cairo_scale (cr, 1.0/height, 1.0/height);
+ cairo_translate (cr, (height - width)/2.0, 0);
+ }
+
+ viewport.x = 0;
+ viewport.y = 0;
+ viewport.width = width;
+ viewport.height = height;
+ if (!rsvg_handle_render_layer (handle, cr, glyph_id, &viewport, &error)) {
+ printf ("librsvg render failed: %s", error->message);
+ return;
+ }
+}
+
+static void
+render_svg (const char *svg_document, svg_renderer_t renderer, const char* out_file)
+{
+ double x, y, w, h;
+
+ cairo_surface_t *recording = cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
+ cairo_t *cr = cairo_create (recording);
+
+ /* Scale up to image size when recording to reduce rounding errors
+ * in cairo_recording_surface_ink_extents()
+ */
+ cairo_scale (cr, WIDTH, HEIGHT);
+
+ if (renderer == CAIRO_SVG) {
+ cairo_render (svg_document, cr);
+ } else {
+ librsvg_render (svg_document, cr);
+ }
+ cairo_destroy (cr);
+
+ if (bbox) {
+ cairo_recording_surface_ink_extents (recording, &x, &y, &w, &h);
+ if (renderer == CAIRO_SVG)
+ printf("cairo ");
+ else
+ printf("librsvg");
+
+ printf(" bbox left: %d right: %d top: %d bottom: %d\n",
+ (int)floor(x),
+ (int)ceil(x + w),
+ (int)floor(y),
+ (int)ceil(y + h));
+ }
+
+ cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT);
+ cr = cairo_create (surface);
+
+ /* If rendering a glyph need to translate base line to bottom of image */
+ if (standard_svg)
+ cairo_set_source_surface (cr, recording, 0, 0);
+ else
+ cairo_set_source_surface (cr, recording, 0, HEIGHT);
+
+ cairo_paint (cr);
+
+ cairo_surface_write_to_png (surface, out_file);
+ cairo_surface_destroy (surface);
+}
+
+static char *
+create_output_name (const char *svg_file, svg_renderer_t renderer)
+{
+ char buf[1000];
+ int len;
+
+ strcpy (buf, svg_file);
+ len = strlen (buf);
+
+ if (strlen (buf) > 5 && strcmp (buf + len - 4, ".svg") == 0)
+ buf[len - 4] = 0;
+
+ if (renderer == CAIRO_SVG)
+ strcat (buf, ".cairo.png");
+ else
+ strcat (buf, ".rsvg.png");
+
+ return strdup (buf);
+}
+
+static char *
+read_file(const char *filename)
+{
+ FILE *fp;
+ int len;
+ char *data;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ return NULL;
+
+ fseek (fp, 0, SEEK_END);
+ len = ftell(fp);
+ rewind (fp);
+ data = malloc (len + 1);
+ if (fread(data, len, 1, fp) != 1)
+ return NULL;
+ data[len] = 0;
+ fclose(fp);
+ return data;
+}
+
+static void
+usage_and_exit()
+{
+ printf ("svg-render [-b] [-s] [-g <id>] [-e <em_size> ] input.svg\n");
+ exit (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ const char *input_file = NULL;
+ char *svg_document;
+ char *output_file;
+
+ argc--;
+ argv++;
+ while (argc > 0) {
+ if (strcmp (argv[0], "-b") == 0) {
+ bbox = TRUE;
+ argc--;
+ argv++;
+ } else if (strcmp (argv[0], "-s") == 0) {
+ standard_svg = TRUE;
+ argc--;
+ argv++;
+ } else if (strcmp (argv[0], "-g") == 0) {
+ if (argc > 1) {
+ glyph_id = argv[1];
+ argc -= 2;
+ argv += 2;
+ } else {
+ usage_and_exit();
+ }
+ } else if (strcmp (argv[0], "-e") == 0) {
+ if (argc > 1) {
+ em_size = atoi (argv[1]);
+ if (em_size <= 0) {
+ usage_and_exit();
+ }
+ argc -= 2;
+ argv += 2;
+ } else {
+ usage_and_exit();
+ }
+ } else {
+ input_file = argv[0];
+ argc--;
+ argv++;
+ }
+ }
+ if (!input_file)
+ usage_and_exit();
+
+ svg_document = read_file (input_file);
+ if (!svg_document) {
+ printf("error reading file %s\n", input_file);
+ exit (1);
+ }
+
+ output_file = create_output_name (input_file, CAIRO_SVG);
+ render_svg (svg_document, CAIRO_SVG, output_file);
+ free (output_file);
+
+ output_file = create_output_name (input_file, LIBRSVG);
+ render_svg (svg_document, LIBRSVG, output_file);
+ free (output_file);
+
+ free (svg_document);
+
+ return 0;
+}
diff --git a/test/svg/transform.0.translate.svg b/test/svg/transform.0.translate.svg
new file mode 100644
index 000000000..5d9555673
--- /dev/null
+++ b/test/svg/transform.0.translate.svg
@@ -0,0 +1,8 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <use xlink:href="#square" transform="translate(600, -400)"/>
+</svg>
diff --git a/test/svg/transform.1.scale.svg b/test/svg/transform.1.scale.svg
new file mode 100644
index 000000000..b7742fc80
--- /dev/null
+++ b/test/svg/transform.1.scale.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -400)">
+ <use xlink:href="#square" transform="scale(1.5, 0.5)"/>
+ </g>
+</svg>
diff --git a/test/svg/transform.2.rotate.svg b/test/svg/transform.2.rotate.svg
new file mode 100644
index 000000000..926ae63fc
--- /dev/null
+++ b/test/svg/transform.2.rotate.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(600, -600)">
+ <use xlink:href="#square" transform="rotate(30)"/>
+ </g>
+</svg>
diff --git a/test/svg/transform.3.skewX.svg b/test/svg/transform.3.skewX.svg
new file mode 100644
index 000000000..f7555534d
--- /dev/null
+++ b/test/svg/transform.3.skewX.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -400)">
+ <use xlink:href="#square" transform="skewX(30)"/>
+ </g>
+</svg>
diff --git a/test/svg/transform.4.skewY.svg b/test/svg/transform.4.skewY.svg
new file mode 100644
index 000000000..cd62c8a8a
--- /dev/null
+++ b/test/svg/transform.4.skewY.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(400, -500)">
+ <use xlink:href="#square" transform="skewY(30)"/>
+ </g>
+</svg>
diff --git a/test/svg/transform.5.matrix.svg b/test/svg/transform.5.matrix.svg
new file mode 100644
index 000000000..643fbe36b
--- /dev/null
+++ b/test/svg/transform.5.matrix.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <rect id="square" width="300" height="300"/>
+ </defs>
+ <use xlink:href="#square" transform="translate(100, -900)"/>
+ <g transform="translate(600, -600)">
+ <use xlink:href="#square" transform="matrix(1, 0.4, -0.6, 1.1, 50, -70)"/>
+ </g>
+</svg>
diff --git a/test/svg/transform.6.multiple.svg b/test/svg/transform.6.multiple.svg
new file mode 100644
index 000000000..90c7b3054
--- /dev/null
+++ b/test/svg/transform.6.multiple.svg
@@ -0,0 +1,16 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <path id="heart" d="M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z" />
+ </defs>
+ <use xlink:href="#heart"
+ transform="translate(10, -650)
+ rotate(-10 50 100)
+ translate(-166 125.5)
+ skewX(40)
+ scale(1 0.5),scale(8, 8)"
+ fill="grey"/>
+ <use xlink:href="#heart"
+ transform="translate(300, -800),scale(6, 6)"
+ fill="none" stroke="red" />
+</svg>
diff --git a/test/svg/transform.7.stroke.svg b/test/svg/transform.7.stroke.svg
new file mode 100644
index 000000000..f56b24dfe
--- /dev/null
+++ b/test/svg/transform.7.stroke.svg
@@ -0,0 +1,20 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <circle id="c1"
+ cx="100" cy="100" r="80"
+ fill="none"
+ stroke="black"
+ stroke-width="20" />
+ <circle id="c2"
+ cx="100" cy="100" r="80"
+ fill="none"
+ stroke="black"
+ stroke-width="20"
+ transform="scale(3,3)" />
+ </defs>
+
+ <use xlink:href="#c1" x="100" y="-900"/>
+ <use xlink:href="#c2" x="300" y="-700"/>
+
+</svg>