More SVGdraw fixups, make namespaces work on import
This commit is contained in:
parent
ae2eb70b6c
commit
0ca5a7fed5
@ -227,6 +227,8 @@ class Attribute:
|
|||||||
self.value = value
|
self.value = value
|
||||||
self.nsname = nsname
|
self.nsname = nsname
|
||||||
self.nsref = nsref
|
self.nsref = nsref
|
||||||
|
def __repr__(self):
|
||||||
|
return "(%s=%s, ns: %s=%s)" % (self.name, self.value, self.nsname, self.nsref)
|
||||||
|
|
||||||
def get_attr_value(attrs, name):
|
def get_attr_value(attrs, name):
|
||||||
return attrs[name]
|
return attrs[name]
|
||||||
@ -271,7 +273,9 @@ class SVGelement:
|
|||||||
def setParent(self, parent):
|
def setParent(self, parent):
|
||||||
self._parent = parent
|
self._parent = parent
|
||||||
|
|
||||||
def setAttribute(self, attribute):
|
def setAttribute(self, attribute, replace=True):
|
||||||
|
if not replace and self.hasAttribute(attribute.name):
|
||||||
|
return
|
||||||
self._attributes[attribute.name] = attribute
|
self._attributes[attribute.name] = attribute
|
||||||
|
|
||||||
def delAttribute(self, name):
|
def delAttribute(self, name):
|
||||||
@ -287,19 +291,63 @@ class SVGelement:
|
|||||||
raise Exception("Can't construct a default object.")
|
raise Exception("Can't construct a default object.")
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
def _get_namespace(attrname, nslist):
|
||||||
|
colon_idx = attrname.find(':')
|
||||||
|
if colon_idx <= 0:
|
||||||
|
return (attrname, None, None)
|
||||||
|
nsname = attrname[:colon_idx]
|
||||||
|
nsref = None
|
||||||
|
attrname = attrname[colon_idx+1:]
|
||||||
|
for (ns, val) in nslist:
|
||||||
|
if ns == nsname:
|
||||||
|
nsref = val
|
||||||
|
break
|
||||||
|
if not nsref:
|
||||||
|
nsname = None
|
||||||
|
return (attrname, nsname, nsref)
|
||||||
|
_get_namespace = staticmethod(_get_namespace)
|
||||||
|
|
||||||
|
_XMLNS_TAG = "xmlns:"
|
||||||
def construct(name, attributes, text=None, cdata=None):
|
def construct(name, attributes, text=None, cdata=None):
|
||||||
try:
|
try:
|
||||||
eltClass = elementTable[name]
|
eltClass = elementTable[name]
|
||||||
except KeyError, e:
|
except KeyError, e:
|
||||||
print "Unknown SVG element %s." % e
|
print "Unknown SVG element %s." % e
|
||||||
return None
|
return None
|
||||||
element = eltClass._construct(attributes)
|
# Coalesce namespaces into the attributes themselves
|
||||||
|
attr_dict = {}
|
||||||
|
elt_namespace = None
|
||||||
|
namespaces = []
|
||||||
|
tmp_attrs = []
|
||||||
|
# Separate namespaces from actual attributes
|
||||||
for attrname, attrvalue in attributes.items():
|
for attrname, attrvalue in attributes.items():
|
||||||
element.setAttribute(Attribute(attrname, attrvalue))
|
if attrname.startswith(SVGelement._XMLNS_TAG):
|
||||||
|
namespaces.append((attrname[len(SVGelement._XMLNS_TAG):], attrvalue))
|
||||||
|
elif attrname.startswith("xmlns"):
|
||||||
|
# Element-wide attribute
|
||||||
|
elt_namespace = attrvalue
|
||||||
|
else:
|
||||||
|
tmp_attrs.append((attrname, attrvalue))
|
||||||
|
|
||||||
|
# Create attributes and assign namespaces to them
|
||||||
|
for (attrname, attrvalue) in tmp_attrs:
|
||||||
|
nsname = nsref = None
|
||||||
|
attr = None
|
||||||
|
# search for its namespace, if any
|
||||||
|
(attrname, nsname, nsref) = SVGelement._get_namespace(attrname, namespaces)
|
||||||
|
attr = Attribute(attrname, attrvalue, nsname, nsref)
|
||||||
|
attr_dict[attrname] = attr
|
||||||
|
|
||||||
|
element = eltClass._construct(attr_dict)
|
||||||
|
if element:
|
||||||
|
for attr in attr_dict.values():
|
||||||
|
element.setAttribute(attr, replace=False)
|
||||||
if text:
|
if text:
|
||||||
element.text = text
|
element.text = text
|
||||||
if cdata:
|
if cdata:
|
||||||
element.cdata = cdata
|
element.cdata = cdata
|
||||||
|
if not element.namespace and elt_namespace:
|
||||||
|
element.namespace = elt_namespace
|
||||||
return element
|
return element
|
||||||
construct = staticmethod(construct)
|
construct = staticmethod(construct)
|
||||||
|
|
||||||
@ -389,10 +437,10 @@ class tref(SVGelement):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
if href and href.nsname == 'xlink':
|
||||||
href = href[len("xlink:"):]
|
return tref(href.value)
|
||||||
return tref(href)
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
class spannedtext:
|
class spannedtext:
|
||||||
@ -458,7 +506,7 @@ class rect(SVGelement):
|
|||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
width = get_attr_value(attributes, 'width')
|
width = get_attr_value(attributes, 'width')
|
||||||
height = get_attr_value(attributes, 'height')
|
height = get_attr_value(attributes, 'height')
|
||||||
return rect(width=width, height=height)
|
return rect(width=width.value, height=height.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -490,7 +538,7 @@ class ellipse(SVGelement):
|
|||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
rx = get_attr_value(attributes, 'rx')
|
rx = get_attr_value(attributes, 'rx')
|
||||||
ry = get_attr_value(attributes, 'ry')
|
ry = get_attr_value(attributes, 'ry')
|
||||||
return ellipse(rx=rx, ry=ry)
|
return ellipse(rx=rx.value, ry=ry.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -516,10 +564,10 @@ class circle(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
r = get_attr_value(attributes, 'r')
|
r = get_attr_value(attributes, 'r')
|
||||||
if int(r) == 1:
|
if int(r.value) == 1:
|
||||||
return point()
|
return point()
|
||||||
else:
|
else:
|
||||||
return circle(r=r)
|
return circle(r=r.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -529,7 +577,7 @@ class point(circle):
|
|||||||
A point is defined as a circle with a size 1 radius. It may be more efficient to use a
|
A point is defined as a circle with a size 1 radius. It may be more efficient to use a
|
||||||
very small rectangle if you use many points because a circle is difficult to render.
|
very small rectangle if you use many points because a circle is difficult to render.
|
||||||
"""
|
"""
|
||||||
def __init__(self,x=None,y=None,fill='black',**args):
|
def __init__(self,x=None,y=None,fill=None,**args):
|
||||||
circle.__init__(self,x,y,1,fill,**args)
|
circle.__init__(self,x,y,1,fill,**args)
|
||||||
|
|
||||||
class line(SVGelement):
|
class line(SVGelement):
|
||||||
@ -573,7 +621,7 @@ class polyline(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
points = get_attr_value(attributes, 'points')
|
points = get_attr_value(attributes, 'points')
|
||||||
return polyline(points)
|
return polyline(points.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -593,7 +641,7 @@ class polygon(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
points = get_attr_value(attributes, 'points')
|
points = get_attr_value(attributes, 'points')
|
||||||
return polygon(points)
|
return polygon(points.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -615,7 +663,7 @@ class path(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
pathdata = get_attr_value(attributes, 'd')
|
pathdata = get_attr_value(attributes, 'd')
|
||||||
return path(d)
|
return path(pathdata.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -656,10 +704,10 @@ class textpath(SVGelement):
|
|||||||
self.text=text
|
self.text=text
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
if href and href.nsname == 'xlink':
|
||||||
href = href[len("xlink:"):]
|
return textpath(href.value)
|
||||||
return textpath(href)
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -782,7 +830,7 @@ class stop(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
offset = get_attr_value(attributes, 'offset')
|
offset = get_attr_value(attributes, 'offset')
|
||||||
return stop(offset)
|
return stop(offset.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
class style(SVGelement):
|
class style(SVGelement):
|
||||||
@ -795,7 +843,7 @@ class style(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
type = get_attr_value(attributes, 'type')
|
type = get_attr_value(attributes, 'type')
|
||||||
return style(type)
|
return style(type.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -820,12 +868,12 @@ class image(SVGelement):
|
|||||||
self.setAttribute(Attribute('y', y))
|
self.setAttribute(Attribute('y', y))
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
|
||||||
href = href[len("xlink:"):]
|
|
||||||
width = get_attr_value(attributes, 'width')
|
width = get_attr_value(attributes, 'width')
|
||||||
height = get_attr_value(attributes, 'height')
|
height = get_attr_value(attributes, 'height')
|
||||||
return image(href, width=width, height=height)
|
if href and href.nsname == 'xlink':
|
||||||
|
return image(href.value, width=width.value, height=height.value)
|
||||||
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -839,10 +887,10 @@ class cursor(SVGelement):
|
|||||||
self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef))
|
self.setAttribute(Attribute('href', url, 'xlink', xlinkNSRef))
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
if href and href.nsname == 'xlink':
|
||||||
href = href[len("xlink:"):]
|
return cursor(href.value)
|
||||||
return cursor(href)
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -955,10 +1003,10 @@ class use(SVGelement):
|
|||||||
self.setAttribute(Attribute('height', height))
|
self.setAttribute(Attribute('height', height))
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
if href and href.nsname == 'xlink':
|
||||||
href = href[len("xlink:"):]
|
return use(href.value)
|
||||||
return use(href)
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -973,10 +1021,10 @@ class link(SVGelement):
|
|||||||
self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef))
|
self.setAttribute(Attribute('href', link, 'xlink', xlinkNSRef))
|
||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
href = get_attr_value(attributes, 'xlink:href')
|
href = get_attr_value(attributes, 'href')
|
||||||
if href and href.startswith("xlink:"):
|
if href and href.nsname == 'xlink':
|
||||||
href = href[len("xlink:"):]
|
return link(href.value)
|
||||||
return link(href)
|
return None
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -1005,7 +1053,7 @@ class script(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
type = get_attr_value(attributes, 'type')
|
type = get_attr_value(attributes, 'type')
|
||||||
return script(type, cdata=cdata)
|
return script(type.value, cdata=cdata.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -1025,7 +1073,7 @@ class animate(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
attribute = get_attr_value(attributes, 'attributeName')
|
attribute = get_attr_value(attributes, 'attributeName')
|
||||||
return animate(attribute)
|
return animate(attribute.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -1086,7 +1134,7 @@ class animateColor(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
attribute = get_attr_value(attributes, 'attributeName')
|
attribute = get_attr_value(attributes, 'attributeName')
|
||||||
return animateColor(attribute)
|
return animateColor(attribute.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -1104,7 +1152,7 @@ class set(SVGelement):
|
|||||||
|
|
||||||
def _construct(attributes):
|
def _construct(attributes):
|
||||||
attribute = get_attr_value(attributes, 'attributeName')
|
attribute = get_attr_value(attributes, 'attributeName')
|
||||||
return set(attribute)
|
return set(attribute.value)
|
||||||
_construct = staticmethod(_construct)
|
_construct = staticmethod(_construct)
|
||||||
|
|
||||||
|
|
||||||
@ -1190,13 +1238,15 @@ class SVGImportParser(object):
|
|||||||
def StartElementHandler(self, name, attrs):
|
def StartElementHandler(self, name, attrs):
|
||||||
self.log("<%s>" % name)
|
self.log("<%s>" % name)
|
||||||
self._indent = self._indent + 1
|
self._indent = self._indent + 1
|
||||||
|
import copy
|
||||||
|
attrs = copy.deepcopy(attrs)
|
||||||
for attrname, attrvalue in attrs.items():
|
for attrname, attrvalue in attrs.items():
|
||||||
self.log("%s = %s" % (attrname, attrvalue))
|
self.log("%s = %s" % (attrname, attrvalue))
|
||||||
parent = self._stack.peek()
|
parent = self._stack.peek()
|
||||||
elt = SVGelement.construct(name, attrs)
|
elt = SVGelement.construct(name, attrs)
|
||||||
if not self._base:
|
if not self._base:
|
||||||
self._base = elt
|
self._base = elt
|
||||||
if parent:
|
if parent and elt:
|
||||||
parent.addElement(elt)
|
parent.addElement(elt)
|
||||||
self._stack.push(elt)
|
self._stack.push(elt)
|
||||||
|
|
||||||
@ -1214,6 +1264,8 @@ class SVGImportParser(object):
|
|||||||
self.log("Text = '%s'" % content.strip())
|
self.log("Text = '%s'" % content.strip())
|
||||||
elt = self._stack.peek()
|
elt = self._stack.peek()
|
||||||
if elt:
|
if elt:
|
||||||
|
if not elt.text:
|
||||||
|
elt.text = ""
|
||||||
elt.text = elt.text + content.strip()
|
elt.text = elt.text + content.strip()
|
||||||
|
|
||||||
def EndCdataSectionHandler(self):
|
def EndCdataSectionHandler(self):
|
||||||
@ -1425,16 +1477,14 @@ elementTable = {
|
|||||||
'svg': svg
|
'svg': svg
|
||||||
}
|
}
|
||||||
|
|
||||||
def main():
|
def from_file(document):
|
||||||
d=drawing()
|
|
||||||
import sys
|
import sys
|
||||||
f = open(sys.argv[1], "r")
|
f = open(sys.argv[1], "r")
|
||||||
fc = f.read()
|
fc = f.read()
|
||||||
d.fromXml(fc)
|
document.fromXml(fc)
|
||||||
print d.toXml()
|
print document.toXml()
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
def to_file(document):
|
||||||
s=svg((0,0,100,100))
|
s=svg((0,0,100,100))
|
||||||
r=rect(-100,-100,300,300,'cyan')
|
r=rect(-100,-100,300,300,'cyan')
|
||||||
s.addElement(r)
|
s.addElement(r)
|
||||||
@ -1465,10 +1515,14 @@ def main():
|
|||||||
for j in range(5,105,10):
|
for j in range(5,105,10):
|
||||||
c=circle(i,j,1,'red','black',.5)
|
c=circle(i,j,1,'red','black',.5)
|
||||||
s.addElement(c)
|
s.addElement(c)
|
||||||
d.setSVG(s)
|
document.setSVG(s)
|
||||||
|
|
||||||
print d.toXml()
|
print document.toXml()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
d=drawing()
|
||||||
|
from_file(d)
|
||||||
|
# to_file(d)
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
main()
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user