Illustrator 14, SVG… propre ?

Dans le cadre de mon projet pro (encore et toujours), j’ai voulu réaliser un parseur SVG pour y inclure des illustrations vectorielles. J’ai pu y rencontrer un sacré problème avec la lecture de fichier SVG exportés depuis Illustrator 14. Voici la solution.

Dans l’idée, je réalise un petit loader, avec un FileReference. Mon framework possédant sa propre structure sauvegardée en base de donnée, je n’ai pas besoin de garder le fichier sur le serveur. Je m’appuie donc sur FileReference.load(), une méthode implémentée dans FP10 qui permet de charger des fichiers dans le client directement.

private function start():void
{
up = new FileReferenceList();
up.addEventListener(Event.SELECT, draw);
up.browse([filefilter]);
}

private function draw(e:Event):void
{
for (var i:int = 0; i < up.fileList.length; i++)
{
var file:FileReference = FileReference(up.fileList[i]);
file.addEventListener(IOErrorEvent.IO_ERROR, option);
file.addEventListener(ProgressEvent.PROGRESS, option);
file.addEventListener(Event.COMPLETE, stop);
file.load();
}
}

private function stop(e:Event):void
{
var svg:XML = new XML(e.target.data);
}

Jusque la, rien d’exceptionnel.

Quand on veut accéder aux noeuds par contre… MOUAHAHAHAHA :)

Après quelques trace, ici et la on trouve ceci :

// trace(e.target.data)
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="369.64px" height="477.14px" viewBox="0 0 369.64 477.14" enable-background="new 0 0 369.64 477.14" xml:space="preserve">
<path opacity="0.54" fill="#FFFFFF" stroke="#000000" d="M85.34,107.12c54.77-93.89,204.55-136.37,251.5,40.24
    C383.79,323.96,107.7,541.93,64.1,396.62C20.51,251.31,30.57,201.01,85.34,107.12z"/>
</svg> 

//trace(new XML(e.target.data));
<svg version="1.0" id="Calque_1" x="0px" y="0px" width="369.64px" height="477.14px" viewBox="0 0 369.64 477.14" enable-background="new 0 0 369.64 477.14" aaa:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:aaa="http://www.w3.org/XML/1998/namespace">
  <path opacity="0.54" fill="#FFFFFF" stroke="#000000" d="M85.34,107.12c54.77-93.89,204.55-136.37,251.5,40.24&# xD;&# xA;&# x9;C383.79,323.96,107.7,541.93,64.1,396.62C20.51,251.31,30.57,201.01,85.34,107.12z"/>
</svg>

Que veulent dire ces caractères bizarres que l’on voir dans l’argument “d” du node “path” dans le 2e retour ?

Space &# 32; hexadecimal is &# x20;
Carriage return &# 13; hexadecimal is &# xD;
Tab &# 9; hexadecimal rep &# x9;
Line feed (newline) &# 10; hexadecimal is &# xA;

Interessant ! Ces caractères “&# xD;”, “&# xA;” et “&# x9;” sont interprétés en tant que caractères normaux. Ils coupent la valeur de l’argument. Après en avoir parlé sur irc, selon [NiKo], de tels caractères dans une valeur d’argument renverrait un xml “broken” (je ne le savais pas :o ).

Mais pourquoi Illustrator s’acharnerait-il a faire une telle chose ?
Je pense qu’il possède un mini moteur d’auto indentation, et que si une ligne fait plus de N caractères, il passe à la ligne et insère une tabulation. Ca parait assez crédible, Adobe veut améliorer la lisibilité de ses SVGs. Mais, qui de nos jours lit les SVG à la main :| ?



Passons à la solution. L’idée est de passer un coup d’expression régulière AVANT l’instanciation d’un XML, et instancier un nouvel XML à partir de ce fichier propre.

private function stop(e:Event = null):void
{
var xml:String = new String(e.target.data);
var pattern:RegExp = new RegExp("&#", "g");

trace("match:" + xml.match(pattern).length); // match: 0
}




Vous vous souvenez que je vous avais dit “…passe a la ligne et ajoute une tabulation…” ?
On rééssaye…

private function stop(e:Event = null):void
{
var xml:String = new String(e.target.data);
var pattern:RegExp = new RegExp("\\t", "g");

trace("match:", xml.match(pattern).length); // match: 1
}




Alors comme ca, l’instanciation d’une chaîne à partir d’un bytearray induirait une transformation des caractères spéciaux ?

L’avantage des caractères &# ; c’était qu’ils étaient encadrants, et je trouvais ca plus simple de faire une regex sur ce genre de chaîne plutôt que sur “\ t”… on est reparti ?

private function stop(e:Event = null):void
{
var xml:String = new XML(e.target.data).toString();
var pattern:RegExp = new RegExp("&#", "g");

trace("match:", xml.match(pattern).length); // match: 4
}

Pour la suite, CQFD ! Alors oui, je sais, c’est moche :) Mais ca a le mérite de marcher sans trop de code.

Si quelqu’un sait comment on désactive l’auto-indentation dans l’export SVG d’illustARtor, ou une solution plus clean, je suis preneur (as usual) :)

Comment (1)

  1. admin wrote::

    Je me lasse pas des chats =_=

    Wednesday, June 24, 2009 at 1:28 am #