SVG Import
Contents
Extension Inkscape d'export SIF
Cette extension pour Inkscape convertit les fichiers SVG au format Synfig Studio (.sif) et c'est la méthode recommandée pour cela. Cette extension peut être trouvée dans la section téléchargement de Scripts & Tools.
Import direct de fichier SVG dans Synfig Studio
Depuis la dernière version de Synfig (au moins la 0.62.02) il y a une option pour l'import SVG dans le menu du canevas Fichier -> Importer. Cela semble mieux fonctionner que les options décrites ci-après, toutefois il peut y avoir des problèmes à importer certain élément SVG. Allez voir ce sujet sur les forums pour avoir des conseils.
- Le premier import peut échouer, essayer d'importer le même fichier plusieurs fois.
- 0.62.02 semble mieux fonctionner sous Ubuntu que la version 0.63.00
Autres méthodes
Ce qui suit présente des méthodes anciennes ou spéciales pour les experts.
Méthode 1
Cette méthode utilise les feuilles de style XSLT 2.0 pour transformer le XML SVG en XML Synfig.
But
Transformer une image SVG en un fichier Synfig pour l'importer. Premier post dans les forums : http://synfig.org/forums/viewtopic.php?t=30
Prérequis
- Vérifiez que l'environnement Java runtime est installé.
- Récupérez une version récente du processeur SAXON XSLT pour Java à http://saxon.sourceforge.net/. La version recommandée est : Saxon-SA 9.0 (saxonsa9-0-0-2j.zip).
- Décompressez le paquet SAXON dans le répertoire de votre choix. En exemple, nous utiliserons d:\saxon pour la suite. Le répertoire devrait contenir un certain nombre de fichiers JAR.
- Créez le fichier d:\saxon\svg2synfig.xsl avec le contenu fourni plus loin de ce document ([[#svg2synfig.xsl|]]).
Traduction en cours
Méthode optionnelle pour Windows
Si vous ne voulez pas utiliser la ligne de commande, créez un fichier batch d:\saxon\svg2synfig.bat contenant :
@java -jar %0\..\saxon9.jar -xsl:%0\..\svg2synfig.xsl %1 > %0\..\synfig.sif @pause
Transformer un SVG en un fichier Synfig
Avec un fichier batch windows
- Il suffit de faire glisser le fichier SVG sur svg2synfig.bat.
Avec la ligne de commande
- Changez de répertoire vers d:\saxon
- Tapez la commande suivante (remplacez your_input.svg par le chemin vers votre fichier SVG) :
java -jar saxon9.jar -xsl:svg2synfig.xsl your_input.svg > synfig.sif
Result
If the conversion has been successful, the result will be written to the file d:\saxon\synfig.sif. You can open this file in Synfig.
Limitations
- Doesn't seem to work with SaxonB (FOSS version)
- Compressed SVG (svgz) must be uncompressed first.
- Only SVG path objects are supported. Try converting all objects to paths.
- Only a subset of path elements is supported. Try to modify all path nodes to have split tangents, and all path segments to be curves.
- Sophisticated coloring (e. g. gradients) is not supported.
- Only basic transformations are supported.
- Fill and outline on the same object is not supported.
svg2synfig.xsl
<xsl:stylesheet version="2.0" exclude-result-prefixes="#all" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://exslt.org/math"> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="svg:svg"> <xsl:variable name="width" select="math:units_to_px(@width)"/> <xsl:variable name="height" select="math:units_to_px(@height)"/> <xsl:variable name="has_view_box" select="matches(@viewBox, '(\d+\s){3}\d+')"/> <canvas version="0.2" id="{@id}" width="{if ($has_view_box) then replace(@viewBox, '(\d+)\s(\d+)\s(\d+)\s(\d+)', '$3') else $width}" height="{if ($has_view_box) then replace(@viewBox, '(\d+)\s(\d+)\s(\d+)\s(\d+)', '$4') else $height}" view-box="{if ($has_view_box) then @viewBox else concat('0 0 ', $width, ' ', $height)}"> <xsl:apply-templates select="svg:g|svg:svg|svg:path"/> </canvas> </xsl:template> <xsl:template match="svg:g"> <layer type="PasteCanvas" active="true" version="0.1" desc="{@id}"> <param name="canvas"> <canvas> <xsl:apply-templates/> </canvas> </param> </layer> </xsl:template> <xsl:template match="svg:path"> <xsl:variable name="style"> <xsl:for-each select="ancestor-or-self::*"> <xsl:sort select="position()" data-type="number" order="descending"/> <xsl:value-of select="concat(@style, ';fill:', @fill, ';stroke:', @stroke, ';stroke-width:', @stroke-width, ';')"/> </xsl:for-each> </xsl:variable> <xsl:variable name="self" select="."/> <xsl:variable name="is_fill" select="not(matches(replace($style, 'fill:[^n;][^o].*', ''), 'fill:none'))"/> <xsl:analyze-string select="@d" regex="m[^z]+(z|$)" flags="i"> <xsl:matching-substring> <layer type="{if ($is_fill) then 'region' else 'outline'}" version="0.1" desc="{$self/@id}"> <xsl:call-template name="style-to-color"> <xsl:with-param name="style" select="replace(replace($style, ':none.*', ''), if ($is_fill) then '.*fill:([^;]+).*' else '.*stroke:([^;]+).*', '$1')"/> </xsl:call-template> <xsl:if test="not ($is_fill)"> <xsl:call-template name="style-to-width"> <xsl:with-param name="style" select="replace($style, '.*stroke-width:([^;]+).*', '$1')"/> </xsl:call-template> </xsl:if> <param name="bline"> <bline type="bline_point" loop="{matches(., 'z', 'i')}"> <xsl:call-template name="path-to-bline"> <xsl:with-param name="path" select="."/> <xsl:with-param name="node" select="$self" tunnel="yes"/> </xsl:call-template> </bline> </param> </layer> </xsl:matching-substring> </xsl:analyze-string> </xsl:template> <xsl:template name="path-to-bline"> <xsl:param name="path"/> <xsl:variable name="stripped" select="replace(replace(translate($path, ',', ' '), '(\d)-', '$1 -'), '\s*([a-z]+)\s*', '$1', 'i')"/> <xsl:variable name="closed" select="if (matches($stripped, 'z', 'i')) then $stripped else replace($stripped, 'm([-\d.]+\s[-\d.]+).*$', '$0l$1z', 'i')"/> <xsl:variable name="tmp" select="replace($closed, '([-\d.]+\s[-\d.]+)l([-\d.]+\s[-\d.]+)', '$1c$1 $2 $2', 'i')"/> <xsl:variable name="curve" select="replace($tmp, '([-\d.]+\s[-\d.]+)l([-\d.]+\s[-\d.]+)', '$1c$1 $2 $2', 'i')"/> <xsl:analyze-string select="$curve" regex="\s([-\d.]+\s[-\d.]+)\s[-\d.]+\s[-\d.]+z" flags="i"> <xsl:matching-substring> <xsl:analyze-string select="concat(regex-group(1), $curve)" regex="([-\d.]+)\s([-\d.]+)[m\s]([-\d.]+)\s([-\d.]+)c([-\d.]+)\s([-\d.]+)" flags="i"> <xsl:matching-substring> <xsl:call-template name="node-to-bline-point"> <xsl:with-param name="c1_x" select="regex-group(1)"/> <xsl:with-param name="c1_y" select="regex-group(2)"/> <xsl:with-param name="x" select="regex-group(3)"/> <xsl:with-param name="y" select="regex-group(4)"/> <xsl:with-param name="c2_x" select="regex-group(5)"/> <xsl:with-param name="c2_y" select="regex-group(6)"/> </xsl:call-template> </xsl:matching-substring> </xsl:analyze-string> </xsl:matching-substring> </xsl:analyze-string> </xsl:template> <xsl:template name="node-to-bline-point"> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:param name="c1_x"/> <xsl:param name="c1_y"/> <xsl:param name="c2_x"/> <xsl:param name="c2_y"/> <xsl:param name="node" tunnel="yes"/> <xsl:variable name="transform"> <xsl:for-each select="$node/ancestor-or-self::*/@transform"> <xsl:value-of select="."/> </xsl:for-each> </xsl:variable> <xsl:variable name="t" select="math:resolve_transform($transform)"/> <xsl:variable name="transformed_x" select="$t[5] + $t[1] * xs:float($x) + $t[3] * xs:float($y)"/> <xsl:variable name="transformed_y" select="$t[6] + $t[2] * xs:float($x) + $t[4] * xs:float($y)"/> <xsl:variable name="transformed_c1_x" select="$t[5] + $t[1] * xs:float($c1_x) + $t[3] * xs:float($c1_y)"/> <xsl:variable name="transformed_c1_y" select="$t[6]+ $t[2] * xs:float($c1_x) + $t[4] * xs:float($c1_y)"/> <xsl:variable name="transformed_c2_x" select="$t[5] + $t[1] * xs:float($c2_x) + $t[3] * xs:float($c2_y)"/> <xsl:variable name="transformed_c2_y" select="$t[6]+ $t[2] * xs:float($c2_x) + $t[4] * xs:float($c2_y)"/> <entry> <composite type="bline_point"> <point> <vector> <x><xsl:value-of select="$transformed_x"/></x> <y><xsl:value-of select="$transformed_y"/></y> </vector> </point> <width> <real value="1"/> </width> <origin> <real value="0.5"/> </origin> <split> <bool value="true"/> </split> <t1> <xsl:call-template name="vector-pair-to-radial"> <xsl:with-param name="origin-x" select="$transformed_c1_x"/> <xsl:with-param name="origin-y" select="$transformed_c1_y"/> <xsl:with-param name="x" select="$transformed_x"/> <xsl:with-param name="y" select="$transformed_y"/> </xsl:call-template> </t1> <t2> <xsl:call-template name="vector-pair-to-radial"> <xsl:with-param name="origin-x" select="$transformed_x"/> <xsl:with-param name="origin-y" select="$transformed_y"/> <xsl:with-param name="x" select="$transformed_c2_x"/> <xsl:with-param name="y" select="$transformed_c2_y"/> </xsl:call-template> </t2> </composite> </entry> </xsl:template> <xsl:template name="vector-pair-to-radial"> <xsl:param name="x"/> <xsl:param name="y"/> <xsl:param name="origin-x"/> <xsl:param name="origin-y"/> <xsl:variable name="dx" select="xs:float($x) - xs:float($origin-x)"/> <xsl:variable name="dy" select="xs:float($y) - xs:float($origin-y)"/> <xsl:variable name="d" select="math:sqrt($dx * $dx + $dy * $dy)"/> <xsl:variable name="angle" select="math:atan2($dy, $dx)"/> <radial_composite type="vector"> <radius> <real value="{$d * 3}"/> </radius> <theta> <angle value="{$angle * 57.295779513082320876798154814105}"/> </theta> </radial_composite> </xsl:template> <xsl:template name="style-to-width"> <xsl:param name="style"/> <xsl:if test="matches($style, '^\d')"> <param name="width"> <real value="{math:units_to_px($style)}"/> </param> </xsl:if> </xsl:template> <xsl:template name="style-to-color"> <xsl:param name="style"/> <xsl:if test="matches($style, '#')"> <xsl:analyze-string select="concat($style, ';')" regex="#([\da-f]{{2}})([\da-f]{{2}})([\da-f]{{2}});"> <xsl:matching-substring> <param name="color"> <color> <r><xsl:value-of select="math:hex_to_color(regex-group(1))"/></r> <g><xsl:value-of select="math:hex_to_color(regex-group(2))"/></g> <b><xsl:value-of select="math:hex_to_color(regex-group(3))"/></b> <a><xsl:value-of select="if (matches($style, 'fill-opacity:')) then math:power(xs:float(replace($style, '.*fill-opacity:([-\d.]+).*', '$1')), 1 div 2.2) else 1"/></a> </color> </param> </xsl:matching-substring> </xsl:analyze-string> </xsl:if> <xsl:if test="matches($style, 'rgb')"> <xsl:analyze-string select="concat($style, ';')" regex="rgb[(\s]+([-\d.]+)[,\s]+([-\d.]+)[,\s]+([-\d.]+)[\s)]+;"> <xsl:matching-substring> <param name="color"> <color> <r><xsl:value-of select="math:power(xs:float(regex-group(1)) div 255, 2.2)"/></r> <g><xsl:value-of select="math:power(xs:float(regex-group(2)) div 255, 2.2)"/></g> <b><xsl:value-of select="math:power(xs:float(regex-group(3)) div 255, 2.2)"/></b> <a>1</a> </color> </param> </xsl:matching-substring> </xsl:analyze-string> </xsl:if> <xsl:if test="matches($style, 'url')"> <param name="color"> <color><r>0.5</r><g>0.5</g><b>0.5</b><a>0.5</a> </color> </param> </xsl:if> </xsl:template> <xsl:function name="math:resolve_transform"> <xsl:param name="transform"/> <xsl:variable name="stripped" select="replace(replace($transform, 'translate\(', 'X(1,0,0,1,'), 'matrix', 'X')"/> <xsl:analyze-string select="concat('X(1,0,0,1,0,0)', $stripped)" regex="(.*)X\((-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+)\)[^X]*X\((-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+),(-?[\d.]+)\).*"> <xsl:non-matching-substring> <xsl:sequence select="(1,0,0,1,0,0)"/> </xsl:non-matching-substring> <xsl:matching-substring> <xsl:variable name="a2" select="xs:float(regex-group(8))"/> <xsl:variable name="b2" select="xs:float(regex-group(9))"/> <xsl:variable name="c2" select="xs:float(regex-group(10))"/> <xsl:variable name="d2" select="xs:float(regex-group(11))"/> <xsl:variable name="e2" select="xs:float(regex-group(12))"/> <xsl:variable name="f2" select="xs:float(regex-group(13))"/> <xsl:variable name="a1" select="xs:float(regex-group(2))"/> <xsl:variable name="b1" select="xs:float(regex-group(3))"/> <xsl:variable name="c1" select="xs:float(regex-group(4))"/> <xsl:variable name="d1" select="xs:float(regex-group(5))"/> <xsl:variable name="e1" select="xs:float(regex-group(6))"/> <xsl:variable name="f1" select="xs:float(regex-group(7))"/> <xsl:variable name="p" select="($a1*$a2+$c1*$b2,$b1*$a2+$d1*$b2,$a1*$c2+$c1*$d2,$b1*$c2+$d1*$d2,$a1*$e2+$c1*$f2+$e1,$b1*$e2+$d1*$f2+$f1)"/> <xsl:variable name="remainder" select="replace(regex-group(1), 'X\(1,0,0,1,0,0\)', '')"/> <xsl:choose> <xsl:when test="matches($remainder, 'X')"> <xsl:variable name="recursion" select="concat($remainder, 'X(', $p[1], ',', $p[2], ',', $p[3], ',', $p[4], ',', $p[5], ',', $p[6], ')')"/> <xsl:sequence select="math:resolve_transform($recursion)"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="$p"/> </xsl:otherwise> </xsl:choose> </xsl:matching-substring> </xsl:analyze-string> </xsl:function> <xsl:function name="math:hex_to_color" as="xs:float"> <xsl:param name="hex"/> <xsl:value-of select="math:power(xs:float(string-length(substring-before('0123456789abcdef', substring($hex,1,1))) * 16 + string-length(substring-before('0123456789abcdef', substring($hex,2,1)))) div 255, 2.2)"/> </xsl:function> <xsl:function name="math:units_to_px" as="xs:float"> <xsl:param name="size"/> <xsl:analyze-string select="$size" regex="^([-\d.]+)([a-z%]*)$"> <xsl:matching-substring> <xsl:variable name="factor"> <xsl:choose> <xsl:when test="regex-group(2) = 'pt'">1.25</xsl:when> <xsl:when test="regex-group(2) = 'em'">16</xsl:when> <xsl:when test="regex-group(2) = 'mm'">3.54</xsl:when> <xsl:when test="regex-group(2) = 'pc'">15</xsl:when> <xsl:when test="regex-group(2) = 'cm'">35.43</xsl:when> <xsl:when test="regex-group(2) = 'in'">90</xsl:when> <xsl:otherwise>1</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:value-of select="xs:float($factor) * xs:float(regex-group(1))"/> </xsl:matching-substring> </xsl:analyze-string> </xsl:function> </xsl:stylesheet>
Option 2
This is a C program by akagogo that uses libxml to convert SVG to Synfig format.
http://none.carlos.googlepages.com/svgtosif.zip
Installation
Just make the usual ./configure && make && sudo make install
Usage
The SVG files needs to be inside a folder called data. You have to run the command from the parent directory, but just using the name file as the command argument. So if:
- You are in folder "/example" you have to create a folder called "/example/data" and put the file "file.svg" there.
- Now you execute svgtosif file.svg when you got "/example" as your current working directory.
As you can see, this is really not to friendly. To quickly fix the problem, use the following bash script:
#!/bin/bash mkdir data cp "$1" data/ /usr/local/bin/svgtosif "$1" NAME=`echo "$1" | cut -d "." -f 1` cp "data/$NAME.sif" . rm data/* rmdir data echo "Conversion complete!"
Put those lines in a file named "svg2sif" (name it as you want, but avoid using "svgtosif") and put it in a PATH directory (suggest /usr/bin). Then:
chmod +x /usr/bin/svg2sif
Thats all. Now use:
svg2sif <file.svg>
and you will get a .sif file in the same folder you are working in.