pySVG - creating svg with python
pySVG is a pure Python library to create SVG documents. Essentially it is a python wrapper around svg with the goal to allow people to "program svg". pySVG can be used to produce svg as an outcome of algorithms you implement (like koch curves, Lindenmayr systems etc.)
Working with pySVG is pretty straightforward. There is a small tutorial in the docs folder but i would suggest refering to the testclasses in the source.
Current status:
Pretty much all elements should be implemented. Type checking, validation and value constraints are NOT. In short: currently you can fill any element with more or less any content. Loading and storing of SVG images also works.
Features
Shapes (circle, ellipses, rectangles, lines, polygons, polylines,paths)
Text
Containers (g-element, defs)
Style attributes (stroke, filling, font)
Transform (in groups)
Filters
Load/Store SVG files
License & Donation
BSD - Style:
Copyright (c) 2008-2010,
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the pySVG nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KERIM MANSOUR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
If you enjoy using pySVG, please considering making a small donation to support further development. See the Donation page for more information.
Downloads
pySVG can be found here (svn is far more current at the moment:
- latest sources (may require a login)
- latest release (usually somewhat older, either as dist or with docs and examples)
Acknowledgements
SVG is a huge format. Some things i already tested, some i already "think to have" implemented but didn't test and others again i didn't implement yet or only made stubs. I can't possibly test all and frankly i am not really a graphics guru. So I will list anybody here who provides me with code testing yet untested but theoretically implemented features.
So IF you happen to create any image using pySVG and the code contains elements and attributes that haven't been tested yet, i would gladly include you in the list along the "feature" you determined to work correctly.
Installation and Requirements
pySVG requires Python (i use version 2.6, other versions may or may not work). pySVG also requires ... nothing else :-)
Discussion List
On request
Releases/History
10/12/2010 Release 5 : Version 0.2.1:
Added
added kwargs to make life a bit easier when instantiating objects
added dropshadows (contributed by Bastian)
added patterns
added turtle graphics
added clip element
added use element
added some methods to get size/edge points or move an element (depends on element)
implemented feMergeNode subclassing
added filterprimitiveswithin
Corrections
setfilter had wrong parameter
corrected intendation
documentation corrected
09/29/2009 Release 4 : Version 0.2.0:
-Complete rewrite of the class hirarchy (multiple inheritance)
most if not all all elements should exist now
gradients supported
filters supported
-Parser implemented that loads svg structures into python
-TODO:
type and content validation (lower priority)
better usage of defs and use commands (higher priority)
rewrite this post and bring it up to date;)
02/27/2009 Release 3 : Version 0.1.6:
-Path now supported (although not optimized)
-lineto (horizontal/vertical/free)
-moveto
-cureveto (cubic, quadratic, closecurve)
-arc
-included epidoc (still much to document though)
02/02/2008 Release 2 : Version 0.1.5:
-Extracted ObjectHelper
-style is now a dictionary instead of a class.
-included transforms (rotation tested so far)
-for style and transforms i created some Helperclass to create the dicts for those that do not know the attribute names
-included a "benchmark" now. Just compare the svg here to the created one to see what still is missing as features.
-broke the tutorial, see the testcode.
01/29/2008 Release 1 : Version 0.1:
-Basic features work. You can draw circles, ellipses, rectangles, lines, polylines and polygones. Filled and empty with different fill colors, stroke colors and stroke widths.
-Documentation is under way
-setup.py should work
-Not working is all the fancy stuff like transforms, gradients, ids etc. Style attributes not mentioned below MAY already work, i just didn't test them all yet. If YOU want to test see "Acknowledgments" below.




