aboutsummaryrefslogtreecommitdiff
path: root/wqflask/utility/svg.py
diff options
context:
space:
mode:
authorzsloan2020-10-29 14:35:09 -0500
committerzsloan2020-10-29 14:35:09 -0500
commit7c1c9e2a519ba662e9f293eea73eb7922b2160e4 (patch)
treef6d4db465d338c1433bbb126e911062a6c31748b /wqflask/utility/svg.py
parent5a1f69aa85809768577069ae63d92c9ef6aecc02 (diff)
parent6e6911b466c2727b16a190d8b714f55d7842d7e2 (diff)
downloadgenenetwork2-7c1c9e2a519ba662e9f293eea73eb7922b2160e4.tar.gz
Merge branch 'testing' of github.com:genenetwork/genenetwork2 into reaper_bootstrap_fix
Diffstat (limited to 'wqflask/utility/svg.py')
-rw-r--r--wqflask/utility/svg.py692
1 files changed, 363 insertions, 329 deletions
diff --git a/wqflask/utility/svg.py b/wqflask/utility/svg.py
index db13b9d1..b92cc2d1 100644
--- a/wqflask/utility/svg.py
+++ b/wqflask/utility/svg.py
@@ -25,54 +25,56 @@
# Last updated by GeneNetwork Core Team 2010/10/20
#!/usr/bin/env python
-##Copyright (c) 2002, Fedor Baart & Hans de Wit (Stichting Farmaceutische Kengetallen)
-##All rights reserved.
+# Copyright (c) 2002, Fedor Baart & Hans de Wit (Stichting Farmaceutische Kengetallen)
+# All rights reserved.
##
-##Redistribution and use in source and binary forms, with or without modification,
-##are permitted provided that the following conditions are met:
+# 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 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.
+# 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 Stichting Farmaceutische Kengetallen nor the names of
-##its contributors may be used to endorse or promote products derived from this
-##software without specific prior written permission.
+# Neither the name of the Stichting Farmaceutische Kengetallen 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
+# 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
+
+# Thanks to Gerald Rosennfellner for his help and useful comments.
-##Thanks to Gerald Rosennfellner for his help and useful comments.
-
-__doc__="""Use SVGdraw to generate your SVGdrawings.
+import sys
+import exceptions
+__doc__ = """Use SVGdraw to generate your SVGdrawings.
SVGdraw uses an object model drawing and a method toXML to create SVG graphics
by using easy to use classes and methods usualy you start by creating a drawing eg
d=drawing()
- #then you create a SVG root element
+ # then you create a SVG root element
s=svg()
- #then you add some elements eg a circle and add it to the svg root element
+ # then you add some elements eg a circle and add it to the svg root element
c=circle()
- #you can supply attributes by using named arguments.
+ # you can supply attributes by using named arguments.
c=circle(fill='red',stroke='blue')
- #or by updating the attributes attribute:
+ # or by updating the attributes attribute:
c.attributes['stroke-width']=1
s.addElement(c)
- #then you add the svg root element to the drawing
+ # then you add the svg root element to the drawing
d.setSVG(s)
- #and finaly you xmlify the drawing
+ # and finaly you xmlify the drawing
d.toXml()
@@ -82,7 +84,7 @@ This module was created using the SVG specification of www.w3c.org and the
O'Reilly (www.oreilly.com) python books as information sources. A svg viewer
is available from www.adobe.com"""
-__version__="1.0"
+__version__ = "1.0"
# there are two possibilities to generate svg:
# via a dom implementation and directly using <element>text</element> strings
@@ -93,33 +95,34 @@ __version__="1.0"
# Note that PyXML is required for using the dom implementation.
# It is also possible to use the standard minidom. But I didn't try that one.
# Anyway the text based approach is about 60 times faster than using the full dom implementation.
-use_dom_implementation=0
+use_dom_implementation = 0
-import exceptions
-if use_dom_implementation<>0:
+if use_dom_implementation != 0:
try:
from xml.dom import implementation
from xml.dom.ext import PrettyPrint
except:
- raise exceptions.ImportError, "PyXML is required for using the dom implementation"
-#The implementation is used for the creating the XML document.
-#The prettyprint module is used for converting the xml document object to a xml file
+ raise exceptions.ImportError(
+ "PyXML is required for using the dom implementation")
+# The implementation is used for the creating the XML document.
+# The prettyprint module is used for converting the xml document object to a xml file
+
+assert sys.version_info[0] >= 2
+if sys.version_info[1] < 2:
+ True = 1
+ False = 0
+ file = open
+
+sys.setrecursionlimit = 50
+# The recursion limit is set conservative so mistakes like s=svg() s.addElement(s)
+# won't eat up too much processor time.
+
+# the following code is pasted form xml.sax.saxutils
+# it makes it possible to run the code without the xml sax package installed
+# To make it possible to have <rubbish> in your text elements, it is necessary to escape the texts
+
-import sys
-assert sys.version_info[0]>=2
-if sys.version_info[1]<2:
- True=1
- False=0
- file=open
-
-sys.setrecursionlimit=50
-#The recursion limit is set conservative so mistakes like s=svg() s.addElement(s)
-#won't eat up too much processor time.
-
-#the following code is pasted form xml.sax.saxutils
-#it makes it possible to run the code without the xml sax package installed
-#To make it possible to have <rubbish> in your text elements, it is necessary to escape the texts
def _escape(data, entities={}):
"""Escape &, <, and > in a string of data.
@@ -127,13 +130,14 @@ def _escape(data, entities={}):
the optional entities parameter. The keys and values must all be
strings; each key will be replaced with its corresponding value.
"""
- #data = data.replace("&", "&amp;")
+ # data = data.replace("&", "&amp;")
data = data.replace("<", "&lt;")
data = data.replace(">", "&gt;")
- for chars, entity in entities.items():
+ for chars, entity in list(entities.items()):
data = data.replace(chars, entity)
return data
+
def _quoteattr(data, entities={}):
"""Escape and quote an attribute value.
@@ -156,96 +160,121 @@ def _quoteattr(data, entities={}):
return data
-
def _xypointlist(a):
"""formats a list of xy pairs"""
- s=''
- for e in a: #this could be done more elegant
- s+=str(e)[1:-1] +' '
+ s = ''
+ for e in a: # this could be done more elegant
+ s += str(e)[1:-1] + ' '
return s
+
def _viewboxlist(a):
"""formats a tuple"""
- s=''
+ s = ''
for e in a:
- s+=str(e)+' '
+ s += str(e)+' '
return s
+
def _pointlist(a):
"""formats a list of numbers"""
return str(a)[1:-1]
+
class pathdata:
"""class used to create a pathdata object which can be used for a path.
although most methods are pretty straightforward it might be useful to look at the SVG specification."""
- #I didn't test the methods below.
- def __init__(self,x=None,y=None):
- self.path=[]
+ # I didn't test the methods below.
+
+ def __init__(self, x=None, y=None):
+ self.path = []
if x is not None and y is not None:
self.path.append('M '+str(x)+' '+str(y))
+
def closepath(self):
"""ends the path"""
self.path.append('z')
- def move(self,x,y):
+
+ def move(self, x, y):
"""move to absolute"""
self.path.append('M '+str(x)+' '+str(y))
- def relmove(self,x,y):
+
+ def relmove(self, x, y):
"""move to relative"""
self.path.append('m '+str(x)+' '+str(y))
- def line(self,x,y):
+
+ def line(self, x, y):
"""line to absolute"""
self.path.append('L '+str(x)+' '+str(y))
- def relline(self,x,y):
+
+ def relline(self, x, y):
"""line to relative"""
self.path.append('l '+str(x)+' '+str(y))
- def hline(self,x):
+
+ def hline(self, x):
"""horizontal line to absolute"""
self.path.append('H'+str(x))
- def relhline(self,x):
+
+ def relhline(self, x):
"""horizontal line to relative"""
self.path.append('h'+str(x))
- def vline(self,y):
+
+ def vline(self, y):
"""verical line to absolute"""
self.path.append('V'+str(y))
- def relvline(self,y):
+
+ def relvline(self, y):
"""vertical line to relative"""
self.path.append('v'+str(y))
- def bezier(self,x1,y1,x2,y2,x,y):
+
+ def bezier(self, x1, y1, x2, y2, x, y):
"""bezier with xy1 and xy2 to xy absolut"""
- self.path.append('C'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
- def relbezier(self,x1,y1,x2,y2,x,y):
+ self.path.append('C'+str(x1)+','+str(y1)+' '+str(x2) +
+ ','+str(y2)+' '+str(x)+','+str(y))
+
+ def relbezier(self, x1, y1, x2, y2, x, y):
"""bezier with xy1 and xy2 to xy relative"""
- self.path.append('c'+str(x1)+','+str(y1)+' '+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
- def smbezier(self,x2,y2,x,y):
+ self.path.append('c'+str(x1)+','+str(y1)+' '+str(x2) +
+ ','+str(y2)+' '+str(x)+','+str(y))
+
+ def smbezier(self, x2, y2, x, y):
"""smooth bezier with xy2 to xy absolut"""
self.path.append('S'+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
- def relsmbezier(self,x2,y2,x,y):
+
+ def relsmbezier(self, x2, y2, x, y):
"""smooth bezier with xy2 to xy relative"""
self.path.append('s'+str(x2)+','+str(y2)+' '+str(x)+','+str(y))
- def qbezier(self,x1,y1,x,y):
+
+ def qbezier(self, x1, y1, x, y):
"""quadratic bezier with xy1 to xy absolut"""
self.path.append('Q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y))
- def relqbezier(self,x1,y1,x,y):
+
+ def relqbezier(self, x1, y1, x, y):
"""quadratic bezier with xy1 to xy relative"""
self.path.append('q'+str(x1)+','+str(y1)+' '+str(x)+','+str(y))
- def smqbezier(self,x,y):
+
+ def smqbezier(self, x, y):
"""smooth quadratic bezier to xy absolut"""
self.path.append('T'+str(x)+','+str(y))
- def relsmqbezier(self,x,y):
+
+ def relsmqbezier(self, x, y):
"""smooth quadratic bezier to xy relative"""
self.path.append('t'+str(x)+','+str(y))
- def ellarc(self,rx,ry,xrot,laf,sf,x,y):
+
+ def ellarc(self, rx, ry, xrot, laf, sf, x, y):
"""elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy absolut"""
- self.path.append('A'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
- def relellarc(self,rx,ry,xrot,laf,sf,x,y):
+ self.path.append('A'+str(rx)+','+str(ry)+' '+str(xrot) +
+ ' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
+
+ def relellarc(self, rx, ry, xrot, laf, sf, x, y):
"""elliptival arc with rx and ry rotating with xrot using large-arc-flag and sweep-flag to xy relative"""
- self.path.append('a'+str(rx)+','+str(ry)+' '+str(xrot)+' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
+ self.path.append('a'+str(rx)+','+str(ry)+' '+str(xrot) +
+ ' '+str(laf)+' '+str(sf)+' '+str(x)+' '+str(y))
+
def __repr__(self):
return ' '.join(self.path)
-
-
class SVGelement:
"""SVGelement(type,attributes,elements,text,namespace,**args)
Creates a arbitrary svg element and is intended to be subclassed not used on its own.
@@ -256,52 +285,56 @@ class SVGelement:
namespace. Note the elements==None, if elements = None:self.elements=[] construction.
This is done because if you default to elements=[] every object has a reference
to the same empty list."""
- def __init__(self,type='',attributes=None,elements=None,text='',namespace='',cdata=None, **args):
- self.type=type
- if attributes==None:
- self.attributes={}
+
+ def __init__(self, type='', attributes=None, elements=None, text='', namespace='', cdata=None, **args):
+ self.type = type
+ if attributes == None:
+ self.attributes = {}
else:
- self.attributes=attributes
- if elements==None:
- self.elements=[]
+ self.attributes = attributes
+ if elements == None:
+ self.elements = []
else:
- self.elements=elements
- self.text=text
- self.namespace=namespace
- self.cdata=cdata
- for arg in args.keys():
+ self.elements = elements
+ self.text = text
+ self.namespace = namespace
+ self.cdata = cdata
+ for arg in list(args.keys()):
arg2 = arg.replace("__", ":")
arg2 = arg2.replace("_", "-")
- self.attributes[arg2]=args[arg]
- def addElement(self,SVGelement):
+ self.attributes[arg2] = args[arg]
+
+ def addElement(self, SVGelement):
"""adds an element to a SVGelement
SVGelement.addElement(SVGelement)
"""
self.elements.append(SVGelement)
- def toXml(self,level,f):
+ def toXml(self, level, f):
f.write('\t'*level)
f.write('<'+self.type)
- for attkey in self.attributes.keys():
- f.write(' '+_escape(str(attkey))+'='+_quoteattr(str(self.attributes[attkey])))
+ for attkey in list(self.attributes.keys()):
+ f.write(' '+_escape(str(attkey))+'=' +
+ _quoteattr(str(self.attributes[attkey])))
if self.namespace:
- f.write(' xmlns="'+ _escape(str(self.namespace))+'" xmlns:xlink="http://www.w3.org/1999/xlink"')
+ f.write(' xmlns="' + _escape(str(self.namespace)) +
+ '" xmlns:xlink="http://www.w3.org/1999/xlink"')
if self.elements or self.text or self.cdata:
f.write('>')
if self.elements:
f.write('\n')
for element in self.elements:
- element.toXml(level+1,f)
+ element.toXml(level+1, f)
if self.cdata:
f.write('\n'+'\t'*(level+1)+'<![CDATA[')
for line in self.cdata.splitlines():
f.write('\n'+'\t'*(level+2)+line)
f.write('\n'+'\t'*(level+1)+']]>\n')
if self.text:
- if type(self.text)==type(''): #If the text is only text
+ if isinstance(self.text, type('')): # If the text is only text
f.write(_escape(str(self.text)))
- else: #If the text is a spannedtext class
+ else: # If the text is a spannedtext class
f.write(str(self.text))
if self.elements:
f.write('\t'*level+'</'+self.type+'>\n')
@@ -312,6 +345,7 @@ class SVGelement:
else:
f.write('/>\n')
+
class tspan(SVGelement):
"""ts=tspan(text='',**args)
@@ -323,19 +357,22 @@ class tspan(SVGelement):
st.addtspan(ts)
t=text(3,5,st)
"""
- def __init__(self,text=None,**args):
- SVGelement.__init__(self,'tspan',**args)
- if self.text<>None:
- self.text=text
+
+ def __init__(self, text=None, **args):
+ SVGelement.__init__(self, 'tspan', **args)
+ if self.text != None:
+ self.text = text
+
def __repr__(self):
- s="<tspan"
- for key,value in self.attributes.items():
- s+= ' %s="%s"' % (key,value)
- s+='>'
- s+=self.text
- s+='</tspan>'
+ s = "<tspan"
+ for key, value in list(self.attributes.items()):
+ s += ' %s="%s"' % (key, value)
+ s += '>'
+ s += self.text
+ s += '</tspan>'
return s
+
class tref(SVGelement):
"""tr=tref(link='',**args)
@@ -346,16 +383,19 @@ class tref(SVGelement):
st.addtref(tr)
t=text(3,5,st)
"""
- def __init__(self,link,**args):
- SVGelement.__init__(self,'tref',{'xlink:href':link},**args)
+
+ def __init__(self, link, **args):
+ SVGelement.__init__(self, 'tref', {'xlink:href': link}, **args)
+
def __repr__(self):
- s="<tref"
+ s = "<tref"
- for key,value in self.attributes.items():
- s+= ' %s="%s"' % (key,value)
- s+='/>'
+ for key, value in list(self.attributes.items()):
+ s += ' %s="%s"' % (key, value)
+ s += '/>'
return s
+
class spannedtext:
"""st=spannedtext(textlist=[])
@@ -374,46 +414,49 @@ class spannedtext:
st.addtext('This text is not bold')
t=text(3,5,st)
"""
- def __init__(self,textlist=None):
- if textlist==None:
- self.textlist=[]
+
+ def __init__(self, textlist=None):
+ if textlist == None:
+ self.textlist = []
else:
- self.textlist=textlist
- def addtext(self,text=''):
+ self.textlist = textlist
+
+ def addtext(self, text=''):
self.textlist.append(text)
- def addtspan(self,tspan):
+
+ def addtspan(self, tspan):
self.textlist.append(tspan)
- def addtref(self,tref):
+
+ def addtref(self, tref):
self.textlist.append(tref)
+
def __repr__(self):
- s=""
+ s = ""
for element in self.textlist:
- s+=str(element)
+ s += str(element)
return s
+
class rect(SVGelement):
"""r=rect(width,height,x,y,fill,stroke,stroke_width,**args)
a rectangle is defined by a width and height and a xy pair
"""
- def __init__(self,x=None,y=None,width=None,height=None,fill=None,stroke=None,stroke_width=None,**args):
- if width==None or height==None:
- if width<>None:
- raise ValueError, 'height is required'
- if height<>None:
- raise ValueError, 'width is required'
- else:
- raise ValueError, 'both height and width are required'
- SVGelement.__init__(self,'rect',{'width':width,'height':height},**args)
- if x<>None:
+
+ def __init__(self, x=None, y=None, width=None, height=None, fill=None, stroke=None, stroke_width=None, **args):
+ if width == None or height == None:
+ raise ValueError('both height and width are required')
+
+ SVGelement.__init__(self, 'rect', {'width':width,'height':height}, **args)
+ if x!=None:
self.attributes['x']=x
- if y<>None:
+ if y!=None:
self.attributes['y']=y
- if fill<>None:
+ if fill!=None:
self.attributes['fill']=fill
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
class ellipse(SVGelement):
@@ -423,22 +466,18 @@ class ellipse(SVGelement):
"""
def __init__(self,cx=None,cy=None,rx=None,ry=None,fill=None,stroke=None,stroke_width=None,**args):
if rx==None or ry== None:
- if rx<>None:
- raise ValueError, 'rx is required'
- if ry<>None:
- raise ValueError, 'ry is required'
- else:
- raise ValueError, 'both rx and ry are required'
- SVGelement.__init__(self,'ellipse',{'rx':rx,'ry':ry},**args)
- if cx<>None:
+ raise ValueError('both rx and ry are required')
+
+ SVGelement.__init__(self, 'ellipse', {'rx':rx,'ry':ry}, **args)
+ if cx!=None:
self.attributes['cx']=cx
- if cy<>None:
+ if cy!=None:
self.attributes['cy']=cy
- if fill<>None:
+ if fill!=None:
self.attributes['fill']=fill
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
@@ -449,17 +488,17 @@ class circle(SVGelement):
"""
def __init__(self,cx=None,cy=None,r=None,fill=None,stroke=None,stroke_width=None,**args):
if r==None:
- raise ValueError, 'r is required'
- SVGelement.__init__(self,'circle',{'r':r},**args)
- if cx<>None:
+ raise ValueError('r is required')
+ SVGelement.__init__(self, 'circle', {'r':r}, **args)
+ if cx!=None:
self.attributes['cx']=cx
- if cy<>None:
+ if cy!=None:
self.attributes['cy']=cy
- if fill<>None:
+ if fill!=None:
self.attributes['fill']=fill
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
class point(circle):
@@ -469,7 +508,7 @@ class point(circle):
very small rectangle if you use many points because a circle is difficult to render.
"""
def __init__(self,x,y,fill='black',**args):
- circle.__init__(self,x,y,1,fill,**args)
+ circle.__init__(self, x, y, 1, fill, **args)
class line(SVGelement):
"""l=line(x1,y1,x2,y2,stroke,stroke_width,**args)
@@ -477,18 +516,18 @@ class line(SVGelement):
A line is defined by a begin x,y pair and an end x,y pair
"""
def __init__(self,x1=None,y1=None,x2=None,y2=None,stroke=None,stroke_width=None,**args):
- SVGelement.__init__(self,'line',**args)
- if x1<>None:
+ SVGelement.__init__(self, 'line', **args)
+ if x1!=None:
self.attributes['x1']=x1
- if y1<>None:
+ if y1!=None:
self.attributes['y1']=y1
- if x2<>None:
+ if x2!=None:
self.attributes['x2']=x2
- if y2<>None:
+ if y2!=None:
self.attributes['y2']=y2
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
class polyline(SVGelement):
@@ -497,12 +536,12 @@ class polyline(SVGelement):
a polyline is defined by a list of xy pairs
"""
def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args):
- SVGelement.__init__(self,'polyline',{'points':_xypointlist(points)},**args)
- if fill<>None:
+ SVGelement.__init__(self, 'polyline', {'points':_xypointlist(points)}, **args)
+ if fill!=None:
self.attributes['fill']=fill
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
class polygon(SVGelement):
@@ -511,12 +550,12 @@ class polygon(SVGelement):
a polygon is defined by a list of xy pairs
"""
def __init__(self,points,fill=None,stroke=None,stroke_width=None,**args):
- SVGelement.__init__(self,'polygon',{'points':_xypointlist(points)},**args)
- if fill<>None:
+ SVGelement.__init__(self, 'polygon', {'points':_xypointlist(points)}, **args)
+ if fill!=None:
self.attributes['fill']=fill
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
- if stroke<>None:
+ if stroke!=None:
self.attributes['stroke']=stroke
class path(SVGelement):
@@ -525,14 +564,14 @@ class path(SVGelement):
a path is defined by a path object and optional width, stroke and fillcolor
"""
def __init__(self,pathdata,fill=None,stroke=None,stroke_width=None,id=None,**args):
- SVGelement.__init__(self,'path',{'d':str(pathdata)},**args)
- if stroke<>None:
+ SVGelement.__init__(self, 'path', {'d':str(pathdata)}, **args)
+ if stroke!=None:
self.attributes['stroke']=stroke
- if fill<>None:
+ if fill!=None:
self.attributes['fill']=fill
- if stroke_width<>None:
+ if stroke_width!=None:
self.attributes['stroke-width']=stroke_width
- if id<>None:
+ if id!=None:
self.attributes['id']=id
@@ -542,18 +581,18 @@ class text(SVGelement):
a text element can bge used for displaying text on the screen
"""
def __init__(self,x=None,y=None,text=None,font_size=None,font_family=None,text_anchor=None,**args):
- SVGelement.__init__(self,'text',**args)
- if x<>None:
+ SVGelement.__init__(self, 'text', **args)
+ if x!=None:
self.attributes['x']=x
- if y<>None:
+ if y!=None:
self.attributes['y']=y
- if font_size<>None:
+ if font_size!=None:
self.attributes['font-size']=font_size
- if font_family<>None:
+ if font_family!=None:
self.attributes['font-family']=font_family
- if text<>None:
+ if text!=None:
self.text=text
- if text_anchor<>None:
+ if text_anchor!=None:
self.attributes['text-anchor']=text_anchor
@@ -563,8 +602,8 @@ class textpath(SVGelement):
a textpath places a text on a path which is referenced by a link.
"""
def __init__(self,link,text=None,**args):
- SVGelement.__init__(self,'textPath',{'xlink:href':link},**args)
- if text<>None:
+ SVGelement.__init__(self, 'textPath', {'xlink:href':link}, **args)
+ if text!=None:
self.text=text
class pattern(SVGelement):
@@ -575,16 +614,16 @@ class pattern(SVGelement):
in x and y to cover the areas to be painted.
"""
def __init__(self,x=None,y=None,width=None,height=None,patternUnits=None,**args):
- SVGelement.__init__(self,'pattern',**args)
- if x<>None:
+ SVGelement.__init__(self, 'pattern', **args)
+ if x!=None:
self.attributes['x']=x
- if y<>None:
+ if y!=None:
self.attributes['y']=y
- if width<>None:
+ if width!=None:
self.attributes['width']=width
- if height<>None:
+ if height!=None:
self.attributes['height']=height
- if patternUnits<>None:
+ if patternUnits!=None:
self.attributes['patternUnits']=patternUnits
class title(SVGelement):
@@ -594,8 +633,8 @@ class title(SVGelement):
add at least one to the root svg element
"""
def __init__(self,text=None,**args):
- SVGelement.__init__(self,'title',**args)
- if text<>None:
+ SVGelement.__init__(self, 'title', **args)
+ if text!=None:
self.text=text
class description(SVGelement):
@@ -605,8 +644,8 @@ class description(SVGelement):
Add this element before adding other elements.
"""
def __init__(self,text=None,**args):
- SVGelement.__init__(self,'desc',**args)
- if text<>None:
+ SVGelement.__init__(self, 'desc', **args)
+ if text!=None:
self.text=text
class lineargradient(SVGelement):
@@ -616,16 +655,16 @@ class lineargradient(SVGelement):
stop elements van be added to define the gradient colors.
"""
def __init__(self,x1=None,y1=None,x2=None,y2=None,id=None,**args):
- SVGelement.__init__(self,'linearGradient',**args)
- if x1<>None:
+ SVGelement.__init__(self, 'linearGradient', **args)
+ if x1!=None:
self.attributes['x1']=x1
- if y1<>None:
+ if y1!=None:
self.attributes['y1']=y1
- if x2<>None:
+ if x2!=None:
self.attributes['x2']=x2
- if y2<>None:
+ if y2!=None:
self.attributes['y2']=y2
- if id<>None:
+ if id!=None:
self.attributes['id']=id
class radialgradient(SVGelement):
@@ -635,18 +674,18 @@ class radialgradient(SVGelement):
stop elements van be added to define the gradient colors.
"""
def __init__(self,cx=None,cy=None,r=None,fx=None,fy=None,id=None,**args):
- SVGelement.__init__(self,'radialGradient',**args)
- if cx<>None:
+ SVGelement.__init__(self, 'radialGradient', **args)
+ if cx!=None:
self.attributes['cx']=cx
- if cy<>None:
+ if cy!=None:
self.attributes['cy']=cy
- if r<>None:
+ if r!=None:
self.attributes['r']=r
- if fx<>None:
+ if fx!=None:
self.attributes['fx']=fx
- if fy<>None:
+ if fy!=None:
self.attributes['fy']=fy
- if id<>None:
+ if id!=None:
self.attributes['id']=id
class stop(SVGelement):
@@ -655,8 +694,8 @@ class stop(SVGelement):
Puts a stop color at the specified radius
"""
def __init__(self,offset,stop_color=None,**args):
- SVGelement.__init__(self,'stop',{'offset':offset},**args)
- if stop_color<>None:
+ SVGelement.__init__(self, 'stop', {'offset':offset}, **args)
+ if stop_color!=None:
self.attributes['stop-color']=stop_color
class style(SVGelement):
@@ -665,7 +704,7 @@ class style(SVGelement):
Add a CDATA element to this element for defing in line stylesheets etc..
"""
def __init__(self,type,cdata=None,**args):
- SVGelement.__init__(self,'style',{'type':type},cdata=cdata, **args)
+ SVGelement.__init__(self, 'style', {'type':type}, cdata=cdata, **args)
class image(SVGelement):
@@ -675,16 +714,11 @@ class image(SVGelement):
"""
def __init__(self,url,x=None,y=None,width=None,height=None,**args):
if width==None or height==None:
- if width<>None:
- raise ValueError, 'height is required'
- if height<>None:
- raise ValueError, 'width is required'
- else:
- raise ValueError, 'both height and width are required'
- SVGelement.__init__(self,'image',{'xlink:href':url,'width':width,'height':height},**args)
- if x<>None:
+ raise ValueError('both height and width are required')
+ SVGelement.__init__(self, 'image', {'xlink:href':url,'width':width,'height':height}, **args)
+ if x!=None:
self.attributes['x']=x
- if y<>None:
+ if y!=None:
self.attributes['y']=y
class cursor(SVGelement):
@@ -693,7 +727,7 @@ class cursor(SVGelement):
defines a custom cursor for a element or a drawing
"""
def __init__(self,url,**args):
- SVGelement.__init__(self,'cursor',{'xlink:href':url},**args)
+ SVGelement.__init__(self, 'cursor', {'xlink:href':url}, **args)
class marker(SVGelement):
@@ -703,18 +737,18 @@ class marker(SVGelement):
add an element to it which should be used as a marker.
"""
def __init__(self,id=None,viewBox=None,refx=None,refy=None,markerWidth=None,markerHeight=None,**args):
- SVGelement.__init__(self,'marker',**args)
- if id<>None:
+ SVGelement.__init__(self, 'marker', **args)
+ if id!=None:
self.attributes['id']=id
- if viewBox<>None:
+ if viewBox!=None:
self.attributes['viewBox']=_viewboxlist(viewBox)
- if refx<>None:
+ if refx!=None:
self.attributes['refX']=refx
- if refy<>None:
+ if refy!=None:
self.attributes['refY']=refy
- if markerWidth<>None:
+ if markerWidth!=None:
self.attributes['markerWidth']=markerWidth
- if markerHeight<>None:
+ if markerHeight!=None:
self.attributes['markerHeight']=markerHeight
class group(SVGelement):
@@ -724,8 +758,8 @@ class group(SVGelement):
g.addElement(SVGelement)
"""
def __init__(self,id=None,**args):
- SVGelement.__init__(self,'g',**args)
- if id<>None:
+ SVGelement.__init__(self, 'g', **args)
+ if id!=None:
self.attributes['id']=id
class symbol(SVGelement):
@@ -738,10 +772,10 @@ class symbol(SVGelement):
"""
def __init__(self,id=None,viewBox=None,**args):
- SVGelement.__init__(self,'symbol',**args)
- if id<>None:
+ SVGelement.__init__(self, 'symbol', **args)
+ if id!=None:
self.attributes['id']=id
- if viewBox<>None:
+ if viewBox!=None:
self.attributes['viewBox']=_viewboxlist(viewBox)
class defs(SVGelement):
@@ -750,7 +784,7 @@ class defs(SVGelement):
container for defining elements
"""
def __init__(self,**args):
- SVGelement.__init__(self,'defs',**args)
+ SVGelement.__init__(self, 'defs', **args)
class switch(SVGelement):
"""sw=switch(**args)
@@ -760,7 +794,7 @@ class switch(SVGelement):
Refer to the SVG specification for details.
"""
def __init__(self,**args):
- SVGelement.__init__(self,'switch',**args)
+ SVGelement.__init__(self, 'switch', **args)
class use(SVGelement):
@@ -769,15 +803,15 @@ class use(SVGelement):
references a symbol by linking to its id and its position, height and width
"""
def __init__(self,link,x=None,y=None,width=None,height=None,**args):
- SVGelement.__init__(self,'use',{'xlink:href':link},**args)
- if x<>None:
+ SVGelement.__init__(self, 'use', {'xlink:href':link}, **args)
+ if x!=None:
self.attributes['x']=x
- if y<>None:
+ if y!=None:
self.attributes['y']=y
- if width<>None:
+ if width!=None:
self.attributes['width']=width
- if height<>None:
+ if height!=None:
self.attributes['height']=height
@@ -788,15 +822,15 @@ class link(SVGelement):
a.addElement(SVGelement)
"""
def __init__(self,link='',**args):
- SVGelement.__init__(self,'a',{'xlink:href':link},**args)
+ SVGelement.__init__(self, 'a', {'xlink:href':link}, **args)
class view(SVGelement):
"""v=view(id,**args)
a view can be used to create a view with different attributes"""
def __init__(self,id=None,**args):
- SVGelement.__init__(self,'view',**args)
- if id<>None:
+ SVGelement.__init__(self, 'view', **args)
+ if id!=None:
self.attributes['id']=id
class script(SVGelement):
@@ -806,7 +840,7 @@ class script(SVGelement):
"""
def __init__(self,type,cdata=None,**args):
- SVGelement.__init__(self,'script',{'type':type},cdata=cdata,**args)
+ SVGelement.__init__(self, 'script', {'type':type}, cdata=cdata, **args)
class animate(SVGelement):
"""an=animate(attribute,from,to,during,**args)
@@ -814,12 +848,12 @@ class animate(SVGelement):
animates an attribute.
"""
def __init__(self,attribute,fr=None,to=None,dur=None,**args):
- SVGelement.__init__(self,'animate',{'attributeName':attribute},**args)
- if fr<>None:
+ SVGelement.__init__(self, 'animate', {'attributeName':attribute}, **args)
+ if fr!=None:
self.attributes['from']=fr
- if to<>None:
+ if to!=None:
self.attributes['to']=to
- if dur<>None:
+ if dur!=None:
self.attributes['dur']=dur
class animateMotion(SVGelement):
@@ -828,10 +862,10 @@ class animateMotion(SVGelement):
animates a SVGelement over the given path in dur seconds
"""
def __init__(self,pathdata,dur,**args):
- SVGelement.__init__(self,'animateMotion',**args)
- if pathdata<>None:
+ SVGelement.__init__(self, 'animateMotion', **args)
+ if pathdata!=None:
self.attributes['path']=str(pathdata)
- if dur<>None:
+ if dur!=None:
self.attributes['dur']=dur
class animateTransform(SVGelement):
@@ -840,15 +874,15 @@ class animateTransform(SVGelement):
transform an element from and to a value.
"""
def __init__(self,type=None,fr=None,to=None,dur=None,**args):
- SVGelement.__init__(self,'animateTransform',{'attributeName':'transform'},**args)
- #As far as I know the attributeName is always transform
- if type<>None:
+ SVGelement.__init__(self, 'animateTransform', {'attributeName':'transform'}, **args)
+ # As far as I know the attributeName is always transform
+ if type!=None:
self.attributes['type']=type
- if fr<>None:
+ if fr!=None:
self.attributes['from']=fr
- if to<>None:
+ if to!=None:
self.attributes['to']=to
- if dur<>None:
+ if dur!=None:
self.attributes['dur']=dur
class animateColor(SVGelement):
"""ac=animateColor(attribute,type,from,to,dur,**args)
@@ -856,14 +890,14 @@ class animateColor(SVGelement):
Animates the color of a element
"""
def __init__(self,attribute,type=None,fr=None,to=None,dur=None,**args):
- SVGelement.__init__(self,'animateColor',{'attributeName':attribute},**args)
- if type<>None:
+ SVGelement.__init__(self, 'animateColor', {'attributeName':attribute}, **args)
+ if type!=None:
self.attributes['type']=type
- if fr<>None:
+ if fr!=None:
self.attributes['from']=fr
- if to<>None:
+ if to!=None:
self.attributes['to']=to
- if dur<>None:
+ if dur!=None:
self.attributes['dur']=dur
class set(SVGelement):
"""st=set(attribute,to,during,**args)
@@ -871,10 +905,10 @@ class set(SVGelement):
sets an attribute to a value for a
"""
def __init__(self,attribute,to=None,dur=None,**args):
- SVGelement.__init__(self,'set',{'attributeName':attribute},**args)
- if to<>None:
+ SVGelement.__init__(self, 'set', {'attributeName':attribute}, **args)
+ if to!=None:
self.attributes['to']=to
- if dur<>None:
+ if dur!=None:
self.attributes['dur']=dur
@@ -895,12 +929,12 @@ class svg(SVGelement):
d.toXml()
"""
def __init__(self,viewBox=None, width=None, height=None,**args):
- SVGelement.__init__(self,'svg',**args)
- if viewBox<>None:
+ SVGelement.__init__(self, 'svg', **args)
+ if viewBox!=None:
self.attributes['viewBox']=_viewboxlist(viewBox)
- if width<>None:
+ if width!=None:
self.attributes['width']=width
- if height<>None:
+ if height!=None:
self.attributes['height']=height
self.namespace="http://www.w3.org/2000/svg"
@@ -918,27 +952,27 @@ class drawing:
def __init__(self, entity={}):
self.svg=None
self.entity = entity
- def setSVG(self,svg):
+ def setSVG(self, svg):
self.svg=svg
- #Voeg een element toe aan de grafiek toe.
+ # Voeg een element toe aan de grafiek toe.
if use_dom_implementation==0:
def toXml(self, filename='',compress=False):
- import cStringIO
- xml=cStringIO.StringIO()
+ import io
+ xml=io.StringIO()
xml.write("<?xml version='1.0' encoding='UTF-8'?>\n")
xml.write("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"")
if self.entity:
xml.write(" [\n")
- for item in self.entity.keys():
+ for item in list(self.entity.keys()):
xml.write("<!ENTITY %s \"%s\">\n" % (item, self.entity[item]))
xml.write("]")
xml.write(">\n")
- self.svg.toXml(0,xml)
+ self.svg.toXml(0, xml)
if not filename:
if compress:
import gzip
- f=cStringIO.StringIO()
- zf=gzip.GzipFile(fileobj=f,mode='wb')
+ f=io.StringIO()
+ zf=gzip.GzipFile(fileobj=f, mode='wb')
zf.write(xml.getvalue())
zf.close()
f.seek(0)
@@ -948,11 +982,11 @@ class drawing:
else:
if filename[-4:]=='svgz':
import gzip
- f=gzip.GzipFile(filename=filename,mode="wb", compresslevel=9)
+ f=gzip.GzipFile(filename=filename, mode="wb", compresslevel=9)
f.write(xml.getvalue())
f.close()
else:
- f=file(filename,'w')
+ f=file(filename, 'w')
f.write(xml.getvalue())
f.close()
@@ -963,40 +997,40 @@ class drawing:
writes a svg drawing to the screen or to a file
compresses if filename ends with svgz or if compress is true
"""
- doctype = implementation.createDocumentType('svg',"-//W3C//DTD SVG 1.0//EN""",'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd ')
+ doctype = implementation.createDocumentType('svg', "-//W3C//DTD SVG 1.0//EN""", 'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd ')
global root
- #root is defined global so it can be used by the appender. Its also possible to use it as an arugument but
- #that is a bit messy.
- root=implementation.createDocument(None,None,doctype)
- #Create the xml document.
+ # root is defined global so it can be used by the appender. Its also possible to use it as an arugument but
+ # that is a bit messy.
+ root=implementation.createDocument(None, None, doctype)
+ # Create the xml document.
global appender
- def appender(element,elementroot):
+ def appender(element, elementroot):
"""This recursive function appends elements to an element and sets the attributes
and type. It stops when alle elements have been appended"""
if element.namespace:
- e=root.createElementNS(element.namespace,element.type)
+ e=root.createElementNS(element.namespace, element.type)
else:
e=root.createElement(element.type)
if element.text:
textnode=root.createTextNode(element.text)
e.appendChild(textnode)
- for attribute in element.attributes.keys(): #in element.attributes is supported from python 2.2
- e.setAttribute(attribute,str(element.attributes[attribute]))
+ for attribute in list(element.attributes.keys()): #in element.attributes is supported from python 2.2
+ e.setAttribute(attribute, str(element.attributes[attribute]))
if element.elements:
for el in element.elements:
- e=appender(el,e)
+ e=appender(el, e)
elementroot.appendChild(e)
return elementroot
- root=appender(self.svg,root)
+ root=appender(self.svg, root)
if not filename:
- import cStringIO
- xml=cStringIO.StringIO()
- PrettyPrint(root,xml)
+ import io
+ xml=io.StringIO()
+ PrettyPrint(root, xml)
if compress:
import gzip
- f=cStringIO.StringIO()
- zf=gzip.GzipFile(fileobj=f,mode='wb')
+ f=io.StringIO()
+ zf=gzip.GzipFile(fileobj=f, mode='wb')
zf.write(xml.getvalue())
zf.close()
f.seek(0)
@@ -1007,23 +1041,23 @@ class drawing:
try:
if filename[-4:]=='svgz':
import gzip
- import cStringIO
- xml=cStringIO.StringIO()
- PrettyPrint(root,xml)
- f=gzip.GzipFile(filename=filename,mode='wb',compresslevel=9)
+ import io
+ xml=io.StringIO()
+ PrettyPrint(root, xml)
+ f=gzip.GzipFile(filename=filename, mode='wb', compresslevel=9)
f.write(xml.getvalue())
f.close()
else:
- f=open(filename,'w')
- PrettyPrint(root,f)
+ f=open(filename, 'w')
+ PrettyPrint(root, f)
f.close()
except:
- print "Cannot write SVG file: " + filename
+ print(("Cannot write SVG file: " + filename))
def validate(self):
try:
import xml.parsers.xmlproc.xmlval
except:
- raise exceptions.ImportError,'PyXml is required for validating SVG'
+ raise exceptions.ImportError('PyXml is required for validating SVG')
svg=self.toXml()
xv=xml.parsers.xmlproc.xmlval.XMLValidator()
try:
@@ -1031,38 +1065,38 @@ class drawing:
except:
raise Exception("SVG is not well formed, see messages above")
else:
- print "SVG well formed"
+ print("SVG well formed")
if __name__=='__main__':
d=drawing()
- s=svg((0,0,100,100))
- r=rect(-100,-100,300,300,'cyan')
+ s=svg((0, 0, 100, 100))
+ r=rect(-100, -100, 300, 300, 'cyan')
s.addElement(r)
t=title('SVGdraw Demo')
s.addElement(t)
g=group('animations')
- e=ellipse(0,0,5,2)
+ e=ellipse(0, 0, 5, 2)
g.addElement(e)
- c=circle(0,0,1,'red')
+ c=circle(0, 0, 1, 'red')
g.addElement(c)
- pd=pathdata(0,-10)
+ pd=pathdata(0, -10)
for i in range(6):
- pd.relsmbezier(10,5,0,10)
- pd.relsmbezier(-10,5,0,10)
- an=animateMotion(pd,10)
+ pd.relsmbezier(10, 5, 0, 10)
+ pd.relsmbezier(-10, 5, 0, 10)
+ an=animateMotion(pd, 10)
an.attributes['rotate']='auto-reverse'
an.attributes['repeatCount']="indefinite"
g.addElement(an)
s.addElement(g)
- for i in range(20,120,20):
- u=use('#animations',i,0)
+ for i in range(20, 120, 20):
+ u=use('#animations', i, 0)
s.addElement(u)
- for i in range(0,120,20):
- for j in range(5,105,10):
- c=circle(i,j,1,'red','black',.5)
+ for i in range(0, 120, 20):
+ for j in range(5, 105, 10):
+ c=circle(i, j, 1, 'red', 'black', .5)
s.addElement(c)
d.setSVG(s)
- print d.toXml()
+ print((d.toXml()))