[483] | 1 | <?xml version="1.0" encoding="UTF-8"?> |
---|
| 2 | <!DOCTYPE xsl:stylesheet [ |
---|
| 3 | <!ENTITY SupportedElements "svg:a|svg:circle|svg:ellipse|svg:g|svg:image|svg:line|svg:path|svg:polygon|svg:polyline|svg:rect|svg:text|svg:textPath|svg:use"> |
---|
| 4 | ]> |
---|
| 5 | <!-- This is a complete rewrite of the original svg2gfx.xslt used for testing. --> |
---|
| 6 | <!-- |
---|
| 7 | This version supports polygons, polylines, circles, ellipses, rectangles, |
---|
| 8 | lines, images, text, patterns, linear gradients, radial gradients, transforms |
---|
| 9 | (although gradient transforms are limited), and more in addition to the |
---|
| 10 | paths, strokes, groups, and constant fills supported by the original. It |
---|
| 11 | even handles little niceties like the SVG use element. All that being said, |
---|
| 12 | It does not even come close to supporting all of the features found in SVG, |
---|
| 13 | but should hopefully be a fairly useful subset. |
---|
| 14 | |
---|
| 15 | Caveats: Completely ignores many SVG features (such as named views, filters, |
---|
| 16 | object bounding box in gradient transforms, etc.). Now requires properly |
---|
| 17 | formed SVG (that is, SVG using the appropriate SVG namespace) which most |
---|
| 18 | editors create by default these days anyhow (the old version required that |
---|
| 19 | namespaces be stripped off). Can't convert to GFX constructs that cannot |
---|
| 20 | be reconstructed from JSON (such as textpath or using vector fonts). |
---|
| 21 | Requires EXSLT for many transforms. Handles nested styles in a simple way |
---|
| 22 | that is usually right but sometimes wrong. |
---|
| 23 | |
---|
| 24 | Questions / comments / bug reports can be sent to Feneric (on Twitter, IRC, |
---|
| 25 | GMail, etc.) or Eric (Saugus.net, ShellTown, etc.) |
---|
| 26 | --> |
---|
| 27 | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" |
---|
| 28 | xmlns:svg="http://www.w3.org/2000/svg" |
---|
| 29 | xmlns:xlink="http://www.w3.org/1999/xlink" |
---|
| 30 | xmlns:math="http://exslt.org/math" |
---|
| 31 | xmlns:exsl="http://exslt.org/common" |
---|
| 32 | xmlns:saxon="http://icl.com/saxon" |
---|
| 33 | xmlns:xalan="http://xml.apache.org/Xalan" |
---|
| 34 | extension-element-prefixes="math exsl saxon xalan"> |
---|
| 35 | <xsl:output method="text" version="1.0" encoding="UTF-8"/> |
---|
| 36 | <xsl:strip-space elements="*"/> |
---|
| 37 | |
---|
| 38 | <!-- We currently need this constant for some transformation calculations. --> |
---|
| 39 | <!-- GFX enhancements could obviate it in the future. --> |
---|
| 40 | <xsl:variable name="degressInRadian" select="57.295779513082322"/> |
---|
| 41 | |
---|
| 42 | <!-- The following templates process little bits of things that can often occur in multiple contexts --> |
---|
| 43 | |
---|
| 44 | <xsl:template name="kill-extra-spaces"> |
---|
| 45 | <xsl:param name="string"/> |
---|
| 46 | <!-- Some don't feel that SVG is verbose enough and thus add extra spaces, which when --> |
---|
| 47 | <!-- untreated can look exactly like delimiters in point sets. --> |
---|
| 48 | <xsl:choose> |
---|
| 49 | <!-- Hopefully most cases won't have the extra spaces --> |
---|
| 50 | <xsl:when test="not(contains($string,', '))"> |
---|
| 51 | <xsl:value-of select="$string"/> |
---|
| 52 | </xsl:when> |
---|
| 53 | <xsl:otherwise> |
---|
| 54 | <!-- We split at comma / space pairs and recursively chop spaces --> |
---|
| 55 | <xsl:call-template name="kill-extra-spaces"> |
---|
| 56 | <xsl:with-param name="string" select="substring-before($string,', ')"/> |
---|
| 57 | </xsl:call-template> |
---|
| 58 | <xsl:text>,</xsl:text> |
---|
| 59 | <xsl:call-template name="kill-extra-spaces"> |
---|
| 60 | <xsl:with-param name="string" select="substring-after($string,', ')"/> |
---|
| 61 | </xsl:call-template> |
---|
| 62 | </xsl:otherwise> |
---|
| 63 | </xsl:choose> |
---|
| 64 | </xsl:template> |
---|
| 65 | |
---|
| 66 | <xsl:template name="arg-processor"> |
---|
| 67 | <xsl:param name="values"/> |
---|
| 68 | <xsl:param name="labels"/> |
---|
| 69 | <!-- Recursively chew through the arguments in a traditional CAR / CDR pattern --> |
---|
| 70 | <xsl:variable name="valuesCdr" select="substring-after($values,',')"/> |
---|
| 71 | <!-- We're going "backwards" here to take advantage of tail recursion --> |
---|
| 72 | <xsl:choose> |
---|
| 73 | <xsl:when test="not($valuesCdr)"> |
---|
| 74 | <!-- handle the final argument --> |
---|
| 75 | <xsl:value-of select="$labels"/> |
---|
| 76 | <xsl:text>:</xsl:text> |
---|
| 77 | <xsl:value-of select="$values"/> |
---|
| 78 | <!-- This last trailing comma is needed in the (odd) case of multiple transforms --> |
---|
| 79 | <xsl:text>,</xsl:text> |
---|
| 80 | </xsl:when> |
---|
| 81 | <xsl:otherwise> |
---|
| 82 | <!-- handle the current argument --> |
---|
| 83 | <xsl:value-of select="substring-before($labels,',')"/> |
---|
| 84 | <xsl:text>:</xsl:text> |
---|
| 85 | <xsl:value-of select="substring-before($values,',')"/> |
---|
| 86 | <xsl:text>,</xsl:text> |
---|
| 87 | <xsl:call-template name="arg-processor"> |
---|
| 88 | <xsl:with-param name="values" select="$valuesCdr"/> |
---|
| 89 | <xsl:with-param name="labels" select="substring-after($labels,',')"/> |
---|
| 90 | </xsl:call-template> |
---|
| 91 | </xsl:otherwise> |
---|
| 92 | </xsl:choose> |
---|
| 93 | </xsl:template> |
---|
| 94 | |
---|
| 95 | <xsl:template name="background-processor"> |
---|
| 96 | <xsl:param name="background"/> |
---|
| 97 | <xsl:choose> |
---|
| 98 | <xsl:when test="starts-with($background,'url')"> |
---|
| 99 | <!-- Check if we have a URL (for a gradient or pattern) --> |
---|
| 100 | <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after($background,'('),')')),' ',',')"/> |
---|
| 101 | <xsl:call-template name="url-processor"> |
---|
| 102 | <xsl:with-param name="url" select="$arguments"/> |
---|
| 103 | </xsl:call-template> |
---|
| 104 | </xsl:when> |
---|
| 105 | <xsl:otherwise> |
---|
| 106 | <!-- We probably have a solid color. --> |
---|
| 107 | <xsl:call-template name="color-processor"> |
---|
| 108 | <xsl:with-param name="color" select="$background"/> |
---|
| 109 | </xsl:call-template> |
---|
| 110 | </xsl:otherwise> |
---|
| 111 | </xsl:choose> |
---|
| 112 | </xsl:template> |
---|
| 113 | |
---|
| 114 | <xsl:template name="color-processor"> |
---|
| 115 | <xsl:param name="color"/> |
---|
| 116 | <xsl:choose> |
---|
| 117 | <xsl:when test="starts-with($color,'rgb')"> |
---|
| 118 | <!-- Check if we have an RGB triple --> |
---|
| 119 | <xsl:variable name="arguments" select="normalize-space(substring-before(substring-after($color,'('),')'))"/> |
---|
| 120 | <xsl:call-template name="rgb-triple-processor"> |
---|
| 121 | <xsl:with-param name="triple" select="$arguments"/> |
---|
| 122 | </xsl:call-template> |
---|
| 123 | </xsl:when> |
---|
| 124 | <xsl:when test="$color='none'"> |
---|
| 125 | <!-- Check if we have a literal 'none' --> |
---|
| 126 | <!-- Literal nones seem to actually map to black in practice --> |
---|
| 127 | <xsl:text>"#000000",</xsl:text> |
---|
| 128 | </xsl:when> |
---|
| 129 | <xsl:otherwise> |
---|
| 130 | <!-- This color could either be by name or value. Either way, we --> |
---|
| 131 | <!-- have to ensure that there are no bogus semi-colons. --> |
---|
| 132 | <xsl:text>"</xsl:text> |
---|
| 133 | <xsl:value-of select="normalize-space(translate($color,';',' '))"/> |
---|
| 134 | <xsl:text>",</xsl:text> |
---|
| 135 | </xsl:otherwise> |
---|
| 136 | </xsl:choose> |
---|
| 137 | </xsl:template> |
---|
| 138 | |
---|
| 139 | <xsl:template name="point-processor"> |
---|
| 140 | <xsl:param name="points"/> |
---|
| 141 | <!-- Recursively process points in a traditional CAR / CDR pattern --> |
---|
| 142 | <xsl:variable name="pointsCdr" select="normalize-space(substring-after($points,' '))"/> |
---|
| 143 | <!-- We're going "backwards" here to take advantage of tail recursion --> |
---|
| 144 | <xsl:choose> |
---|
| 145 | <xsl:when test="not($pointsCdr)"> |
---|
| 146 | <!-- handle the final argument --> |
---|
| 147 | <xsl:text>{x:</xsl:text> |
---|
| 148 | <xsl:value-of select="substring-before($points,',')"/> |
---|
| 149 | <xsl:text>,y:</xsl:text> |
---|
| 150 | <xsl:value-of select="substring-after($points,',')"/> |
---|
| 151 | <xsl:text>},</xsl:text> |
---|
| 152 | </xsl:when> |
---|
| 153 | <xsl:otherwise> |
---|
| 154 | <!-- handle the current argument --> |
---|
| 155 | <xsl:variable name="pointsCar" select="substring-before($points,' ')"/> |
---|
| 156 | <xsl:text>{x:</xsl:text> |
---|
| 157 | <xsl:value-of select="substring-before($pointsCar,',')"/> |
---|
| 158 | <xsl:text>,y:</xsl:text> |
---|
| 159 | <xsl:value-of select="substring-after($pointsCar,',')"/> |
---|
| 160 | <xsl:text>},</xsl:text> |
---|
| 161 | <xsl:call-template name="point-processor"> |
---|
| 162 | <xsl:with-param name="points" select="$pointsCdr"/> |
---|
| 163 | </xsl:call-template> |
---|
| 164 | </xsl:otherwise> |
---|
| 165 | </xsl:choose> |
---|
| 166 | </xsl:template> |
---|
| 167 | |
---|
| 168 | <xsl:template name="rgb-triple-processor"> |
---|
| 169 | <xsl:param name="triple"/> |
---|
| 170 | <!-- Note that as SVG triples cannot contain alpha values, we hardcode it to be fully opaque --> |
---|
| 171 | <!-- This could theoretically be better handled by watching for fill-opacity --> |
---|
| 172 | <xsl:variable name="red" select="substring-before($triple,',')"/> |
---|
| 173 | <xsl:variable name="green" select="substring-before(substring-after($triple,concat($red,',')),',')"/> |
---|
| 174 | <xsl:variable name="blue" select="substring-after($triple,concat($red,',',$green,','))"/> |
---|
| 175 | <xsl:text>{"r":</xsl:text> |
---|
| 176 | <xsl:value-of select="normalize-space($red)"/> |
---|
| 177 | <xsl:text>,"g":</xsl:text> |
---|
| 178 | <xsl:value-of select="normalize-space($green)"/> |
---|
| 179 | <xsl:text>,"b":</xsl:text> |
---|
| 180 | <xsl:value-of select="normalize-space($blue)"/> |
---|
| 181 | <xsl:text>,"a":1},</xsl:text> |
---|
| 182 | </xsl:template> |
---|
| 183 | |
---|
| 184 | <xsl:template name="styles-processor"> |
---|
| 185 | <xsl:param name="styles"/> |
---|
| 186 | <!-- Recursively chew through the styles in a traditional CAR / CDR pattern --> |
---|
| 187 | <xsl:variable name="stylesCdr" select="substring-after($styles,';')"/> |
---|
| 188 | <!-- We're going "backwards" here to take advantage of tail recursion --> |
---|
| 189 | <xsl:choose> |
---|
| 190 | <xsl:when test="not($stylesCdr)"> |
---|
| 191 | <!-- handle the final style --> |
---|
| 192 | <xsl:attribute name="{normalize-space(substring-before($styles,':'))}"> |
---|
| 193 | <xsl:value-of select="normalize-space(substring-after($styles,':'))"/> |
---|
| 194 | </xsl:attribute> |
---|
| 195 | </xsl:when> |
---|
| 196 | <xsl:otherwise> |
---|
| 197 | <!-- handle the current style --> |
---|
| 198 | <xsl:variable name="stylesCar" select="substring-before($styles,';')"/> |
---|
| 199 | <xsl:attribute name="{normalize-space(substring-before($stylesCar,':'))}"> |
---|
| 200 | <xsl:value-of select="normalize-space(substring-after($stylesCar,':'))"/> |
---|
| 201 | </xsl:attribute> |
---|
| 202 | <xsl:call-template name="styles-processor"> |
---|
| 203 | <xsl:with-param name="styles" select="$stylesCdr"/> |
---|
| 204 | </xsl:call-template> |
---|
| 205 | </xsl:otherwise> |
---|
| 206 | </xsl:choose> |
---|
| 207 | </xsl:template> |
---|
| 208 | |
---|
| 209 | <xsl:template name="transform-processor"> |
---|
| 210 | <xsl:param name="transforms"/> |
---|
| 211 | <!-- Recursively chew through the transforms in a traditional CAR / CDR pattern --> |
---|
| 212 | <xsl:variable name="transformsCdr" select="normalize-space(substring-after($transforms,')'))"/> |
---|
| 213 | <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after($transforms,'('),')')),' ',',')"/> |
---|
| 214 | <xsl:choose> |
---|
| 215 | <!-- We only handle simple (i.e. nonoverlapping) chained transforms. --> |
---|
| 216 | <!-- This covers most real-world cases, and exceptions are generally --> |
---|
| 217 | <!-- hand-generated and can likewise be hand fixed. --> |
---|
| 218 | <xsl:when test="starts-with($transforms,'matrix')"> |
---|
| 219 | <xsl:call-template name="arg-processor"> |
---|
| 220 | <xsl:with-param name="values" select="$arguments"/> |
---|
| 221 | <xsl:with-param name="labels" select="string('xx,yx,xy,yy,dx,dy')"/> |
---|
| 222 | </xsl:call-template> |
---|
| 223 | </xsl:when> |
---|
| 224 | <xsl:when test="starts-with($transforms,'translate')"> |
---|
| 225 | <!-- If only one argument is provided, it's assumed for both --> |
---|
| 226 | <xsl:choose> |
---|
| 227 | <xsl:when test="contains($arguments,',')"> |
---|
| 228 | <xsl:call-template name="arg-processor"> |
---|
| 229 | <xsl:with-param name="values" select="$arguments"/> |
---|
| 230 | <xsl:with-param name="labels" select="string('dx,dy')"/> |
---|
| 231 | </xsl:call-template> |
---|
| 232 | </xsl:when> |
---|
| 233 | <xsl:otherwise> |
---|
| 234 | <xsl:call-template name="arg-processor"> |
---|
| 235 | <xsl:with-param name="values" select="concat($arguments,',',$arguments)"/> |
---|
| 236 | <xsl:with-param name="labels" select="string('dx,dy')"/> |
---|
| 237 | </xsl:call-template> |
---|
| 238 | </xsl:otherwise> |
---|
| 239 | </xsl:choose> |
---|
| 240 | </xsl:when> |
---|
| 241 | <xsl:when test="starts-with($transforms,'scale')"> |
---|
| 242 | <!-- If only one argument is provided, it's assumed for both --> |
---|
| 243 | <xsl:choose> |
---|
| 244 | <xsl:when test="contains($arguments,',')"> |
---|
| 245 | <xsl:call-template name="arg-processor"> |
---|
| 246 | <xsl:with-param name="values" select="$arguments"/> |
---|
| 247 | <xsl:with-param name="labels" select="string('xx,yy')"/> |
---|
| 248 | </xsl:call-template> |
---|
| 249 | </xsl:when> |
---|
| 250 | <xsl:otherwise> |
---|
| 251 | <xsl:call-template name="arg-processor"> |
---|
| 252 | <xsl:with-param name="values" select="concat($arguments,',',$arguments)"/> |
---|
| 253 | <xsl:with-param name="labels" select="string('xx,yy')"/> |
---|
| 254 | </xsl:call-template> |
---|
| 255 | </xsl:otherwise> |
---|
| 256 | </xsl:choose> |
---|
| 257 | </xsl:when> |
---|
| 258 | <xsl:when test="starts-with($transforms,'rotate')"> |
---|
| 259 | <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> |
---|
| 260 | <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> |
---|
| 261 | <!-- If you don't have the extensions, comment the following out (bye bye rotate). --> |
---|
| 262 | <xsl:choose> |
---|
| 263 | <xsl:when test="function-available('math:sin') and function-available('math:cos')"> |
---|
| 264 | <xsl:variable name="sinOfAngle" select="math:sin($arguments div $degressInRadian)"/> |
---|
| 265 | <xsl:variable name="cosOfAngle" select="math:cos($arguments div $degressInRadian)"/> |
---|
| 266 | <xsl:variable name="subarguments" select="concat($cosOfAngle,',',-$sinOfAngle,',',$sinOfAngle,',',$cosOfAngle)"/> |
---|
| 267 | <xsl:call-template name="arg-processor"> |
---|
| 268 | <xsl:with-param name="values" select="$subarguments"/> |
---|
| 269 | <xsl:with-param name="labels" select="string('xx,yx,xy,yy')"/> |
---|
| 270 | </xsl:call-template> |
---|
| 271 | </xsl:when> |
---|
| 272 | <xsl:otherwise> |
---|
| 273 | <xsl:message> |
---|
| 274 | <xsl:text>exslt:sin and exslt:cos must be supported for a rotation.</xsl:text> |
---|
| 275 | </xsl:message> |
---|
| 276 | </xsl:otherwise> |
---|
| 277 | </xsl:choose> |
---|
| 278 | </xsl:when> |
---|
| 279 | <xsl:when test="starts-with($transforms,'skewX')"> |
---|
| 280 | <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> |
---|
| 281 | <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> |
---|
| 282 | <!-- If you don't have the extensions, comment the following out (bye bye skewX). --> |
---|
| 283 | <xsl:choose> |
---|
| 284 | <xsl:when test="function-available('math:tan')"> |
---|
| 285 | <xsl:variable name="tanOfAngle" select="math:tan($arguments div $degressInRadian)"/> |
---|
| 286 | <xsl:call-template name="arg-processor"> |
---|
| 287 | <xsl:with-param name="values" select="$tanOfAngle"/> |
---|
| 288 | <xsl:with-param name="labels" select="string('xy')"/> |
---|
| 289 | </xsl:call-template> |
---|
| 290 | </xsl:when> |
---|
| 291 | <xsl:otherwise> |
---|
| 292 | <xsl:message> |
---|
| 293 | <xsl:text>exslt:tan must be supported for a skewX.</xsl:text> |
---|
| 294 | </xsl:message> |
---|
| 295 | </xsl:otherwise> |
---|
| 296 | </xsl:choose> |
---|
| 297 | </xsl:when> |
---|
| 298 | <xsl:when test="starts-with($transforms,'skewY')"> |
---|
| 299 | <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> |
---|
| 300 | <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> |
---|
| 301 | <!-- If you don't have the extensions, comment the following out (bye bye skewY). --> |
---|
| 302 | <xsl:choose> |
---|
| 303 | <xsl:when test="function-available('math:tan')"> |
---|
| 304 | <xsl:variable name="tanOfAngle" select="math:tan($arguments div $degressInRadian)"/> |
---|
| 305 | <xsl:call-template name="arg-processor"> |
---|
| 306 | <xsl:with-param name="values" select="$tanOfAngle"/> |
---|
| 307 | <xsl:with-param name="labels" select="string('yx')"/> |
---|
| 308 | </xsl:call-template> |
---|
| 309 | </xsl:when> |
---|
| 310 | <xsl:otherwise> |
---|
| 311 | <xsl:message> |
---|
| 312 | <xsl:text>exslt:tan must be supported for a skewY.</xsl:text> |
---|
| 313 | </xsl:message> |
---|
| 314 | </xsl:otherwise> |
---|
| 315 | </xsl:choose> |
---|
| 316 | </xsl:when> |
---|
| 317 | </xsl:choose> |
---|
| 318 | <xsl:if test="$transformsCdr"> |
---|
| 319 | <!-- handle the other transforms --> |
---|
| 320 | <xsl:call-template name="transform-processor"> |
---|
| 321 | <xsl:with-param name="transforms" select="$transformsCdr"/> |
---|
| 322 | </xsl:call-template> |
---|
| 323 | </xsl:if> |
---|
| 324 | </xsl:template> |
---|
| 325 | |
---|
| 326 | <xsl:template name="url-processor"> |
---|
| 327 | <xsl:param name="url"/> |
---|
| 328 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 329 | <!-- We can only handle local references; that's probably all we should get anyway --> |
---|
| 330 | <xsl:if test="starts-with($url,'#')"> |
---|
| 331 | <xsl:apply-templates select="id(substring-after($url,'#'))"> |
---|
| 332 | <xsl:with-param name="groupAttrs" select="$groupAttrs"/> |
---|
| 333 | </xsl:apply-templates> |
---|
| 334 | </xsl:if> |
---|
| 335 | </xsl:template> |
---|
| 336 | |
---|
| 337 | <!-- The following templates help with gradient transforms --> |
---|
| 338 | |
---|
| 339 | <!-- We're temporarily supporting a few SVG features that GFX does not currently support. --> |
---|
| 340 | <!-- The biggest of these is gradient transforms; when GFX natively supports it all the --> |
---|
| 341 | <!-- kluges made to support it here (including all the following code) should be removed. --> |
---|
| 342 | |
---|
| 343 | <xsl:template name="gradient-transform-helper"> |
---|
| 344 | <!-- This nasty little routine helps gradient adjuster and can be --> |
---|
| 345 | <!-- removed when GFX gets gradientTransform support. --> |
---|
| 346 | <xsl:param name="cxa"/> |
---|
| 347 | <xsl:param name="cya"/> |
---|
| 348 | <xsl:param name="x1a"/> |
---|
| 349 | <xsl:param name="y1a"/> |
---|
| 350 | <xsl:param name="x2a"/> |
---|
| 351 | <xsl:param name="y2a"/> |
---|
| 352 | <xsl:param name="xx"/> |
---|
| 353 | <xsl:param name="xy"/> |
---|
| 354 | <xsl:param name="yx"/> |
---|
| 355 | <xsl:param name="yy"/> |
---|
| 356 | <xsl:param name="dx"/> |
---|
| 357 | <xsl:param name="dy"/> |
---|
| 358 | <xsl:choose> |
---|
| 359 | <xsl:when test="local-name()='radialGradient'"> |
---|
| 360 | <xsl:variable name="cx" select="$xx*$cxa+$xy*$cya+$dx"/> |
---|
| 361 | <xsl:text>cx:</xsl:text> |
---|
| 362 | <xsl:value-of select="$cx"/> |
---|
| 363 | <xsl:text>,</xsl:text> |
---|
| 364 | <xsl:variable name="cy" select="$yx*$cxa+$yy*$cya+$dy"/> |
---|
| 365 | <xsl:text>cy:</xsl:text> |
---|
| 366 | <xsl:value-of select="$cy"/> |
---|
| 367 | <xsl:text>,</xsl:text> |
---|
| 368 | <!-- The results for r here are going to just be approximate --> |
---|
| 369 | <xsl:variable name="r" select="($cx+$cy) div 2"/> |
---|
| 370 | <xsl:text>r:</xsl:text> |
---|
| 371 | <xsl:value-of select="$r"/> |
---|
| 372 | </xsl:when> |
---|
| 373 | <xsl:otherwise> |
---|
| 374 | <xsl:variable name="x1" select="$xx*$x1a+$xy*$y1a+$dx"/> |
---|
| 375 | <xsl:text>x1:</xsl:text> |
---|
| 376 | <xsl:value-of select="$x1"/> |
---|
| 377 | <xsl:text>,</xsl:text> |
---|
| 378 | <xsl:variable name="y1" select="$yx*$x1a+$yy*$y1a+$dy"/> |
---|
| 379 | <xsl:text>y1:</xsl:text> |
---|
| 380 | <xsl:value-of select="$y1"/> |
---|
| 381 | <xsl:text>,</xsl:text> |
---|
| 382 | <xsl:variable name="x2" select="$xx*$x2a+$xy*$y2a+$dx"/> |
---|
| 383 | <xsl:text>x2:</xsl:text> |
---|
| 384 | <xsl:value-of select="$x2"/> |
---|
| 385 | <xsl:text>,</xsl:text> |
---|
| 386 | <xsl:variable name="y2" select="$yx*$x2a+$yy*$y2a+$dy"/> |
---|
| 387 | <xsl:text>y2:</xsl:text> |
---|
| 388 | <xsl:value-of select="$y2"/> |
---|
| 389 | </xsl:otherwise> |
---|
| 390 | </xsl:choose> |
---|
| 391 | </xsl:template> |
---|
| 392 | |
---|
| 393 | <xsl:template name="gradient-adjuster"> |
---|
| 394 | <xsl:param name="node"/> |
---|
| 395 | <!-- This code is awful and only meant to serve until GFX gets gradientTransform support. --> |
---|
| 396 | <!-- Once GFX does gradientTransforms, the following should be destroyed and forgotten. --> |
---|
| 397 | <!-- While this support is better than nothing, it cannot 100% reproduce the effects --> |
---|
| 398 | <!-- that true gradientTransform support in GFX could provide. --> |
---|
| 399 | <xsl:choose> |
---|
| 400 | <xsl:when test="starts-with($node/@gradientTransform,'matrix')"> |
---|
| 401 | <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'matrix('),')'))"/> |
---|
| 402 | <xsl:variable name="xx" select="substring-before($args,' ')"/> |
---|
| 403 | <xsl:variable name="yx" select="substring-before(substring-after($args,' '),' ')"/> |
---|
| 404 | <xsl:variable name="xy" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ')),' ')"/> |
---|
| 405 | <xsl:variable name="yy" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ',$xy,' ')),' ')"/> |
---|
| 406 | <xsl:variable name="dx" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ',$xy,' ',$yy,' ')),' ')"/> |
---|
| 407 | <xsl:variable name="dy" select="substring-after($args,concat($xx,' ',$yx,' ',$xy,' ',$yy,' ',$dx,' '))"/> |
---|
| 408 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 409 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 410 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 411 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 412 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 413 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 414 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 415 | <xsl:with-param name="xx" select="$xx"/> |
---|
| 416 | <xsl:with-param name="yx" select="$yx"/> |
---|
| 417 | <xsl:with-param name="xy" select="$xy"/> |
---|
| 418 | <xsl:with-param name="yy" select="$yy"/> |
---|
| 419 | <xsl:with-param name="dx" select="$dx"/> |
---|
| 420 | <xsl:with-param name="dy" select="$dy"/> |
---|
| 421 | </xsl:call-template> |
---|
| 422 | </xsl:when> |
---|
| 423 | <xsl:when test="starts-with($node/@gradientTransform,'translate')"> |
---|
| 424 | <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'translate('),')'))"/> |
---|
| 425 | <!-- If only one argument is provided, it's assumed for both --> |
---|
| 426 | <xsl:choose> |
---|
| 427 | <xsl:when test="contains($args,',')"> |
---|
| 428 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 429 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 430 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 431 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 432 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 433 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 434 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 435 | <xsl:with-param name="xx" select="1"/> |
---|
| 436 | <xsl:with-param name="yx" select="0"/> |
---|
| 437 | <xsl:with-param name="xy" select="1"/> |
---|
| 438 | <xsl:with-param name="yy" select="0"/> |
---|
| 439 | <xsl:with-param name="dx" select="substring-before($args,' ')"/> |
---|
| 440 | <xsl:with-param name="dy" select="substring-after($args,' ')"/> |
---|
| 441 | </xsl:call-template> |
---|
| 442 | </xsl:when> |
---|
| 443 | <xsl:otherwise> |
---|
| 444 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 445 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 446 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 447 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 448 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 449 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 450 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 451 | <xsl:with-param name="xx" select="1"/> |
---|
| 452 | <xsl:with-param name="yx" select="0"/> |
---|
| 453 | <xsl:with-param name="xy" select="1"/> |
---|
| 454 | <xsl:with-param name="yy" select="0"/> |
---|
| 455 | <xsl:with-param name="dx" select="$args"/> |
---|
| 456 | <xsl:with-param name="dy" select="$args"/> |
---|
| 457 | </xsl:call-template> |
---|
| 458 | </xsl:otherwise> |
---|
| 459 | </xsl:choose> |
---|
| 460 | </xsl:when> |
---|
| 461 | <xsl:when test="starts-with($node/@gradientTransform,'scale')"> |
---|
| 462 | <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'scale('),')'))"/> |
---|
| 463 | <!-- If only one argument is provided, it's assumed for both --> |
---|
| 464 | <xsl:choose> |
---|
| 465 | <xsl:when test="contains($args,',')"> |
---|
| 466 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 467 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 468 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 469 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 470 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 471 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 472 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 473 | <xsl:with-param name="xx" select="substring-before($args,' ')"/> |
---|
| 474 | <xsl:with-param name="yx" select="0"/> |
---|
| 475 | <xsl:with-param name="xy" select="substring-after($args,' ')"/> |
---|
| 476 | <xsl:with-param name="yy" select="0"/> |
---|
| 477 | <xsl:with-param name="dx" select="0"/> |
---|
| 478 | <xsl:with-param name="dy" select="0"/> |
---|
| 479 | </xsl:call-template> |
---|
| 480 | </xsl:when> |
---|
| 481 | <xsl:otherwise> |
---|
| 482 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 483 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 484 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 485 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 486 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 487 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 488 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 489 | <xsl:with-param name="xx" select="$args"/> |
---|
| 490 | <xsl:with-param name="yx" select="0"/> |
---|
| 491 | <xsl:with-param name="xy" select="$args"/> |
---|
| 492 | <xsl:with-param name="yy" select="0"/> |
---|
| 493 | <xsl:with-param name="dx" select="0"/> |
---|
| 494 | <xsl:with-param name="dy" select="0"/> |
---|
| 495 | </xsl:call-template> |
---|
| 496 | </xsl:otherwise> |
---|
| 497 | </xsl:choose> |
---|
| 498 | </xsl:when> |
---|
| 499 | <xsl:otherwise> <!-- Otherwise it's got to be a rotation --> |
---|
| 500 | <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'rotate('),')'))"/> |
---|
| 501 | <xsl:choose> |
---|
| 502 | <xsl:when test="function-available('math:sin') and function-available('math:cos')"> |
---|
| 503 | <xsl:variable name="sinOfAngle" select="math:sin($args div $degressInRadian)"/> |
---|
| 504 | <xsl:variable name="cosOfAngle" select="math:cos($args div $degressInRadian)"/> |
---|
| 505 | <xsl:call-template name="gradient-transform-helper"> |
---|
| 506 | <xsl:with-param name="cxa" select="$node/@cx"/> |
---|
| 507 | <xsl:with-param name="cya" select="$node/@cy"/> |
---|
| 508 | <xsl:with-param name="x1a" select="$node/@x1"/> |
---|
| 509 | <xsl:with-param name="y1a" select="$node/@y1"/> |
---|
| 510 | <xsl:with-param name="x2a" select="$node/@x2"/> |
---|
| 511 | <xsl:with-param name="y2a" select="$node/@y2"/> |
---|
| 512 | <xsl:with-param name="xx" select="$cosOfAngle"/> |
---|
| 513 | <xsl:with-param name="yx" select="-$sinOfAngle"/> |
---|
| 514 | <xsl:with-param name="xy" select="$sinOfAngle"/> |
---|
| 515 | <xsl:with-param name="yy" select="$cosOfAngle"/> |
---|
| 516 | <xsl:with-param name="dy" select="0"/> |
---|
| 517 | <xsl:with-param name="dy" select="0"/> |
---|
| 518 | </xsl:call-template> |
---|
| 519 | </xsl:when> |
---|
| 520 | <xsl:otherwise> |
---|
| 521 | <xsl:message> |
---|
| 522 | <xsl:text>exslt:sin and exslt:cos must be supported for a gradient rotation.</xsl:text> |
---|
| 523 | </xsl:message> |
---|
| 524 | </xsl:otherwise> |
---|
| 525 | </xsl:choose> |
---|
| 526 | </xsl:otherwise> |
---|
| 527 | </xsl:choose> |
---|
| 528 | <xsl:text>,</xsl:text> |
---|
| 529 | </xsl:template> |
---|
| 530 | |
---|
| 531 | <!-- The following templates handle related batches of attributes --> |
---|
| 532 | |
---|
| 533 | <xsl:template name="font"> |
---|
| 534 | <xsl:param name="node"/> |
---|
| 535 | <!-- Only include if we have at least some font properties defined --> |
---|
| 536 | <xsl:if test="$node/@font-style or $node/@font-variant or $node/@font-weight or $node/@font-size or $node/@font-family"> |
---|
| 537 | <xsl:text>font:{ type:"font",</xsl:text> |
---|
| 538 | <xsl:if test="$node/@font-style"> |
---|
| 539 | <xsl:text>style:"</xsl:text> |
---|
| 540 | <xsl:value-of select="$node/@font-style"/> |
---|
| 541 | <xsl:text>",</xsl:text> |
---|
| 542 | </xsl:if> |
---|
| 543 | <xsl:if test="$node/@font-variant"> |
---|
| 544 | <xsl:text>variant:"</xsl:text> |
---|
| 545 | <xsl:value-of select="$node/@font-variant"/> |
---|
| 546 | <xsl:text>",</xsl:text> |
---|
| 547 | </xsl:if> |
---|
| 548 | <xsl:if test="$node/@font-weight"> |
---|
| 549 | <xsl:text>weight:"</xsl:text> |
---|
| 550 | <xsl:value-of select="$node/@font-weight"/> |
---|
| 551 | <xsl:text>",</xsl:text> |
---|
| 552 | </xsl:if> |
---|
| 553 | <xsl:if test="$node/@font-size"> |
---|
| 554 | <xsl:text>size:"</xsl:text> |
---|
| 555 | <xsl:value-of select="$node/@font-size"/> |
---|
| 556 | <xsl:text>",</xsl:text> |
---|
| 557 | </xsl:if> |
---|
| 558 | <xsl:if test="$node/@font-family"> |
---|
| 559 | <xsl:text>family:"</xsl:text> |
---|
| 560 | <xsl:value-of select="$node/@font-family"/> |
---|
| 561 | <xsl:text>",</xsl:text> |
---|
| 562 | </xsl:if> |
---|
| 563 | <xsl:text>},</xsl:text> |
---|
| 564 | </xsl:if> |
---|
| 565 | </xsl:template> |
---|
| 566 | |
---|
| 567 | <xsl:template name="stroke"> |
---|
| 568 | <xsl:param name="node"/> |
---|
| 569 | <!-- Only include if we have at least some stroke properties defined --> |
---|
| 570 | <xsl:if test="$node/@stroke or $node/@stroke-width or $node/@stroke-linecap or $node/@stroke-linejoin"> |
---|
| 571 | <xsl:text>stroke:{</xsl:text> |
---|
| 572 | <!-- We don't currently handle stroke-dasharray or stroke-dashoffset --> |
---|
| 573 | <!-- Note that while we'll pass stroke background info, GFX won't yet use it. --> |
---|
| 574 | <xsl:if test="$node/@stroke"> |
---|
| 575 | <xsl:text>color:</xsl:text> |
---|
| 576 | <xsl:call-template name="background-processor"> |
---|
| 577 | <xsl:with-param name="background" select="$node/@stroke"/> |
---|
| 578 | </xsl:call-template> |
---|
| 579 | </xsl:if> |
---|
| 580 | <xsl:if test="$node/@stroke-width"> |
---|
| 581 | <xsl:text>width:"</xsl:text> |
---|
| 582 | <xsl:value-of select="$node/@stroke-width"/> |
---|
| 583 | <xsl:text>",</xsl:text> |
---|
| 584 | </xsl:if> |
---|
| 585 | <xsl:if test="$node/@stroke-linecap"> |
---|
| 586 | <xsl:text>cap:"</xsl:text> |
---|
| 587 | <xsl:value-of select="$node/@stroke-linecap"/> |
---|
| 588 | <xsl:text>",</xsl:text> |
---|
| 589 | </xsl:if> |
---|
| 590 | <xsl:if test="$node/@stroke-linejoin"> |
---|
| 591 | <xsl:text>join:"</xsl:text> |
---|
| 592 | <xsl:value-of select="$node/@stroke-linejoin"/> |
---|
| 593 | <xsl:text>",</xsl:text> |
---|
| 594 | </xsl:if> |
---|
| 595 | <xsl:choose> |
---|
| 596 | <!-- This is really cheesy but better than nothing. --> |
---|
| 597 | <!-- We probably ought to match a few specific cases when we can. %FIX% --> |
---|
| 598 | <xsl:when test="$node/@stroke-dasharray"> |
---|
| 599 | <xsl:text>style:"Dash",</xsl:text> |
---|
| 600 | </xsl:when> |
---|
| 601 | <xsl:otherwise> |
---|
| 602 | <xsl:text>style:"Solid",</xsl:text> |
---|
| 603 | </xsl:otherwise> |
---|
| 604 | </xsl:choose> |
---|
| 605 | <xsl:text>},</xsl:text> |
---|
| 606 | </xsl:if> |
---|
| 607 | </xsl:template> |
---|
| 608 | |
---|
| 609 | <xsl:template name="common-attributes"> |
---|
| 610 | <xsl:param name="node"/> |
---|
| 611 | <!-- Pretty much every shape has to handle this same batch of attributes. --> |
---|
| 612 | <xsl:apply-templates select="$node/@style"/> |
---|
| 613 | <!-- Note that we make no effort to guard against overlapping styles. --> |
---|
| 614 | <xsl:apply-templates select="$node/@fill"/> |
---|
| 615 | <xsl:call-template name="stroke"> |
---|
| 616 | <xsl:with-param name="node" select="$node"/> |
---|
| 617 | </xsl:call-template> |
---|
| 618 | <xsl:apply-templates select="$node/@transform"/> |
---|
| 619 | <!-- Fonts are actually illegal in most shapes, but including them here doesn't --> |
---|
| 620 | <!-- really slow things down much and does clean up code a bit for the shapes --> |
---|
| 621 | <!-- that do allow them. --> |
---|
| 622 | <xsl:call-template name="font"> |
---|
| 623 | <xsl:with-param name="node" select="$node"/> |
---|
| 624 | </xsl:call-template> |
---|
| 625 | <!-- Ditto for stop-colors. --> |
---|
| 626 | <xsl:apply-templates select="$node/@stop-color"/> |
---|
| 627 | </xsl:template> |
---|
| 628 | |
---|
| 629 | <!-- SVG Attribute Handling --> |
---|
| 630 | |
---|
| 631 | <xsl:template match="@id"> |
---|
| 632 | <xsl:text>name:"</xsl:text> |
---|
| 633 | <xsl:apply-templates/> |
---|
| 634 | <xsl:text>",</xsl:text> |
---|
| 635 | </xsl:template> |
---|
| 636 | |
---|
| 637 | <xsl:template match="@x|@y|@x1|@x2|@y1|@y2|@cx|@cy|@r|@rx|@ry|@fx|@fy|@width|@height|@offset"> |
---|
| 638 | <!-- Generic attribute followed by comma --> |
---|
| 639 | <xsl:value-of select="local-name()"/> |
---|
| 640 | <xsl:text>:</xsl:text> |
---|
| 641 | <xsl:value-of select="."/> |
---|
| 642 | <xsl:text>,</xsl:text> |
---|
| 643 | </xsl:template> |
---|
| 644 | |
---|
| 645 | <xsl:template match="@d"> |
---|
| 646 | <!-- Used only by path objects; often has tons of extra whitespace --> |
---|
| 647 | <xsl:text>path:"</xsl:text> |
---|
| 648 | <xsl:value-of select="normalize-space(.)"/> |
---|
| 649 | <xsl:text>",</xsl:text> |
---|
| 650 | </xsl:template> |
---|
| 651 | |
---|
| 652 | <xsl:template match="@fill"> |
---|
| 653 | <!-- Used by most shapes and can have a URL, a solid color, or "none" --> |
---|
| 654 | <xsl:if test=". != 'none'"> |
---|
| 655 | <xsl:text>fill:</xsl:text> |
---|
| 656 | <xsl:call-template name="background-processor"> |
---|
| 657 | <xsl:with-param name="background" select="."/> |
---|
| 658 | </xsl:call-template> |
---|
| 659 | </xsl:if> |
---|
| 660 | </xsl:template> |
---|
| 661 | |
---|
| 662 | <xsl:template match="@stop-color"> |
---|
| 663 | <xsl:call-template name="color-processor"> |
---|
| 664 | <xsl:with-param name="color" select="."/> |
---|
| 665 | </xsl:call-template> |
---|
| 666 | </xsl:template> |
---|
| 667 | |
---|
| 668 | <xsl:template match="@style"> |
---|
| 669 | <!-- A style property is really a bunch of other properties crammed together. --> |
---|
| 670 | <!-- We therefore make a dummy element and process it as normal. --> |
---|
| 671 | <xsl:variable name="dummy"> |
---|
| 672 | <dummy> |
---|
| 673 | <xsl:call-template name="styles-processor"> |
---|
| 674 | <xsl:with-param name="styles" select="."/> |
---|
| 675 | </xsl:call-template> |
---|
| 676 | </dummy> |
---|
| 677 | </xsl:variable> |
---|
| 678 | <xsl:choose> |
---|
| 679 | <!-- Using a dummy element requires node-set capability. Straight XSLT 1.0 --> |
---|
| 680 | <!-- lacks this, but pretty much every XSLT processor offers it as an extension. --> |
---|
| 681 | <xsl:when test="function-available('exsl:node-set')"> |
---|
| 682 | <xsl:call-template name="common-attributes"> |
---|
| 683 | <xsl:with-param name="node" select="exsl:node-set($dummy)/dummy"/> |
---|
| 684 | </xsl:call-template> |
---|
| 685 | </xsl:when> |
---|
| 686 | <xsl:when test="function-available('saxon:node-set')"> |
---|
| 687 | <xsl:call-template name="common-attributes"> |
---|
| 688 | <xsl:with-param name="node" select="saxon:node-set($dummy)"/> |
---|
| 689 | </xsl:call-template> |
---|
| 690 | </xsl:when> |
---|
| 691 | <xsl:when test="function-available('xalan:nodeSet')"> |
---|
| 692 | <xsl:call-template name="common-attributes"> |
---|
| 693 | <xsl:with-param name="node" select="xalan:nodeSet($dummy)"/> |
---|
| 694 | </xsl:call-template> |
---|
| 695 | </xsl:when> |
---|
| 696 | <xsl:otherwise> |
---|
| 697 | <xsl:message> |
---|
| 698 | <xsl:text>exslt:node-set is required for processing the style attribute.</xsl:text> |
---|
| 699 | </xsl:message> |
---|
| 700 | </xsl:otherwise> |
---|
| 701 | </xsl:choose> |
---|
| 702 | </xsl:template> |
---|
| 703 | |
---|
| 704 | <xsl:template match="@transform|@gradientTransform"> |
---|
| 705 | <!-- Several transform types are supported --> |
---|
| 706 | <xsl:text>transform:{</xsl:text> |
---|
| 707 | <xsl:call-template name="transform-processor"> |
---|
| 708 | <xsl:with-param name="transforms" select="."/> |
---|
| 709 | </xsl:call-template> |
---|
| 710 | <xsl:text>}</xsl:text> |
---|
| 711 | <xsl:if test="not(position()=last())"> |
---|
| 712 | <xsl:text >,</xsl:text> |
---|
| 713 | </xsl:if> |
---|
| 714 | </xsl:template> |
---|
| 715 | |
---|
| 716 | <!-- SVG Element Handling --> |
---|
| 717 | |
---|
| 718 | <xsl:template match="svg:a"> |
---|
| 719 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 720 | <!-- Anchors are actually meaningless to us, but their contents should usually be processed. --> |
---|
| 721 | <xsl:variable name="newGroupAttrs"> |
---|
| 722 | <xsl:value-of select="$groupAttrs"/> |
---|
| 723 | <xsl:apply-templates select="@style"/> |
---|
| 724 | <!-- Note that we make no effort to guard against overlapping styles; we just order --> |
---|
| 725 | <!-- them to be consistent. This naive approach will usually, but not always, work. --> |
---|
| 726 | <xsl:apply-templates select="@fill"/> |
---|
| 727 | <xsl:call-template name="stroke"> |
---|
| 728 | <xsl:with-param name="node" select="."/> |
---|
| 729 | </xsl:call-template> |
---|
| 730 | </xsl:variable> |
---|
| 731 | <xsl:apply-templates select="&SupportedElements;"> |
---|
| 732 | <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> |
---|
| 733 | </xsl:apply-templates> |
---|
| 734 | </xsl:template> |
---|
| 735 | |
---|
| 736 | <xsl:template match="svg:circle"> |
---|
| 737 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 738 | <xsl:text>{</xsl:text> |
---|
| 739 | <xsl:apply-templates select="@id"/> |
---|
| 740 | <xsl:text>shape:{type:"circle",</xsl:text> |
---|
| 741 | <xsl:apply-templates select="@cx|@cy|@r"/> |
---|
| 742 | <xsl:text>},</xsl:text> |
---|
| 743 | <xsl:value-of select="$groupAttrs"/> |
---|
| 744 | <xsl:call-template name="common-attributes"> |
---|
| 745 | <xsl:with-param name="node" select="."/> |
---|
| 746 | </xsl:call-template> |
---|
| 747 | <xsl:text>}</xsl:text> |
---|
| 748 | <xsl:if test="not(position()=last())"> |
---|
| 749 | <xsl:text >,</xsl:text> |
---|
| 750 | </xsl:if> |
---|
| 751 | </xsl:template> |
---|
| 752 | |
---|
| 753 | <xsl:template match="svg:ellipse"> |
---|
| 754 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 755 | <xsl:text>{</xsl:text> |
---|
| 756 | <xsl:apply-templates select="@id"/> |
---|
| 757 | <xsl:text>shape:{type:"ellipse",</xsl:text> |
---|
| 758 | <xsl:apply-templates select="@cx|@cy|@rx|@ry"/> |
---|
| 759 | <xsl:text>}</xsl:text> |
---|
| 760 | <xsl:value-of select="$groupAttrs"/> |
---|
| 761 | <xsl:call-template name="common-attributes"> |
---|
| 762 | <xsl:with-param name="node" select="."/> |
---|
| 763 | </xsl:call-template> |
---|
| 764 | <xsl:text>}</xsl:text> |
---|
| 765 | <xsl:if test="not(position()=last())"> |
---|
| 766 | <xsl:text >,</xsl:text> |
---|
| 767 | </xsl:if> |
---|
| 768 | </xsl:template> |
---|
| 769 | |
---|
| 770 | <xsl:template match="svg:g"> |
---|
| 771 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 772 | <!-- The basic grouping type can contain shapes, other groups, and have a transform --> |
---|
| 773 | <xsl:text>{</xsl:text> |
---|
| 774 | <xsl:apply-templates select="@id"/> |
---|
| 775 | <xsl:text>children:[</xsl:text> |
---|
| 776 | <!-- Note that GFX does not yet support fills etc. on a group, even though SVG does. --> |
---|
| 777 | <!-- It's a planned enhancement though, so when GFX gets the ability to handle these, --> |
---|
| 778 | <!-- remove the following ten lines and stop propagating groupAttrs. --> |
---|
| 779 | <xsl:variable name="newGroupAttrs"> |
---|
| 780 | <xsl:value-of select="$groupAttrs"/> |
---|
| 781 | <xsl:apply-templates select="@style"/> |
---|
| 782 | <!-- Note that we make no effort to guard against overlapping styles; we just order --> |
---|
| 783 | <!-- them to be consistent. This naive approach will usually, but not always, work. --> |
---|
| 784 | <xsl:apply-templates select="@fill"/> |
---|
| 785 | <xsl:call-template name="stroke"> |
---|
| 786 | <xsl:with-param name="node" select="."/> |
---|
| 787 | </xsl:call-template> |
---|
| 788 | </xsl:variable> |
---|
| 789 | <xsl:apply-templates select="&SupportedElements;"> |
---|
| 790 | <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> |
---|
| 791 | </xsl:apply-templates> |
---|
| 792 | <xsl:text>]</xsl:text> |
---|
| 793 | <xsl:if test="not(position()=last())"> |
---|
| 794 | <xsl:text >,</xsl:text> |
---|
| 795 | </xsl:if> |
---|
| 796 | <!-- When GFX gets group fills etc., remove the following line and uncomment the ones below. --> |
---|
| 797 | <xsl:apply-templates select="@transform"/> |
---|
| 798 | <!--<xsl:call-template name="common-attributes">--> |
---|
| 799 | <!-- <xsl:with-param name="node" select="."/>--> |
---|
| 800 | <!--</xsl:call-template>--> |
---|
| 801 | <xsl:text>}</xsl:text> |
---|
| 802 | <xsl:if test="not(position()=last())"> |
---|
| 803 | <xsl:text >,</xsl:text> |
---|
| 804 | </xsl:if> |
---|
| 805 | </xsl:template> |
---|
| 806 | |
---|
| 807 | <xsl:template match="svg:image"> |
---|
| 808 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 809 | <!-- Note that images must be GIF, JPEG, or PNG. --> |
---|
| 810 | <xsl:if test="not(parent::pattern)"> |
---|
| 811 | <!-- When being used as a background pattern we don't want type info. --> |
---|
| 812 | <xsl:text>{</xsl:text> |
---|
| 813 | <xsl:apply-templates select="@id"/> |
---|
| 814 | <xsl:text>shape:{type:"image",</xsl:text> |
---|
| 815 | </xsl:if> |
---|
| 816 | <xsl:apply-templates select="@x|@y|@width|@height"/> |
---|
| 817 | <xsl:text>src:"</xsl:text> |
---|
| 818 | <xsl:value-of select="@xlink:href"/> |
---|
| 819 | <xsl:text>",</xsl:text> |
---|
| 820 | <xsl:if test="not(parent::pattern)"> |
---|
| 821 | <xsl:text>},</xsl:text> |
---|
| 822 | <xsl:value-of select="$groupAttrs"/> |
---|
| 823 | <xsl:call-template name="common-attributes"> |
---|
| 824 | <xsl:with-param name="node" select="."/> |
---|
| 825 | </xsl:call-template> |
---|
| 826 | <xsl:text>},</xsl:text> |
---|
| 827 | </xsl:if> |
---|
| 828 | </xsl:template> |
---|
| 829 | |
---|
| 830 | <xsl:template match="svg:line"> |
---|
| 831 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 832 | <xsl:text>{</xsl:text> |
---|
| 833 | <xsl:apply-templates select="@id"/> |
---|
| 834 | <xsl:text>shape:{type:"line",</xsl:text> |
---|
| 835 | <xsl:apply-templates select="@x1|@y1|@x2|@y2"/> |
---|
| 836 | <xsl:text>},</xsl:text> |
---|
| 837 | <xsl:value-of select="$groupAttrs"/> |
---|
| 838 | <xsl:call-template name="common-attributes"> |
---|
| 839 | <xsl:with-param name="node" select="."/> |
---|
| 840 | </xsl:call-template> |
---|
| 841 | <xsl:text>}</xsl:text> |
---|
| 842 | <xsl:if test="not(position()=last())"> |
---|
| 843 | <xsl:text >,</xsl:text> |
---|
| 844 | </xsl:if> |
---|
| 845 | </xsl:template> |
---|
| 846 | |
---|
| 847 | <xsl:template match="svg:linearGradient"> |
---|
| 848 | <xsl:text>{type:"linear",</xsl:text> |
---|
| 849 | <!-- Kluge alert - GFX doesn't handle gradientTransforms. We can help in --> |
---|
| 850 | <!-- the common case of matrix transforms in user space. Other cases we ignore. --> |
---|
| 851 | <!-- Even for this one case the results aren't anywhere near as good as real support in GFX. --> |
---|
| 852 | <xsl:choose> |
---|
| 853 | <!-- Kluge alert - this code is only meant to serve until GFX gets gradientTransform support. --> |
---|
| 854 | <!-- Once GFX does gradientTransforms, only the straight apply-templates should be kept. --> |
---|
| 855 | <xsl:when test="starts-with(@gradientTransform,'matrix') and @gradientUnits='userSpaceOnUse'"> |
---|
| 856 | <xsl:call-template name="gradient-adjuster"> |
---|
| 857 | <xsl:with-param name="node" select="."/> |
---|
| 858 | </xsl:call-template> |
---|
| 859 | </xsl:when> |
---|
| 860 | <xsl:otherwise> |
---|
| 861 | <xsl:apply-templates select="@x1|@x2|@y1|@y2"/> |
---|
| 862 | </xsl:otherwise> |
---|
| 863 | </xsl:choose> |
---|
| 864 | <xsl:text>colors:[</xsl:text> |
---|
| 865 | <xsl:apply-templates select="svg:stop"/> |
---|
| 866 | <!-- Unfortunately GFX doesn't do gradientTransforms. --> |
---|
| 867 | <!-- Uncommenting the following would support it here. --> |
---|
| 868 | <!-- <xsl:apply-templates select="@x1|@x2|@y1|@y2"/> --> |
---|
| 869 | <!-- <xsl:apply-templates select="@gradientTransform"/> --> |
---|
| 870 | <xsl:text>]}</xsl:text> |
---|
| 871 | <xsl:if test="not(position()=last())"> |
---|
| 872 | <xsl:text >,</xsl:text> |
---|
| 873 | </xsl:if> |
---|
| 874 | </xsl:template> |
---|
| 875 | |
---|
| 876 | <xsl:template match="svg:path"> |
---|
| 877 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 878 | <xsl:if test="not(parent::textpath)"> |
---|
| 879 | <!-- When being used within a textpath we don't want type info. --> |
---|
| 880 | <xsl:text>{</xsl:text> |
---|
| 881 | <xsl:apply-templates select="@id"/> |
---|
| 882 | <xsl:text>shape:{type:"path",</xsl:text> |
---|
| 883 | </xsl:if> |
---|
| 884 | <xsl:apply-templates select="@d"/> |
---|
| 885 | <xsl:if test="not(parent::textpath)"> |
---|
| 886 | <xsl:text>},</xsl:text> |
---|
| 887 | <xsl:value-of select="$groupAttrs"/> |
---|
| 888 | <xsl:call-template name="common-attributes"> |
---|
| 889 | <xsl:with-param name="node" select="."/> |
---|
| 890 | </xsl:call-template> |
---|
| 891 | <xsl:text>},</xsl:text> |
---|
| 892 | </xsl:if> |
---|
| 893 | </xsl:template> |
---|
| 894 | |
---|
| 895 | <xsl:template match="svg:pattern"> |
---|
| 896 | <!-- GFX only seems to handle image pattern type fills, so that's all we do --> |
---|
| 897 | <xsl:text>{type:"pattern",</xsl:text> |
---|
| 898 | <xsl:apply-templates select="@width|@height|@xlink:href"/> |
---|
| 899 | <xsl:text>}</xsl:text> |
---|
| 900 | <xsl:if test="not(position()=last())"> |
---|
| 901 | <xsl:text >,</xsl:text> |
---|
| 902 | </xsl:if> |
---|
| 903 | </xsl:template> |
---|
| 904 | |
---|
| 905 | <xsl:template match="svg:polygon|svg:polyline"> |
---|
| 906 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 907 | <!-- Polygons are mostly treated as polylines --> |
---|
| 908 | <xsl:text>{</xsl:text> |
---|
| 909 | <xsl:apply-templates select="@id"/> |
---|
| 910 | <xsl:text>shape:{type:"polyline",points:[</xsl:text> |
---|
| 911 | <!-- We just have to ensure that endpoints match for a polygon; it's assumed in SVG --> |
---|
| 912 | <xsl:variable name="seminormalizedPoints" select="normalize-space(@points)"/> |
---|
| 913 | <xsl:variable name="normalizedPoints"> |
---|
| 914 | <xsl:call-template name="kill-extra-spaces"> |
---|
| 915 | <xsl:with-param name="string" select="$seminormalizedPoints"/> |
---|
| 916 | </xsl:call-template> |
---|
| 917 | </xsl:variable> |
---|
| 918 | <xsl:variable name="firstPoint" select="substring-before($normalizedPoints,' ')"/> |
---|
| 919 | <xsl:choose> |
---|
| 920 | <xsl:when test="contains(local-name(),'polygon') and |
---|
| 921 | $firstPoint!=substring($normalizedPoints,string-length($normalizedPoints)-string-length($firstPoint)+1)"> |
---|
| 922 | <xsl:call-template name="point-processor"> |
---|
| 923 | <xsl:with-param name="points" select="concat($normalizedPoints,' ',$firstPoint)"/> |
---|
| 924 | </xsl:call-template> |
---|
| 925 | </xsl:when> |
---|
| 926 | <xsl:otherwise> |
---|
| 927 | <xsl:call-template name="point-processor"> |
---|
| 928 | <xsl:with-param name="points" select="$normalizedPoints"/> |
---|
| 929 | </xsl:call-template> |
---|
| 930 | </xsl:otherwise> |
---|
| 931 | </xsl:choose> |
---|
| 932 | <xsl:text>]},</xsl:text> |
---|
| 933 | <xsl:value-of select="$groupAttrs"/> |
---|
| 934 | <xsl:call-template name="common-attributes"> |
---|
| 935 | <xsl:with-param name="node" select="."/> |
---|
| 936 | </xsl:call-template> |
---|
| 937 | <xsl:text>}</xsl:text> |
---|
| 938 | <xsl:if test="not(position()=last())"> |
---|
| 939 | <xsl:text >,</xsl:text> |
---|
| 940 | </xsl:if> |
---|
| 941 | </xsl:template> |
---|
| 942 | |
---|
| 943 | <xsl:template match="svg:radialGradient"> |
---|
| 944 | <xsl:text>{type:"radial",</xsl:text> |
---|
| 945 | <!-- Kluge alert - GFX doesn't handle gradientTransforms. We can help in --> |
---|
| 946 | <!-- the common case of matrix transforms in user space. Other cases we ignore. --> |
---|
| 947 | <!-- Even for this one case the results aren't anywhere near as good as real support in GFX. --> |
---|
| 948 | <xsl:choose> |
---|
| 949 | <!-- Kluge alert - this code is only meant to serve until GFX gets gradientTransform support. --> |
---|
| 950 | <!-- Once GFX does gradientTransforms, only the straight apply-templates should be kept. --> |
---|
| 951 | <xsl:when test="starts-with(@gradientTransform,'matrix') and @gradientUnits='userSpaceOnUse'"> |
---|
| 952 | <xsl:call-template name="gradient-adjuster"> |
---|
| 953 | <xsl:with-param name="node" select="."/> |
---|
| 954 | </xsl:call-template> |
---|
| 955 | </xsl:when> |
---|
| 956 | <xsl:otherwise> |
---|
| 957 | <xsl:apply-templates select="@cx|@cy|@r"/> |
---|
| 958 | </xsl:otherwise> |
---|
| 959 | </xsl:choose> |
---|
| 960 | <!-- GFX doesn't currently support fx & fy --> |
---|
| 961 | <!-- Uncommenting the following would support it here. --> |
---|
| 962 | <!-- <xsl:apply-templates select="@fx|@fy"/> --> |
---|
| 963 | <xsl:text>colors:[</xsl:text> |
---|
| 964 | <xsl:apply-templates select="svg:stop"/> |
---|
| 965 | <!-- Unfortunately GFX doesn't do gradientTransforms. --> |
---|
| 966 | <!-- Uncommenting the following would support it here. --> |
---|
| 967 | <!-- <xsl:apply-templates select="@cx|@cy|@r"/> --> |
---|
| 968 | <!-- <xsl:apply-templates select="@gradientTransform"/> --> |
---|
| 969 | <xsl:text>]}</xsl:text> |
---|
| 970 | <xsl:if test="not(position()=last())"> |
---|
| 971 | <xsl:text >,</xsl:text> |
---|
| 972 | </xsl:if> |
---|
| 973 | </xsl:template> |
---|
| 974 | |
---|
| 975 | <xsl:template match="svg:rect"> |
---|
| 976 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 977 | <xsl:text>{</xsl:text> |
---|
| 978 | <xsl:apply-templates select="@id"/> |
---|
| 979 | <xsl:text>shape:{type:"rect",</xsl:text> |
---|
| 980 | <xsl:apply-templates select="@x|@y|@width|@height"/> |
---|
| 981 | <xsl:if test="@rx and @ry"> |
---|
| 982 | <!-- Do approximate rounded corners if both an rx and ry are present. --> |
---|
| 983 | <xsl:variable name="r" select="(@rx+@ry) div 2"/> |
---|
| 984 | <xsl:text>r:</xsl:text> |
---|
| 985 | <xsl:value-of select="$r"/> |
---|
| 986 | </xsl:if> |
---|
| 987 | <xsl:text>},</xsl:text> |
---|
| 988 | <xsl:value-of select="$groupAttrs"/> |
---|
| 989 | <xsl:call-template name="common-attributes"> |
---|
| 990 | <xsl:with-param name="node" select="."/> |
---|
| 991 | </xsl:call-template> |
---|
| 992 | <xsl:text>}</xsl:text> |
---|
| 993 | <xsl:if test="not(position()=last())"> |
---|
| 994 | <xsl:text >,</xsl:text> |
---|
| 995 | </xsl:if> |
---|
| 996 | </xsl:template> |
---|
| 997 | |
---|
| 998 | <xsl:template match="svg:stop"> |
---|
| 999 | <!-- Both gradient types use the same sort of stops --> |
---|
| 1000 | <xsl:text>{</xsl:text> |
---|
| 1001 | <xsl:apply-templates select="@offset"/> |
---|
| 1002 | <xsl:text>color:</xsl:text> |
---|
| 1003 | <xsl:apply-templates select="@style"/> |
---|
| 1004 | <xsl:text>}</xsl:text> |
---|
| 1005 | <xsl:if test="not(position()=last())"> |
---|
| 1006 | <xsl:text >,</xsl:text> |
---|
| 1007 | </xsl:if> |
---|
| 1008 | </xsl:template> |
---|
| 1009 | |
---|
| 1010 | <xsl:template match="svg:text|svg:textPath"> |
---|
| 1011 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 1012 | <!-- Support for textPath is not functional as GFX doesn't seem to have a --> |
---|
| 1013 | <!-- complete serialized form at this time. %FIX% --> |
---|
| 1014 | <xsl:text>{</xsl:text> |
---|
| 1015 | <xsl:apply-templates select="@id"/> |
---|
| 1016 | <xsl:choose> |
---|
| 1017 | <xsl:when test="contains(local-name(),'textpath')"> |
---|
| 1018 | <xsl:text>shape:{type:"textpath",text:"</xsl:text> |
---|
| 1019 | <xsl:apply-templates/> |
---|
| 1020 | <xsl:text>",</xsl:text> |
---|
| 1021 | <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after(@xlink:href,'('),')')),' ',',')"/> |
---|
| 1022 | <xsl:call-template name="url-processor"> |
---|
| 1023 | <xsl:with-param name="url" select="$arguments"/> |
---|
| 1024 | </xsl:call-template> |
---|
| 1025 | </xsl:when> |
---|
| 1026 | <xsl:otherwise> |
---|
| 1027 | <!-- Regular text has slightly different attributes --> |
---|
| 1028 | <xsl:choose> |
---|
| 1029 | <!-- It's possible for a text element to contain a textpath element. --> |
---|
| 1030 | <xsl:when test="not(textpath)"> |
---|
| 1031 | <xsl:text>shape:{type:"text",text:"</xsl:text> |
---|
| 1032 | <xsl:apply-templates/> |
---|
| 1033 | <xsl:text>",</xsl:text> |
---|
| 1034 | <xsl:apply-templates select="@x|@y"/> |
---|
| 1035 | </xsl:when> |
---|
| 1036 | <xsl:otherwise> |
---|
| 1037 | <xsl:apply-templates/> |
---|
| 1038 | </xsl:otherwise> |
---|
| 1039 | </xsl:choose> |
---|
| 1040 | </xsl:otherwise> |
---|
| 1041 | </xsl:choose> |
---|
| 1042 | <xsl:text>},</xsl:text> |
---|
| 1043 | <!-- Kluge alert - if no fill is defined, GFX won't display anything --> |
---|
| 1044 | <!-- Our quick fix here is to force a fill of some sort. --> |
---|
| 1045 | <xsl:if test="not(@fill)"> |
---|
| 1046 | <xsl:text>fill:"#000000",</xsl:text> |
---|
| 1047 | </xsl:if> |
---|
| 1048 | <xsl:value-of select="$groupAttrs"/> |
---|
| 1049 | <xsl:call-template name="common-attributes"> |
---|
| 1050 | <xsl:with-param name="node" select="."/> |
---|
| 1051 | </xsl:call-template> |
---|
| 1052 | <xsl:text>}</xsl:text> |
---|
| 1053 | <xsl:if test="not(position()=last())"> |
---|
| 1054 | <xsl:text >,</xsl:text> |
---|
| 1055 | </xsl:if> |
---|
| 1056 | </xsl:template> |
---|
| 1057 | |
---|
| 1058 | <xsl:template match="svg:use"> |
---|
| 1059 | <xsl:param name="groupAttrs" select="''"/> |
---|
| 1060 | <!-- Use just refers to an existing element, essentially duplicating it. --> |
---|
| 1061 | <xsl:variable name="newGroupAttrs"> |
---|
| 1062 | <xsl:value-of select="$groupAttrs"/> |
---|
| 1063 | <xsl:apply-templates select="@style"/> |
---|
| 1064 | <!-- Note that we make no effort to guard against overlapping styles; we just order --> |
---|
| 1065 | <!-- them to be consistent. This naive approach will usually, but not always, work. --> |
---|
| 1066 | <xsl:apply-templates select="@fill"/> |
---|
| 1067 | <xsl:call-template name="stroke"> |
---|
| 1068 | <xsl:with-param name="node" select="."/> |
---|
| 1069 | </xsl:call-template> |
---|
| 1070 | <xsl:apply-templates select="@transform"/> |
---|
| 1071 | </xsl:variable> |
---|
| 1072 | <xsl:call-template name="url-processor"> |
---|
| 1073 | <xsl:with-param name="url" select="normalize-space(@xlink:href)"/> |
---|
| 1074 | <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> |
---|
| 1075 | </xsl:call-template> |
---|
| 1076 | </xsl:template> |
---|
| 1077 | |
---|
| 1078 | <!-- The main SVG element itself --> |
---|
| 1079 | |
---|
| 1080 | <xsl:template match="/svg:svg"> |
---|
| 1081 | <xsl:text>[</xsl:text> |
---|
| 1082 | <xsl:apply-templates select="&SupportedElements;"/> |
---|
| 1083 | <xsl:text>]</xsl:text> |
---|
| 1084 | </xsl:template> |
---|
| 1085 | </xsl:stylesheet> |
---|