Code

Extensions. Text support improvement in XAML and FXG export.
[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   * Get font size
1741   * Font size
1742   * Font weight
1743   * Font family
1744   * Font style
1745   * Baseline shift
1746   * Line height
1747   * Writing mode
1748   * Text decoration
1749   * Text fill
1750   * Text direction
1751   * Text size
1752   * Text position
1753   * Text object
1754   * FlowRoot object
1755 -->
1757  <!-- 
1758   // Text span //
1759   SVG: tspan, flowSpan, FXG: span
1760   
1761   Not supported in FXG:
1762   * span position
1763 -->
1764 <xsl:template mode="forward" match="*[name(.) = 'tspan'  or name(.) = 'flowSpan']">
1765   <span>
1766     <xsl:if test="../@xml:space='preserve'">
1767       <xsl:attribute name="whiteSpaceCollapse">preserve</xsl:attribute>
1768     </xsl:if>
1769     <xsl:variable name="fill">
1770       <xsl:apply-templates mode="fill" select="." />
1771     </xsl:variable>
1772     <xsl:variable name="fill_opacity">
1773       <xsl:apply-templates mode="fill_opacity" select="." />
1774     </xsl:variable>
1775     <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
1776       <xsl:attribute name="color">
1777         <xsl:call-template name="template_color">
1778           <xsl:with-param name="colorspec">
1779             <xsl:value-of select="$fill" />
1780           </xsl:with-param>
1781         </xsl:call-template>
1782       </xsl:attribute>
1783       <xsl:attribute name="textAlpha">
1784         <xsl:value-of select="$fill_opacity" />
1785       </xsl:attribute>
1786     </xsl:if>
1787     <xsl:apply-templates mode="font_size" select="." />
1788     <xsl:apply-templates mode="font_weight" select="." />
1789     <xsl:apply-templates mode="font_family" select="." />
1790     <xsl:apply-templates mode="font_style" select="." />
1791     <xsl:apply-templates mode="text_fill" select="." />
1792     <xsl:apply-templates mode="text_decoration" select="." />
1793     <xsl:apply-templates mode="line_height" select="." />
1794     <xsl:apply-templates mode="baseline_shift" select="." />
1795     
1796     <xsl:if test="text()">
1797       <xsl:value-of select="text()" />
1798     </xsl:if>
1799   </span>
1800 </xsl:template>
1802  <!-- 
1803   // Text flowPara //
1804   SVG: flowPara, flowDiv FXG: p
1805   
1806   Not supported in FXG:
1807   * paragraph position
1808 -->
1809 <xsl:template mode="forward" match="*[name(.) = 'flowPara' or name(.) = 'flowDiv']">
1810   <p>
1811     <xsl:if test="../@xml:space='preserve'">
1812       <xsl:attribute name="whiteSpaceCollapse">preserve</xsl:attribute>
1813     </xsl:if>
1814     <xsl:variable name="fill">
1815       <xsl:apply-templates mode="fill" select="." />
1816     </xsl:variable>
1817     <xsl:variable name="fill_opacity">
1818       <xsl:apply-templates mode="fill_opacity" select="." />
1819     </xsl:variable>
1820     <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
1821       <xsl:attribute name="color">
1822         <xsl:call-template name="template_color">
1823           <xsl:with-param name="colorspec">
1824             <xsl:value-of select="$fill" />
1825           </xsl:with-param>
1826         </xsl:call-template>
1827       </xsl:attribute>
1828       <xsl:attribute name="textAlpha">
1829         <xsl:value-of select="$fill_opacity" />
1830       </xsl:attribute>
1831     </xsl:if>
1832     <xsl:apply-templates mode="font_size" select="." />
1833     <xsl:apply-templates mode="font_weight" select="." />
1834     <xsl:apply-templates mode="font_family" select="." />
1835     <xsl:apply-templates mode="font_style" select="." />
1836     <xsl:apply-templates mode="text_fill" select="." />
1837     <xsl:apply-templates mode="text_decoration" select="." />
1838     <xsl:apply-templates mode="line_height" select="." />
1839     <xsl:apply-templates mode="baseline_shift" select="." />
1841     <xsl:choose>
1842       <xsl:when test="*[name(.) = 'flowSpan']/text()">
1843         <xsl:apply-templates mode="forward" />
1844       </xsl:when>
1845       <xsl:otherwise>
1846         <xsl:choose>
1847           <xsl:when test="@xml:space='preserve'">
1848             <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
1849           </xsl:when>
1850           <xsl:otherwise>
1851             <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
1852           </xsl:otherwise>
1853         </xsl:choose>  
1854       </xsl:otherwise>
1855     </xsl:choose>
1856   </p>
1857 </xsl:template>
1860  <!-- 
1861   // Text flowRegion //
1862 -->
1863 <xsl:template mode="flow_region" match="*">
1864   <xsl:apply-templates mode="text_size" select="." />
1865   <xsl:apply-templates mode="text_position" select="." />
1866 </xsl:template>
1868 <!-- 
1869   // Get text font size //
1870 -->
1871 <xsl:template mode="get_font_size" match="*">
1872   <xsl:choose>
1873     <xsl:when test="@font-size">
1874       <xsl:value-of select="@font-size" />
1875     </xsl:when>
1876     <xsl:when test="@style and contains(@style, 'font-size:')">
1877       <xsl:variable name="font_size" select="normalize-space(substring-after(@style, 'font-size:'))" />
1878       <xsl:choose>
1879         <xsl:when test="contains($font_size, ';')">
1880           <xsl:value-of select="substring-before($font_size, ';')" />
1881         </xsl:when>
1882         <xsl:otherwise>
1883           <xsl:value-of select="$font_size" />
1884         </xsl:otherwise>
1885       </xsl:choose>
1886     </xsl:when>
1887     <xsl:when test="name(..) = 'g' or name(..) = 'svg'">
1888       <xsl:apply-templates mode="get_font_size" select="parent::*"/>
1889     </xsl:when>
1890   </xsl:choose>
1891 </xsl:template>
1893 <!-- 
1894   // Text font size //
1895   SVG: font-size, FXG: fontSize
1896 -->
1897 <xsl:template mode="font_size" match="*">
1898   <xsl:variable name="value">
1899     <xsl:apply-templates mode="get_font_size" select="." />
1900   </xsl:variable>
1901   <xsl:if test="$value != ''">
1902     <xsl:attribute name="fontSize">
1903       <xsl:call-template name="convert_unit">
1904         <xsl:with-param name="convert_value" select="$value" />
1905       </xsl:call-template>
1906     </xsl:attribute>
1907   </xsl:if>
1908 </xsl:template>
1910 <!-- 
1911   // Text font weight //
1912   SVG: font-weight, FXG: fontWeight
1913 -->
1914 <xsl:template mode="font_weight" match="*">
1915   <xsl:variable name="value">
1916     <xsl:if test="@font-weight">
1917       <xsl:value-of select="@font-weight" />
1918     </xsl:if>
1919     <xsl:if test="@style and contains(@style, 'font-weight:')">
1920       <xsl:variable name="font_weight" select="normalize-space(substring-after(@style, 'font-weight:'))" />
1921       <xsl:choose>
1922         <xsl:when test="contains($font_weight, ';')">
1923           <xsl:value-of select="substring-before($font_weight, ';')" />
1924         </xsl:when>
1925         <xsl:otherwise>
1926           <xsl:value-of select="$font_weight" />
1927         </xsl:otherwise>
1928       </xsl:choose>
1929     </xsl:if>
1930   </xsl:variable>
1931   <xsl:if test="$value != ''">
1932     <xsl:attribute name="fontWeight">
1933       <xsl:choose>
1934         <xsl:when test="$value='normal' or $value='bold'">
1935           <xsl:value-of select="$value" />
1936         </xsl:when>
1937         <xsl:when test="$value &lt; 500 or $value = 'lighter'">normal</xsl:when>
1938         <xsl:when test="$value &gt; 499 or $value = 'bolder'">bold</xsl:when>
1939         <xsl:otherwise>normal</xsl:otherwise>
1940       </xsl:choose>
1941     </xsl:attribute>
1942   </xsl:if>
1943 </xsl:template>
1945 <!-- 
1946   // Text font family //
1947   SVG: font-family, FXG: fontFamily
1948 -->
1949 <xsl:template mode="font_family" match="*">
1950   <xsl:variable name="value">
1951     <xsl:if test="@font-family">
1952       <xsl:value-of select="translate(@font-family, &quot;'&quot;, '')" />
1953     </xsl:if>
1954     <xsl:if test="@style and contains(@style, 'font-family:')">
1955       <xsl:variable name="font_family" select="normalize-space(substring-after(@style, 'font-family:'))" />
1956       <xsl:choose>
1957         <xsl:when test="contains($font_family, ';')">
1958           <xsl:value-of select="translate(substring-before($font_family, ';'), &quot;'&quot;, '')" />
1959         </xsl:when>
1960         <xsl:otherwise>
1961           <xsl:value-of select="translate($font_family, &quot;'&quot;, '')" />
1962         </xsl:otherwise>
1963       </xsl:choose>
1964     </xsl:if>
1965   </xsl:variable>
1966   <xsl:if test="$value != ''">
1967     <xsl:attribute name="fontFamily">
1968       <xsl:choose>
1969         <xsl:when test="$value='Sans'">Arial</xsl:when>
1970         <xsl:otherwise>
1971           <xsl:value-of select="$value" />
1972         </xsl:otherwise>
1973       </xsl:choose>
1974     </xsl:attribute>
1975   </xsl:if>
1976 </xsl:template>
1978 <!-- 
1979   // Text font style //
1980   SVG: font-style, FXG: fontStyle
1981 -->
1982 <xsl:template mode="font_style" match="*">
1983   <xsl:variable name="value">
1984     <xsl:if test="@font-style">
1985       <xsl:value-of select="@font-style" />
1986     </xsl:if>
1987     <xsl:if test="@style and contains(@style, 'font-style:')">
1988       <xsl:variable name="font_style" select="normalize-space(substring-after(@style, 'font-style:'))" />
1989       <xsl:choose>
1990         <xsl:when test="contains($font_style, ';')">
1991           <xsl:value-of select="substring-before($font_style, ';')" />
1992         </xsl:when>
1993         <xsl:otherwise>
1994           <xsl:value-of select="$font_style" />
1995         </xsl:otherwise>
1996       </xsl:choose>
1997     </xsl:if>
1998   </xsl:variable>
1999   <xsl:if test="$value != ''">
2000     <xsl:attribute name="fontStyle">
2001       <xsl:value-of select="$value" />
2002     </xsl:attribute>
2003   </xsl:if>
2004 </xsl:template>
2006 <!-- 
2007   // Text baseline shift //
2008   SVG: baseline-shift, FXG: baselineShift
2009 -->
2010 <xsl:template mode="baseline_shift" match="*">
2011   <xsl:variable name="value">
2012     <xsl:if test="@baseline-shift">
2013       <xsl:value-of select="@baseline-shift" />
2014     </xsl:if>
2015     <xsl:if test="@style and contains(@style, 'baseline-shift:') and not(contains(substring-after(@style, 'baseline-shift:'), ';'))">
2016       <xsl:value-of select="substring-after(@style, 'baseline-shift:')" />
2017     </xsl:if>
2018     <xsl:if test="@style and contains(@style, 'baseline-shift:') and contains(substring-after(@style, 'baseline-shift:'), ';')">
2019       <xsl:value-of select="substring-before(substring-after(@style, 'baseline-shift:'), ';')" />
2020     </xsl:if>   
2021   </xsl:variable>
2022   <xsl:if test="$value != ''">
2023     <xsl:attribute name="baselineShift">  
2024       <xsl:choose>
2025         <xsl:when test="$value='baseline'">0</xsl:when>
2026         <xsl:when test="$value='super'">superscript</xsl:when>
2027         <xsl:when test="$value='sub'">subscript</xsl:when>
2028         <xsl:when test="translate($value, '%', '') &lt; -1000">-1000</xsl:when>
2029         <xsl:when test="translate($value, '%', '') &gt; 1000">1000</xsl:when>
2030         <xsl:otherwise>
2031           <xsl:value-of select="translate($value, '%', '')" />
2032         </xsl:otherwise>
2033       </xsl:choose>  
2034       <xsl:if test="contains($value, '%')">%</xsl:if>
2035     </xsl:attribute>
2036   </xsl:if>
2037 </xsl:template>
2039 <!-- 
2040   // Text line height //
2041   SVG: line-height, FXG: lineHeight
2042 -->
2043 <xsl:template mode="line_height" match="*">
2044   <xsl:variable name="value">
2045     <xsl:if test="@line-height">
2046       <xsl:value-of select="@line-height" />
2047     </xsl:if>
2048     <xsl:if test="@style and contains(@style, 'line-height:')">
2049       <xsl:variable name="line_height" select="normalize-space(substring-after(@style, 'line-height:'))" />
2050       <xsl:choose>
2051         <xsl:when test="contains($line_height, ';')">
2052           <xsl:value-of select="substring-before($line_height, ';')" />
2053         </xsl:when>
2054         <xsl:otherwise>
2055           <xsl:value-of select="$line_height" />
2056         </xsl:otherwise>
2057       </xsl:choose>
2058     </xsl:if>
2059   </xsl:variable>
2060   <xsl:if test="$value != ''">
2061     <xsl:attribute name="lineHeight">
2062       <xsl:call-template name="convert_unit">
2063         <xsl:with-param name="convert_value" select="$value" />
2064       </xsl:call-template>
2065     </xsl:attribute>
2066   </xsl:if>
2067 </xsl:template>
2069 <!-- 
2070   // Text writing mode //
2071   SVG: writing-mode, FXG: blockProgression 
2072   
2073   Values inverted in FXG...
2074 -->
2075 <xsl:template mode="writing_mode" match="*">
2076   <xsl:variable name="value">
2077     <xsl:if test="@writing-mode">
2078       <xsl:value-of select="@writing-mode" />
2079     </xsl:if>
2080     <xsl:if test="@style and contains(@style, 'writing-mode:') and not(contains(substring-after(@style, 'writing-mode:'), ';'))">
2081       <xsl:value-of select="substring-after(@style, 'writing-mode:')" />
2082     </xsl:if>
2083     <xsl:if test="@style and contains(@style, 'writing-mode:') and contains(substring-after(@style, 'writing-mode:'), ';')">
2084       <xsl:value-of select="substring-before(substring-after(@style, 'writing-mode:'), ';')" />
2085     </xsl:if>   
2086   </xsl:variable>
2087   <xsl:if test="$value != ''">
2088     <xsl:attribute name="blockProgression">  
2089       <xsl:choose>
2090         <xsl:when test="$value='tb'">rl</xsl:when>
2091         <xsl:otherwise>tb</xsl:otherwise>
2092       </xsl:choose>  
2093     </xsl:attribute>
2094     <xsl:if test="$value='tb'">
2095       <xsl:attribute name="textRotation">rotate270</xsl:attribute>
2096     </xsl:if>  
2097   </xsl:if>
2098 </xsl:template>
2099   
2100 <!-- 
2101   // Text decoration //
2102   SVG: text-decoration, FXG: textDecoration, lineThrough 
2103 -->
2104 <xsl:template mode="text_decoration" match="*">
2105   <xsl:variable name="value">
2106     <xsl:if test="@text-decoration">
2107       <xsl:value-of select="@text-decoration" />
2108     </xsl:if>
2109     <xsl:if test="@style and contains(@style, 'text-decoration:') and not(contains(substring-after(@style, 'text-decoration:'), ';'))">
2110       <xsl:value-of select="substring-after(@style, 'text-decoration:')" />
2111     </xsl:if>
2112     <xsl:if test="@style and contains(@style, 'text-decoration:') and contains(substring-after(@style, 'text-decoration:'), ';')">
2113       <xsl:value-of select="substring-before(substring-after(@style, 'text-decoration:'), ';')" />
2114     </xsl:if>   
2115   </xsl:variable>
2116   <xsl:if test="$value != ''">  
2117     <xsl:choose>
2118       <xsl:when test="$value='underline'">
2119         <xsl:attribute name="textDecoration">underline</xsl:attribute>
2120       </xsl:when>
2121       <xsl:when test="$value='line-through'">
2122         <xsl:attribute name="lineThrough">true</xsl:attribute>
2123       </xsl:when>
2124     </xsl:choose>  
2125   </xsl:if>
2126 </xsl:template>
2128 <!-- 
2129   // Text fill //
2130   SVG: fill, fill-opacity, FXG: color, textAlpha
2131 -->
2132 <xsl:template mode="text_fill" match="*">
2133   <xsl:variable name="fill">
2134     <xsl:apply-templates mode="fill" select="." />
2135   </xsl:variable>
2136   <xsl:variable name="fill_opacity">
2137     <xsl:apply-templates mode="fill_opacity" select="." />
2138   </xsl:variable>
2139   <xsl:if test="starts-with($fill, '#') or (not(starts-with($fill, 'url')) and $fill != '' and $fill != 'none')">
2140     <xsl:attribute name="color">
2141       <xsl:call-template name="template_color">
2142         <xsl:with-param name="colorspec">
2143           <xsl:value-of select="$fill" />
2144         </xsl:with-param>
2145       </xsl:call-template>
2146     </xsl:attribute>
2147     <xsl:attribute name="textAlpha">
2148       <xsl:value-of select="$fill_opacity" />
2149     </xsl:attribute>
2150   </xsl:if>
2151 </xsl:template>
2153 <!-- 
2154   // Text direction //
2155   SVG: direction, unicode-bidi, FXG: direction
2156 -->
2157 <xsl:template mode="direction" match="*">
2158   <xsl:variable name="value">
2159     <xsl:if test="@direction">
2160       <xsl:value-of select="@direction" />
2161     </xsl:if>
2162     <xsl:if test="@style and contains(@style, 'direction:') and not(contains(substring-after(@style, 'direction:'), ';'))">
2163       <xsl:value-of select="substring-after(@style, 'direction:')" />
2164     </xsl:if>
2165     <xsl:if test="@style and contains(@style, 'direction:') and contains(substring-after(@style, 'direction:'), ';')">
2166       <xsl:value-of select="substring-before(substring-after(@style, 'direction:'), ';')" />
2167     </xsl:if>   
2168   </xsl:variable>
2169   <xsl:variable name="bidi">
2170     <xsl:if test="@unicode-bidi">
2171       <xsl:value-of select="@unicode-bidi" />
2172     </xsl:if>
2173     <xsl:if test="@style and contains(@style, 'unicode-bidi:') and not(contains(substring-after(@style, 'unicode-bidi:'), ';'))">
2174       <xsl:value-of select="substring-after(@style, 'unicode-bidi:')" />
2175     </xsl:if>
2176     <xsl:if test="@style and contains(@style, 'unicode-bidi:') and contains(substring-after(@style, 'unicode-bidi:'), ';')">
2177       <xsl:value-of select="substring-before(substring-after(@style, 'unicode-bidi:'), ';')" />
2178     </xsl:if>   
2179   </xsl:variable>
2181   <xsl:if test="$value != '' and ($bidi='embed' or $bidi='bidi-override')">  
2182     <xsl:attribute name="direction">
2183       <xsl:choose>
2184         <xsl:when test="$value='ltr'">ltr</xsl:when>
2185         <xsl:when test="$value='rtl'">rtl</xsl:when>
2186       </xsl:choose>  
2187     </xsl:attribute>
2188   </xsl:if>
2189 </xsl:template>
2191  <!-- 
2192   // Text size //
2193 -->
2194 <xsl:template mode="text_size" match="*">
2195   <xsl:if test="@width">
2196     <xsl:attribute name="width">
2197       <xsl:call-template name="convert_unit">
2198         <xsl:with-param name="convert_value" select="@width" />
2199       </xsl:call-template>
2200     </xsl:attribute>
2201   </xsl:if>
2202   <xsl:if test="@height">
2203     <xsl:attribute name="height">
2204       <xsl:call-template name="convert_unit">
2205         <xsl:with-param name="convert_value" select="@height" />
2206       </xsl:call-template>
2207     </xsl:attribute>
2208   </xsl:if>
2209 </xsl:template>
2211  <!-- 
2212   // Text position //
2213 -->
2214 <xsl:template mode="text_position" match="*">
2215   <!-- Keep the first x value only -->
2216   <xsl:if test="@x">
2217     <xsl:attribute name="x">
2218       <xsl:choose>
2219         <xsl:when test="contains(@x, ' ')">
2220           <xsl:call-template name="convert_unit">
2221             <xsl:with-param name="convert_value" select="substring-before(@x, ' ')" />
2222           </xsl:call-template>   
2223           </xsl:when>
2224           <xsl:otherwise>
2225           <xsl:call-template name="convert_unit">
2226             <xsl:with-param name="convert_value" select="@x" />
2227           </xsl:call-template>  
2228         </xsl:otherwise>
2229       </xsl:choose>
2230     </xsl:attribute>
2231   </xsl:if>
2232   <!-- Keep the first y value only -->
2233   <xsl:if test="@y">
2234     <xsl:attribute name="y">
2235       <xsl:choose>
2236         <xsl:when test="contains(@y, ' ')">
2237           <xsl:call-template name="convert_unit">
2238             <xsl:with-param name="convert_value" select="substring-before(@y, ' ')" />
2239           </xsl:call-template>   
2240           </xsl:when>
2241           <xsl:otherwise>
2242           <xsl:call-template name="convert_unit">
2243             <xsl:with-param name="convert_value" select="@y" />
2244           </xsl:call-template>  
2245         </xsl:otherwise>
2246       </xsl:choose>
2247     </xsl:attribute>
2248   </xsl:if>
2249 </xsl:template>
2252 <!-- 
2253   // Text objects //
2254   SVG: text, FXG: RichText
2256   Not supported by FXG:
2257   * Generic fonts.
2258   * Embedded fonts (in defs).
2259   * Character rotation.
2260   * Character positionning (x and y).
2261   * Text-anchor.
2262   * Text stroke.
2263   
2264   Partial support:
2265   * Text rotation (0, 90, 180 and 270 degrees only) -> not implemented.
2266   * Font weight (normal and bold only) -> values under 500 are considered normal, the others bold.
2267   * Whitespace handling, issues with xml:whitespace='preserve'.
2268 -->
2269 <xsl:template mode="forward" match="*[name(.) = 'text']">
2270   <xsl:variable name="object">
2271     <RichText>
2272       <!-- Force default baseline to "ascent" -->
2273       <xsl:attribute name="alignmentBaseline">ascent</xsl:attribute>
2274       
2275       <xsl:apply-templates mode="font_size" select="." />
2276       <xsl:apply-templates mode="font_weight" select="." />
2277       <xsl:apply-templates mode="font_family" select="." />
2278       <xsl:apply-templates mode="font_style" select="." />
2279       <xsl:apply-templates mode="text_fill" select="." />
2280       <xsl:apply-templates mode="text_decoration" select="." />
2281       <xsl:apply-templates mode="line_height" select="." />
2282       <xsl:apply-templates mode="text_size" select="." />
2283       <xsl:apply-templates mode="text_position" select="." />
2284       <xsl:apply-templates mode="direction" select="." />
2285       <xsl:apply-templates mode="writing_mode" select="." />
2286       <xsl:apply-templates mode="id" select="." />
2288       <xsl:if test="not(*[name(.) = 'tspan']/text())">
2289         <xsl:attribute name="whiteSpaceCollapse">preserve</xsl:attribute>
2290       </xsl:if>
2291       
2292       <xsl:apply-templates mode="filter_effect" select="." />
2293       <xsl:apply-templates mode="desc" select="." />
2295       <!--xsl:apply-templates mode="forward" /-->
2296       <content>
2297         <xsl:choose>
2298           <xsl:when test="*[name(.) = 'tspan']/text()">
2299             <xsl:apply-templates mode="forward" />
2300           </xsl:when>
2301           <xsl:otherwise>
2302             <xsl:choose>
2303               <xsl:when test="@xml:space='preserve'">
2304                 <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
2305               </xsl:when>
2306               <xsl:otherwise>
2307                 <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
2308               </xsl:otherwise>
2309             </xsl:choose>  
2310           </xsl:otherwise>
2311         </xsl:choose>
2312       </content>
2313     </RichText>
2314   </xsl:variable>
2316   <xsl:variable name="clipped_object">
2317     <xsl:apply-templates mode="clip" select="." >
2318       <xsl:with-param name="object" select="$object" />
2319       <xsl:with-param name="clip_type" select="'clip'" />
2320     </xsl:apply-templates>
2321   </xsl:variable>
2323   <xsl:variable name="masked_object">
2324     <xsl:apply-templates mode="clip" select="." >
2325       <xsl:with-param name="object" select="$clipped_object" />
2326       <xsl:with-param name="clip_type" select="'mask'" />
2327     </xsl:apply-templates>
2328   </xsl:variable>
2329   
2330   <xsl:choose>
2331     <xsl:when test="@transform">
2332     <Group>
2333       <xsl:call-template name="object_transform">
2334         <xsl:with-param name="object" select="$masked_object" />
2335         <xsl:with-param name="transform" select="@transform" />
2336       </xsl:call-template>
2337     </Group>
2338     </xsl:when>
2339     <xsl:otherwise>
2340       <xsl:copy-of select="$masked_object" />
2341     </xsl:otherwise>
2342   </xsl:choose>
2343 </xsl:template>
2344  
2345  <!-- 
2346   // FlowRoot objects //
2347   SVG: flowRoot, FXG: RichText
2349   Not supported by FXG:
2350   * See text objects
2351 -->
2352 <xsl:template mode="forward" match="*[name(.) = 'flowRoot']">
2353   <xsl:variable name="object">
2354     <RichText>
2355       <!-- Force default baseline to "ascent" -->
2356       <xsl:attribute name="alignmentBaseline">ascent</xsl:attribute>
2357       
2358       <xsl:apply-templates mode="font_size" select="." />
2359       <xsl:apply-templates mode="font_weight" select="." />
2360       <xsl:apply-templates mode="font_family" select="." />
2361       <xsl:apply-templates mode="font_style" select="." />
2362       <xsl:apply-templates mode="text_fill" select="." />
2363       <xsl:apply-templates mode="text_decoration" select="." />
2364       <xsl:apply-templates mode="line_height" select="." />
2365       <xsl:apply-templates mode="direction" select="." />
2366       <xsl:apply-templates mode="writing_mode" select="." />
2367       <xsl:apply-templates mode="id" select="." />
2368       <xsl:apply-templates mode="flow_region" select="*[name(.) = 'flowRegion']/child::node()" />
2369       
2370       <xsl:apply-templates mode="filter_effect" select="." />
2371       <xsl:apply-templates mode="desc" select="." />
2373       <content>
2374         <xsl:choose>
2375           <xsl:when test="*[name(.) = 'flowPara' or name(.) = 'flowDiv']/text()">
2376             <xsl:apply-templates mode="forward" />
2377           </xsl:when>
2378           <xsl:otherwise>
2379             <xsl:choose>
2380               <xsl:when test="@xml:space='preserve'">
2381                 <xsl:copy-of select="translate(text(), '&#x9;&#xA;&#xD;', ' ')" />
2382               </xsl:when>
2383               <xsl:otherwise>
2384                 <xsl:copy-of select="normalize-space(translate(text(), '&#x9;&#xA;&#xD;', ' '))" />
2385               </xsl:otherwise>
2386             </xsl:choose>  
2387           </xsl:otherwise>
2388         </xsl:choose>
2389       </content>
2390     </RichText>
2391   </xsl:variable>
2393   <xsl:variable name="clipped_object">
2394     <xsl:apply-templates mode="clip" select="." >
2395       <xsl:with-param name="object" select="$object" />
2396       <xsl:with-param name="clip_type" select="'clip'" />
2397     </xsl:apply-templates>
2398   </xsl:variable>
2400   <xsl:variable name="masked_object">
2401     <xsl:apply-templates mode="clip" select="." >
2402       <xsl:with-param name="object" select="$clipped_object" />
2403       <xsl:with-param name="clip_type" select="'mask'" />
2404     </xsl:apply-templates>
2405   </xsl:variable>
2406   
2407   <xsl:choose>
2408     <xsl:when test="@transform">
2409     <Group>
2410       <xsl:call-template name="object_transform">
2411         <xsl:with-param name="object" select="$masked_object" />
2412         <xsl:with-param name="transform" select="@transform" />
2413       </xsl:call-template>
2414     </Group>
2415     </xsl:when>
2416     <xsl:otherwise>
2417       <xsl:copy-of select="$masked_object" />
2418     </xsl:otherwise>
2419   </xsl:choose>
2420 </xsl:template>
2422 <!-- 
2423   // Shapes //
2424   
2425   * Lines
2426   * Rectangle
2427   * Path
2428   * Ellipse
2429   * Circle
2430   * Image
2431   * Polygon (not supported)
2432   * Polyline (not supported)
2433 -->
2435 <!-- 
2436   // Line object //
2437   SVG: line, FXG: Line
2438 -->
2439 <xsl:template mode="forward" match="*[name(.) = 'line']">
2440   <xsl:variable name="object">
2441     <Line>
2442       <xsl:if test="@x1">
2443         <xsl:attribute name="xFrom">
2444           <xsl:call-template name="convert_unit">
2445             <xsl:with-param name="convert_value" select="@x1" />
2446           </xsl:call-template>
2447         </xsl:attribute>
2448       </xsl:if>
2449       <xsl:if test="@y1">
2450         <xsl:attribute name="yFrom">
2451           <xsl:call-template name="convert_unit">
2452             <xsl:with-param name="convert_value" select="@y1" />
2453           </xsl:call-template>
2454         </xsl:attribute>
2455       </xsl:if>
2456       <xsl:if test="@x2">
2457         <xsl:attribute name="xTo">
2458           <xsl:call-template name="convert_unit">
2459             <xsl:with-param name="convert_value" select="@x2" />
2460           </xsl:call-template>
2461         </xsl:attribute>
2462       </xsl:if>
2463       <xsl:if test="@y2">
2464         <xsl:attribute name="yTo">
2465           <xsl:call-template name="convert_unit">
2466             <xsl:with-param name="convert_value" select="@y2" />
2467           </xsl:call-template>
2468         </xsl:attribute>
2469       </xsl:if>
2470       <xsl:apply-templates mode="object_opacity" select="." />
2471       <xsl:apply-templates mode="id" select="." />
2473       <xsl:apply-templates mode="template_fill" select="." />
2474       <xsl:apply-templates mode="template_stroke" select="." />
2475       <xsl:apply-templates mode="filter_effect" select="." />
2476       <xsl:apply-templates mode="desc" select="." />   
2478       <xsl:apply-templates mode="forward" />
2479     </Line>
2480   </xsl:variable>
2482   <xsl:variable name="clipped_object">
2483     <xsl:apply-templates mode="clip" select="." >
2484       <xsl:with-param name="object" select="$object" />
2485       <xsl:with-param name="clip_type" select="'clip'" />
2486     </xsl:apply-templates>
2487   </xsl:variable>
2489   <xsl:variable name="masked_object">
2490     <xsl:apply-templates mode="clip" select="." >
2491       <xsl:with-param name="object" select="$clipped_object" />
2492       <xsl:with-param name="clip_type" select="'mask'" />
2493     </xsl:apply-templates>
2494   </xsl:variable>
2495   
2496   <xsl:choose>
2497     <xsl:when test="@transform">
2498     <Group>
2499       <xsl:call-template name="object_transform">
2500         <xsl:with-param name="object" select="$masked_object" />
2501         <xsl:with-param name="transform" select="@transform" />
2502       </xsl:call-template>
2503     </Group>
2504     </xsl:when>
2505     <xsl:otherwise>
2506       <xsl:copy-of select="$masked_object" />
2507     </xsl:otherwise>
2508   </xsl:choose>
2509 </xsl:template>
2511 <!-- 
2512   // Rectangle object //
2513   SVG: rect, FXG: Rect
2514 -->
2515 <xsl:template mode="forward" match="*[name(.) = 'rect']">
2516   <xsl:variable name="object">
2517     <Rect>
2518       <xsl:if test="@x">
2519         <xsl:attribute name="x">
2520           <xsl:call-template name="convert_unit">
2521             <xsl:with-param name="convert_value" select="@x" />
2522           </xsl:call-template>
2523         </xsl:attribute>
2524       </xsl:if>
2525       <xsl:if test="@y">
2526         <xsl:attribute name="y">
2527           <xsl:call-template name="convert_unit">
2528             <xsl:with-param name="convert_value" select="@y" />
2529           </xsl:call-template>
2530         </xsl:attribute>
2531       </xsl:if>
2532       <xsl:if test="@width">
2533         <xsl:attribute name="width">
2534           <xsl:call-template name="convert_unit">
2535             <xsl:with-param name="convert_value" select="@width" />
2536           </xsl:call-template>
2537         </xsl:attribute>
2538       </xsl:if>
2539       <xsl:if test="@height">
2540         <xsl:attribute name="height">
2541           <xsl:call-template name="convert_unit">
2542             <xsl:with-param name="convert_value" select="@height" />
2543           </xsl:call-template>
2544         </xsl:attribute>
2545       </xsl:if>
2546       <xsl:if test="@rx">
2547         <xsl:attribute name="radiusX">
2548           <xsl:value-of select="@rx" />
2549         </xsl:attribute>
2550       </xsl:if>
2551       <xsl:if test="@ry">
2552         <xsl:attribute name="radiusY">
2553           <xsl:value-of select="@ry" />
2554         </xsl:attribute>
2555       </xsl:if>
2556       <xsl:if test="@rx and not(@ry)">
2557         <xsl:attribute name="radiusX">
2558           <xsl:value-of select="@rx" />
2559         </xsl:attribute>
2560         <xsl:attribute name="radiusY">
2561           <xsl:value-of select="@rx" />
2562         </xsl:attribute>
2563       </xsl:if>
2564       <xsl:if test="@ry and not(@rx)">
2565         <xsl:attribute name="radiusX">
2566           <xsl:value-of select="@ry" />
2567         </xsl:attribute>
2568         <xsl:attribute name="radiusY">
2569           <xsl:value-of select="@ry" />
2570         </xsl:attribute>
2571       </xsl:if>
2572       <xsl:apply-templates mode="object_opacity" select="." />
2573       <xsl:apply-templates mode="id" select="." />
2575       <xsl:apply-templates mode="template_fill" select="." />
2576       <xsl:apply-templates mode="template_stroke" select="." />
2577       <xsl:apply-templates mode="filter_effect" select="." />
2578       <!--  <xsl:apply-templates mode="resources" select="." /> -->
2579       <xsl:apply-templates mode="desc" select="." />
2581       <xsl:apply-templates mode="forward" />
2582     </Rect>
2583   </xsl:variable>
2585   <xsl:variable name="clipped_object">
2586     <xsl:apply-templates mode="clip" select="." >
2587       <xsl:with-param name="object" select="$object" />
2588       <xsl:with-param name="clip_type" select="'clip'" />
2589     </xsl:apply-templates>
2590   </xsl:variable>
2592   <xsl:variable name="masked_object">
2593     <xsl:apply-templates mode="clip" select="." >
2594       <xsl:with-param name="object" select="$clipped_object" />
2595       <xsl:with-param name="clip_type" select="'mask'" />
2596     </xsl:apply-templates>
2597   </xsl:variable>
2598   
2599   <xsl:choose>
2600     <xsl:when test="@transform">
2601     <Group>
2602       <xsl:call-template name="object_transform">
2603         <xsl:with-param name="object" select="$masked_object" />
2604         <xsl:with-param name="transform" select="@transform" />
2605       </xsl:call-template>
2606     </Group>
2607     </xsl:when>
2608     <xsl:otherwise>
2609       <xsl:copy-of select="$masked_object" />
2610     </xsl:otherwise>
2611   </xsl:choose>
2612 </xsl:template>
2614 <!-- 
2615   // Path //
2616   SVG: path, FXG: Path
2617   
2618   Not supported by FXG:
2619   * elliptical arc curve commands (workaround: convert to path first)
2620   TODO:
2621   * Implement an arc to curve convertor
2622 -->
2623 <xsl:template mode="forward" match="*[name(.) = 'path']">
2624   <xsl:variable name="object">
2625     <Path>
2626       <!-- Path element -->
2627       <!-- Exclude arcs in order to prevent the mxml compiler from failing -->
2628       <xsl:if test="@d and not(contains(@d, 'a') or contains(@d, 'A'))">
2629         <xsl:attribute name="data">
2630           <xsl:value-of select="normalize-space(translate(@d , ',', ' '))" />
2631         </xsl:attribute>
2632       </xsl:if>
2633       <xsl:apply-templates mode="fill_rule" select="." />
2634       <xsl:apply-templates mode="object_opacity" select="." />
2635       <xsl:apply-templates mode="id" select="." />
2637       <!-- Child elements -->
2638       <xsl:apply-templates mode="template_fill" select="." />
2639       <xsl:apply-templates mode="template_stroke" select="." />
2640       <xsl:apply-templates mode="filter_effect" select="." />
2641       <xsl:apply-templates mode="desc" select="." />
2643       <xsl:apply-templates mode="forward" />
2644     </Path>
2645   </xsl:variable>
2646   
2647   <xsl:variable name="clipped_object">
2648     <xsl:apply-templates mode="clip" select="." >
2649       <xsl:with-param name="object" select="$object" />
2650       <xsl:with-param name="clip_type" select="'clip'" />
2651     </xsl:apply-templates>
2652   </xsl:variable>
2654   <xsl:variable name="masked_object">
2655     <xsl:apply-templates mode="clip" select="." >
2656       <xsl:with-param name="object" select="$clipped_object" />
2657       <xsl:with-param name="clip_type" select="'mask'" />
2658     </xsl:apply-templates>
2659   </xsl:variable>
2660   
2661   <xsl:choose>
2662     <xsl:when test="@transform">
2663     <Group>
2664       <xsl:call-template name="object_transform">
2665         <xsl:with-param name="object" select="$masked_object" />
2666         <xsl:with-param name="transform" select="@transform" />
2667       </xsl:call-template>
2668     </Group>
2669     </xsl:when>
2670     <xsl:otherwise>
2671       <xsl:copy-of select="$masked_object" />
2672     </xsl:otherwise>
2673   </xsl:choose>
2674   <xsl:if test="contains(@d, 'a') or contains(@d, 'A')">
2675     <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>
2676   </xsl:if> 
2677 </xsl:template>
2679 <!-- 
2680   // Ellipse object //
2681   SVG: ellipse, FXG: Ellipse
2682 -->
2683 <xsl:template mode="forward" match="*[name(.) = 'ellipse']">
2684   <xsl:variable name="object">
2685     <Ellipse>
2686       <xsl:variable name="cx">
2687         <xsl:choose>
2688           <xsl:when test="@cx">
2689             <xsl:call-template name="convert_unit">
2690               <xsl:with-param name="convert_value" select="@cx" />
2691             </xsl:call-template>
2692           </xsl:when>
2693           <xsl:otherwise>0</xsl:otherwise>
2694         </xsl:choose>
2695       </xsl:variable>
2696       <xsl:variable name="cy">
2697         <xsl:choose>
2698           <xsl:when test="@cy">
2699             <xsl:call-template name="convert_unit">
2700               <xsl:with-param name="convert_value" select="@cy" />
2701             </xsl:call-template>
2702           </xsl:when>
2703           <xsl:otherwise>0</xsl:otherwise>
2704         </xsl:choose>
2705       </xsl:variable>
2706       <xsl:variable name="rx">
2707         <xsl:choose>
2708           <xsl:when test="@rx">
2709             <xsl:call-template name="convert_unit">
2710               <xsl:with-param name="convert_value" select="@rx" />
2711             </xsl:call-template>
2712           </xsl:when>
2713           <xsl:otherwise>0</xsl:otherwise>
2714         </xsl:choose>
2715       </xsl:variable>
2716       <xsl:variable name="ry">
2717         <xsl:choose>
2718           <xsl:when test="@ry">
2719             <xsl:call-template name="convert_unit">
2720               <xsl:with-param name="convert_value" select="@ry" />
2721             </xsl:call-template>
2722           </xsl:when>
2723           <xsl:otherwise>0</xsl:otherwise>
2724         </xsl:choose>
2725       </xsl:variable>
2727       <xsl:choose>
2728         <xsl:when test="$rx != 0">
2729           <xsl:attribute name="x">
2730             <xsl:value-of select='format-number($cx - $rx, "#.#")' />
2731           </xsl:attribute>
2732           <xsl:attribute name="width">
2733             <xsl:value-of select='format-number(2 * $rx, "#.#")' />
2734           </xsl:attribute>
2735         </xsl:when>
2736         <xsl:otherwise>
2737           <xsl:attribute name="x">
2738             <xsl:value-of select='format-number($cx, "#.#")' />
2739           </xsl:attribute>
2740           <xsl:attribute name="width">0</xsl:attribute>
2741         </xsl:otherwise>
2742       </xsl:choose>
2743       <xsl:choose>
2744         <xsl:when test="$ry != 0">
2745           <xsl:attribute name="y">
2746             <xsl:value-of select='format-number($cy - $ry, "#.#")' />
2747           </xsl:attribute>
2748           <xsl:attribute name="height">
2749             <xsl:value-of select='format-number(2 * $ry, "#.#")' />
2750           </xsl:attribute>
2751         </xsl:when>
2752         <xsl:otherwise>
2753           <xsl:attribute name="y">
2754             <xsl:value-of select='format-number($cy, "#.#")' />
2755           </xsl:attribute>
2756           <xsl:attribute name="height">0</xsl:attribute>
2757         </xsl:otherwise>
2758       </xsl:choose>
2759       <xsl:apply-templates mode="object_opacity" select="." />
2760       <xsl:apply-templates mode="id" select="." />
2762       <!-- Child elements -->
2763       <xsl:apply-templates mode="template_fill" select="." />
2764       <xsl:apply-templates mode="template_stroke" select="." />
2765       <xsl:apply-templates mode="filter_effect" select="." />
2766       <xsl:apply-templates mode="desc" select="." />
2768       <xsl:apply-templates mode="forward" />
2769     </Ellipse>
2770   </xsl:variable>
2772   <xsl:variable name="clipped_object">
2773     <xsl:apply-templates mode="clip" select="." >
2774       <xsl:with-param name="object" select="$object" />
2775       <xsl:with-param name="clip_type" select="'clip'" />
2776     </xsl:apply-templates>
2777   </xsl:variable>
2779   <xsl:variable name="masked_object">
2780     <xsl:apply-templates mode="clip" select="." >
2781       <xsl:with-param name="object" select="$clipped_object" />
2782       <xsl:with-param name="clip_type" select="'mask'" />
2783     </xsl:apply-templates>
2784   </xsl:variable>
2785   
2786   <xsl:choose>
2787     <xsl:when test="@transform">
2788     <Group>
2789       <xsl:call-template name="object_transform">
2790         <xsl:with-param name="object" select="$masked_object" />
2791         <xsl:with-param name="transform" select="@transform" />
2792       </xsl:call-template>
2793     </Group>
2794     </xsl:when>
2795     <xsl:otherwise>
2796       <xsl:copy-of select="$masked_object" />
2797     </xsl:otherwise>
2798   </xsl:choose>
2799 </xsl:template>
2801 <!-- 
2802   // Circle object //
2803   SVG: circle, FXG: Ellipse
2804 -->
2805 <xsl:template mode="forward" match="*[name(.) = 'circle']">
2806   <xsl:variable name="object">
2807     <Ellipse>
2808       <xsl:variable name="cx">
2809         <xsl:choose>
2810           <xsl:when test="@cx">
2811             <xsl:call-template name="convert_unit">
2812               <xsl:with-param name="convert_value" select="@cx" />
2813             </xsl:call-template>
2814           </xsl:when>
2815           <xsl:otherwise>0</xsl:otherwise>
2816         </xsl:choose>
2817       </xsl:variable>
2818       <xsl:variable name="cy">
2819         <xsl:choose>
2820           <xsl:when test="@cy">
2821             <xsl:call-template name="convert_unit">
2822               <xsl:with-param name="convert_value" select="@cy" />
2823             </xsl:call-template>
2824           </xsl:when>
2825           <xsl:otherwise>0</xsl:otherwise>
2826         </xsl:choose>
2827       </xsl:variable>
2828       <xsl:variable name="r">
2829         <xsl:choose>
2830           <xsl:when test="@r">
2831             <xsl:call-template name="convert_unit">
2832               <xsl:with-param name="convert_value" select="@r" />
2833             </xsl:call-template>
2834           </xsl:when>
2835           <xsl:otherwise>0</xsl:otherwise>
2836         </xsl:choose>
2837       </xsl:variable>
2838       
2839       <xsl:choose>
2840         <xsl:when test="$r != 0">
2841           <xsl:attribute name="x">
2842             <xsl:value-of select='format-number($cx - $r, "#.#")' />
2843           </xsl:attribute>
2844           <xsl:attribute name="y">
2845             <xsl:value-of select='format-number($cy - $r, "#.#")' />
2846           </xsl:attribute>
2847           <xsl:attribute name="width">
2848             <xsl:value-of select='format-number(2 * $r, "#.#")' />
2849           </xsl:attribute>
2850           <xsl:attribute name="height">
2851             <xsl:value-of select='format-number(2 * $r, "#.#")' />
2852           </xsl:attribute>
2853         </xsl:when>
2854         <xsl:otherwise>
2855           <xsl:attribute name="x">
2856             <xsl:value-of select='format-number($cx, "#.#")' />
2857           </xsl:attribute>
2858           <xsl:attribute name="y">
2859             <xsl:value-of select='format-number($cy, "#.#")' />
2860           </xsl:attribute>
2861           <xsl:attribute name="width">0</xsl:attribute>
2862           <xsl:attribute name="height">0</xsl:attribute>
2863         </xsl:otherwise>
2864       </xsl:choose>
2865       <xsl:apply-templates mode="object_opacity" select="." />
2866       <xsl:apply-templates mode="id" select="." />
2868       <!-- Child elements -->
2869       <xsl:apply-templates mode="template_fill" select="." />
2870       <xsl:apply-templates mode="template_stroke" select="." />
2871       <xsl:apply-templates mode="filter_effect" select="." />
2872       <xsl:apply-templates mode="desc" select="." />
2874       <xsl:apply-templates mode="forward" />
2875     </Ellipse>
2876   </xsl:variable>
2878   <xsl:variable name="clipped_object">
2879     <xsl:apply-templates mode="clip" select="." >
2880       <xsl:with-param name="object" select="$object" />
2881       <xsl:with-param name="clip_type" select="'clip'" />
2882     </xsl:apply-templates>
2883   </xsl:variable>
2885   <xsl:variable name="masked_object">
2886     <xsl:apply-templates mode="clip" select="." >
2887       <xsl:with-param name="object" select="$clipped_object" />
2888       <xsl:with-param name="clip_type" select="'mask'" />
2889     </xsl:apply-templates>
2890   </xsl:variable>
2891   
2892   <xsl:choose>
2893     <xsl:when test="@transform">
2894     <Group>
2895       <xsl:call-template name="object_transform">
2896         <xsl:with-param name="object" select="$masked_object" />
2897         <xsl:with-param name="transform" select="@transform" />
2898       </xsl:call-template>
2899     </Group>
2900     </xsl:when>
2901     <xsl:otherwise>
2902       <xsl:copy-of select="$masked_object" />
2903     </xsl:otherwise>
2904   </xsl:choose>
2905 </xsl:template>
2907 <!-- 
2908   // Image objects //
2909   SVG: image, FXG: Rect+BitmapFill
2910   
2911   Not supported by FXG:
2912   * Embedded images (base64).
2913   * Preserve ratio.
2914 -->
2915 <xsl:template mode="forward" match="*[name(.) = 'image']">
2916   <xsl:variable name="object">
2917     <Rect>
2918       <xsl:if test="@x">
2919         <xsl:attribute name="x">
2920           <xsl:call-template name="convert_unit">
2921             <xsl:with-param name="convert_value" select="@x" />
2922           </xsl:call-template>
2923         </xsl:attribute>
2924       </xsl:if>
2925       <xsl:if test="@y">
2926         <xsl:attribute name="y">
2927           <xsl:call-template name="convert_unit">
2928             <xsl:with-param name="convert_value" select="@y" />
2929           </xsl:call-template>
2930         </xsl:attribute>
2931       </xsl:if>
2932       <xsl:if test="@width">
2933         <xsl:attribute name="width">
2934           <xsl:call-template name="convert_unit">
2935             <xsl:with-param name="convert_value" select="@width" />
2936           </xsl:call-template>
2937         </xsl:attribute>
2938       </xsl:if>
2939       <xsl:if test="@height">
2940         <xsl:attribute name="height">
2941           <xsl:call-template name="convert_unit">
2942             <xsl:with-param name="convert_value" select="@height" />
2943           </xsl:call-template>
2944         </xsl:attribute>
2945       </xsl:if>
2946       <xsl:apply-templates mode="object_opacity" select="." />
2947       <xsl:apply-templates mode="id" select="." />
2948       
2949       <xsl:apply-templates mode="desc" select="." />
2950       
2951       <xsl:if test="@xlink:href">
2952         <fill>
2953           <BitmapFill>
2954             <xsl:attribute name="source">@Embed('<xsl:value-of select="@xlink:href"/>')</xsl:attribute>
2955           </BitmapFill>
2956         </fill> 
2957       </xsl:if>
2958       
2959       <xsl:apply-templates mode="forward" />
2960     </Rect>
2961   </xsl:variable>
2963   <xsl:variable name="clipped_object">
2964     <xsl:apply-templates mode="clip" select="." >
2965       <xsl:with-param name="object" select="$object" />
2966       <xsl:with-param name="clip_type" select="'clip'" />
2967     </xsl:apply-templates>
2968   </xsl:variable>
2970   <xsl:variable name="masked_object">
2971     <xsl:apply-templates mode="clip" select="." >
2972       <xsl:with-param name="object" select="$clipped_object" />
2973       <xsl:with-param name="clip_type" select="'mask'" />
2974     </xsl:apply-templates>
2975   </xsl:variable>
2976   
2977   <xsl:choose>
2978     <xsl:when test="@transform">
2979     <Group>
2980       <xsl:call-template name="object_transform">
2981         <xsl:with-param name="object" select="$masked_object" />
2982         <xsl:with-param name="transform" select="@transform" />
2983       </xsl:call-template>
2984     </Group>
2985     </xsl:when>
2986     <xsl:otherwise>
2987       <xsl:copy-of select="$masked_object" />
2988     </xsl:otherwise>
2989   </xsl:choose>
2990 </xsl:template>
2992 <!-- 
2993   // Polygon object //
2994   !! Not supported !!
2995 -->
2996 <xsl:template mode="forward" match="*[name(.) = 'polygon']">
2997   <xsl:comment>FXG does not support polygons</xsl:comment>
2998 </xsl:template>
3000 <!-- 
3001   // Polyline object //
3002   !! Not supported !!
3003 -->
3004 <xsl:template mode="forward" match="*[name(.) = 'polyline']">
3005   <xsl:comment>FXG does not support polylines</xsl:comment>
3006 </xsl:template>
3008 </xsl:stylesheet>