Hello Of!
I’ve been using Theo’s ofxSVGLoader a lot and it’s great but I wanted something different, something more convenient that fit better to my workflow. So I decided to start writing a new little addon for handling SVG files.
It’s a work in progress and it’s really not finished but here’s a small list of the features I wrote so far:
-
Depth (2D z order).
-
One or Multiple Layers support.
-
All primitives of Illustrator are working!
-
Stroke and Fills support.
-
Stroke Weight support.
-
Support for single and multiline texts.
-
Rich Text and Fonts Support (with FTGL in option).
-
Most AI PathFinder operation are supported.
-
Illustrator SVGs and “Preserve Illustrator Editing Capabilities” SVGs are supported too!
(Opacity and matrix transforms(rotations) are not supported for the moment. Paths are not supported neither but will certainly be tonight!)
[attachment=0:3u6gdu4y]ofxSVG.zip[/attachment:3u6gdu4y]
The use of this addon is pretty straight forward:
// Setup and load SVG
//--------------------------------------------------------
ofxSVG svg;
svg.setup("mySvg.svg");
// Draw everything
//--------------------------------------------------------
svg.draw();
// Draw by layers
//--------------------------------------------------------
for(int i=0; i<svg.layers.size(); i++)
svg.layers[i].draw();
// Draw by Objects
//--------------------------------------------------------
for(int i=0; i<svg.layers[0].objects.size(); i++)
svg.layers[0].objects[i].draw();
For now every SVGObjects only consists in an Opengl display list for the rendering so you can’t access the vertexs directly (I’ll try to manage that in the next versions).
Something really useful is that you can read back the names you gave to the layers and to the different objects. Which mean that you could for example built an entire GUI Layer inside your favorite Vector Graphic Editor and then read it back in OF! (ex: by tagging a rectangle with something like “slider:background” you get enough datas to build the slider with any GUI system)
// Print Layer Name
//--------------------------------------------------------
cout<<svg.layers[0].name<<endl;
// Print Object Name and type
//--------------------------------------------------------
cout<<svg.layers[0].objects[0].name<<endl;
cout<<svg.layers[0].objects[0].type<<endl;
Unfortunately I had to hack ofxXMLSettings just a little to be able to parse the svg correctly (by the way I think this can be a good addition to the existing addon, actually it just enable to parse xml datas even if you don’t know the tags name and more important it allow to parse data in the right order, which is very useful/needed sometimes) :
in ofxXMLSettings.h:
int getNumTags();
string getName(int which = 0);
string getValue(int which = 0);
string getAttribute(const string& attribute, int which = 0);
bool pushTag(int which = 0);
and in ofxXMLSettings.cpp:
int ofxXmlSettings::getNumTags(){
TiXmlHandle tagHandle = storedHandle;
int count = 0;
TiXmlElement* child = storedHandle.FirstChildElement().ToElement();
for (count = 0; child; child = child->NextSiblingElement(), ++count){}
return count;
}
//--------------------------------------------------------
string ofxXmlSettings::getName(int which){
TiXmlHandle tagHandle = storedHandle;
int i = 0;
TiXmlElement* child = storedHandle.FirstChildElement().ToElement();
for (; i<which && child; i++, child = child->NextSiblingElement()){}
return (i==which) ? child->ValueStr() : "";
}
//--------------------------------------------------------
string ofxXmlSettings::getValue(int which){
TiXmlHandle tagHandle = storedHandle;
int i = 0;
TiXmlElement* child = storedHandle.FirstChildElement().ToElement();
for (; i<which && child; i++, child = child->NextSiblingElement()){}
const char* value;
if(i==which) value = child->GetText();
return (value!=NULL) ? value : "";
}
//--------------------------------------------------------
string ofxXmlSettings::getAttribute(const string& attribute, int which){
TiXmlHandle tagHandle = storedHandle;
int i = 0;
TiXmlElement* child = storedHandle.FirstChildElement().ToElement();
for (; i<which && child; i++, child = child->NextSiblingElement()){}
const char* attributeValue;
if(i==which) attributeValue = child->Attribute(attribute.c_str());
return (attributeValue!=NULL) ? attributeValue : "";
}
//--------------------------------------------------------
bool ofxXmlSettings::pushTag(int which){
TiXmlHandle isRealHandle = storedHandle.Child(which);
if( isRealHandle.ToNode() ){
storedHandle = isRealHandle;
level++;
return true;
}
return false;
}
And you will need this very small ofxFTGL addon to render the texts correctly (or disable FTGL by commenting this line in ofxSVG.h:
#define USE_OFXFTGL
(FTGL Texts rendering seems a bit better than the classic OF Texts rendering)
[attachment=2:3u6gdu4y]ofxFTGL.zip[/attachment:3u6gdu4y]
This is a work in progress, so I may be spamming this post again!
I really think that the SVG format can offer a lot more possibilities than just importing vectors (as I was saying with my GUI example) … and this is why I’m posting that here, and feel very exited
Please feel free to post every comments or suggestions!
Thanks!
Simon.
ps: The birth of this addon would not have been that easy without the incredible works of OF developers and without this great forum!
pps: If you want to use text you will still need to add the fonts you are using inside “data/fonts” (and sometimes rename them as they are in the svg).
ppps: ofxSVG_2_ofxGUI is on the way!
ppps: If you are using Illustrator don’t forget to use “Preserve Illustrator Editing Capabilities” when you save you’re SVG or you will have troubles next time you open it!
Edit* You’ll need this too for the rendering:
[attachment=1:3u6gdu4y]ofxDisplayList.zip[/attachment:3u6gdu4y]