Code

Extensions. New SVG to FXG export extension (see Bug #625140, Support export to FXG).
[inkscape.git] / share / extensions / svg2fxg.xsl
1 <?xml version="1.0" encoding="UTF-8"?>
3 <!--
4 Authors:
5   Nicolas Dufour <nicoduf@yahoo.fr>
6   
7 Copyright (c) 2010 authors
9 Released under GNU GPL, read the file 'COPYING' for more information
10 -->
12 <xsl:stylesheet version="1.0"
13 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
14 xmlns:xlink="http://www.w3.org/1999/xlink"
15 xmlns:xs="http://www.w3.org/2001/XMLSchema"
16 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
17 xmlns="http://ns.adobe.com/fxg/2008"
18 xmlns:fxg="http://ns.adobe.com/fxg/2008"
19 xmlns:d="http://ns.adobe.com/fxg/2008/dt"
20 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
21 xmlns:exsl="http://exslt.org/common"
22 xmlns:math="http://exslt.org/math"
23 xmlns:libxslt="http://xmlsoft.org/XSLT/namespace"
24 xmlns:svg="http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd"
25 exclude-result-prefixes="rdf xlink xs exsl libxslt"
26 extension-element-prefixes="math">
28 <xsl:strip-space elements="*" />
29 <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
31 <!-- 
32   // Containers //
34   * Root templace
35   * Graphic attributes
36   * Groups
37 -->
39 <!-- 
40   // Root template //
41 -->
42 <xsl:template match="/">
43     <xsl:apply-templates mode="forward" />
44 </xsl:template>
45 <!--
46   // Graphic //
47   First SVG element is converted to Graphic
48 -->
49 <xsl:template mode="forward" match="/*[name(.) = 'svg']" priority="1">
50   <Graphic>
51     <xsl:attribute name="version">2.0</xsl:attribute>
52     <xsl:if test="@width and not(contains(@width, '%'))">
53       <xsl:attribute name="viewWidth">
54         <xsl:call-template name="convert_unit">
55           <xsl:with-param name="convert_value" select="@width" />
56         </xsl:call-template>
57       </xsl:attribute>
58     </xsl:if>
59     <xsl:if test="@height and not(contains(@height, '%'))">
60       <xsl:attribute name="viewHeight">
61         <xsl:call-template name="convert_unit">
62           <xsl:with-param name="convert_value" select="@height" />
63         </xsl:call-template>
64       </xsl:attribute>
65     </xsl:if>
66     <xsl:if test="@width and not(contains(@width, '%')) and @height and not(contains(@height, '%'))">
67       <mask>
68         <Group>
69           <Rect>
70             <xsl:attribute name="width">
71               <xsl:call-template name="convert_unit">
72                 <xsl:with-param name="convert_value" select="@width" />
73               </xsl:call-template>
74             </xsl:attribute>
75             <xsl:attribute name="height">
76               <xsl:call-template name="convert_unit">
77                 <xsl:with-param name="convert_value" select="@height" />
78               </xsl:call-template>
79             </xsl:attribute>
80             <fill>
81               <SolidColor color="#ffffff" alpha="1"/>
82             </fill>
83           </Rect>
84         </Group>
85       </mask>
86     </xsl:if>
87     <xsl:apply-templates mode="forward" />
88   </Graphic>
89 </xsl:template>
91 <!--
92   // inner SVG elements //
93   Converted to groups
94 -->
95 <xsl:template mode="forward" match="*[name(.) = 'svg']">
96   <Group>
97     <xsl:if test="@x">
98       <xsl:attribute name="x">
99           <xsl:call-template name="convert_unit">
100             <xsl:with-param name="convert_value" select="@x" />
101           </xsl:call-template>
102       </xsl:attribute>
103     </xsl:if>
104     <xsl:if test="@y">
105       <xsl:attribute name="y">
106         <xsl:call-template name="convert_unit">
107           <xsl:with-param name="convert_value" select="@y" />
108         </xsl:call-template>
109       </xsl:attribute>
110     </xsl:if>
111     <xsl:if test="@width and not(contains(@width, '%')) and @height and not(contains(@height, '%'))">
112       <xsl:attribute name="maskType"><xsl:value-of select="'clip'"/></xsl:attribute>
113       <mask>
114         <Group>
115           <Rect>
116             <xsl:attribute name="width">
117               <xsl:call-template name="convert_unit">
118                 <xsl:with-param name="convert_value" select="@width" />
119               </xsl:call-template>
120             </xsl:attribute>
121             <xsl:attribute name="height">
122               <xsl:call-template name="convert_unit">
123                 <xsl:with-param name="convert_value" select="@height" />
124               </xsl:call-template>
125             </xsl:attribute>
126             <fill>
127               <SolidColor color="#ffffff" alpha="1"/>
128             </fill>
129           </Rect>
130         </Group>
131       </mask>
132     </xsl:if>
133     <xsl:apply-templates mode="forward" />
134   </Group>
135 </xsl:template>
137 <!--
138   // Groups //
139   (including layers)
140   
141   FXG's Group doesn't support other elements attributes (such as font-size, etc.) 
142 -->
143 <xsl:template mode="forward" match="*[name(.) = 'g']">
144   <xsl:variable name="object">
145     <Group>
146       <xsl:if test="@style and contains(@style, 'display:none')">
147         <xsl:attribute name="Visibility">Collapsed</xsl:attribute>
148       </xsl:if>
149       <xsl:if test="@width and not(contains(@width, '%'))">
150         <xsl:attribute name="width">
151           <xsl:call-template name="convert_unit">
152             <xsl:with-param name="convert_value" select="@width" />
153           </xsl:call-template>
154         </xsl:attribute>
155       </xsl:if>
156       <xsl:if test="@height and not(contains(@height, '%'))">
157         <xsl:attribute name="height">
158           <xsl:call-template name="convert_unit">
159             <xsl:with-param name="convert_value" select="@height" />
160           </xsl:call-template>
161         </xsl:attribute>
162       </xsl:if>
163       <xsl:if test="@x">
164         <xsl:attribute name="x">
165             <xsl:call-template name="convert_unit">
166               <xsl:with-param name="convert_value" select="@x" />
167             </xsl:call-template>
168         </xsl:attribute>
169       </xsl:if>
170       <xsl:if test="@y">
171         <xsl:attribute name="y">
172           <xsl:call-template name="convert_unit">
173             <xsl:with-param name="convert_value" select="@y" />
174           </xsl:call-template>
175         </xsl:attribute>
176       </xsl:if>
177       <xsl:apply-templates mode="object_opacity" select="." />
178       <xsl:apply-templates mode="id" select="." />
179       
180       <xsl:apply-templates mode="layer_blend" select="." />
181       <xsl:apply-templates mode="filter_effect" select="." />
182       <xsl:apply-templates mode="forward" select="*" />
183     </Group>
184   </xsl:variable>
185   
186   <xsl:variable name="clipped_object">
187     <xsl:apply-templates mode="clip" select="." >
188       <xsl:with-param name="object" select="$object" />
189       <xsl:with-param name="clip_type" select="'clip'" />
190     </xsl:apply-templates>
191   </xsl:variable>
193   <xsl:variable name="masked_object">
194     <xsl:apply-templates mode="clip" select="." >
195       <xsl:with-param name="object" select="$clipped_object" />
196       <xsl:with-param name="clip_type" select="'mask'" />
197     </xsl:apply-templates>
198   </xsl:variable>
199   
200   <xsl:choose>
201     <xsl:when test="@transform">
202     <Group>
203       <xsl:call-template name="object_transform">
204         <xsl:with-param name="object" select="$masked_object" />
205         <xsl:with-param name="transform" select="@transform" />
206       </xsl:call-template>
207     </Group>
208     </xsl:when>
209     <xsl:otherwise>
210       <xsl:copy-of select="$masked_object" />
211     </xsl:otherwise>
212   </xsl:choose>
213 </xsl:template>
215 <!-- 
216   // Transforms //
217   All the matrix, translate, rotate... stuff.
218   * Parse objects transform
219   * Object transform
220   * Parse gradient transform  
221   * Gradient transform
222   
223   Not supported by FXG:
224   * Skew transform.
225   * Multiple values rotation.
226 -->
228 <!-- 
229   // Parse object transform //
230 -->
231 <xsl:template name="parse_object_transform">
232   <xsl:param name="input" />  
233     <xsl:choose>
234   <!-- Matrix transform -->
235     <xsl:when test="starts-with($input, 'matrix(')">
236       <transform>
237       <Transform>
238       <matrix>
239         <Matrix>
240           <xsl:variable name="matrix" select="normalize-space(translate(substring-before(substring-after($input, 'matrix('), ')'), ',', ' '))" />
241           <xsl:variable name="a" select="substring-before($matrix, ' ')"/>
242           <xsl:variable name="ra" select="substring-after($matrix, ' ')"/>
243           <xsl:variable name="b" select="substring-before($ra, ' ')"/>
244           <xsl:variable name="rb" select="substring-after($ra, ' ')"/>
245           <xsl:variable name="c" select="substring-before($rb, ' ')"/>
246           <xsl:variable name="rc" select="substring-after($rb, ' ')"/>
247           <xsl:variable name="d" select="substring-before($rc, ' ')"/>
248           <xsl:variable name="rd" select="substring-after($rc, ' ')"/>
249           <xsl:variable name="tx" select="substring-before($rd, ' ')"/>
250           <xsl:variable name="ty" select="substring-after($rd, ' ')"/>
251           <xsl:attribute name="a"><xsl:value-of select="$a" /></xsl:attribute>
252           <xsl:attribute name="b"><xsl:value-of select="$b" /></xsl:attribute>
253           <xsl:attribute name="c"><xsl:value-of select="$c" /></xsl:attribute>
254           <xsl:attribute name="d"><xsl:value-of select="$d" /></xsl:attribute>
255           <xsl:attribute name="tx"><xsl:value-of select='format-number($tx, "#.##")' /></xsl:attribute>
256           <xsl:attribute name="ty"><xsl:value-of select='format-number($ty, "#.##")' /></xsl:attribute>
257         </Matrix>
258       </matrix>
259       </Transform>
260       </transform>  
261     </xsl:when>
263   <!-- Scale transform -->
264     <xsl:when test="starts-with($input, 'scale(')">
265       <xsl:variable name="scale" select="normalize-space(translate(substring-before(substring-after($input, 'scale('), ')'), ',', ' '))" />
266       <xsl:choose>
267         <xsl:when test="contains($scale, ' ')">
268           <xsl:attribute name="scaleX">
269             <xsl:value-of select="substring-before($scale, ' ')" />
270           </xsl:attribute>
271           <xsl:attribute name="scaleY">
272             <xsl:value-of select="substring-after($scale, ' ')" />
273           </xsl:attribute>
274         </xsl:when>
275         <xsl:otherwise>
276           <xsl:attribute name="scaleX">
277             <xsl:value-of select="$scale" />
278           </xsl:attribute>
279           <xsl:attribute name="scaleY">
280             <xsl:value-of select="$scale" />
281           </xsl:attribute>
282         </xsl:otherwise>
283       </xsl:choose>
284     </xsl:when>
285   
286   <!-- Rotate transform -->
287     <xsl:when test="starts-with($input, 'rotate(')">
288       <xsl:variable name="rotate" select="normalize-space(translate(substring-before(substring-after($input, 'rotate('), ')'), ',', ' '))" />
289       <xsl:attribute name="rotation">
290         <xsl:choose>
291           <xsl:when test="contains($rotate, ' ')">
292             <xsl:value-of select="substring-before($rotate, ' ')" />
293           </xsl:when>
294           <xsl:otherwise>
295             <xsl:value-of select="$rotate" />
296           </xsl:otherwise>
297         </xsl:choose>
298       </xsl:attribute>
299       <xsl:if test="@rx">
300         <xsl:attribute name="CenterX">
301           <xsl:value-of select="@rx" />
302         </xsl:attribute>
303       </xsl:if>
304       <xsl:if test="@ry">
305         <xsl:attribute name="CenterY">
306           <xsl:value-of select="@ry" />
307         </xsl:attribute>
308       </xsl:if>
309     </xsl:when>
310   
311   <!-- Translate transform -->
312     <xsl:when test="starts-with($input, 'translate(')">
313       <xsl:variable name="translate" select="normalize-space(translate(substring-before(substring-after($input, 'translate('), ')'), ',', ' '))" />
314       <xsl:choose>
315         <xsl:when test="contains($translate, ' ')">
316           <xsl:attribute name="x">
317             <xsl:value-of select="substring-before($translate, ' ')" />
318           </xsl:attribute>
319           <xsl:attribute name="y">
320             <xsl:value-of select="substring-after($translate, ' ')" />
321           </xsl:attribute>
322         </xsl:when>
323         <xsl:otherwise>
324           <xsl:attribute name="x">
325             <xsl:value-of select="$translate" />
326           </xsl:attribute>
327         </xsl:otherwise>
328       </xsl:choose>
329     </xsl:when>
330   </xsl:choose>
331 </xsl:template>
333 <!-- 
334   // Object transform //
335   FXG needs a separate group for each transform type in the transform attribute (scale+translate != translate+scale)
336 -->
337 <xsl:template name="object_transform">
338   <xsl:param name="object" />  
339   <xsl:param name="transform" />
341   <xsl:variable name="values" select="normalize-space(translate($transform, ',', ' '))" />
342   <xsl:choose>
343     <xsl:when test="contains($values, ') ')">
344       <xsl:call-template name="parse_object_transform">
345         <xsl:with-param name="input" select="concat(substring-before($values, ') '), ')')" />
346       </xsl:call-template>
347       <xsl:variable name="values2" select="substring-after($values, ') ')" />
348       <Group>
349       <xsl:choose>
350         <xsl:when test="contains($values2, ') ')">
351           <xsl:call-template name="parse_object_transform">
352             <xsl:with-param name="input" select="concat(substring-before($values2, ') '), ')')" />
353           </xsl:call-template>
354           <xsl:variable name="values3" select="substring-after($values2, ') ')" />
355           <Group>
356             <xsl:call-template name="parse_object_transform">
357               <xsl:with-param name="input" select="concat($values3, ')')" />
358             </xsl:call-template>
359             <xsl:copy-of select="$object" />
360           </Group>
361         </xsl:when>
362         <xsl:otherwise>
363           <xsl:call-template name="parse_object_transform">
364             <xsl:with-param name="input" select="$values2" />
365           </xsl:call-template>
366           <xsl:copy-of select="$object" />
367         </xsl:otherwise>
368       </xsl:choose>
369       </Group>
370     </xsl:when>
371     <xsl:otherwise>
372       <xsl:call-template name="parse_object_transform">
373         <xsl:with-param name="input" select="$values" />
374       </xsl:call-template>
375       <xsl:copy-of select="$object" />
376     </xsl:otherwise>
377   </xsl:choose>
378 </xsl:template>
380 <!-- 
381   // Parse gradient transform //
382 -->
383 <xsl:template name="parse_gradient_transform">
384   <xsl:param name="input" />  
385   <xsl:param name="type" />
386   <xsl:choose>
387   <!-- Scale transform -->
388     <xsl:when test="starts-with($input, 'scale(')">
389       <xsl:variable name="scale" select="normalize-space(translate(substring-before(substring-after($input, 'scale('), ')'), ',', ' '))" />
390       <xsl:choose>
391         <xsl:when test="$type='radial'">
392           <xsl:choose>
393             <xsl:when test="contains($scale, ' ')">
394               <xsl:attribute name="scaleX">
395                 <xsl:value-of select="substring-before($scale, ' ')" />
396               </xsl:attribute>
397               <xsl:attribute name="scaleY">
398                 <xsl:value-of select="substring-after($scale, ' ')" />
399               </xsl:attribute>
400             </xsl:when>
401             <xsl:otherwise>
402               <xsl:attribute name="scaleX">
403                 <xsl:value-of select="$scale" />
404               </xsl:attribute>
405               <xsl:attribute name="scaleY">
406                 <xsl:value-of select="$scale" />
407               </xsl:attribute>
408             </xsl:otherwise>
409           </xsl:choose>
410         </xsl:when>
411         <xsl:otherwise>
412           <xsl:attribute name="scaleX">
413             <xsl:value-of select="$scale" />
414           </xsl:attribute>
415         </xsl:otherwise>
416       </xsl:choose>
417     </xsl:when>
418     
419   <!-- Rotate transform -->
420     <xsl:when test="starts-with($input, 'rotate(')">
421       <xsl:variable name="rotate" select="normalize-space(translate(substring-before(substring-after($input, 'rotate('), ')'), ',', ' '))" />
422       <xsl:attribute name="rotation">
423         <xsl:choose>
424           <xsl:when test="contains($rotate, ' ')">
425             <xsl:value-of select="substring-before($rotate, ' ')" />
426           </xsl:when>
427           <xsl:otherwise>
428             <xsl:value-of select="$rotate" />
429           </xsl:otherwise>
430         </xsl:choose>
431       </xsl:attribute>
432     </xsl:when>
433     
434   <!-- Translate transform -->
435     <xsl:when test="starts-with($input, 'translate(')">
436       <xsl:variable name="translate" select="normalize-space(translate(substring-before(substring-after($input, 'translate('), ')'), ',', ' '))" />
437       <xsl:choose>
438         <xsl:when test="contains($translate, ' ')">
439           <xsl:attribute name="x">
440             <xsl:value-of select="substring-before($translate, ' ')" />
441           </xsl:attribute>
442           <xsl:attribute name="y">
443             <xsl:value-of select="substring-after($translate, ' ')" />
444           </xsl:attribute>
445         </xsl:when>
446         <xsl:otherwise>
447           <xsl:attribute name="x">
448             <xsl:value-of select="$translate" />
449           </xsl:attribute>
450         </xsl:otherwise>
451       </xsl:choose>
452     </xsl:when>
453   </xsl:choose>
454 </xsl:template>
456 <!-- 
457   // Gradient transform //
458   Not implemented yet
459   Gradient positioning and tranformation are very different in FXG
460 -->
461 <xsl:template name="gradient_transform">
462   <xsl:param name="transform" />
463   <xsl:param name="type" />
464   
465   <xsl:if test="contains($transform, 'translate')">
466     <xsl:call-template name="parse_gradient_transform">
467       <xsl:with-param name="input" select="concat('translate(', substring-before(substring-after($transform, 'translate('), ')'), ')')" />
468       <xsl:with-param name="type" select="$type" />
469     </xsl:call-template>
470   </xsl:if>
471 </xsl:template>
473 <!--
474   // Resources (defs) //
476   * Resources ids
477   * Generic defs template
478   * Defs gradients
479   * Layers blend mode
480   * Generic filters template
481   * Filter effects
482   * Linked filter effects
483   * Linear gradients
484   * Radial gradients
485   * Gradient stops list
486   * Gradient stop
487   * Clipping
488 -->
490 <!-- 
491   // Resources ids //
492 -->
493 <xsl:template mode="resources" match="*">
494   <!-- should be in-depth -->
495   <xsl:if test="ancestor::*[name(.) = 'defs']"><xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute></xsl:if>
496 </xsl:template>
498 <!--
499   // Generic defs template //
500 -->
501 <xsl:template mode="forward" match="defs">
502 <!-- Ignoring defs, do nothing  
503   <xsl:apply-templates mode="forward" />
504 -->
505 </xsl:template>
507 <!--
508   // Defs gradients //
509   ignored
510 -->
511 <xsl:template mode="forward" match="*[name(.) = 'linearGradient' or name(.) = 'radialGradient']">
513 </xsl:template>
515 <!-- 
516   // Layers blend mode //
518   Partial support
519   Looks good with normal, multiply, and darken
520 -->
521 <xsl:template mode="layer_blend" match="*">
522   <xsl:if test="@inkscape:groupmode='layer' and @style and contains(@style, 'filter:url(#')">
523     <xsl:variable name="id" select="substring-before(substring-after(@style, 'filter:url(#'), ')')" />
524     <xsl:for-each select="//*[@id=$id]">
525       <xsl:if test="name(child::node()) = 'feBlend'">
526         <xsl:attribute name="blendMode">
527           <xsl:value-of select="child::node()/@mode"/>
528         </xsl:attribute>
529       </xsl:if>
530     </xsl:for-each>
531   </xsl:if>
532 </xsl:template>
534 <!--
535   // Generic filters template //
536   Limited to one filter (can be improved)
537 -->
538 <xsl:template mode="forward" match="*[name(.) = 'filter']">
539   <xsl:if test="count(*) = 1">
540     <xsl:apply-templates mode="forward" />
541   </xsl:if> 
542 </xsl:template>
544 <!--
545   // GaussianBlur filter effects //
546   Blur values approximated with d = floor(s * 3*sqrt(2*pi)/4 + 0.5) from:
547     http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
548   Blur quality=2 recommended by the FXG specifications:
549     http://opensource.adobe.com/wiki/display/flexsdk/FXG+2.0+Specification#FXG2.0Specification-FilterEffects
550 -->
551 <xsl:template mode="forward" match="*[name(.) = 'feGaussianBlur']">
552   <xsl:if test="name(.)='feGaussianBlur'">
553     <filters>
554       <BlurFilter>
555         <xsl:attribute name="quality">2</xsl:attribute>
556         <xsl:if test="@stdDeviation">
557           <xsl:variable name="blur" select="normalize-space(translate(@stdDeviation, ',', ' '))" />
558           <xsl:choose>
559             <xsl:when test="not(contains($blur, ' '))">
560               <xsl:attribute name="blurX">
561                 <xsl:value-of select="floor($blur * 1.88 + 0.5)" />
562               </xsl:attribute>
563               <xsl:attribute name="blurY">
564                 <xsl:value-of select="floor($blur * 1.88 + 0.5)" />
565               </xsl:attribute>
566             </xsl:when>
567             <xsl:otherwise>
568               <xsl:attribute name="blurX">
569                 <xsl:value-of select="floor(substring-before($blur, ' ') * 1.88 + 0.5)" />
570               </xsl:attribute>
571               <xsl:attribute name="blurY">
572                 <xsl:value-of select="floor(substring-after($blur, ' ') * 1.88 + 0.5)" />
573               </xsl:attribute>
574             </xsl:otherwise>
575           </xsl:choose>          
576         </xsl:if>
577       </BlurFilter>
578     </filters>
579   </xsl:if>
580 </xsl:template>
582 <!--
583   // Linked filter effect //
584   Only supports blurs
585 -->
586 <xsl:template mode="filter_effect" match="*">
587   <xsl:variable name="id">
588     <xsl:choose>
589       <xsl:when test="@filter and starts-with(@filter, 'url(#')">
590         <xsl:value-of select="substring-before(substring-after(@filter, 'url(#'), ')')" />
591       </xsl:when>
592       <xsl:when test="@style and contains(@style, 'filter:url(#')">
593         <xsl:value-of select="substring-before(substring-after(@style, 'filter:url(#'), ')')" />
594       </xsl:when>
595     </xsl:choose>
596   </xsl:variable>
598   <xsl:for-each select="//*[@id=$id]">
599     <xsl:apply-templates mode="forward" />
600   </xsl:for-each>
601 </xsl:template>
603 <!--
604   // Linear gradient //
605   Full convertion to FXG would require some math.
606 -->
607 <xsl:template name="linearGradient">
608   <xsl:param name="id" />
609   <xsl:for-each select="//*[@id=$id]">
610     <xsl:if test="@id">
611       <xsl:attribute name="id">
612         <xsl:value-of select="@id" />
613       </xsl:attribute>
614     </xsl:if>
615     <xsl:if test="@spreadMethod">
616       <xsl:attribute name="spreadMethod">
617         <xsl:choose>
618           <xsl:when test="@spreadMethod = 'pad'">pad</xsl:when>
619           <xsl:when test="@spreadMethod = 'reflect'">reflect</xsl:when>
620           <xsl:when test="@spreadMethod = 'repeat'">repeat</xsl:when>
621         </xsl:choose>
622       </xsl:attribute>
623     </xsl:if>
624     <xsl:if test="@color-interpolation">
625       <xsl:attribute name="interpolationMethod">
626         <xsl:choose>
627           <xsl:when test="@color-interpolation = 'linearRGB'">linearRGB</xsl:when>
628           <xsl:otherwise>rgb</xsl:otherwise>
629         </xsl:choose>
630       </xsl:attribute>
631     </xsl:if>
632     <xsl:if test="@x1 and @x2 and @y1 and @y2 and function-available('math:atan')">
633       <xsl:attribute name="rotation">
634         <xsl:value-of select="57.3 * math:atan((@y2 - @y1) div (@x2 - @x1))" />
635       </xsl:attribute>
636     </xsl:if>
637     <xsl:if test="@gradientTransform">
638       <xsl:call-template name="gradient_transform">
639         <xsl:with-param name="transform" select="@gradientTransform" />
640         <xsl:with-param name="type" select="linear" />
641       </xsl:call-template>
642     </xsl:if> 
643     <xsl:choose>
644       <xsl:when test="@xlink:href">
645         <xsl:variable name="reference_id" select="@xlink:href" />
646         <xsl:call-template name="gradientStops" >
647           <xsl:with-param name="id">
648             <xsl:value-of select="substring-after($reference_id, '#')" />
649           </xsl:with-param>
650         </xsl:call-template>
651       </xsl:when>
652       <xsl:otherwise><xsl:apply-templates mode="forward" /></xsl:otherwise>
653     </xsl:choose>
654   </xsl:for-each>
655 </xsl:template>
657 <!--
658   // Radial gradient //
659     
660   Full convertion to FXG would require some math.
661 -->
662 <xsl:template name="radialGradient">
663   <xsl:param name="id" />
664   <xsl:for-each select="//*[@id=$id]">
665     <xsl:if test="@id">
666       <xsl:attribute name="id">
667         <xsl:value-of select="@id" />
668       </xsl:attribute>
669     </xsl:if>
670     <xsl:if test="@spreadMethod">
671       <xsl:attribute name="spreadMethod">
672         <xsl:choose>
673           <xsl:when test="@spreadMethod = 'pad'">pad</xsl:when>
674           <xsl:when test="@spreadMethod = 'reflect'">reflect</xsl:when>
675           <xsl:when test="@spreadMethod = 'repeat'">repeat</xsl:when>
676         </xsl:choose>
677       </xsl:attribute>
678     </xsl:if>
679     <xsl:if test="@color-interpolation">
680       <xsl:attribute name="interpolationMethod">
681         <xsl:choose>
682           <xsl:when test="@color-interpolation = 'linearRGB'">linearRGB</xsl:when>
683           <xsl:otherwise>rgb</xsl:otherwise>
684         </xsl:choose>
685       </xsl:attribute>
686     </xsl:if>
687     <xsl:if test="@gradientTransform">
688       <xsl:call-template name="gradient_transform">
689         <xsl:with-param name="transform" select="@gradientTransform" />
690         <xsl:with-param name="type" select="radial" />
691       </xsl:call-template>
692     </xsl:if>
693     <xsl:choose>
694       <xsl:when test="@xlink:href">
695         <xsl:variable name="reference_id" select="@xlink:href" />
696         <xsl:call-template name="gradientStops" >
697           <xsl:with-param name="id">
698             <xsl:value-of select="substring-after($reference_id, '#')" />
699           </xsl:with-param>
700         </xsl:call-template>
701       </xsl:when>
702       <xsl:otherwise><xsl:apply-templates mode="forward" /></xsl:otherwise>
703     </xsl:choose>
704   </xsl:for-each>
705 </xsl:template>
707 <!--
708   // Gradient stops list //
709   
710   TODO: Find a way to test the existence of the node-set
711 -->
712 <xsl:template name="gradientStops">
713   <xsl:param name="id" />
714   <xsl:variable name="stops">
715     <xsl:for-each select="//*[@id=$id]">
716       <xsl:apply-templates mode="forward" />
717     </xsl:for-each>
718   </xsl:variable>
719   <xsl:choose>
720     <xsl:when test="not($stops)">
721       <GradientEntry>
722         <xsl:attribute name="alpha">0</xsl:attribute>
723       </GradientEntry>
724     </xsl:when>
725     <xsl:otherwise><xsl:copy-of select="$stops" /></xsl:otherwise>
726   </xsl:choose>
727 </xsl:template>
729 <!--
730   // Gradient stop //
731 -->
732 <xsl:template mode="forward" match="*[name(.) = 'stop']">
733   <GradientEntry>
734     <!--xsl:apply-templates mode="stop_opacity" select="." /-->
735     <xsl:apply-templates mode="stop_color" select="." />
736     <xsl:apply-templates mode="offset" select="." />
737     <xsl:apply-templates mode="forward" />
738   </GradientEntry>
739 </xsl:template>
741 <!--
742   // Clipping and masking//
743 -->
744 <xsl:template mode="clip" match="*">
745   <xsl:param name="object" />
746   <xsl:param name="clip_type" />
748   <xsl:choose>
749     <xsl:when test="$clip_type='clip' and @clip-path and contains(@clip-path, 'url')">
750       <Group>
751         <xsl:attribute name="maskType"><xsl:value-of select="'clip'"/></xsl:attribute>
752         <mask>
753           <Group>
754             <xsl:variable name="clip_id" select="substring-before(substring-after(@clip-path, 'url(#'), ')')"/>
755             <xsl:for-each select="//*[@id=$clip_id]">
756               <xsl:if test="not(@clipPathUnits) or @clipPathUnits != 'objectBoundingBox'">
757                 <xsl:apply-templates mode="forward" />
758               </xsl:if>
759             </xsl:for-each>
760           </Group>
761         </mask>
762         <xsl:copy-of select="$object"/>
763       </Group>
764     </xsl:when>
765     <xsl:when test="$clip_type='mask' and @mask and contains(@mask, 'url')">
766       <Group>
767         <xsl:attribute name="maskType"><xsl:value-of select="'alpha'"/></xsl:attribute>
768         <mask>
769           <Group>
770             <xsl:variable name="mask_id" select="substring-before(substring-after(@mask, 'url(#'), ')')"/>
771             <xsl:for-each select="//*[@id=$mask_id]">
772               <xsl:if test="not(@maskUnits) or @maskUnits != 'objectBoundingBox'">
773                 <xsl:apply-templates mode="forward" />
774               </xsl:if>
775             </xsl:for-each>
776           </Group>
777         </mask>
778         <xsl:copy-of select="$object"/>
779       </Group>
780     </xsl:when>
781     <xsl:otherwise>
782       <xsl:copy-of select="$object" />
783     </xsl:otherwise>
784   </xsl:choose>
785 </xsl:template>
787 <!--
788   // Misc templates //
790   * Id converter
791   * Decimal to hexadecimal converter
792   * Unit to pixel converter
793   * Switch
794   * Unknows tags
795   * Object description (not supported)
796   * Title and description (not supported)
797   * Symbols (not supported)
798   * Use (not supported)
799   * RDF and foreign objects (not supported)
800   * Misc ignored stuff (markers, patterns, styles)
801 -->
803 <!--
804   // Id converter //
805   Removes "-" from the original id
806   (Not sure FXG really needs it)
807 -->
808 <xsl:template mode="id" match="*">
809   <xsl:if test="@id">
810     <xsl:attribute name="id"><xsl:value-of select="translate(@id, '- ', '')" /></xsl:attribute>
811   </xsl:if>
812 </xsl:template>
814 <!--
815   // Decimal to hexadecimal converter //
816 -->
817 <xsl:template name="to_hex">
818   <xsl:param name="convert" />
819   <xsl:value-of select="concat(substring('0123456789ABCDEF', 1 + floor(round($convert) div 16), 1), substring('0123456789ABCDEF', 1 + round($convert) mod 16, 1))" />
820 </xsl:template>
822 <!-- 
823   // Unit to pixel converter //
824   Values with units (except %) are converted to pixels and rounded.
825   Unknown units are kept.
826   em, ex and % not implemented
827 -->
828 <xsl:template name="convert_unit">
829   <xsl:param name="convert_value" />
830   <xsl:choose>
831     <xsl:when test="contains($convert_value, 'px')">
832       <xsl:value-of select="round(translate($convert_value, 'px', ''))" />
833     </xsl:when>
834     <xsl:when test="contains($convert_value, 'pt')">
835       <xsl:value-of select="round(translate($convert_value, 'pt', '') * 1.25)" />
836     </xsl:when>
837     <xsl:when test="contains($convert_value, 'pc')">
838       <xsl:value-of select="round(translate($convert_value, 'pc', '') * 15)" />
839     </xsl:when>
840     <xsl:when test="contains($convert_value, 'mm')">
841       <xsl:value-of select="round(translate($convert_value, 'mm', '') * 3.543307)" />
842     </xsl:when>
843     <xsl:when test="contains($convert_value, 'cm')">
844       <xsl:value-of select="round(translate($convert_value, 'cm', '') * 35.43307)" />
845     </xsl:when>
846     <xsl:when test="contains($convert_value, 'in')">
847       <xsl:value-of select="round(translate($convert_value, 'in', '') * 90)" />
848     </xsl:when>
849     <xsl:when test="contains($convert_value, 'ft')">
850       <xsl:value-of select="round(translate($convert_value, 'ft', '') * 1080)" />
851     </xsl:when>
852     <xsl:when test="not(string(number($convert_value))='NaN')">
853       <xsl:value-of select="round($convert_value)" />
854     </xsl:when>
855     <xsl:otherwise>
856       <xsl:value-of select="$convert_value" />
857     </xsl:otherwise>
858   </xsl:choose>
859 </xsl:template>
861 <!--
862   // Switch //
863 -->
864 <xsl:template mode="forward" match="*[name(.) = 'switch']">
865   <xsl:apply-templates mode="forward" />
866 </xsl:template>
868 <!-- 
869   // Unknown tags //
870   With generic and mode="forward" templates
871 -->
872 <xsl:template match="*">
873   <xsl:comment><xsl:value-of select="concat('Unknown tag: ', name(.))" /></xsl:comment>
874 </xsl:template>
876 <xsl:template mode="forward" match="*">
877   <xsl:comment><xsl:value-of select="concat('Unknown tag: ', name(.))" /></xsl:comment>
878 </xsl:template>
880 <!-- 
881   // Object description //
882 -->
883 <xsl:template mode="desc" match="*">
885 </xsl:template>
887 <!-- 
888   // Title and description //
889   Title is ignored and desc is converted to Tag in the mode="desc" template
890 -->
891 <xsl:template mode="forward" match="*[name(.) = 'title' or name(.) = 'desc']">
893 </xsl:template>
895 <!--
896   // Symbols //
897 -->
898 <xsl:template mode="forward" match="*[name(.) = 'symbol']">
900 </xsl:template>
902 <!--
903   // Use //
904   Could be implemented via librairies
905   (but since it is not supported by Inkscape, not implemented yet)
906 -->
907 <xsl:template mode="forward" match="*[name(.) = 'use']">
909 </xsl:template>
911 <!--
912   // RDF and foreign objects //
913 -->
914 <xsl:template mode="forward" match="rdf:RDF | *[name(.) = 'foreignObject']">
916 </xsl:template>
918 <!--
919   // Misc ignored stuff (markers, patterns, styles) //
920 -->
921 <xsl:template mode="forward" match="*[name(.) = 'marker' or name(.) = 'pattern' or name(.) = 'style']">
923 </xsl:template>
925 <!--
926   // Colors and patterns //
928   * Generic color template
929   * Object opacity
930   * Fill
931   * Fill opacity
932   * Fill rule
933   * Generic fill template
934   * Stroke
935   * Stroke opacity
936   * Generic stroke template
937   * Stroke width
938   * Stroke mitterlimit
939   * Stroke dasharray (not supported in FXG)
940   * Stroke dashoffset (not supported in FXG)
941   * Linejoin SVG to FxG converter
942   * Stroke linejoin
943   * Linecap SVG to FXG converter
944   * Stroke linecap
945   * Gradient stop
946   * Gradient stop opacity
947   * Gradient stop offset
948 -->
950 <!--
951   // Generic color template //
952 -->
953 <xsl:template name="template_color">
954   <xsl:param name="colorspec" />
955   <xsl:choose>
956     <xsl:when test="starts-with($colorspec, 'rgb(') and not(contains($colorspec , '%'))">
957       <xsl:value-of select="'#'" />
958       <xsl:call-template name="to_hex">
959         <xsl:with-param name="convert">
960           <xsl:value-of select="substring-before(substring-after($colorspec, 'rgb('), ',')" />
961         </xsl:with-param>
962       </xsl:call-template>
963       <xsl:call-template name="to_hex">
964         <xsl:with-param name="convert">
965           <xsl:value-of select="substring-before(substring-after(substring-after($colorspec, 'rgb('), ','), ',')" />
966         </xsl:with-param>
967       </xsl:call-template>
968       <xsl:call-template name="to_hex">
969         <xsl:with-param name="convert">
970           <xsl:value-of select="substring-before(substring-after(substring-after(substring-after($colorspec, 'rgb('), ','), ','), ')')" />
971         </xsl:with-param>
972       </xsl:call-template>
973     </xsl:when>
974     <xsl:when test="starts-with($colorspec, 'rgb(') and contains($colorspec , '%')">
975       <xsl:value-of select="'#'" />
976       <xsl:call-template name="to_hex">
977         <xsl:with-param name="convert">
978           <xsl:value-of select="number(substring-before(substring-after($colorspec, 'rgb('), '%,')) * 255 div 100" />
979         </xsl:with-param>
980       </xsl:call-template>
981       <xsl:call-template name="to_hex">
982         <xsl:with-param name="convert">
983           <xsl:value-of select="number(substring-before(substring-after(substring-after($colorspec, 'rgb('), ','), '%,')) * 255 div 100" />
984         </xsl:with-param>
985       </xsl:call-template>
986       <xsl:call-template name="to_hex">
987         <xsl:with-param name="convert">
988           <xsl:value-of select="number(substring-before(substring-after(substring-after(substring-after($colorspec, 'rgb('), ','), ','), '%)')) * 255 div 100" />
989         </xsl:with-param>
990       </xsl:call-template>
991     </xsl:when>
992     <xsl:when test="starts-with($colorspec, '#')">
993       <xsl:value-of select="'#'" />
994       <xsl:choose>
995         <xsl:when test="string-length(substring-after($colorspec, '#')) = 3">
996           <xsl:variable name="colorspec3">
997             <xsl:value-of select="translate(substring-after($colorspec, '#'), 'abcdefgh', 'ABCDEFGH')" />
998           </xsl:variable>
999           <xsl:value-of select="concat(substring($colorspec3, 1, 1), substring($colorspec3, 1, 1))" />
1000           <xsl:value-of select="concat(substring($colorspec3, 2, 1), substring($colorspec3, 2, 1))" />
1001           <xsl:value-of select="concat(substring($colorspec3, 3, 1), substring($colorspec3, 3, 1))" />
1002         </xsl:when>
1003         <xsl:otherwise>
1004           <xsl:value-of select="translate(substring-after($colorspec, '#'), 'abcdefgh', 'ABCDEFGH')" />
1005         </xsl:otherwise>
1006       </xsl:choose>
1007     </xsl:when>
1008     <xsl:otherwise>
1009       <xsl:variable name="named_color_hex" select="document('colors.xml')/colors/color[@name = translate($colorspec, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')]/@hex" />
1010       <xsl:choose>
1011         <xsl:when test="$named_color_hex and $named_color_hex != ''">
1012           <xsl:value-of select="'#'" />
1013           <xsl:value-of select="substring-after($named_color_hex, '#')" />
1014         </xsl:when>
1015         <xsl:otherwise>
1016           <xsl:value-of select="$colorspec" />
1017         </xsl:otherwise>
1018       </xsl:choose>
1019     </xsl:otherwise>
1020   </xsl:choose>
1021 </xsl:template>
1023 <!--
1024   // Object opacity //
1025 -->
1026 <xsl:template mode="object_opacity" match="*">
1027   <xsl:if test="@opacity or (@style and (contains(@style, ';opacity:') or starts-with(@style, 'opacity:')))">
1028     <xsl:variable name="value">
1029     <xsl:choose>
1030       <xsl:when test="@opacity">
1031         <xsl:value-of select="@opacity" />
1032       </xsl:when>
1033       <xsl:when test="@style and contains(@style, ';opacity:')">
1034         <xsl:variable name="Opacity" select="substring-after(@style, ';opacity:')" />
1035         <xsl:choose>
1036           <xsl:when test="contains($Opacity, ';')">
1037             <xsl:value-of select="substring-before($Opacity, ';')" />
1038           </xsl:when>
1039           <xsl:otherwise>
1040             <xsl:value-of select="$Opacity" />
1041           </xsl:otherwise>
1042         </xsl:choose>
1043       </xsl:when>
1044       <xsl:when test="@style and starts-with(@style, 'opacity:')">
1045         <xsl:variable name="Opacity" select="substring-after(@style, 'opacity:')" />
1046         <xsl:choose>
1047           <xsl:when test="contains($Opacity, ';')">
1048             <xsl:value-of select="substring-before($Opacity, ';')" />
1049           </xsl:when>
1050           <xsl:otherwise>
1051             <xsl:value-of select="$Opacity" />
1052           </xsl:otherwise>
1053         </xsl:choose>
1054       </xsl:when>
1055       <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1056         <xsl:apply-templates mode="object_opacity" select="parent::*" />
1057       </xsl:when>
1058       <xsl:otherwise>1</xsl:otherwise>
1059     </xsl:choose>
1060     </xsl:variable>
1061     <xsl:attribute name="alpha">
1062     <xsl:choose>
1063       <xsl:when test="$value &lt; 0">0</xsl:when>
1064       <xsl:when test="$value &gt; 1">1</xsl:when>
1065       <xsl:otherwise>
1066         <xsl:value-of select="$value" />
1067       </xsl:otherwise>
1068     </xsl:choose>
1069     </xsl:attribute>
1070   </xsl:if>
1071 </xsl:template>
1073 <!--
1074   // Fill //
1075 -->
1076 <xsl:template mode="fill" match="*">
1077   <xsl:variable name="value">
1078     <xsl:choose>
1079       <xsl:when test="@fill">
1080         <xsl:value-of select="@fill" />
1081       </xsl:when>
1082       <xsl:when test="@style and contains(@style, 'fill:')">
1083         <xsl:variable name="Fill" select="normalize-space(substring-after(@style, 'fill:'))" />
1084         <xsl:choose>
1085           <xsl:when test="contains($Fill, ';')">
1086             <xsl:value-of select="substring-before($Fill, ';')" />
1087           </xsl:when>
1088           <xsl:otherwise>
1089             <xsl:value-of select="$Fill" />
1090           </xsl:otherwise>
1091         </xsl:choose>
1092       </xsl:when>
1093       <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1094         <xsl:apply-templates mode="fill" select="parent::*"/>
1095       </xsl:when>
1096     </xsl:choose>
1097   </xsl:variable>
1098   <xsl:if test="$value">
1099     <!-- Removes unwanted characters in the color link (TODO: export to a specific template)-->
1100     <xsl:value-of select="normalize-space(translate($value, '&quot;', ''))" />
1101   </xsl:if>
1102 </xsl:template>
1104 <!--
1105   // Fill opacity //
1106 -->
1107 <xsl:template mode="fill_opacity" match="*">
1108   <xsl:variable name="value">
1109   <xsl:choose>
1110     <xsl:when test="@fill-opacity">
1111       <xsl:value-of select="@fill-opacity" />
1112     </xsl:when>
1113     <xsl:when test="@style and contains(@style, 'fill-opacity:')">
1114       <xsl:variable name="Opacity" select="substring-after(@style, 'fill-opacity:')" />
1115       <xsl:choose>
1116         <xsl:when test="contains($Opacity, ';')">
1117           <xsl:value-of select="substring-before($Opacity, ';')" />
1118         </xsl:when>
1119         <xsl:otherwise>
1120           <xsl:value-of select="$Opacity" />
1121         </xsl:otherwise>
1122       </xsl:choose>
1123     </xsl:when>
1124     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1125       <xsl:apply-templates mode="fill_opacity" select="parent::*" />
1126     </xsl:when>
1127     <xsl:otherwise>1</xsl:otherwise>
1128   </xsl:choose>
1129   </xsl:variable>
1130   <xsl:choose>
1131     <xsl:when test="$value &lt; 0">0</xsl:when>
1132     <xsl:when test="$value &gt; 1">1</xsl:when>
1133     <xsl:otherwise>
1134       <xsl:value-of select="$value" />
1135     </xsl:otherwise>
1136   </xsl:choose>
1137 </xsl:template>
1139 <!--
1140   // Fill rule //
1141 -->
1142 <xsl:template mode="fill_rule" match="*">
1143   <xsl:choose>
1144     <xsl:when test="@fill-rule and (@fill-rule = 'nonzero' or @fill-rule = 'evenodd')">
1145       <xsl:if test="@fill-rule = 'nonzero'">
1146         <xsl:attribute name="winding">nonZero</xsl:attribute>
1147       </xsl:if>
1148       <xsl:if test="@fill-rule = 'evenodd'">
1149         <xsl:attribute name="winding">evenOdd</xsl:attribute>
1150       </xsl:if>
1151     </xsl:when>
1152     <xsl:when test="@style and contains(@style, 'fill-rule:')">
1153       <xsl:variable name="FillRule" select="normalize-space(substring-after(@style, 'fill-rule:'))" />
1154       <xsl:choose>
1155         <xsl:when test="contains($FillRule, ';')">
1156           <xsl:if test="substring-before($FillRule, ';') = 'nonzero'">
1157             <xsl:attribute name="winding">nonZero</xsl:attribute>
1158           </xsl:if>
1159           <xsl:if test="substring-before($FillRule, ';') = 'evenodd'">
1160             <xsl:attribute name="winding">evenOdd</xsl:attribute>
1161           </xsl:if>
1162         </xsl:when>
1163         <xsl:when test="$FillRule = 'nonzero'">
1164           <xsl:attribute name="winding">nonZero</xsl:attribute>
1165         </xsl:when>
1166         <xsl:when test=" $FillRule = 'evenodd'">
1167           <xsl:attribute name="winding">evenOdd</xsl:attribute>
1168         </xsl:when>
1169       </xsl:choose>
1170     </xsl:when>
1171     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1172       <xsl:apply-templates mode="fill_rule" select="parent::*"/>
1173         </xsl:when>
1174     <xsl:otherwise>
1175       <xsl:attribute name="winding">nonZero</xsl:attribute>
1176     </xsl:otherwise>
1177   </xsl:choose>
1178 </xsl:template>
1180 <!--
1181   // Generic fill template //
1182 -->
1183 <xsl:template mode="template_fill" match="*">
1184   <xsl:variable name="fill"><xsl:apply-templates mode="fill" select="." /></xsl:variable>
1185   <xsl:variable name="fill_opacity"><xsl:apply-templates mode="fill_opacity" select="." /></xsl:variable>
1186     
1187   <xsl:choose>
1188     <xsl:when test="$fill != '' and $fill != 'none' and not(starts-with($fill, 'url(#'))">
1189     <!-- Solid color -->
1190       <fill>
1191         <SolidColor>
1192           <xsl:attribute name="color">
1193             <xsl:call-template name="template_color">
1194               <xsl:with-param name="colorspec">
1195                 <xsl:value-of select="$fill" />
1196               </xsl:with-param>
1197             </xsl:call-template>
1198           </xsl:attribute>
1199           <xsl:attribute name="alpha">
1200             <xsl:value-of select="$fill_opacity" />
1201           </xsl:attribute>
1202         </SolidColor>
1203       </fill>
1204     </xsl:when>
1205     <!-- Gradients -->
1206     <xsl:when test="starts-with($fill, 'url(#')">
1207       <xsl:for-each select="//*[@id=substring-before(substring-after($fill, 'url(#'), ')')]">
1208         <xsl:if test="name(.) = 'linearGradient'">
1209           <fill>
1210             <LinearGradient>
1211               <xsl:call-template name="linearGradient" >
1212                 <xsl:with-param name="id">
1213                   <xsl:value-of select="substring-before(substring-after($fill, 'url(#'), ')')" />
1214                 </xsl:with-param>
1215               </xsl:call-template>
1216             </LinearGradient>
1217           </fill>
1218         </xsl:if>
1219         <xsl:if test="name(.) = 'radialGradient'">
1220           <fill>
1221             <RadialGradient>
1222               <xsl:call-template name="radialGradient" >
1223                 <xsl:with-param name="id">
1224                   <xsl:value-of select="substring-before(substring-after($fill, 'url(#'), ')')" />
1225                 </xsl:with-param>
1226               </xsl:call-template>
1227             </RadialGradient>
1228           </fill>
1229         </xsl:if>
1230       </xsl:for-each>
1231     </xsl:when>
1232     <xsl:when test="$fill = 'none'">
1233     </xsl:when>
1234     <xsl:otherwise>
1235       <fill>
1236         <SolidColor color="#ffffff" alpha="1"/>
1237       </fill>
1238     </xsl:otherwise>
1239   </xsl:choose>
1240 </xsl:template>
1242 <!--
1243   // Stroke //
1244 -->
1245 <xsl:template mode="stroke" match="*">
1246   <xsl:choose>
1247     <xsl:when test="@stroke">
1248       <xsl:value-of select="@stroke" />
1249     </xsl:when>
1250     <xsl:when test="@style and contains(@style, 'stroke:')">
1251       <xsl:variable name="Stroke" select="normalize-space(substring-after(@style, 'stroke:'))" />
1252       <xsl:choose>
1253         <xsl:when test="contains($Stroke, ';')">
1254           <xsl:value-of select="substring-before($Stroke, ';')" />
1255         </xsl:when>
1256         <xsl:when test="$Stroke">
1257           <xsl:value-of select="$Stroke" />
1258         </xsl:when>
1259       </xsl:choose>
1260     </xsl:when>
1261     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1262       <xsl:apply-templates mode="stroke" select="parent::*"/>
1263     </xsl:when>
1264   </xsl:choose>
1265 </xsl:template>
1267 <!--
1268   // Stroke opacity //
1269 -->
1270 <xsl:template mode="stroke_opacity" match="*">
1271   <xsl:variable name="value">
1272   <xsl:choose>
1273     <xsl:when test="@stroke-opacity"><xsl:value-of select="@stroke-opacity" /></xsl:when>
1274     <xsl:when test="@style and contains(@style, 'stroke-opacity:')">
1275       <xsl:variable name="Opacity" select="substring-after(@style, 'stroke-opacity:')" />
1276       <xsl:choose>
1277         <xsl:when test="contains($Opacity, ';')">
1278           <xsl:value-of select="substring-before($Opacity, ';')" />
1279         </xsl:when>
1280         <xsl:otherwise>
1281           <xsl:value-of select="$Opacity" />
1282         </xsl:otherwise>
1283       </xsl:choose>
1284     </xsl:when>
1285     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1286       <xsl:apply-templates mode="stroke_opacity" select="parent::*" />
1287     </xsl:when>
1288     <xsl:otherwise>1</xsl:otherwise>
1289   </xsl:choose>
1290   </xsl:variable>
1291   <xsl:choose>
1292     <xsl:when test="$value &lt; 0">0</xsl:when>
1293     <xsl:when test="$value &gt; 1">1</xsl:when>
1294     <xsl:otherwise>
1295       <xsl:value-of select="$value" />
1296     </xsl:otherwise>
1297   </xsl:choose>
1298 </xsl:template>
1300 <!-- 
1301   // Generic stroke template //
1302   
1303   Not supported in FXG:
1304   * stroke-dasharray
1305   * stroke-dashoffset
1306   
1307  -->
1308 <xsl:template mode="template_stroke" match="*">
1309   <xsl:variable name="stroke"><xsl:apply-templates mode="stroke" select="." /></xsl:variable>
1310   <xsl:variable name="stroke_opacity"><xsl:apply-templates mode="stroke_opacity" select="." /></xsl:variable>
1311   <xsl:variable name="stroke_width"><xsl:apply-templates mode="stroke_width" select="." /></xsl:variable>
1312   <xsl:variable name="stroke_miterlimit"><xsl:apply-templates mode="stroke_miterlimit" select="." /></xsl:variable>
1313   <xsl:variable name="stroke_linejoin"><xsl:apply-templates mode="stroke_linejoin" select="." /></xsl:variable>
1314   <xsl:variable name="stroke_linecap"><xsl:apply-templates mode="stroke_linecap" select="." /></xsl:variable>
1316   <!-- Solid color -->
1317   <xsl:if  test="$stroke != '' and $stroke != 'none' and not(starts-with($stroke, 'url(#'))">
1318     <stroke>
1319       <SolidColorStroke>
1320         <xsl:attribute name="color">
1321           <xsl:call-template name="template_color">
1322             <xsl:with-param name="colorspec">
1323               <xsl:value-of select="$stroke" />
1324             </xsl:with-param>
1325           </xsl:call-template>
1326         </xsl:attribute>
1327         <xsl:attribute name="alpha">
1328           <xsl:value-of select="$stroke_opacity" />
1329         </xsl:attribute>
1330         <xsl:attribute name="weight">
1331           <xsl:value-of select="$stroke_width" />
1332         </xsl:attribute>
1333         <xsl:if test="$stroke_miterlimit != ''">
1334           <xsl:attribute name="miterLimit">
1335             <xsl:value-of select="$stroke_miterlimit" />
1336           </xsl:attribute>
1337         </xsl:if>
1338         <xsl:attribute name="joints">
1339           <xsl:value-of select="$stroke_linejoin" />
1340         </xsl:attribute>
1341         <xsl:attribute name="caps">
1342           <xsl:value-of select="$stroke_linecap" />
1343         </xsl:attribute>
1344       </SolidColorStroke>  
1345     </stroke>
1346   </xsl:if>
1347     
1348   <!-- Gradients -->
1349   <xsl:if test="starts-with($stroke, 'url(#')">
1350     <xsl:for-each select="//*[@id=substring-before(substring-after($stroke, 'url(#'), ')')]">
1351       <xsl:if test="name(.) = 'linearGradient'">
1352         <stroke>
1353           <LinearGradientStroke>
1354             <xsl:attribute name="weight">
1355               <xsl:value-of select="$stroke_width" />
1356             </xsl:attribute>
1357             <xsl:if test="$stroke_miterlimit != ''">
1358               <xsl:attribute name="miterLimit">
1359                 <xsl:value-of select="$stroke_miterlimit" />
1360               </xsl:attribute>
1361             </xsl:if>
1362             <xsl:attribute name="joints">
1363               <xsl:value-of select="$stroke_linejoin" />
1364             </xsl:attribute>
1365             <xsl:attribute name="caps">
1366               <xsl:value-of select="$stroke_linecap" />
1367             </xsl:attribute>
1368             <xsl:call-template name="linearGradient" >
1369               <xsl:with-param name="id">
1370                 <xsl:value-of select="substring-before(substring-after($stroke, 'url(#'), ')')" />
1371               </xsl:with-param>
1372             </xsl:call-template>
1373           </LinearGradientStroke>
1374         </stroke>
1375       </xsl:if>
1376       <xsl:if test="name(.) = 'radialGradient'">
1377         <stroke>
1378           <RadialGradientStroke>
1379             <xsl:attribute name="weight">
1380               <xsl:value-of select="$stroke_width" />
1381             </xsl:attribute>
1382             <xsl:if test="$stroke_miterlimit != ''">
1383               <xsl:attribute name="miterLimit">
1384                 <xsl:value-of select="$stroke_miterlimit" />
1385               </xsl:attribute>
1386             </xsl:if>
1387             <xsl:attribute name="joints">
1388               <xsl:value-of select="$stroke_linejoin" />
1389             </xsl:attribute>
1390             <xsl:attribute name="caps">
1391               <xsl:value-of select="$stroke_linecap" />
1392             </xsl:attribute>
1393             <xsl:call-template name="radialGradient" >
1394               <xsl:with-param name="id">
1395                 <xsl:value-of select="substring-before(substring-after($stroke, 'url(#'), ')')" />
1396               </xsl:with-param>
1397             </xsl:call-template>
1398           </RadialGradientStroke>
1399         </stroke>
1400       </xsl:if>
1401     </xsl:for-each>
1402   </xsl:if>
1403 </xsl:template>
1405 <!--
1406   // Stroke width //
1407 -->
1408 <xsl:template mode="stroke_width" match="*">
1409   <xsl:choose>
1410     <xsl:when test="@stroke-width">
1411       <xsl:call-template name="convert_unit">
1412         <xsl:with-param name="convert_value">
1413           <xsl:value-of select="@stroke-width" />
1414         </xsl:with-param>
1415       </xsl:call-template> 
1416     </xsl:when>
1417     <xsl:when test="@style and contains(@style, 'stroke-width:')">
1418       <xsl:call-template name="convert_unit">
1419         <xsl:with-param name="convert_value">
1420         <xsl:choose>
1421           <xsl:when test="contains(substring-after(@style, 'stroke-width:'), ';')">
1422             <xsl:value-of select="substring-before(substring-after(@style, 'stroke-width:'), ';')" />
1423           </xsl:when>
1424           <xsl:otherwise>
1425             <xsl:value-of select="substring-after(@style, 'stroke-width:')" />
1426           </xsl:otherwise>
1427         </xsl:choose>
1428         </xsl:with-param>
1429       </xsl:call-template> 
1430     </xsl:when>
1431     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1432       <xsl:apply-templates mode="stroke_width" select="parent::*"/>
1433     </xsl:when>
1434     <xsl:otherwise>1</xsl:otherwise>
1435   </xsl:choose>
1436 </xsl:template>
1438 <!--
1439   // Stroke miterlimit //
1441   Probably not calculated the same way in SVG and FXG (same value but different result)
1442 -->
1443 <xsl:template mode="stroke_miterlimit" match="*">
1444   <xsl:choose>
1445     <xsl:when test="@stroke-miterlimit">
1446       <xsl:value-of select="@stroke-miterlimit" />
1447     </xsl:when>
1448     <xsl:when test="@style and contains(@style, 'stroke-miterlimit:')">
1449       <xsl:variable name="miterLimit" select="substring-after(@style, 'stroke-miterlimit:')" />
1450       <xsl:choose>
1451         <xsl:when test="contains($miterLimit, ';')">
1452           <xsl:value-of select="substring-before($miterLimit, ';')" />
1453         </xsl:when>
1454         <xsl:otherwise>
1455           <xsl:value-of select="$miterLimit" />
1456         </xsl:otherwise>
1457       </xsl:choose>
1458     </xsl:when>
1459     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1460       <xsl:apply-templates mode="stroke_miterlimit" select="parent::*"/>
1461     </xsl:when>
1462   </xsl:choose>
1463 </xsl:template>
1465 <!-- 
1466   // Stroke dasharray //
1467   !! Not supported !!
1468 -->
1469 <xsl:template mode="stroke_dasharray" match="*">
1470   <xsl:comment>FXG does not support dasharrays</xsl:comment>
1471 </xsl:template>
1473 <!-- 
1474   // Stroke dashoffset //
1475   !! Not supported !!
1476 -->
1477 <xsl:template mode="stroke_dashoffset" match="*">
1478   <xsl:comment>FXG does not support dashoffsets</xsl:comment>
1479 </xsl:template>
1481 <!-- 
1482   // Linejoin SVG to FXG converter //
1483 -->
1484 <xsl:template name="linejoin_svg_to_fxg">
1485   <xsl:param name="linejoin" />
1486   <xsl:choose>
1487     <xsl:when test="$linejoin = 'bevel'">bevel</xsl:when>
1488     <xsl:when test="$linejoin = 'round'">round</xsl:when>
1489     <xsl:otherwise>miter</xsl:otherwise>
1490   </xsl:choose>
1491 </xsl:template>
1493 <!-- 
1494   // Stroke linejoin //
1495 -->
1496 <xsl:template mode="stroke_linejoin" match="*">
1497   <xsl:choose>
1498     <xsl:when test="@stroke-linejoin">
1499       <xsl:call-template name="linejoin_svg_to_fxg">
1500         <xsl:with-param name="linejoin">
1501           <xsl:value-of select="@stroke-linejoin" />
1502         </xsl:with-param>
1503       </xsl:call-template>
1504     </xsl:when>
1505     <xsl:when test="@style and contains(@style, 'stroke-linejoin:')">
1506       <xsl:variable name="joints" select="substring-after(@style, 'stroke-linejoin:')" />
1507       <xsl:choose>
1508         <xsl:when test="contains($joints, ';')">
1509           <xsl:call-template name="linejoin_svg_to_fxg">
1510             <xsl:with-param name="linejoin">
1511               <xsl:value-of select="substring-before($joints, ';')" />
1512             </xsl:with-param>
1513           </xsl:call-template>
1514         </xsl:when>
1515         <xsl:otherwise>
1516           <xsl:call-template name="linejoin_svg_to_fxg">
1517             <xsl:with-param name="linejoin">
1518               <xsl:value-of select="$joints" />
1519             </xsl:with-param>
1520           </xsl:call-template>
1521         </xsl:otherwise>
1522       </xsl:choose>
1523     </xsl:when>
1524     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1525       <xsl:apply-templates mode="stroke_linejoin" select="parent::*"/>
1526     </xsl:when>
1527     <xsl:otherwise>miter</xsl:otherwise>
1528   </xsl:choose>
1529 </xsl:template>
1531 <!--
1532   // Linecap SVG to FXG converter //
1533   
1534   Not supported in FXG:
1535   * butt linecap
1536 -->
1537 <xsl:template name="linecap_svg_to_fxg">
1538   <xsl:param name="linecap" />
1539   <xsl:choose>
1540     <xsl:when test="$linecap = 'round'">round</xsl:when>
1541     <xsl:when test="$linecap = 'square'">square</xsl:when>
1542     <xsl:when test="$linecap = 'butt'">round</xsl:when>
1543     <xsl:otherwise>none</xsl:otherwise>
1544   </xsl:choose>
1545 </xsl:template>
1547 <!--
1548   // Stroke linecap //
1549 -->
1550 <xsl:template mode="stroke_linecap" match="*">
1551   <xsl:choose>
1552     <xsl:when test="@stroke-linecap">
1553       <xsl:call-template name="linecap_svg_to_fxg">
1554         <xsl:with-param name="linecap">
1555           <xsl:value-of select="@stroke-linecap" />
1556         </xsl:with-param>
1557       </xsl:call-template>
1558     </xsl:when>
1559     <xsl:when test="@style and contains(@style, 'stroke-linecap:')">
1560       <xsl:variable name="caps" select="substring-after(@style, 'stroke-linecap:')" />
1561       <xsl:choose>
1562         <xsl:when test="contains($caps, ';')">
1563           <xsl:call-template name="linecap_svg_to_fxg">
1564             <xsl:with-param name="linecap">
1565               <xsl:value-of select="substring-before($caps, ';')" />
1566             </xsl:with-param>
1567           </xsl:call-template>
1568         </xsl:when>
1569         <xsl:otherwise>
1570           <xsl:call-template name="linecap_svg_to_fxg">
1571             <xsl:with-param name="linecap">
1572               <xsl:value-of select="$caps" />
1573             </xsl:with-param>
1574           </xsl:call-template>
1575         </xsl:otherwise>
1576       </xsl:choose>
1577     </xsl:when>
1578     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1579       <xsl:apply-templates mode="stroke_linecap" select="parent::*"/>
1580     </xsl:when>
1581     <xsl:otherwise>none</xsl:otherwise>
1582   </xsl:choose>
1583 </xsl:template>
1585 <!-- 
1586   // Gradient stops //
1587 -->
1588 <xsl:template mode="stop_color" match="*">
1589   <xsl:variable name="Opacity">
1590     <xsl:choose>
1591       <xsl:when test="@stop-opacity">
1592         <xsl:value-of select="@stop-opacity" />
1593       </xsl:when>
1594       <xsl:when test="@style and contains(@style, 'stop-opacity:')">
1595         <xsl:variable name="temp_opacity" select="substring-after(@style, 'stop-opacity:')" />
1596         <xsl:choose>
1597           <xsl:when test="contains($temp_opacity, ';')">
1598             <xsl:value-of select="substring-before($temp_opacity, ';')" />
1599           </xsl:when>
1600           <xsl:otherwise>
1601             <xsl:value-of select="$temp_opacity" />
1602           </xsl:otherwise>
1603         </xsl:choose>
1604       </xsl:when>
1605       <xsl:otherwise><xsl:value-of select="''" /></xsl:otherwise>
1606     </xsl:choose>
1607   </xsl:variable>
1608   <xsl:variable name="hex_opacity">
1609     <xsl:choose>
1610       <xsl:when test="$Opacity != ''">
1611         <xsl:call-template name="to_hex">
1612           <xsl:with-param name="convert">
1613             <xsl:value-of select="number($Opacity) * 255" />
1614           </xsl:with-param>
1615         </xsl:call-template>
1616       </xsl:when>
1617       <xsl:otherwise>
1618         <xsl:value-of select="$Opacity" />
1619       </xsl:otherwise>
1620     </xsl:choose>
1621   </xsl:variable>
1622   <xsl:variable name="stopcolor">
1623     <xsl:choose>
1624       <xsl:when test="@stop-color">
1625         <xsl:call-template name="template_color">
1626           <xsl:with-param name="colorspec">
1627             <xsl:value-of select="@stop-color" />
1628           </xsl:with-param>
1629         </xsl:call-template>
1630       </xsl:when>
1631       <xsl:when test="@style and contains(@style, 'stop-color:')">
1632         <xsl:variable name="Color" select="normalize-space(substring-after(@style, 'stop-color:'))" />
1633         <xsl:choose>
1634           <xsl:when test="contains($Color, ';')">
1635             <xsl:call-template name="template_color">
1636               <xsl:with-param name="colorspec">
1637                 <xsl:value-of select="substring-before($Color, ';')" />
1638               </xsl:with-param>
1639             </xsl:call-template>
1640           </xsl:when>
1641           <xsl:otherwise>
1642             <xsl:call-template name="template_color">
1643               <xsl:with-param name="colorspec">
1644                 <xsl:value-of select="$Color" />
1645               </xsl:with-param>
1646             </xsl:call-template>
1647           </xsl:otherwise>
1648         </xsl:choose>
1649       </xsl:when>
1650       <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1651         <xsl:apply-templates mode="stop_color" select="parent::*"/>
1652       </xsl:when>
1653       <xsl:otherwise>#000</xsl:otherwise>
1654     </xsl:choose>
1655   </xsl:variable>
1656   <xsl:attribute name="color">
1657     <xsl:value-of select="$stopcolor" />
1658   </xsl:attribute>
1659   <xsl:if test="$Opacity != ''">
1660     <xsl:attribute name="alpha">
1661       <xsl:value-of select="$Opacity" />
1662     </xsl:attribute>
1663   </xsl:if>
1664 </xsl:template>
1666 <!--
1667   // Gradient stop opacity //
1668 -->
1669 <xsl:template mode="stop_opacity" match="*">
1670   <xsl:choose>
1671     <xsl:when test="@stop-opacity">
1672       <xsl:attribute name="Opacity">
1673         <xsl:value-of select="@stop-opacity" />
1674       </xsl:attribute>
1675     </xsl:when>
1676     <xsl:when test="@style and contains(@style, 'stop-opacity:')">
1677       <xsl:variable name="Opacity" select="substring-after(@style, 'stop-opacity:')" />
1678       <xsl:attribute name="opacity">
1679         <xsl:choose>
1680           <xsl:when test="contains($Opacity, ';')">
1681             <xsl:value-of select="substring-before($Opacity, ';')" />
1682           </xsl:when>
1683           <xsl:otherwise>
1684             <xsl:value-of select="$Opacity" />
1685           </xsl:otherwise>
1686         </xsl:choose>
1687       </xsl:attribute>
1688     </xsl:when>
1689     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1690       <xsl:apply-templates mode="stop_opacity" select="parent::*"/>
1691     </xsl:when>
1692   </xsl:choose>
1693 </xsl:template>
1695 <!--
1696   // Gradient stop offset //
1697 -->
1698 <xsl:template mode="offset" match="*">
1699   <xsl:choose>
1700     <xsl:when test="@offset">
1701       <xsl:attribute name="ratio">
1702         <xsl:choose>
1703           <xsl:when test="contains(@offset, '%')">
1704             <xsl:value-of select="number(substring-before(@offset, '%')) div 100" />
1705           </xsl:when>
1706           <xsl:otherwise>
1707             <xsl:value-of select="@offset" />
1708           </xsl:otherwise>
1709         </xsl:choose>
1710       </xsl:attribute>
1711     </xsl:when>
1712     <xsl:when test="@style and contains(@style, 'offset:')">
1713       <xsl:variable name="Offset" select="substring-after(@style, 'offset:')" />
1714       <xsl:attribute name="ratio">
1715         <xsl:choose>
1716           <xsl:when test="contains($Offset, '%')">
1717             <xsl:value-of select="number(substring-before($Offset, '%')) div 100" />
1718           </xsl:when>    
1719           <xsl:when test="contains($Offset, ';')">
1720             <xsl:value-of select="substring-before($Offset, ';')" />
1721           </xsl:when>
1722           <xsl:otherwise>
1723             <xsl:value-of select="$Offset" />
1724           </xsl:otherwise>
1725         </xsl:choose>
1726       </xsl:attribute>
1727     </xsl:when>
1728     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1729       <xsl:apply-templates mode="stop_offset" select="parent::*"/>
1730     </xsl:when>
1731   </xsl:choose>
1732 </xsl:template>
1734 <!-- 
1735   // Text specific templates //
1737   * Text tspan
1738   * Text flowPara
1739   * Text flowRegion (text frame)
1740   * Font size
1741   * Baseline shift
1742   * Writing mode
1743   * Text decoration
1744   * Text direction
1745   * Text size
1746   * Text position
1747 -->
1749  <!-- 
1750   // Text span //
1751   SVG: tspan, flowSpan, FXG: span
1752   
1753   Not supported in FXG:
1754   * span position
1755 -->
1756 <xsl:template mode="forward" match="*[name(.) = 'tspan'  or name(.) = 'flowSpan']">
1757   <span>
1758     <xsl:variable name="fill">
1759       <xsl:apply-templates mode="fill" select="." />
1760     </xsl:variable>
1761     <xsl:variable name="fill_opacity">
1762       <xsl:apply-templates mode="fill_opacity" select="." />
1763     </xsl:variable>
1764     <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
1765       <xsl:attribute name="color">
1766         <xsl:call-template name="template_color">
1767           <xsl:with-param name="colorspec">
1768             <xsl:value-of select="$fill" />
1769           </xsl:with-param>
1770         </xsl:call-template>
1771       </xsl:attribute>
1772       <xsl:attribute name="textAlpha">
1773         <xsl:value-of select="$fill_opacity" />
1774       </xsl:attribute>
1775     </xsl:if>
1776     <xsl:apply-templates mode="font_size" select="." />
1777     <xsl:apply-templates mode="baseline_shift" select="." />
1778     <xsl:apply-templates mode="text_decoration" select="." />
1779     
1780     <xsl:if test="text()">
1781       <xsl:value-of select="text()" />
1782     </xsl:if>
1783   </span>
1784 </xsl:template>
1786  <!-- 
1787   // Text flowPara //
1788   SVG: flowPara, flowDiv FXG: p
1789   
1790   Not supported in FXG:
1791   * paragraph position
1792 -->
1793 <xsl:template mode="forward" match="*[name(.) = 'flowPara' or name(.) = 'flowDiv']">
1794   <p>
1795     <xsl:variable name="fill">
1796       <xsl:apply-templates mode="fill" select="." />
1797     </xsl:variable>
1798     <xsl:variable name="fill_opacity">
1799       <xsl:apply-templates mode="fill_opacity" select="." />
1800     </xsl:variable>
1801     <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
1802       <xsl:attribute name="color">
1803         <xsl:call-template name="template_color">
1804           <xsl:with-param name="colorspec">
1805             <xsl:value-of select="$fill" />
1806           </xsl:with-param>
1807         </xsl:call-template>
1808       </xsl:attribute>
1809       <xsl:attribute name="textAlpha">
1810         <xsl:value-of select="$fill_opacity" />
1811       </xsl:attribute>
1812     </xsl:if>
1813     <xsl:apply-templates mode="font_size" select="." />
1814     <xsl:apply-templates mode="baseline_shift" select="." />
1815     <xsl:apply-templates mode="text_decoration" select="." />
1817     <xsl:choose>
1818       <xsl:when test="*[name(.) = 'flowSpan']/text()">
1819         <xsl:apply-templates mode="forward" />
1820       </xsl:when>
1821       <xsl:otherwise>
1822         <xsl:choose>
1823           <xsl:when test="@xml:space='preserve'">
1824             <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
1825           </xsl:when>
1826           <xsl:otherwise>
1827             <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
1828           </xsl:otherwise>
1829         </xsl:choose>  
1830       </xsl:otherwise>
1831     </xsl:choose>
1832   </p>
1833 </xsl:template>
1836  <!-- 
1837   // Text flowRegion //
1838 -->
1839 <xsl:template mode="flow_region" match="*">
1840   <xsl:apply-templates mode="text_size" select="." />
1841   <xsl:apply-templates mode="text_position" select="." />
1842 </xsl:template>
1844 <!-- 
1845   // Text font size //
1846   SVG: font-size, FXG: fontSize
1847 -->
1848 <xsl:template mode="font_size" match="*">
1849   <xsl:variable name="value">
1850     <xsl:if test="@font-size">
1851       <xsl:value-of select="@font-size" />
1852     </xsl:if>
1853     <xsl:if test="@style and contains(@style, 'font-size:')">
1854       <xsl:variable name="font_size" select="normalize-space(substring-after(@style, 'font-size:'))" />
1855       <xsl:choose>
1856         <xsl:when test="contains($font_size, ';')">
1857           <xsl:value-of select="substring-before($font_size, ';')" />
1858         </xsl:when>
1859         <xsl:otherwise>
1860           <xsl:value-of select="$font_size" />
1861         </xsl:otherwise>
1862       </xsl:choose>
1863     </xsl:if>
1864   </xsl:variable>
1865   <xsl:if test="$value != ''">
1866     <xsl:attribute name="fontSize">
1867       <xsl:call-template name="convert_unit">
1868         <xsl:with-param name="convert_value" select="$value" />
1869       </xsl:call-template>
1870     </xsl:attribute>
1871   </xsl:if>
1872 </xsl:template>
1874 <!-- 
1875   // Text baseline shift //
1876   SVG: baseline-shift, FXG: baselineShift
1877 -->
1878 <xsl:template mode="baseline_shift" match="*">
1879   <xsl:variable name="value">
1880     <xsl:if test="@baseline-shift">
1881       <xsl:value-of select="@baseline-shift" />
1882     </xsl:if>
1883     <xsl:if test="@style and contains(@style, 'baseline-shift:') and not(contains(substring-after(@style, 'baseline-shift:'), ';'))">
1884       <xsl:value-of select="substring-after(@style, 'baseline-shift:')" />
1885     </xsl:if>
1886     <xsl:if test="@style and contains(@style, 'baseline-shift:') and contains(substring-after(@style, 'baseline-shift:'), ';')">
1887       <xsl:value-of select="substring-before(substring-after(@style, 'baseline-shift:'), ';')" />
1888     </xsl:if>   
1889   </xsl:variable>
1890   <xsl:if test="$value != ''">
1891     <xsl:attribute name="baselineShift">  
1892       <xsl:choose>
1893         <xsl:when test="$value='baseline'">0</xsl:when>
1894         <xsl:when test="$value='super'">superscript</xsl:when>
1895         <xsl:when test="$value='sub'">subscript</xsl:when>
1896         <xsl:when test="translate($value, '%', '') &lt; -1000">-1000</xsl:when>
1897         <xsl:when test="translate($value, '%', '') &gt; 1000">1000</xsl:when>
1898         <xsl:otherwise>
1899           <xsl:value-of select="translate($value, '%', '')" />
1900         </xsl:otherwise>
1901       </xsl:choose>  
1902       <xsl:if test="contains($value, '%')">%</xsl:if>
1903     </xsl:attribute>
1904   </xsl:if>
1905 </xsl:template>
1907 <!-- 
1908   // Text writing mode //
1909   SVG: writing-mode, FXG: blockProgression 
1910   
1911   Values inverted in FXG...
1912 -->
1913 <xsl:template mode="writing_mode" match="*">
1914   <xsl:variable name="value">
1915     <xsl:if test="@writing-mode">
1916       <xsl:value-of select="@writing-mode" />
1917     </xsl:if>
1918     <xsl:if test="@style and contains(@style, 'writing-mode:') and not(contains(substring-after(@style, 'writing-mode:'), ';'))">
1919       <xsl:value-of select="substring-after(@style, 'writing-mode:')" />
1920     </xsl:if>
1921     <xsl:if test="@style and contains(@style, 'writing-mode:') and contains(substring-after(@style, 'writing-mode:'), ';')">
1922       <xsl:value-of select="substring-before(substring-after(@style, 'writing-mode:'), ';')" />
1923     </xsl:if>   
1924   </xsl:variable>
1925   <xsl:if test="$value != ''">
1926     <xsl:attribute name="blockProgression">  
1927       <xsl:choose>
1928         <xsl:when test="$value='tb'">rl</xsl:when>
1929         <xsl:otherwise>tb</xsl:otherwise>
1930       </xsl:choose>  
1931     </xsl:attribute>
1932     <xsl:if test="$value='tb'">
1933       <xsl:attribute name="textRotation">rotate270</xsl:attribute>
1934     </xsl:if>  
1935   </xsl:if>
1936 </xsl:template>
1937   
1938 <!-- 
1939   // Text decoration //
1940   SVG: text-decoration, FXG: textDecoration, lineThrough 
1941 -->
1942 <xsl:template mode="text_decoration" match="*">
1943   <xsl:variable name="value">
1944     <xsl:if test="@text-decoration">
1945       <xsl:value-of select="@text-decoration" />
1946     </xsl:if>
1947     <xsl:if test="@style and contains(@style, 'text-decoration:') and not(contains(substring-after(@style, 'text-decoration:'), ';'))">
1948       <xsl:value-of select="substring-after(@style, 'text-decoration:')" />
1949     </xsl:if>
1950     <xsl:if test="@style and contains(@style, 'text-decoration:') and contains(substring-after(@style, 'text-decoration:'), ';')">
1951       <xsl:value-of select="substring-before(substring-after(@style, 'text-decoration:'), ';')" />
1952     </xsl:if>   
1953   </xsl:variable>
1954   <xsl:if test="$value != ''">  
1955     <xsl:choose>
1956       <xsl:when test="$value='underline'">
1957         <xsl:attribute name="textDecoration">underline</xsl:attribute>
1958       </xsl:when>
1959       <xsl:when test="$value='line-through'">
1960         <xsl:attribute name="lineThrough">true</xsl:attribute>
1961       </xsl:when>
1962     </xsl:choose>  
1963   </xsl:if>
1964 </xsl:template>
1965   
1966 <!-- 
1967   // Text direction //
1968   SVG: direction, unicode-bidi, FXG: direction
1969 -->
1970 <xsl:template mode="direction" match="*">
1971   <xsl:variable name="value">
1972     <xsl:if test="@direction">
1973       <xsl:value-of select="@direction" />
1974     </xsl:if>
1975     <xsl:if test="@style and contains(@style, 'direction:') and not(contains(substring-after(@style, 'direction:'), ';'))">
1976       <xsl:value-of select="substring-after(@style, 'direction:')" />
1977     </xsl:if>
1978     <xsl:if test="@style and contains(@style, 'direction:') and contains(substring-after(@style, 'direction:'), ';')">
1979       <xsl:value-of select="substring-before(substring-after(@style, 'direction:'), ';')" />
1980     </xsl:if>   
1981   </xsl:variable>
1982   <xsl:variable name="bidi">
1983     <xsl:if test="@unicode-bidi">
1984       <xsl:value-of select="@unicode-bidi" />
1985     </xsl:if>
1986     <xsl:if test="@style and contains(@style, 'unicode-bidi:') and not(contains(substring-after(@style, 'unicode-bidi:'), ';'))">
1987       <xsl:value-of select="substring-after(@style, 'unicode-bidi:')" />
1988     </xsl:if>
1989     <xsl:if test="@style and contains(@style, 'unicode-bidi:') and contains(substring-after(@style, 'unicode-bidi:'), ';')">
1990       <xsl:value-of select="substring-before(substring-after(@style, 'unicode-bidi:'), ';')" />
1991     </xsl:if>   
1992   </xsl:variable>
1994   <xsl:if test="$value != '' and ($bidi='embed' or $bidi='bidi-override')">  
1995     <xsl:attribute name="direction">
1996       <xsl:choose>
1997         <xsl:when test="$value='ltr'">ltr</xsl:when>
1998         <xsl:when test="$value='rtl'">rtl</xsl:when>
1999       </xsl:choose>  
2000     </xsl:attribute>
2001   </xsl:if>
2002 </xsl:template>
2004  <!-- 
2005   // Text size //
2006 -->
2007 <xsl:template mode="text_size" match="*">
2008   <xsl:if test="@width">
2009     <xsl:attribute name="width">
2010       <xsl:call-template name="convert_unit">
2011         <xsl:with-param name="convert_value" select="@width" />
2012       </xsl:call-template>
2013     </xsl:attribute>
2014   </xsl:if>
2015   <xsl:if test="@height">
2016     <xsl:attribute name="height">
2017       <xsl:call-template name="convert_unit">
2018         <xsl:with-param name="convert_value" select="@height" />
2019       </xsl:call-template>
2020     </xsl:attribute>
2021   </xsl:if>
2022 </xsl:template>
2024  <!-- 
2025   // Text position //
2026 -->
2027 <xsl:template mode="text_position" match="*">
2028   <!-- Keep the first x value only -->
2029   <xsl:if test="@x">
2030     <xsl:attribute name="x">
2031       <xsl:choose>
2032         <xsl:when test="contains(@x, ' ')">
2033           <xsl:call-template name="convert_unit">
2034             <xsl:with-param name="convert_value" select="substring-before(@x, ' ')" />
2035           </xsl:call-template>   
2036           </xsl:when>
2037           <xsl:otherwise>
2038           <xsl:call-template name="convert_unit">
2039             <xsl:with-param name="convert_value" select="@x" />
2040           </xsl:call-template>  
2041         </xsl:otherwise>
2042       </xsl:choose>
2043     </xsl:attribute>
2044   </xsl:if>
2045   <!-- Keep the first y value only -->
2046   <xsl:if test="@y">
2047     <xsl:attribute name="y">
2048       <xsl:choose>
2049         <xsl:when test="contains(@y, ' ')">
2050           <xsl:call-template name="convert_unit">
2051             <xsl:with-param name="convert_value" select="substring-before(@y, ' ')" />
2052           </xsl:call-template>   
2053           </xsl:when>
2054           <xsl:otherwise>
2055           <xsl:call-template name="convert_unit">
2056             <xsl:with-param name="convert_value" select="@y" />
2057           </xsl:call-template>  
2058         </xsl:otherwise>
2059       </xsl:choose>
2060     </xsl:attribute>
2061   </xsl:if>
2062 </xsl:template>
2064 <!-- 
2065   // Objects //
2066   
2067   * Text
2068   * Lines
2069   * Rectangle
2070   * Path
2071   * Ellipse
2072   * Circle
2073   * Image
2074   * Polygon (not supported)
2075   * Polyline (not supported)
2076 -->
2078 <!-- 
2079   // Text objects //
2080   SVG: text, FXG: RichText
2082   Not supported by FXG:
2083   * Generic fonts.
2084   * Embedded fonts (in defs).
2085   * Character rotation.
2086   * Character positionning (x and y).
2087   * Text-anchor.
2088   * Text stroke.
2089   
2090   Partial support:
2091   * Text rotation (0, 90, 180 and 270 degrees only) -> not implemented.
2092   * Font weight (normal and bold only) -> values under 500 are considered normal, the others bold.
2093   * Whitespace handling, issues with xml:whitespace='preserve'.
2094 -->
2095 <xsl:template mode="forward" match="*[name(.) = 'text']">
2096   <xsl:variable name="object">
2097     <RichText>
2098       <xsl:apply-templates mode="font_size" select="." />
2099       
2100       <xsl:variable name="font_weight">
2101         <xsl:if test="@font-weight">
2102           <xsl:value-of select="@font-weight" />
2103         </xsl:if>
2104         <xsl:if test="@style and contains(@style, 'font-weight:') and not(contains(substring-after(@style, 'font-weight:'), ';'))">
2105           <xsl:value-of select="substring-after(@style, 'font-weight:')" />
2106         </xsl:if>
2107         <xsl:if test="@style and contains(@style, 'font-weight:') and contains(substring-after(@style, 'font-weight:'), ';')">
2108           <xsl:value-of select="substring-before(substring-after(@style, 'font-weight:'), ';')" />
2109         </xsl:if>   
2110       </xsl:variable>
2111       <xsl:attribute name="fontWeight">
2112         <xsl:choose>
2113           <xsl:when test="$font_weight='normal' or $font_weight='bold'">
2114             <xsl:value-of select="$font_weight" />
2115           </xsl:when>
2116           <xsl:when test="$font_weight &lt; 500 or $font_weight = 'lighter'">normal</xsl:when>
2117           <xsl:when test="$font_weight &gt; 499 or $font_weight = 'bolder'">bold</xsl:when>
2118           <xsl:otherwise>normal</xsl:otherwise>
2119         </xsl:choose>
2120       </xsl:attribute>
2122       <xsl:if test="@font-family">
2123         <xsl:attribute name="fontFamily">
2124           <xsl:value-of select="translate(@font-family, &quot;'&quot;, '')" />
2125         </xsl:attribute>
2126       </xsl:if>
2127       <xsl:if test="@style and contains(@style, 'font-family:')">
2128         <xsl:variable name="font_family" select="substring-after(@style, 'font-family:')" />
2129         <xsl:attribute name="fontFamily">
2130           <xsl:choose>
2131             <xsl:when test="contains($font_family, ';')">
2132               <xsl:value-of select="translate(substring-before($font_family, ';'), &quot;'&quot;, '')" />
2133             </xsl:when>
2134             <xsl:otherwise>
2135               <xsl:value-of select="translate($font_family, &quot;'&quot;, '')" />
2136             </xsl:otherwise>
2137           </xsl:choose>
2138         </xsl:attribute>
2139       </xsl:if>
2140       <xsl:if test="@font-style">
2141         <xsl:attribute name="fontStyle">
2142           <xsl:value-of select="@font-style" />
2143         </xsl:attribute>
2144       </xsl:if>
2145       <xsl:if test="@style and contains(@style, 'font-style:')">
2146         <xsl:variable name="font_style" select="substring-after(@style, 'font-style:')" />
2147         <xsl:attribute name="fontStyle">
2148           <xsl:choose>
2149             <xsl:when test="contains($font_style, ';')">
2150               <xsl:value-of select="substring-before($font_style, ';')" />
2151             </xsl:when>
2152             <xsl:otherwise>
2153               <xsl:value-of select="$font_style" />
2154             </xsl:otherwise>
2155           </xsl:choose>
2156         </xsl:attribute>
2157       </xsl:if>
2158       
2159       <xsl:variable name="fill">
2160         <xsl:apply-templates mode="fill" select="." />
2161       </xsl:variable>
2162       <xsl:variable name="fill_opacity">
2163         <xsl:apply-templates mode="fill_opacity" select="." />
2164       </xsl:variable>
2166       <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
2167         <xsl:attribute name="color">
2168           <xsl:call-template name="template_color">
2169             <xsl:with-param name="colorspec">
2170               <xsl:value-of select="$fill" />
2171             </xsl:with-param>
2172           </xsl:call-template>
2173         </xsl:attribute>
2174         <xsl:attribute name="textAlpha">
2175           <xsl:value-of select="$fill_opacity" />
2176         </xsl:attribute>
2177       </xsl:if>
2179       <!-- Force default baseline to "ascent" -->
2180       <xsl:attribute name="alignmentBaseline">ascent</xsl:attribute>
2181       
2182       <xsl:if test="@xml:space='preserve'">
2183         <xsl:attribute name="whiteSpaceCollapse">preserve</xsl:attribute>
2184       </xsl:if>
2186       <xsl:apply-templates mode="text_size" select="." />
2187       <xsl:apply-templates mode="text_position" select="." />
2188       <xsl:apply-templates mode="text_decoration" select="." />
2189       <xsl:apply-templates mode="direction" select="." />
2190       <xsl:apply-templates mode="writing_mode" select="." />
2191       <xsl:apply-templates mode="id" select="." />
2193       <xsl:apply-templates mode="filter_effect" select="." />
2194       <xsl:apply-templates mode="desc" select="." />
2197       <!--xsl:apply-templates mode="forward" /-->
2198       <content>
2199         <xsl:choose>
2200           <xsl:when test="*[name(.) = 'tspan']/text()">
2201             <xsl:apply-templates mode="forward" />
2202           </xsl:when>
2203           <xsl:otherwise>
2204             <xsl:choose>
2205               <xsl:when test="@xml:space='preserve'">
2206                 <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
2207               </xsl:when>
2208               <xsl:otherwise>
2209                 <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
2210               </xsl:otherwise>
2211             </xsl:choose>  
2212           </xsl:otherwise>
2213         </xsl:choose>
2214       </content>
2215     </RichText>
2216   </xsl:variable>
2218   <xsl:variable name="clipped_object">
2219     <xsl:apply-templates mode="clip" select="." >
2220       <xsl:with-param name="object" select="$object" />
2221       <xsl:with-param name="clip_type" select="'clip'" />
2222     </xsl:apply-templates>
2223   </xsl:variable>
2225   <xsl:variable name="masked_object">
2226     <xsl:apply-templates mode="clip" select="." >
2227       <xsl:with-param name="object" select="$clipped_object" />
2228       <xsl:with-param name="clip_type" select="'mask'" />
2229     </xsl:apply-templates>
2230   </xsl:variable>
2231   
2232   <xsl:choose>
2233     <xsl:when test="@transform">
2234     <Group>
2235       <xsl:call-template name="object_transform">
2236         <xsl:with-param name="object" select="$masked_object" />
2237         <xsl:with-param name="transform" select="@transform" />
2238       </xsl:call-template>
2239     </Group>
2240     </xsl:when>
2241     <xsl:otherwise>
2242       <xsl:copy-of select="$masked_object" />
2243     </xsl:otherwise>
2244   </xsl:choose>
2245 </xsl:template>
2246  
2247  <!-- 
2248   // FlowRoot objects //
2249   SVG: flowRoot, FXG: RichText
2251   Not supported by FXG:
2252   * See text objects
2253 -->
2254 <xsl:template mode="forward" match="*[name(.) = 'flowRoot']">
2255   <xsl:variable name="object">
2256     <RichText>
2257       <xsl:apply-templates mode="font_size" select="." />
2258       
2259       <xsl:variable name="font_weight">
2260         <xsl:if test="@font-weight">
2261           <xsl:value-of select="@font-weight" />
2262         </xsl:if>
2263         <xsl:if test="@style and contains(@style, 'font-weight:') and not(contains(substring-after(@style, 'font-weight:'), ';'))">
2264           <xsl:value-of select="substring-after(@style, 'font-weight:')" />
2265         </xsl:if>
2266         <xsl:if test="@style and contains(@style, 'font-weight:') and contains(substring-after(@style, 'font-weight:'), ';')">
2267           <xsl:value-of select="substring-before(substring-after(@style, 'font-weight:'), ';')" />
2268         </xsl:if>   
2269       </xsl:variable>
2270       <xsl:attribute name="fontWeight">
2271         <xsl:choose>
2272           <xsl:when test="$font_weight='normal' or $font_weight='bold'">
2273             <xsl:value-of select="$font_weight" />
2274           </xsl:when>
2275           <xsl:when test="$font_weight &lt; 500 or $font_weight = 'lighter'">normal</xsl:when>
2276           <xsl:when test="$font_weight &gt; 499 or $font_weight = 'bolder'">bold</xsl:when>
2277           <xsl:otherwise>normal</xsl:otherwise>
2278         </xsl:choose>
2279       </xsl:attribute>
2281       <xsl:if test="@font-family">
2282         <xsl:attribute name="fontFamily">
2283           <xsl:value-of select="translate(@font-family, &quot;'&quot;, '')" />
2284         </xsl:attribute>
2285       </xsl:if>
2286       <xsl:if test="@style and contains(@style, 'font-family:')">
2287         <xsl:variable name="font_family" select="substring-after(@style, 'font-family:')" />
2288         <xsl:attribute name="fontFamily">
2289           <xsl:choose>
2290             <xsl:when test="contains($font_family, ';')">
2291               <xsl:value-of select="translate(substring-before($font_family, ';'), &quot;'&quot;, '')" />
2292             </xsl:when>
2293             <xsl:otherwise>
2294               <xsl:value-of select="translate($font_family, &quot;'&quot;, '')" />
2295             </xsl:otherwise>
2296           </xsl:choose>
2297         </xsl:attribute>
2298       </xsl:if>
2299       <xsl:if test="@font-style">
2300         <xsl:attribute name="fontStyle">
2301           <xsl:value-of select="@font-style" />
2302         </xsl:attribute>
2303       </xsl:if>
2304       <xsl:if test="@style and contains(@style, 'font-style:')">
2305         <xsl:variable name="font_style" select="substring-after(@style, 'font-style:')" />
2306         <xsl:attribute name="fontStyle">
2307           <xsl:choose>
2308             <xsl:when test="contains($font_style, ';')">
2309               <xsl:value-of select="substring-before($font_style, ';')" />
2310             </xsl:when>
2311             <xsl:otherwise>
2312               <xsl:value-of select="$font_style" />
2313             </xsl:otherwise>
2314           </xsl:choose>
2315         </xsl:attribute>
2316       </xsl:if>
2317       
2318       <xsl:variable name="fill">
2319         <xsl:apply-templates mode="fill" select="." />
2320       </xsl:variable>
2321       <xsl:variable name="fill_opacity">
2322         <xsl:apply-templates mode="fill_opacity" select="." />
2323       </xsl:variable>
2325       <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
2326         <xsl:attribute name="color">
2327           <xsl:call-template name="template_color">
2328             <xsl:with-param name="colorspec">
2329               <xsl:value-of select="$fill" />
2330             </xsl:with-param>
2331           </xsl:call-template>
2332         </xsl:attribute>
2333         <xsl:attribute name="textAlpha">
2334           <xsl:value-of select="$fill_opacity" />
2335         </xsl:attribute>
2336       </xsl:if>
2338       <!-- Force default baseline to "ascent" -->
2339       <xsl:attribute name="alignmentBaseline">ascent</xsl:attribute>
2340       
2341       <xsl:if test="@xml:space='preserve'">
2342         <xsl:attribute name="whiteSpaceCollapse">preserve</xsl:attribute>
2343       </xsl:if>
2345       <xsl:apply-templates mode="text_decoration" select="." />
2346       <xsl:apply-templates mode="direction" select="." />
2347       <xsl:apply-templates mode="writing_mode" select="." />
2348       <xsl:apply-templates mode="id" select="." />
2349       <xsl:apply-templates mode="flow_region" select="*[name(.) = 'flowRegion']/child::node()" />
2350       <xsl:apply-templates mode="filter_effect" select="." />
2351       <xsl:apply-templates mode="desc" select="." />
2353       <content>
2354         <xsl:choose>
2355           <xsl:when test="*[name(.) = 'flowPara' or name(.) = 'flowDiv']/text()">
2356             <xsl:apply-templates mode="forward" />
2357           </xsl:when>
2358           <xsl:otherwise>
2359             <xsl:choose>
2360               <xsl:when test="@xml:space='preserve'">
2361                 <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
2362               </xsl:when>
2363               <xsl:otherwise>
2364                 <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
2365               </xsl:otherwise>
2366             </xsl:choose>  
2367           </xsl:otherwise>
2368         </xsl:choose>
2369       </content>
2370     </RichText>
2371   </xsl:variable>
2373   <xsl:variable name="clipped_object">
2374     <xsl:apply-templates mode="clip" select="." >
2375       <xsl:with-param name="object" select="$object" />
2376       <xsl:with-param name="clip_type" select="'clip'" />
2377     </xsl:apply-templates>
2378   </xsl:variable>
2380   <xsl:variable name="masked_object">
2381     <xsl:apply-templates mode="clip" select="." >
2382       <xsl:with-param name="object" select="$clipped_object" />
2383       <xsl:with-param name="clip_type" select="'mask'" />
2384     </xsl:apply-templates>
2385   </xsl:variable>
2386   
2387   <xsl:choose>
2388     <xsl:when test="@transform">
2389     <Group>
2390       <xsl:call-template name="object_transform">
2391         <xsl:with-param name="object" select="$masked_object" />
2392         <xsl:with-param name="transform" select="@transform" />
2393       </xsl:call-template>
2394     </Group>
2395     </xsl:when>
2396     <xsl:otherwise>
2397       <xsl:copy-of select="$masked_object" />
2398     </xsl:otherwise>
2399   </xsl:choose>
2400 </xsl:template>
2402 <!-- 
2403   // Line object //
2404   SVG: line, FXG: Line
2405 -->
2406 <xsl:template mode="forward" match="*[name(.) = 'line']">
2407   <xsl:variable name="object">
2408     <Line>
2409       <xsl:if test="@x1">
2410         <xsl:attribute name="xFrom">
2411           <xsl:call-template name="convert_unit">
2412             <xsl:with-param name="convert_value" select="@x1" />
2413           </xsl:call-template>
2414         </xsl:attribute>
2415       </xsl:if>
2416       <xsl:if test="@y1">
2417         <xsl:attribute name="yFrom">
2418           <xsl:call-template name="convert_unit">
2419             <xsl:with-param name="convert_value" select="@y1" />
2420           </xsl:call-template>
2421         </xsl:attribute>
2422       </xsl:if>
2423       <xsl:if test="@x2">
2424         <xsl:attribute name="xTo">
2425           <xsl:call-template name="convert_unit">
2426             <xsl:with-param name="convert_value" select="@x2" />
2427           </xsl:call-template>
2428         </xsl:attribute>
2429       </xsl:if>
2430       <xsl:if test="@y2">
2431         <xsl:attribute name="yTo">
2432           <xsl:call-template name="convert_unit">
2433             <xsl:with-param name="convert_value" select="@y2" />
2434           </xsl:call-template>
2435         </xsl:attribute>
2436       </xsl:if>
2437       <xsl:apply-templates mode="object_opacity" select="." />
2438       <xsl:apply-templates mode="id" select="." />
2440       <xsl:apply-templates mode="template_fill" select="." />
2441       <xsl:apply-templates mode="template_stroke" select="." />
2442       <xsl:apply-templates mode="filter_effect" select="." />
2443       <xsl:apply-templates mode="desc" select="." />   
2445       <xsl:apply-templates mode="forward" />
2446     </Line>
2447   </xsl:variable>
2449   <xsl:variable name="clipped_object">
2450     <xsl:apply-templates mode="clip" select="." >
2451       <xsl:with-param name="object" select="$object" />
2452       <xsl:with-param name="clip_type" select="'clip'" />
2453     </xsl:apply-templates>
2454   </xsl:variable>
2456   <xsl:variable name="masked_object">
2457     <xsl:apply-templates mode="clip" select="." >
2458       <xsl:with-param name="object" select="$clipped_object" />
2459       <xsl:with-param name="clip_type" select="'mask'" />
2460     </xsl:apply-templates>
2461   </xsl:variable>
2462   
2463   <xsl:choose>
2464     <xsl:when test="@transform">
2465     <Group>
2466       <xsl:call-template name="object_transform">
2467         <xsl:with-param name="object" select="$masked_object" />
2468         <xsl:with-param name="transform" select="@transform" />
2469       </xsl:call-template>
2470     </Group>
2471     </xsl:when>
2472     <xsl:otherwise>
2473       <xsl:copy-of select="$masked_object" />
2474     </xsl:otherwise>
2475   </xsl:choose>
2476 </xsl:template>
2478 <!-- 
2479   // Rectangle object //
2480   SVG: rect, FXG: Rect
2481 -->
2482 <xsl:template mode="forward" match="*[name(.) = 'rect']">
2483   <xsl:variable name="object">
2484     <Rect>
2485       <xsl:if test="@x">
2486         <xsl:attribute name="x">
2487           <xsl:call-template name="convert_unit">
2488             <xsl:with-param name="convert_value" select="@x" />
2489           </xsl:call-template>
2490         </xsl:attribute>
2491       </xsl:if>
2492       <xsl:if test="@y">
2493         <xsl:attribute name="y">
2494           <xsl:call-template name="convert_unit">
2495             <xsl:with-param name="convert_value" select="@y" />
2496           </xsl:call-template>
2497         </xsl:attribute>
2498       </xsl:if>
2499       <xsl:if test="@width">
2500         <xsl:attribute name="width">
2501           <xsl:call-template name="convert_unit">
2502             <xsl:with-param name="convert_value" select="@width" />
2503           </xsl:call-template>
2504         </xsl:attribute>
2505       </xsl:if>
2506       <xsl:if test="@height">
2507         <xsl:attribute name="height">
2508           <xsl:call-template name="convert_unit">
2509             <xsl:with-param name="convert_value" select="@height" />
2510           </xsl:call-template>
2511         </xsl:attribute>
2512       </xsl:if>
2513       <xsl:if test="@rx">
2514         <xsl:attribute name="radiusX">
2515           <xsl:value-of select="@rx" />
2516         </xsl:attribute>
2517       </xsl:if>
2518       <xsl:if test="@ry">
2519         <xsl:attribute name="radiusY">
2520           <xsl:value-of select="@ry" />
2521         </xsl:attribute>
2522       </xsl:if>
2523       <xsl:if test="@rx and not(@ry)">
2524         <xsl:attribute name="radiusX">
2525           <xsl:value-of select="@rx" />
2526         </xsl:attribute>
2527         <xsl:attribute name="radiusY">
2528           <xsl:value-of select="@rx" />
2529         </xsl:attribute>
2530       </xsl:if>
2531       <xsl:if test="@ry and not(@rx)">
2532         <xsl:attribute name="radiusX">
2533           <xsl:value-of select="@ry" />
2534         </xsl:attribute>
2535         <xsl:attribute name="radiusY">
2536           <xsl:value-of select="@ry" />
2537         </xsl:attribute>
2538       </xsl:if>
2539       <xsl:apply-templates mode="object_opacity" select="." />
2540       <xsl:apply-templates mode="id" select="." />
2542       <xsl:apply-templates mode="template_fill" select="." />
2543       <xsl:apply-templates mode="template_stroke" select="." />
2544       <xsl:apply-templates mode="filter_effect" select="." />
2545       <!--  <xsl:apply-templates mode="resources" select="." /> -->
2546       <xsl:apply-templates mode="desc" select="." />
2548       <xsl:apply-templates mode="forward" />
2549     </Rect>
2550   </xsl:variable>
2552   <xsl:variable name="clipped_object">
2553     <xsl:apply-templates mode="clip" select="." >
2554       <xsl:with-param name="object" select="$object" />
2555       <xsl:with-param name="clip_type" select="'clip'" />
2556     </xsl:apply-templates>
2557   </xsl:variable>
2559   <xsl:variable name="masked_object">
2560     <xsl:apply-templates mode="clip" select="." >
2561       <xsl:with-param name="object" select="$clipped_object" />
2562       <xsl:with-param name="clip_type" select="'mask'" />
2563     </xsl:apply-templates>
2564   </xsl:variable>
2565   
2566   <xsl:choose>
2567     <xsl:when test="@transform">
2568     <Group>
2569       <xsl:call-template name="object_transform">
2570         <xsl:with-param name="object" select="$masked_object" />
2571         <xsl:with-param name="transform" select="@transform" />
2572       </xsl:call-template>
2573     </Group>
2574     </xsl:when>
2575     <xsl:otherwise>
2576       <xsl:copy-of select="$masked_object" />
2577     </xsl:otherwise>
2578   </xsl:choose>
2579 </xsl:template>
2581 <!-- 
2582   // Path //
2583   SVG: path, FXG: Path
2584   
2585   Not supported by FXG:
2586   * elliptical arc curve commands (workaround: convert to path first)
2587   TODO:
2588   * Implement an arc to curve convertor
2589 -->
2590 <xsl:template mode="forward" match="*[name(.) = 'path']">
2591   <xsl:variable name="object">
2592     <Path>
2593       <!-- Path element -->
2594       <!-- Exclude arcs in order to prevent the mxml compiler from failing -->
2595       <xsl:if test="@d and not(contains(@d, 'a') or contains(@d, 'A'))">
2596         <xsl:attribute name="data">
2597           <xsl:value-of select="normalize-space(translate(@d , ',', ' '))" />
2598         </xsl:attribute>
2599       </xsl:if>
2600       <xsl:apply-templates mode="fill_rule" select="." />
2601       <xsl:apply-templates mode="object_opacity" select="." />
2602       <xsl:apply-templates mode="id" select="." />
2604       <!-- Child elements -->
2605       <xsl:apply-templates mode="template_fill" select="." />
2606       <xsl:apply-templates mode="template_stroke" select="." />
2607       <xsl:apply-templates mode="filter_effect" select="." />
2608       <xsl:apply-templates mode="desc" select="." />
2610       <xsl:apply-templates mode="forward" />
2611     </Path>
2612   </xsl:variable>
2613   
2614   <xsl:variable name="clipped_object">
2615     <xsl:apply-templates mode="clip" select="." >
2616       <xsl:with-param name="object" select="$object" />
2617       <xsl:with-param name="clip_type" select="'clip'" />
2618     </xsl:apply-templates>
2619   </xsl:variable>
2621   <xsl:variable name="masked_object">
2622     <xsl:apply-templates mode="clip" select="." >
2623       <xsl:with-param name="object" select="$clipped_object" />
2624       <xsl:with-param name="clip_type" select="'mask'" />
2625     </xsl:apply-templates>
2626   </xsl:variable>
2627   
2628   <xsl:choose>
2629     <xsl:when test="@transform">
2630     <Group>
2631       <xsl:call-template name="object_transform">
2632         <xsl:with-param name="object" select="$masked_object" />
2633         <xsl:with-param name="transform" select="@transform" />
2634       </xsl:call-template>
2635     </Group>
2636     </xsl:when>
2637     <xsl:otherwise>
2638       <xsl:copy-of select="$masked_object" />
2639     </xsl:otherwise>
2640   </xsl:choose>
2641   <xsl:if test="contains(@d, 'a') or contains(@d, 'A')">
2642     <xsl:comment><xsl:value-of select="'Elliptic arc command in path data not supported, please convert to path (arcs are thus converted to curves) before exporting.'" /></xsl:comment>
2643   </xsl:if> 
2644 </xsl:template>
2646 <!-- 
2647   // Ellipse object //
2648   SVG: ellipse, FXG: Ellipse
2649 -->
2650 <xsl:template mode="forward" match="*[name(.) = 'ellipse']">
2651   <xsl:variable name="object">
2652     <Ellipse>
2653       <xsl:variable name="cx">
2654         <xsl:choose>
2655           <xsl:when test="@cx">
2656             <xsl:call-template name="convert_unit">
2657               <xsl:with-param name="convert_value" select="@cx" />
2658             </xsl:call-template>
2659           </xsl:when>
2660           <xsl:otherwise>0</xsl:otherwise>
2661         </xsl:choose>
2662       </xsl:variable>
2663       <xsl:variable name="cy">
2664         <xsl:choose>
2665           <xsl:when test="@cy">
2666             <xsl:call-template name="convert_unit">
2667               <xsl:with-param name="convert_value" select="@cy" />
2668             </xsl:call-template>
2669           </xsl:when>
2670           <xsl:otherwise>0</xsl:otherwise>
2671         </xsl:choose>
2672       </xsl:variable>
2673       <xsl:variable name="rx">
2674         <xsl:choose>
2675           <xsl:when test="@rx">
2676             <xsl:call-template name="convert_unit">
2677               <xsl:with-param name="convert_value" select="@rx" />
2678             </xsl:call-template>
2679           </xsl:when>
2680           <xsl:otherwise>0</xsl:otherwise>
2681         </xsl:choose>
2682       </xsl:variable>
2683       <xsl:variable name="ry">
2684         <xsl:choose>
2685           <xsl:when test="@ry">
2686             <xsl:call-template name="convert_unit">
2687               <xsl:with-param name="convert_value" select="@ry" />
2688             </xsl:call-template>
2689           </xsl:when>
2690           <xsl:otherwise>0</xsl:otherwise>
2691         </xsl:choose>
2692       </xsl:variable>
2694       <xsl:choose>
2695         <xsl:when test="$rx != 0">
2696           <xsl:attribute name="x">
2697             <xsl:value-of select='format-number($cx - $rx, "#.#")' />
2698           </xsl:attribute>
2699           <xsl:attribute name="width">
2700             <xsl:value-of select='format-number(2 * $rx, "#.#")' />
2701           </xsl:attribute>
2702         </xsl:when>
2703         <xsl:otherwise>
2704           <xsl:attribute name="x">
2705             <xsl:value-of select='format-number($cx, "#.#")' />
2706           </xsl:attribute>
2707           <xsl:attribute name="width">0</xsl:attribute>
2708         </xsl:otherwise>
2709       </xsl:choose>
2710       <xsl:choose>
2711         <xsl:when test="$ry != 0">
2712           <xsl:attribute name="y">
2713             <xsl:value-of select='format-number($cy - $ry, "#.#")' />
2714           </xsl:attribute>
2715           <xsl:attribute name="height">
2716             <xsl:value-of select='format-number(2 * $ry, "#.#")' />
2717           </xsl:attribute>
2718         </xsl:when>
2719         <xsl:otherwise>
2720           <xsl:attribute name="y">
2721             <xsl:value-of select='format-number($cy, "#.#")' />
2722           </xsl:attribute>
2723           <xsl:attribute name="height">0</xsl:attribute>
2724         </xsl:otherwise>
2725       </xsl:choose>
2726       <xsl:apply-templates mode="object_opacity" select="." />
2727       <xsl:apply-templates mode="id" select="." />
2729       <!-- Child elements -->
2730       <xsl:apply-templates mode="template_fill" select="." />
2731       <xsl:apply-templates mode="template_stroke" select="." />
2732       <xsl:apply-templates mode="filter_effect" select="." />
2733       <xsl:apply-templates mode="desc" select="." />
2735       <xsl:apply-templates mode="forward" />
2736     </Ellipse>
2737   </xsl:variable>
2739   <xsl:variable name="clipped_object">
2740     <xsl:apply-templates mode="clip" select="." >
2741       <xsl:with-param name="object" select="$object" />
2742       <xsl:with-param name="clip_type" select="'clip'" />
2743     </xsl:apply-templates>
2744   </xsl:variable>
2746   <xsl:variable name="masked_object">
2747     <xsl:apply-templates mode="clip" select="." >
2748       <xsl:with-param name="object" select="$clipped_object" />
2749       <xsl:with-param name="clip_type" select="'mask'" />
2750     </xsl:apply-templates>
2751   </xsl:variable>
2752   
2753   <xsl:choose>
2754     <xsl:when test="@transform">
2755     <Group>
2756       <xsl:call-template name="object_transform">
2757         <xsl:with-param name="object" select="$masked_object" />
2758         <xsl:with-param name="transform" select="@transform" />
2759       </xsl:call-template>
2760     </Group>
2761     </xsl:when>
2762     <xsl:otherwise>
2763       <xsl:copy-of select="$masked_object" />
2764     </xsl:otherwise>
2765   </xsl:choose>
2766 </xsl:template>
2768 <!-- 
2769   // Circle object //
2770   SVG: circle, FXG: Ellipse
2771 -->
2772 <xsl:template mode="forward" match="*[name(.) = 'circle']">
2773   <xsl:variable name="object">
2774     <Ellipse>
2775       <xsl:variable name="cx">
2776         <xsl:choose>
2777           <xsl:when test="@cx">
2778             <xsl:call-template name="convert_unit">
2779               <xsl:with-param name="convert_value" select="@cx" />
2780             </xsl:call-template>
2781           </xsl:when>
2782           <xsl:otherwise>0</xsl:otherwise>
2783         </xsl:choose>
2784       </xsl:variable>
2785       <xsl:variable name="cy">
2786         <xsl:choose>
2787           <xsl:when test="@cy">
2788             <xsl:call-template name="convert_unit">
2789               <xsl:with-param name="convert_value" select="@cy" />
2790             </xsl:call-template>
2791           </xsl:when>
2792           <xsl:otherwise>0</xsl:otherwise>
2793         </xsl:choose>
2794       </xsl:variable>
2795       <xsl:variable name="r">
2796         <xsl:choose>
2797           <xsl:when test="@r">
2798             <xsl:call-template name="convert_unit">
2799               <xsl:with-param name="convert_value" select="@r" />
2800             </xsl:call-template>
2801           </xsl:when>
2802           <xsl:otherwise>0</xsl:otherwise>
2803         </xsl:choose>
2804       </xsl:variable>
2805       
2806       <xsl:choose>
2807         <xsl:when test="$r != 0">
2808           <xsl:attribute name="x">
2809             <xsl:value-of select='format-number($cx - $r, "#.#")' />
2810           </xsl:attribute>
2811           <xsl:attribute name="y">
2812             <xsl:value-of select='format-number($cy - $r, "#.#")' />
2813           </xsl:attribute>
2814           <xsl:attribute name="width">
2815             <xsl:value-of select='format-number(2 * $r, "#.#")' />
2816           </xsl:attribute>
2817           <xsl:attribute name="height">
2818             <xsl:value-of select='format-number(2 * $r, "#.#")' />
2819           </xsl:attribute>
2820         </xsl:when>
2821         <xsl:otherwise>
2822           <xsl:attribute name="x">
2823             <xsl:value-of select='format-number($cx, "#.#")' />
2824           </xsl:attribute>
2825           <xsl:attribute name="y">
2826             <xsl:value-of select='format-number($cy, "#.#")' />
2827           </xsl:attribute>
2828           <xsl:attribute name="width">0</xsl:attribute>
2829           <xsl:attribute name="height">0</xsl:attribute>
2830         </xsl:otherwise>
2831       </xsl:choose>
2832       <xsl:apply-templates mode="object_opacity" select="." />
2833       <xsl:apply-templates mode="id" select="." />
2835       <!-- Child elements -->
2836       <xsl:apply-templates mode="template_fill" select="." />
2837       <xsl:apply-templates mode="template_stroke" select="." />
2838       <xsl:apply-templates mode="filter_effect" select="." />
2839       <xsl:apply-templates mode="desc" select="." />
2841       <xsl:apply-templates mode="forward" />
2842     </Ellipse>
2843   </xsl:variable>
2845   <xsl:variable name="clipped_object">
2846     <xsl:apply-templates mode="clip" select="." >
2847       <xsl:with-param name="object" select="$object" />
2848       <xsl:with-param name="clip_type" select="'clip'" />
2849     </xsl:apply-templates>
2850   </xsl:variable>
2852   <xsl:variable name="masked_object">
2853     <xsl:apply-templates mode="clip" select="." >
2854       <xsl:with-param name="object" select="$clipped_object" />
2855       <xsl:with-param name="clip_type" select="'mask'" />
2856     </xsl:apply-templates>
2857   </xsl:variable>
2858   
2859   <xsl:choose>
2860     <xsl:when test="@transform">
2861     <Group>
2862       <xsl:call-template name="object_transform">
2863         <xsl:with-param name="object" select="$masked_object" />
2864         <xsl:with-param name="transform" select="@transform" />
2865       </xsl:call-template>
2866     </Group>
2867     </xsl:when>
2868     <xsl:otherwise>
2869       <xsl:copy-of select="$masked_object" />
2870     </xsl:otherwise>
2871   </xsl:choose>
2872 </xsl:template>
2874 <!-- 
2875   // Image objects //
2876   SVG: image, FXG: Rect+BitmapFill
2877   
2878   Not supported by FXG:
2879   * Embedded images (base64).
2880   * Preserve ratio.
2881 -->
2882 <xsl:template mode="forward" match="*[name(.) = 'image']">
2883   <xsl:variable name="object">
2884     <Rect>
2885       <xsl:if test="@x">
2886         <xsl:attribute name="x">
2887           <xsl:call-template name="convert_unit">
2888             <xsl:with-param name="convert_value" select="@x" />
2889           </xsl:call-template>
2890         </xsl:attribute>
2891       </xsl:if>
2892       <xsl:if test="@y">
2893         <xsl:attribute name="y">
2894           <xsl:call-template name="convert_unit">
2895             <xsl:with-param name="convert_value" select="@y" />
2896           </xsl:call-template>
2897         </xsl:attribute>
2898       </xsl:if>
2899       <xsl:if test="@width">
2900         <xsl:attribute name="width">
2901           <xsl:call-template name="convert_unit">
2902             <xsl:with-param name="convert_value" select="@width" />
2903           </xsl:call-template>
2904         </xsl:attribute>
2905       </xsl:if>
2906       <xsl:if test="@height">
2907         <xsl:attribute name="height">
2908           <xsl:call-template name="convert_unit">
2909             <xsl:with-param name="convert_value" select="@height" />
2910           </xsl:call-template>
2911         </xsl:attribute>
2912       </xsl:if>
2913       <xsl:apply-templates mode="object_opacity" select="." />
2914       <xsl:apply-templates mode="id" select="." />
2915       
2916       <xsl:apply-templates mode="desc" select="." />
2917       
2918       <xsl:if test="@xlink:href">
2919         <fill>
2920           <BitmapFill>
2921             <xsl:attribute name="source">@Embed('<xsl:value-of select="@xlink:href"/>')</xsl:attribute>
2922           </BitmapFill>
2923         </fill> 
2924       </xsl:if>
2925       
2926       <xsl:apply-templates mode="forward" />
2927     </Rect>
2928   </xsl:variable>
2930   <xsl:variable name="clipped_object">
2931     <xsl:apply-templates mode="clip" select="." >
2932       <xsl:with-param name="object" select="$object" />
2933       <xsl:with-param name="clip_type" select="'clip'" />
2934     </xsl:apply-templates>
2935   </xsl:variable>
2937   <xsl:variable name="masked_object">
2938     <xsl:apply-templates mode="clip" select="." >
2939       <xsl:with-param name="object" select="$clipped_object" />
2940       <xsl:with-param name="clip_type" select="'mask'" />
2941     </xsl:apply-templates>
2942   </xsl:variable>
2943   
2944   <xsl:choose>
2945     <xsl:when test="@transform">
2946     <Group>
2947       <xsl:call-template name="object_transform">
2948         <xsl:with-param name="object" select="$masked_object" />
2949         <xsl:with-param name="transform" select="@transform" />
2950       </xsl:call-template>
2951     </Group>
2952     </xsl:when>
2953     <xsl:otherwise>
2954       <xsl:copy-of select="$masked_object" />
2955     </xsl:otherwise>
2956   </xsl:choose>
2957 </xsl:template>
2959 <!-- 
2960   // Polygon object //
2961   !! Not supported !!
2962 -->
2963 <xsl:template mode="forward" match="*[name(.) = 'polygon']">
2964   <xsl:comment>FXG does not support polygons</xsl:comment>
2965 </xsl:template>
2967 <!-- 
2968   // Polyline object //
2969   !! Not supported !!
2970 -->
2971 <xsl:template mode="forward" match="*[name(.) = 'polyline']">
2972   <xsl:comment>FXG does not support polylines</xsl:comment>
2973 </xsl:template>
2975 </xsl:stylesheet>