This post is being delayed forever since I was planning to improve my SVG parser but finally I decided to release it since I don’t have plans to work on it anymore.. the basic functionalities are working since July 2009 and I abandoned the project for a while just going back to it a couple months ago when I finally decided to fix a few bugs and add the option to export HTML5 Canvas and Flash AS3 drawing commands… so let’s explain how it all started.
How it started
The whole thing started when I had to import some complex graphics into a Flash project that I was doing using FIVe3d (created by my co-worker Mathieu Badimon). – For those who don’t know FIVe3D is a really cool vector-based 3D engine for Flash, and it doesn’t support regular Sprites or MovieClips, everything needs to be drawn by code using a syntax that mimics the AS3 Graphics class (that is similar to the HTML5 canvas context – if you’re not an AS3 developer), it’s pretty easy to use but it can be very limiting and time consuming if you have to draw a complex shape… so I decided to create a SVG parser from scratch – even knowing that it was done by many people before – I thought it would be a good opportunity to learn a lot of stuff (it was), I couldn’t find any other parser capable to export FIVe3D code and I love to reinvent the wheel… – that way I could just generate all the vector files on Adobe Illustrator (or any other vector drawing software) and export it as an SVG file and then convert it to FIVe3D..
FIVe3D uses an internal format that Mathieu decided to call “motifs” that is nothing more than an Array containing drawing commands that he uses to store all the points of each shape. For instance [['M'],[0,50]] means “moveTo(0,50)”, [['L'], [10, 25]] means “lineTo(10, 25)” and so on… – he even created a tool to convert font files into a Class containing all the motifs for each letter that way we can easily use text without having to convert it manually, so my idea was to do the same but instead of converting font files I was going to convert SVG files!
Problems / Limitations
There were many limitations that I had to contour to make it work properly since SVG has hundreds of features (SVG Elements Index, SVG Attributes Index, SVG Property Index) and Flash & FIVe3D doesn’t support some of then natively… – it took me a while just to figure out which features were really required and could be supported by FIVe3D…
Absurd amount of elements, attributes and properties on the SVG spec
I don’t know how they managed to transform something as simple as XML into something so complex… The first big problem was to figure out how to convert the absurd amount of Elements, Attributes and Properties that exist on the SVG specification into the 6 motifs used by FIVe3D (that’s right, just six!!!).
Convert Bézier Curves and Shapes
The next thing was to figure out how to convert a Cubic Bézier Curve into a Quadratic Bézier Curve (Flash and FIVe3D only supports Quadratic Bézier Curves) and than how to convert a circle into Quadratic Bézier Curves (FIVe3D doesn’t have a motif for circle), rounded rectangles and so on.
Groups and Inheritance
Another problem that I had to deal was that sometimes shapes can be grouped and if one property is applied to the group it is inherited by all the group members and some of them are cumulative (like alpha, rotation, etc..) – I wasn’t expecting that since my first tests didn’t had any grouping, so I had to refactor the parser to support groups…
After I had finished almost all the elements I discovered that if you don’t “expand the shape” in Illustrator sometimes it generates the transform attribute (transformation matrix) and that it is cumulative if applied into a group of elements (inheritance), so I had to refactor the whole parser again to support this feature…
The Elliptical Arc
Next big thing that I had to deal was with the insane Elliptical Arc Implementation, since I didn’t had Math during College and also never learned how to read those crazy Mathematical Symbols it took me a while to learn how to implement the stupid elliptical arc path command – I had to first learn how to read the symbols, and believe me, that isn’t easy if you are doing by yourself – after a long time on Wikipedia and getting angry many times it finally worked…
Adding new Features / Stupid Ideas
Since it was raining during the weekend, I was bored and “everything” was working I decided to create new parsers to convert the Motifs into HTML5 Canvas drawing commands and also AS3 Graphics drawing commands – which wasn’t really a smart idea by the way, since the result file should be around 4x bigger than the original file because I’m converting each Cubic Bézier into 4 Quadratic Bézier, each rectangle into 4 lines, etc.. (see problems/limitations above) – also what’s the point of converting SVG into canvas since you are not going to manipulate the coordinates anymore? why don’t you just use a JPG/GIF? it will be way smaller and has the same use… so I only recommend using the HTML5 Canvas and AS3 commands if you’re converting a simple shape… it was created more as a proof-of-concept and because it was easy (I’ve spent just a couple hours implementing both..) – I already knew it wasn’t really useful before building it BUT I WAS BORED
PS: the file size can be easily reduced if the Canvas and Graphics parsers didn’t used Motifs as the input – right now I’m converting everything to motifs and than converting it to Canvas/AS3 graphics, a lot of information is lost during this conversion – but It shouldn’t be hard to create a new parser based on SVGToMotifs Class to output direct Canvas/AS3 commands. (maybe I will do it if I get bored again)
What is missing
A lot of stuff is missing, some of then I wouldn’t even try to implement since it would take forever (i.e. masking, animation) or aren’t that useful for me right now.. the <style> tag support is one of them, since Illustrator don’t use it I decided to not implement it in the end (but I’ve implemented in-line style) – all the path drawing commands and shapes are currently supported, gradient fill isn’t supported since FIVe3D doesn’t support it, fonts and bitmaps aren’t supported either.
If something isn’t supported the tool will display a message on the “Warnings Panel”.
Make the vector file as simple as possible removing all the masks, avoiding groups and flattening the file as much as possible..
The parser is actually really fast (it can parse a +1000 lines SVG in less than 1s) but since it outputs an insane amount of text it can even crash your browser if the SVG file is too big since Flash takes a long time to update the text into the output panel, use at your own risk.
Here are some simple examples of SVG files converted using the tool:
I’ve created this simple tool to make it easier to use the parser:
You need flash player 10 to view this content. Good luck if you are using an iPad
I’ve just published the source code of the parser on GitHub in case you want to check it out and maybe contribute with the project: http://github.com/millermedeiros/SVGParser – the source code is just of the parser API since the tool is really stupid right now.. – I hope it’s useful for someone!