1 from __future__ import absolute_import
2 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
8 from xml.etree import ElementTree
10 from Cura.util.drawingLoader import drawing
12 def applyTransformString(matrix, transform):
13 while transform != '':
14 if transform[0] == ',':
15 transform = transform[1:].strip()
16 s = transform.find('(')
17 e = transform.find(')')
19 print 'Unknown transform: %s' % (transform)
22 data = map(float, re.split('[ \t,]+', transform[s+1:e].strip()))
23 if tag == 'matrix' and len(data) == 6:
24 matrix = numpy.matrix([[data[0],data[1],0],[data[2],data[3],0],[data[4],data[5],1]], numpy.float64) * matrix
25 elif tag == 'translate' and len(data) == 1:
26 matrix = numpy.matrix([[1,0,data[0]],[0,1,0],[0,0,1]], numpy.float64) * matrix
27 elif tag == 'translate' and len(data) == 2:
28 matrix = numpy.matrix([[1,0,0],[0,1,0],[data[0],data[1],1]], numpy.float64) * matrix
29 elif tag == 'scale' and len(data) == 1:
30 matrix = numpy.matrix([[data[0],0,0],[0,data[0],0],[0,0,1]], numpy.float64) * matrix
31 elif tag == 'scale' and len(data) == 2:
32 matrix = numpy.matrix([[data[0],0,0],[0,data[1],0],[0,0,1]], numpy.float64) * matrix
33 elif tag == 'rotate' and len(data) == 1:
34 r = math.radians(data[0])
35 matrix = numpy.matrix([[math.cos(r),math.sin(r),0],[-math.sin(r),math.cos(r),0],[0,0,1]], numpy.float64) * matrix
36 elif tag == 'rotate' and len(data) == 3:
37 matrix = numpy.matrix([[1,0,0],[0,1,0],[data[1],data[2],1]], numpy.float64) * matrix
38 r = math.radians(data[0])
39 matrix = numpy.matrix([[math.cos(r),math.sin(r),0],[-math.sin(r),math.cos(r),0],[0,0,1]], numpy.float64) * matrix
40 matrix = numpy.matrix([[1,0,0],[0,1,0],[-data[1],-data[2],1]], numpy.float64) * matrix
41 elif tag == 'skewX' and len(data) == 1:
42 matrix = numpy.matrix([[1,0,0],[math.tan(data[0]),1,0],[0,0,1]], numpy.float64) * matrix
43 elif tag == 'skewY' and len(data) == 1:
44 matrix = numpy.matrix([[1,math.tan(data[0]),0],[0,1,0],[0,0,1]], numpy.float64) * matrix
46 print 'Unknown transform: %s' % (transform)
48 transform = transform[e+1:].strip()
52 f = re.search('^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?', f).group(0)
55 class SVG(drawing.Drawing):
56 def __init__(self, filename):
57 super(SVG, self).__init__()
59 self.tagProcess['rect'] = self._processRectTag
60 self.tagProcess['line'] = self._processLineTag
61 self.tagProcess['polyline'] = self._processPolylineTag
62 self.tagProcess['polygon'] = self._processPolygonTag
63 self.tagProcess['elipse'] = self._processPolygonTag
64 self.tagProcess['circle'] = self._processCircleTag
65 self.tagProcess['ellipse'] = self._processEllipseTag
66 self.tagProcess['path'] = self._processPathTag
67 self.tagProcess['use'] = self._processUseTag
68 self.tagProcess['g'] = self._processGTag
69 self.tagProcess['a'] = self._processGTag
70 self.tagProcess['svg'] = self._processGTag
71 self.tagProcess['text'] = None #No text implementation yet
72 self.tagProcess['image'] = None
73 self.tagProcess['metadata'] = None
74 self.tagProcess['defs'] = None
75 self.tagProcess['style'] = None
76 self.tagProcess['marker'] = None
77 self.tagProcess['desc'] = None
78 self.tagProcess['filter'] = None
79 self.tagProcess['linearGradient'] = None
80 self.tagProcess['radialGradient'] = None
81 self.tagProcess['pattern'] = None
82 self.tagProcess['title'] = None
83 self.tagProcess['animate'] = None
84 self.tagProcess['animateColor'] = None
85 self.tagProcess['animateTransform'] = None
86 self.tagProcess['set'] = None
87 self.tagProcess['script'] = None
90 self.tagProcess['namedview'] = None
92 self.tagProcess['SVGTestCase'] = None
94 f = open(filename, "r")
95 self._xml = ElementTree.parse(f)
96 self._recursiveCount = 0
97 self._processGTag(self._xml.getroot(), numpy.matrix(numpy.identity(3, numpy.float64)))
101 for path in self.paths:
102 if not path.isClosed():
105 def _processGTag(self, tag, baseMatrix):
107 if e.get('transform') is None:
110 matrix = applyTransformString(baseMatrix, e.get('transform'))
111 tagName = e.tag[e.tag.find('}')+1:]
112 if not tagName in self.tagProcess:
113 print 'unknown tag: %s' % (tagName)
114 elif self.tagProcess[tagName] is not None:
115 self.tagProcess[tagName](e, matrix)
117 def _processUseTag(self, tag, baseMatrix):
118 if self._recursiveCount > 16:
120 self._recursiveCount += 1
121 id = tag.get('{http://www.w3.org/1999/xlink}href')
123 for e in self._xml.findall(".//*[@id='%s']" % (id[1:])):
124 if e.get('transform') is None:
127 matrix = applyTransformString(baseMatrix, e.get('transform'))
128 tagName = e.tag[e.tag.find('}')+1:]
129 if not tagName in self.tagProcess:
130 print 'unknown tag: %s' % (tagName)
131 elif self.tagProcess[tagName] is not None:
132 self.tagProcess[tagName](e, matrix)
133 self._recursiveCount -= 1
135 def _processLineTag(self, tag, matrix):
136 x1 = toFloat(tag.get('x1', '0'))
137 y1 = toFloat(tag.get('y1', '0'))
138 x2 = toFloat(tag.get('x2', '0'))
139 y2 = toFloat(tag.get('y2', '0'))
140 p = self.addPath(x1, y1, matrix)
143 def _processPolylineTag(self, tag, matrix):
144 values = map(toFloat, re.split('[, \t]+', tag.get('points', '').strip()))
145 p = self.addPath(values[0], values[1], matrix)
146 for n in xrange(2, len(values)-1, 2):
147 p.addLineTo(values[n], values[n+1])
149 def _processPolygonTag(self, tag, matrix):
150 values = map(toFloat, re.split('[, \t]+', tag.get('points', '').strip()))
151 p = self.addPath(values[0], values[1], matrix)
152 for n in xrange(2, len(values)-1, 2):
153 p.addLineTo(values[n], values[n+1])
156 def _processCircleTag(self, tag, matrix):
157 cx = toFloat(tag.get('cx', '0'))
158 cy = toFloat(tag.get('cy', '0'))
159 r = toFloat(tag.get('r', '0'))
160 p = self.addPath(cx-r, cy, matrix)
161 p.addArcTo(cx+r, cy, 0, r, r, False, False)
162 p.addArcTo(cx-r, cy, 0, r, r, False, False)
164 def _processEllipseTag(self, tag, matrix):
165 cx = toFloat(tag.get('cx', '0'))
166 cy = toFloat(tag.get('cy', '0'))
167 rx = toFloat(tag.get('rx', '0'))
168 ry = toFloat(tag.get('rx', '0'))
169 p = self.addPath(cx-rx, cy, matrix)
170 p.addArcTo(cx+rx, cy, 0, rx, ry, False, False)
171 p.addArcTo(cx-rx, cy, 0, rx, ry, False, False)
173 def _processRectTag(self, tag, matrix):
174 x = toFloat(tag.get('x', '0'))
175 y = toFloat(tag.get('y', '0'))
176 width = toFloat(tag.get('width', '0'))
177 height = toFloat(tag.get('height', '0'))
178 if width <= 0 or height <= 0:
182 if rx is not None or ry is not None:
197 if rx > 0 and ry > 0:
198 p = self.addPath(x+width-rx, y, matrix)
199 p.addArcTo(x+width,y+ry, 0, rx, ry, False, True)
200 p.addLineTo(x+width, y+height-ry)
201 p.addArcTo(x+width-rx,y+height, 0, rx, ry, False, True)
202 p.addLineTo(x+rx, y+height)
203 p.addArcTo(x,y+height-ry, 0, rx, ry, False, True)
205 p.addArcTo(x+rx,y, 0, rx, ry, False, True)
208 p = self.addPath(x, y, matrix)
209 p.addLineTo(x,y+height)
210 p.addLineTo(x+width,y+height)
211 p.addLineTo(x+width,y)
214 def _processPathTag(self, tag, matrix):
215 pathString = tag.get('d', '').replace(',', ' ')
221 for command in re.findall('[a-df-zA-DF-Z][^a-df-zA-DF-Z]*', pathString):
222 params = re.split(' +', command[1:].strip())
223 if len(params) > 0 and params[0] == '':
225 if len(params) > 0 and params[-1] == '':
227 params = map(toFloat, params)
233 path = self.addPath(x, y, matrix)
235 while len(params) > 1:
244 path = self.addPath(x, y, matrix)
246 while len(params) > 1:
253 while len(params) > 1:
260 while len(params) > 1:
283 while len(params) > 6:
286 path.addArcTo(x, y, params[2], params[0], params[1], params[3] > 0, params[4] > 0)
290 while len(params) > 6:
293 path.addArcTo(x, y, params[2], params[0], params[1], params[3] > 0, params[4] > 0)
297 while len(params) > 5:
304 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
307 while len(params) > 5:
314 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
317 while len(params) > 3:
324 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
327 while len(params) > 3:
334 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
337 while len(params) > 3:
344 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
347 while len(params) > 3:
354 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
357 while len(params) > 1:
364 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
367 while len(params) > 1:
374 path.addCurveTo(x, y, c1x, c1y, c2x, c2y)
376 elif command == 'z' or command == 'Z':
378 x = path._startPoint.real
379 y = path._startPoint.imag
381 print 'Unknown path command:', command, params
384 if __name__ == '__main__':
385 for n in xrange(1, len(sys.argv)):
386 print 'File: %s' % (sys.argv[n])
387 svg = SVG(sys.argv[n])
389 svg.saveAsHtml("test_export.html")