on 16 January 2009 at 07:04 tulcod said …
I've looked at this project a couple of times now, and I think I'm finally going to use it for, among more, my website. I've also made and submitted an ebuild (=Gentoo Linux package) to the ebuild maintainers, so hopefully it will soon enter the tree.
It would be really great if a little bit of documentation and API references would be near. Please continue development on this project, I think it can be useful for a lot of automagically generated graphics, especially considering the fact that most browsers are getting svg support right now. Imagine all those statistics graphics on the web, for example. They can now be generated using pysvg, instead of having to render them directly with something like gd.
on 1 February 2009 at 09:31 Kerim Mansour said …
Thanks for the nice comments tulcod.
I do have a modified working copy where i added more comments, as i already had some ideas about modifying the framework in the sense of better "abstract" support of svg.
I will see to it that i can add the new codebase soon.
Greetings
Kerim
on 4 February 2009 at 08:56 tulcod said …
So when I received an email this morning, I decided to take a look here again. New code sounds good, and documentation is even better.
Oh, an email. It was a new comment to a bug I posted to the Gentoo bugtracker: pysvg is now in the portage package tree! Congrats!
on 14 February 2009 at 02:44 Saul said …
I am interested in using this; however I really need support for paths. Is there anything I can do to motivate or help you to do this?
on 19 February 2009 at 16:47 kehander said …
This is just what I needed. rsvg in Cairo does something similar, but I'm using an environment where Cairo is not an option.
Python 2.4.4 doesn't seem to like the syntax of "class Group():" on line 99 of pysvg.py , but after changing it to "class Group:" it seems to work fine.
on 26 February 2009 at 04:01 Kerim Mansour said …
Hi Saul, kehander, tulcod
sorry for the late reply. Currently i am in "sickbay" and don't often look at my mails.
@tulcod:
good news, thanks :-)
I checked in something to lessen the time for you folks. Don't know if i haven't broken something though ... as said above ... time is short.
@kehander:
Python < 2.5 seems to have that problem with the brackets. I don't know why (since i started with 2.5 and never had a look at the lower versions). Simply removing them would solve the problem indeed.
I was wondering if i should even switch to 2.6 so that it can later be ported to 3.0 more easily (although i think that this won't be much of a problem anyway)
@Saul:
There is "some" support for paths. If you look in pysvg.pysvg you will find a class that appends lines, moves or arcs. However what i (personally) find missing are optimization routines and some helper classes that make it easier to use this.
You can look in testpySVG to see a simply test for an arc.
Since i am not so much of a pro when it comes to graphics the best thing people can do to improove the lib (apart of joining in the programming) is to provide me with information on what is needed.
on 27 February 2009 at 06:41 tulcod said …
Cool, wicked, neat!
Well, gradients would be very nice, since they can provide all the neat effects people may want. Masks could also be nice for some specific purposes, but it has a kind of lower priority.
More importantly, I think some kind of API to reuse objects and shapes would be nice. I don't know what already is possible, but having to create a new object explicitly is kind of the stuff people should actually try to avoid.
In inkscape, there is a really neat feature "path along path" which deforms paths based on the shape of another path. Check: http://math.univ-lille1.fr/~barraud/Inkscape/pathdeform/
If pysvg would have that, it would definitely show people that it's actually pretty mature already.
on 3 March 2009 at 13:20 kehander said …
I've actually got plans to store metadata in the "desc" property of each object (editing this field is supported in the dev release of Inkscape 0.47), but it's fairly trivial to pop in the relevant nodes with ElementTree after getting the XML of the generated SVG.
on 9 March 2009 at 14:34 Steve McClure said …
I had good luck with this module on my first usage of it.
One thing that I wanted to do but could not figure out was text at a 45 degree angle on the page. Can someone point me to an example for that?
Otherwise, great module, thanks very much.
on 11 March 2009 at 12:54 kerim mansour said …
Hi everyone,
just a small update.
Reading what tulcod said i was taking a look at the "use" command of svg. I would define the shapes using def and then add use tags (its not implemented yet).
Of course you could also try to use python constructs. Something similar in idea to:
c=circle....
svg.addElement(c)
c2=c
c2.cx=100
svg.addElement(c2)
For a programmer it might be better to use the second, for the svg file however the first solution would seem more apropriate.
So i thought about the overall structure again and came up with the idea that it might be best to try to convert the xml schema of svg into python data classes and write wrappers and helpers that would allow for both solutions.
I mailed Dave Kuhlman in the hope that his tool might do the job (currently it seems it doesn't).
@Steve:
Thanks for the feedback. Your question might be answered by this example here:
http://code.google.com/p/matrixfse/source/browse/trunk/pySVG/src/pySVGLogo.py
See however that i define a transform on a group there. Seems i forgot to add that attribute to the baseelements .... !
@kehander:
desc is not there yet. I limited the implementation to those things i needed at the time. Will see if i can add it in the near future.
on 12 March 2009 at 07:57 Steve McClure said …
@kerim mansour:
Thanks for the pointer. I had to take a step back as I didn't fully understand the model when I jumped in. I ended up needing to use several transformations to get my text in the position and orientation where I wanted it. Once I understood the model, I had no problems getting what I wanted.
Having never used SVG before, (actually I have but it was way back in my college days in a graphics class, it was just before SVG and XML had been invented) it was quite easy to use pySVG to get the output that I wanted and it looks great.
Thanks!
on 31 March 2009 at 09:01 samwyse said …
Here's my version of an SVG library. It's not very complete right now, but it's super easy to extend when I need more features:
<pre>
from xml.etree import ElementTree
def define_element(element_name, valid_attibutes):
def wrapper(**kwds):
attributes = dict()
for key, value in kwds.iteritems():
if key.startswith('_'): # hack to handle attributes that are Python keywords
key = key[1:]
if key in valid_attibutes:
attributes[key] = str(value)
else:
raise TypeError, "%s() got an unexpected keyword argument '%s'" % (element_name, key)
element = ElementTree.Element(element_name, **attributes)
setattr(element, 'tostring', MethodType(ElementTree.tostring, element, element.__class__))
return element
wrapper.__name__ = element_name
wrapper.__doc__ = 'Returns a tag for an SVG "%s" element.' % element_name
return wrapper
def define_elements(**kwds):
g=globals()
for key, value in kwds.iteritems():
g[key] = define_element(key, value)
define_elements(
svg = ('width', 'height', 'viewBox', 'xmlns'),
g = ('id', 'transform'),
line = ('x1', 'y1', 'x2', 'y2', 'class'),
rect = ('x', 'y', 'height', 'width', 'class'),
text = ('x', 'y', 'class'),
)
</pre>
on 31 March 2009 at 16:57 kehander said …
After much headache, I have finally realized that line 528 of pysvg.py should read
self.__append__('a',[rx,ry,x_axis_rotation,large_arc_flag,sweep_flag,x,y], relative)
and not
self.__append__('a',[rx,ry,x,y,x_axis_rotation,large_arc_flag,sweep_flag], relative) .
on 1 April 2009 at 11:29 Kerim Mansour said …
Hi again,
for all those wondering what I am doing at the moment.
I am still working a bit on generateDS by Dave Kuhlmann trying to see if i can use that with pysvg. It would deal with A LOT of problems that arise during development of the lib including loading and saving VALID svgs (with validation against the schema).
Sadly it still doesn't work because of (for now) ONE single problem with elements that are defined as "choice" in the schema.
I will give it some two more weeks, before returning to my version of pysvg and adding some code by contributors and making corrections like the one of kehander.
@samwyse:
Well thats similar to what i initially wanted to do once ... but if you look at the complexity of the definition of valid svg .... you might see shortcommings. Thats why i am currently trying to convert the schema into python data objects first.
on 1 April 2009 at 15:19 kehander said …
Is this the appropriate place to post new additions, or would you prefer them to be E-mailed somewhere? (Putting together a rudimentary "image" class didn't take long.)
on 2 April 2009 at 07:22 Kerim Mansour said …
You can contact me at kerim at this domain.
I think thats the most efficient way.
I must think about a solution for this blog entry as well .... seems it is getting longer and longer....
Perhaps i should set up a discussion board.
on 5 April 2009 at 14:54 Basu said …
Have you seen the SVGfig framework? http://code.google.com/p/svgfig/
It seems rather mature, though development seems to have frozen. I am currently in need of a robust SVG framework for a research project I'm working on. Would you be interested in unifying your code base with the SVGfig codebase (assuming that can be done without too much rewriting) so that we can create a 'standard' Python SVG library? I would be very willing to help work this out. I am currently trying to contact the SVGfig developers.
on 8 April 2009 at 04:03 Kerim Mansour said …
I never mind taking the best ideas out of several solutions.
Seems svgfig is GPL2 however which would collide with my BSD license.
Also the approach is somewhat different without validation of the svg for example and much svg knowledge required from the developer on the one side, while good support for serialization/deserialization on the other side.
Some classes are really neat. I like the Curve class for example.
on 15 April 2009 at 13:28 Kerim Mansour said …
Ok, for all fans of trial and error i included a folder called "bleeding edge" in the svn repository: You can browse the code at http://code.google.com/p/matrixfse/source/browse/#svn/trunk/pySVG
In the folder /bleedingEdge/src you should find the current pysvg.py as generated by my modified version of Dave Kuhlmans generateDS.py.
You will see that the api looks somewhat different (thats the bad news), but loading, saving of svg and many elements now work (thats the good news)
testXML.py is used to load an svg image and write it out again in a file named out.svg.
testManualAssembly was a try today to see how it looks like to create a simple svg by code.
I still have some problems with the size of the python file (1 MB is much) and with some elements (especially filters). Autogeneration of subclasses seems to work as well, so extensions should soon be possible (@Bastian: I haven`t forgotten about you. I still hope to include your code in the new lib instead of the old one.)
on 16 April 2009 at 15:57 Vic said …
I'm going to try this out soon in conjunction with Django. I'm generating SVG now using the jquery svg plugin, but I need to create some larger svg docs server side as well to prevent timeouts on the clientside.
on 7 May 2009 at 16:27 kehander said …
So, is there going to be some kind of new release soon?
I've written a minor tool using pySVG that I was thinking of sharing with others, but I wanted to wait until the next version was officially released (not to mention Inkscape 0.47).
on 26 May 2009 at 06:47 kerim said …
Hi kehander,
yes, i am working on a new release. Since i changed projects (work) some weeks ago i live out of the suitcase and didn't find the time to finish things.
I see to it that i check stuff in this week and with a little bit of luck make a release this weekend.
on 24 June 2009 at 06:44 Jörg said …
I've just discovered your nice project, and I already have 2 enhancement proposals ;) :
1) write a proper header à la
SVG_HEADER = """\
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" """
so that 'even' firefox can display your pictures
2) insert the "package path" in your setup.py (parameter 'package_dir={"pysvg":"pysvg"}' for setup(), so you can use "setup.py sdist" or similar
Keep up the good Work!
on 21 August 2009 at 13:05 kehander said …
There's been no news for a while now.
on 23 September 2009 at 08:11 kerim said …
Hi everyone,
sorry for the delay.
I guess i will have something within next week (latest time).
Currently i tried to create a seperate project at google and ran into a name conflict with a guy who some 4 or 5 years ago started a lib with the same name.
I must sort out that problem first.
As far as I can see I only have the animation structue and the font structure still missing.
on 3 December 2009 at 10:24 Bastian said …
Hi Kerim,
I am very pleased to see that you managed to squeeze out a very feature rich release.
Congratulations.
I will jump with two feet at using and extending it to my needs.
Two questions after the first 5 minutes:
1) Is there any way to get the rendered size of an element? Especially Text?
2) You (still) use old style classes. Is there any particular reason for this?
Once again. Thank you very much for the release!!
Cheers, Bastian
on 8 March 2010 at 03:03 Ben said …
Hi Kerim,
thanks for getting pySVG where it is now.
I've tried several options: Using the Jquery SVG library to render the SVG (works, but is slow when you have many objects and unpredictable due to the client side approach)
Second option was to generate the SVG server side with Cairo. Works very fast and is good if you want to output other formats than SVG as well, but Cairo lacks support to set the ID's of individual elements/groups
I'm now generating the SVG serverside using pysvg where I specifically set ID's on the groups in my SVG and load that svg into the jquery SVG library using an ajax call. This way I can access the full SVG DOM.
Once again, many thanks for this project.
Ben
on 8 March 2010 at 12:25 Kerim Mansour said …
I see that i have some catching up to do concerning the comments.
@Ben:
thank you so much for your comments. Its always good to see and hear from people that use pysvg. Keeps me improving it.
If there is anything worth posting about i would welcome a text i could put in my blog or a reference to your project.
@Bastian:
Sorry, i really didn't see your comment till now.
Lets try your questions:
1) Size: Have a look at http://code.google.com/p/pysvg/issues/list and you see that this indeed is an issue i still have to work on. I so far only implemented methods to get the edge points and the lower/upper left/right of some shapes like rects etc. This allows for inner borders or outer boundaries. But no method for the sizes yet.
2) old style classes: I am not sure what you mean here. There is a style element class that is corresponding to the svg xsd. And of course there is a style attribute created either directly as a string or using the builder who utilizes a dict for that. I see no way that is more practical now and doesnt contradict the paradigma to have classes for elements and member variables for attributes.
on 22 March 2010 at 12:02 kehander said …
It's fairly trivial to get the rendered size of text using get_pixel_extents from Pango (GTK). There may be a better way.
on 23 March 2010 at 00:38 Kerim Mansour said …
Hi kehander,
i am not sure what you mean. pySVG is pure python and doesn't use any secondary apis.
I guess PyGTK calculates the size using its own graphic context?
I am no font expert but i do not think its trivial to calculate the size of a text. You would first have to know the width of each letter of that text along with the width of the spacing. And the height of the line should normally be higher than the letters themselves.
I guess i need to get into that sooner or later anyway ;-)
If you have a tip (or better even code) drop me a line.
on 23 March 2010 at 17:15 kehander said …
Yes indeed, PyGTK calculates the size using its own graphic context. But if you want to stick with pure Python, then indeed that is not an option.
I'm finally converting my old code to use the new API in 0.2.0, and I'm kind of ambivalent about it. There doesn't seem to be a one-line equivalent of, say, obj.style_dict['display'] = 'none'
on 24 April 2010 at 06:32 Wladimir said …
Very nice idea and implementation! I'm working on a next-gen browser game and might well choose to use SVG instead of Flash. On-the-fly generation is a great thing to have.
on 9 May 2010 at 08:39 merwok said …
Hello
I think you’ve misread the GPL: Free software can be sold, so the opposition you make between the free license and the commercial use license does not work.
Regards
on 21 July 2010 at 08:08 Seba said …
Hello
It's very nice piece of work.
Is there any possibility to change the encoding? It seems to be fixed to "ISO-8859-1" and I need to have "UTF-8".
I have tried to change it with xml_wrap() but it only adds the xml to the fixed header.
Regards
on 21 July 2010 at 13:50 Kerim Mansour said …
Hi Seba, thanks for the nice comment. You are right, currently it is not possible to change the encoding except for modifying the source.
A new release should be available this month and i will incorporate a change however.
I will add a parameter to the save and the wrap methods.
on 3 January 2011 at 14:19 David said …
So happy to have discovered an SVG generator in Python, one that looks like a usable tool. I've barely begun with it, but expect to be giving it a thorough workout in coming months, and will be happy to contribute back any modifications I find necessary. Previously I have used a Perl module from CPAN for this purpose, but very much wanted to get away from Perl...
on 4 January 2011 at 03:38 Kerim Mansour said …
Hi David,
the more issues you find, the better for the library :-)
Looking forward to your comments.
on 20 July 2011 at 13:50 Florian said …
Hi,
I have compared pySVG to svgwrite at http://florian-berger.de/en/articles/creating-simple-svg-from-python . I'm afraid that pySVG loses in terms of quick accessibility in the case that someone needs to create SVG with a minimum of time for figuring out how to use the module.
Regards,
Florian
on 15 October 2011 at 17:07 קופיקו said …
happy to have discovered an SVG generator in Python, one that looks like a usable tool. I've barely begun with it, but expect to be giving it a thorough workout in coming months, and will be happy to contribute back any modifications I find necessary. Previously I have used a Perl module from CPAN for this purpose, but very much wanted to get away from Perl...