root / trunk / web / dojo / dojox / gfx / resources / svg2gfx.xsl
History | View | Annotate | Download (44.2 KB)
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" mode="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" mode="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" mode="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" mode="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" mode="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" mode="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" mode="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" mode="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" mode="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" mode="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> |