svg2gcode/svg/svg.py

Fri, 22 Sep 2017 17:38:36 +0200

author
mdd
date
Fri, 22 Sep 2017 17:38:36 +0200
changeset 31
92035ebc4743
parent 12
a90b8113be25
permissions
-rw-r--r--

ModuleWatcher code embed, doesnt work on windows os

2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
1 # SVG parser in Python
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
3 # Copyright (C) 2013 -- CJlano < cjlano @ free.fr >
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
4
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
5 # This program is free software; you can redistribute it and/or modify
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
6 # it under the terms of the GNU General Public License as published by
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
7 # the Free Software Foundation; either version 2 of the License, or
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
8 # (at your option) any later version.
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
9 #
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
10 # This program is distributed in the hope that it will be useful,
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
13 # GNU General Public License for more details.
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
14 #
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
15 # You should have received a copy of the GNU General Public License along
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
16 # with this program; if not, write to the Free Software Foundation, Inc.,
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
18
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
19 from __future__ import absolute_import
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
20 import sys
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
21 import os
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
22 import copy
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
23 import re
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
24 import xml.etree.ElementTree as etree
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
25 import itertools
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
26 import operator
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
27 import json
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
28 from .geometry import *
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
29
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
30 svg_ns = '{http://www.w3.org/2000/svg}'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
31
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
32 # Regex commonly used
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
33 number_re = r'[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
34 unit_re = r'em|ex|px|in|cm|mm|pt|pc|%'
3
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
35 point_re = r'(?:\d+(?:\.\d*)?|\.\d+),(?:\d+(?:\.\d*)?|\.\d+)'
2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
36
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
37 # Unit converter
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
38 unit_convert = {
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
39 None: 1, # Default unit (same as pixel)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
40 'px': 1, # px: pixel. Default SVG unit
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
41 'em': 10, # 1 em = 10 px FIXME
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
42 'ex': 5, # 1 ex = 5 px FIXME
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
43 'in': 96, # 1 in = 96 px
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
44 'cm': 96 / 2.54, # 1 cm = 1/2.54 in
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
45 'mm': 96 / 25.4, # 1 mm = 1/25.4 in
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
46 'pt': 96 / 72.0, # 1 pt = 1/72 in
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
47 'pc': 96 / 6.0, # 1 pc = 1/6 in
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
48 '%' : 1 / 100.0 # 1 percent
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
49 }
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
50
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
51 class Transformable:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
52 '''Abstract class for objects that can be geometrically drawn & transformed'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
53 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
54 # a 'Transformable' is represented as a list of Transformable items
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
55 self.items = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
56 self.id = hex(id(self))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
57 # Unit transformation matrix on init
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
58 self.matrix = Matrix()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
59 self.viewport = Point(800, 600) # default viewport is 800x600
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
60 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
61 self.id = elt.get('id', self.id)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
62 # Parse transform attibute to update self.matrix
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
63 self.getTransformations(elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
64
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
65 def bbox(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
66 '''Bounding box'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
67 bboxes = [x.bbox() for x in self.items]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
68 xmin = min([b[0].x for b in bboxes])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
69 xmax = max([b[1].x for b in bboxes])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
70 ymin = min([b[0].y for b in bboxes])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
71 ymax = max([b[1].y for b in bboxes])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
72
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
73 return (Point(xmin,ymin), Point(xmax,ymax))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
74
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
75 # Parse transform field
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
76 def getTransformations(self, elt):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
77 t = elt.get('transform')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
78 if t is None: return
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
79
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
80 svg_transforms = [
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
81 'matrix', 'translate', 'scale', 'rotate', 'skewX', 'skewY']
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
82
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
83 # match any SVG transformation with its parameter (until final parenthese)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
84 # [^)]* == anything but a closing parenthese
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
85 # '|'.join == OR-list of SVG transformations
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
86 transforms = re.findall(
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
87 '|'.join([x + '[^)]*\)' for x in svg_transforms]), t)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
88
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
89 for t in transforms:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
90 op, arg = t.split('(')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
91 op = op.strip()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
92 # Keep only numbers
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
93 arg = [float(x) for x in re.findall(number_re, arg)]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
94 print('transform: ' + op + ' '+ str(arg))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
95
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
96 if op == 'matrix':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
97 self.matrix *= Matrix(arg)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
98
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
99 if op == 'translate':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
100 tx = arg[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
101 if len(arg) == 1: ty = 0
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
102 else: ty = arg[1]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
103 self.matrix *= Matrix([1, 0, 0, 1, tx, ty])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
104
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
105 if op == 'scale':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
106 sx = arg[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
107 if len(arg) == 1: sy = sx
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
108 else: sy = arg[1]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
109 self.matrix *= Matrix([sx, 0, 0, sy, 0, 0])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
110
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
111 if op == 'rotate':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
112 cosa = math.cos(math.radians(arg[0]))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
113 sina = math.sin(math.radians(arg[0]))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
114 if len(arg) != 1:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
115 tx, ty = arg[1:3]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
116 self.matrix *= Matrix([1, 0, 0, 1, tx, ty])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
117 self.matrix *= Matrix([cosa, sina, -sina, cosa, 0, 0])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
118 if len(arg) != 1:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
119 self.matrix *= Matrix([1, 0, 0, 1, -tx, -ty])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
120
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
121 if op == 'skewX':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
122 tana = math.tan(math.radians(arg[0]))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
123 self.matrix *= Matrix([1, 0, tana, 1, 0, 0])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
124
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
125 if op == 'skewY':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
126 tana = math.tan(math.radians(arg[0]))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
127 self.matrix *= Matrix([1, tana, 0, 1, 0, 0])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
128
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
129 def transform(self, matrix=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
130 for x in self.items:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
131 x.transform(self.matrix)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
132
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
133 def length(self, v, mode='xy'):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
134 # Handle empty (non-existing) length element
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
135 if v is None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
136 return 0
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
137
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
138 # Get length value
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
139 m = re.search(number_re, v)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
140 if m: value = m.group(0)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
141 else: raise TypeError(v + 'is not a valid length')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
142
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
143 # Get length unit
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
144 m = re.search(unit_re, v)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
145 if m: unit = m.group(0)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
146 else: unit = None
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
147
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
148 if unit == '%':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
149 if mode == 'x':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
150 return float(value) * unit_convert[unit] * self.viewport.x
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
151 if mode == 'y':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
152 return float(value) * unit_convert[unit] * self.viewport.y
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
153 if mode == 'xy':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
154 return float(value) * unit_convert[unit] * self.viewport.x # FIXME
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
155
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
156 return float(value) * unit_convert[unit]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
157
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
158 def xlength(self, x):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
159 return self.length(x, 'x')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
160 def ylength(self, y):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
161 return self.length(y, 'y')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
162
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
163 def flatten(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
164 '''Flatten the SVG objects nested list into a flat (1-D) list,
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
165 removing Groups'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
166 # http://rightfootin.blogspot.fr/2006/09/more-on-python-flatten.html
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
167 # Assigning a slice a[i:i+1] with a list actually replaces the a[i]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
168 # element with the content of the assigned list
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
169 i = 0
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
170 flat = copy.deepcopy(self.items)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
171 while i < len(flat):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
172 while isinstance(flat[i], Group):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
173 flat[i:i+1] = flat[i].items
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
174 i += 1
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
175 return flat
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
176
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
177 def scale(self, ratio):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
178 for x in self.items:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
179 x.scale(ratio)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
180 return self
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
181
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
182 def translate(self, offset):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
183 for x in self.items:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
184 x.translate(offset)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
185 return self
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
186
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
187 def rotate(self, angle):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
188 for x in self.items:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
189 x.rotate(angle)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
190 return self
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
191
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
192 class Svg(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
193 '''SVG class: use parse to parse a file'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
194 # class Svg handles the <svg> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
195 # tag = 'svg'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
196
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
197 def __init__(self, filename=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
198 Transformable.__init__(self)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
199 if filename:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
200 self.parse(filename)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
201
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
202 def parse(self, filename):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
203 self.filename = filename
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
204 tree = etree.parse(filename)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
205 self.root = tree.getroot()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
206 if self.root.tag != svg_ns + 'svg':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
207 raise TypeError('file %s does not seem to be a valid SVG file', filename)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
208
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
209 # Create a top Group to group all other items (useful for viewBox elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
210 top_group = Group()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
211 self.items.append(top_group)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
212
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
213 # SVG dimension
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
214 width = self.xlength(self.root.get('width'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
215 height = self.ylength(self.root.get('height'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
216 # update viewport
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
217 top_group.viewport = Point(width, height)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
218
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
219 # viewBox
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
220 if self.root.get('viewBox') is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
221 viewBox = re.findall(number_re, self.root.get('viewBox'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
222 sx = width / float(viewBox[2])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
223 sy = height / float(viewBox[3])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
224 tx = -float(viewBox[0])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
225 ty = -float(viewBox[1])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
226 top_group.matrix = Matrix([sx, 0, 0, sy, tx, ty])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
227
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
228 # Parse XML elements hierarchically with groups <g>
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
229 top_group.append(self.root)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
230
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
231 self.transform()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
232
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
233 def title(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
234 t = self.root.find(svg_ns + 'title')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
235 if t is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
236 return t
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
237 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
238 return os.path.splitext(os.path.basename(self.filename))[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
239
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
240 def json(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
241 return self.items
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
242
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
243
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
244 class Group(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
245 '''Handle svg <g> elements'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
246 # class Group handles the <g> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
247 tag = 'g'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
248
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
249 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
250 Transformable.__init__(self, elt)
12
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
251 if elt is not None:
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
252 self.style = elt.get('style')
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
253 else:
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
254 self.style = ''
2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
255
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
256 def append(self, element):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
257 for elt in element:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
258 elt_class = svgClass.get(elt.tag, None)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
259 if elt_class is None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
260 print('No handler for element %s' % elt.tag)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
261 continue
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
262 # instanciate elt associated class (e.g. <path>: item = Path(elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
263 item = elt_class(elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
264 # Apply group matrix to the newly created object
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
265 item.matrix = self.matrix * item.matrix
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
266 item.viewport = self.viewport
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
267
12
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
268 # inherit style from group
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
269 if item.style == '':
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
270 item.style = self.style
a90b8113be25 bugfixes
mbayer
parents: 3
diff changeset
271
2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
272 self.items.append(item)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
273 # Recursively append if elt is a <g> (group)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
274 if elt.tag == svg_ns + 'g':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
275 item.append(elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
276
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
277 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
278 return '<Group ' + self.id + '>: ' + repr(self.items)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
279
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
280 def json(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
281 return {'Group ' + self.id : self.items}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
282
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
283 class Matrix:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
284 ''' SVG transformation matrix and its operations
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
285 a SVG matrix is represented as a list of 6 values [a, b, c, d, e, f]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
286 (named vect hereafter) which represent the 3x3 matrix
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
287 ((a, c, e)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
288 (b, d, f)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
289 (0, 0, 1))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
290 see http://www.w3.org/TR/SVG/coords.html#EstablishingANewUserSpace '''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
291
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
292 def __init__(self, vect=[1, 0, 0, 1, 0, 0]):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
293 # Unit transformation vect by default
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
294 if len(vect) != 6:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
295 raise ValueError("Bad vect size %d" % len(vect))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
296 self.vect = list(vect)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
297
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
298 def __mul__(self, other):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
299 '''Matrix multiplication'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
300 if isinstance(other, Matrix):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
301 a = self.vect[0] * other.vect[0] + self.vect[2] * other.vect[1]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
302 b = self.vect[1] * other.vect[0] + self.vect[3] * other.vect[1]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
303 c = self.vect[0] * other.vect[2] + self.vect[2] * other.vect[3]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
304 d = self.vect[1] * other.vect[2] + self.vect[3] * other.vect[3]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
305 e = self.vect[0] * other.vect[4] + self.vect[2] * other.vect[5] \
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
306 + self.vect[4]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
307 f = self.vect[1] * other.vect[4] + self.vect[3] * other.vect[5] \
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
308 + self.vect[5]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
309 return Matrix([a, b, c, d, e, f])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
310
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
311 elif isinstance(other, Point):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
312 x = other.x * self.vect[0] + other.y * self.vect[2] + self.vect[4]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
313 y = other.x * self.vect[1] + other.y * self.vect[3] + self.vect[5]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
314 return Point(x,y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
315
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
316 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
317 return NotImplemented
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
318
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
319 def __str__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
320 return str(self.vect)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
321
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
322 def xlength(self, x):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
323 return x * self.vect[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
324 def ylength(self, y):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
325 return y * self.vect[3]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
326
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
327
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
328 COMMANDS = 'MmZzLlHhVvCcSsQqTtAa'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
329
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
330 class Path(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
331 '''SVG <path>'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
332 # class Path handles the <path> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
333 tag = 'path'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
334
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
335 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
336 Transformable.__init__(self, elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
337 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
338 self.style = elt.get('style')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
339 self.parse(elt.get('d'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
340
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
341 def parse(self, pathstr):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
342 """Parse path string and build elements list"""
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
343
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
344 pathlst = re.findall(number_re + r"|\ *[%s]\ *" % COMMANDS, pathstr)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
345
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
346 pathlst.reverse()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
347
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
348 command = None
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
349 current_pt = Point(0,0)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
350 start_pt = None
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
351
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
352 while pathlst:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
353 if pathlst[-1].strip() in COMMANDS:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
354 last_command = command
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
355 command = pathlst.pop().strip()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
356 absolute = (command == command.upper())
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
357 command = command.upper()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
358 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
359 if command is None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
360 raise ValueError("No command found at %d" % len(pathlst))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
361
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
362 if command == 'M':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
363 # MoveTo
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
364 x = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
365 y = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
366 pt = Point(x, y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
367 if absolute:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
368 current_pt = pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
369 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
370 current_pt += pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
371 start_pt = current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
372
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
373 self.items.append(MoveTo(current_pt))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
374
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
375 # MoveTo with multiple coordinates means LineTo
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
376 command = 'L'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
377
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
378 elif command == 'Z':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
379 # Close Path
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
380 l = Segment(current_pt, start_pt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
381 self.items.append(l)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
382
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
383
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
384 elif command in 'LHV':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
385 # LineTo, Horizontal & Vertical line
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
386 # extra coord for H,V
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
387 if absolute:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
388 x,y = current_pt.coord()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
389 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
390 x,y = (0,0)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
391
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
392 if command in 'LH':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
393 x = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
394 if command in 'LV':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
395 y = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
396
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
397 pt = Point(x, y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
398 if not absolute:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
399 pt += current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
400
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
401 self.items.append(Segment(current_pt, pt))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
402 current_pt = pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
403
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
404 elif command in 'CQ':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
405 dimension = {'Q':3, 'C':4}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
406 bezier_pts = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
407 bezier_pts.append(current_pt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
408 for i in range(1,dimension[command]):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
409 x = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
410 y = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
411 pt = Point(x, y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
412 if not absolute:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
413 pt += current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
414 bezier_pts.append(pt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
415
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
416 self.items.append(Bezier(bezier_pts))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
417 current_pt = pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
418
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
419 elif command in 'TS':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
420 # number of points to read
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
421 nbpts = {'T':1, 'S':2}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
422 # the control point, from previous Bezier to mirror
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
423 ctrlpt = {'T':1, 'S':2}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
424 # last command control
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
425 last = {'T': 'QT', 'S':'CS'}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
426
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
427 bezier_pts = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
428 bezier_pts.append(current_pt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
429
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
430 if last_command in last[command]:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
431 pt0 = self.items[-1].control_point(ctrlpt[command])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
432 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
433 pt0 = current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
434 pt1 = current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
435 # Symetrical of pt1 against pt0
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
436 bezier_pts.append(pt1 + pt1 - pt0)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
437
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
438 for i in range(0,nbpts[command]):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
439 x = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
440 y = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
441 pt = Point(x, y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
442 if not absolute:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
443 pt += current_pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
444 bezier_pts.append(pt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
445
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
446 self.items.append(Bezier(bezier_pts))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
447 current_pt = pt
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
448
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
449 elif command == 'A':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
450 rx = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
451 ry = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
452 xrot = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
453 # Arc flags are not necesarily sepatated numbers
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
454 flags = pathlst.pop().strip()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
455 large_arc_flag = flags[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
456 if large_arc_flag not in '01':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
457 print('Arc parsing failure')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
458 break
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
459
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
460 if len(flags) > 1: flags = flags[1:].strip()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
461 else: flags = pathlst.pop().strip()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
462 sweep_flag = flags[0]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
463 if sweep_flag not in '01':
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
464 print('Arc parsing failure')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
465 break
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
466
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
467 if len(flags) > 1: x = flags[1:]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
468 else: x = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
469 y = pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
470 # TODO
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
471 print('ARC: ' +
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
472 ', '.join([rx, ry, xrot, large_arc_flag, sweep_flag, x, y]))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
473 # self.items.append(
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
474 # Arc(rx, ry, xrot, large_arc_flag, sweep_flag, Point(x, y)))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
475
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
476 else:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
477 pathlst.pop()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
478
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
479 def __str__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
480 return '\n'.join(str(x) for x in self.items)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
481
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
482 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
483 return '<Path ' + self.id + '>'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
484
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
485 def segments(self, precision=0):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
486 '''Return a list of segments, each segment is ended by a MoveTo.
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
487 A segment is a list of Points'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
488 ret = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
489 # group items separated by MoveTo
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
490 for moveTo, group in itertools.groupby(self.items,
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
491 lambda x: isinstance(x, MoveTo)):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
492 # Use only non MoveTo item
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
493 if not moveTo:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
494 # Generate segments for each relevant item
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
495 seg = [x.segments(precision) for x in group]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
496 # Merge all segments into one
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
497 ret.append(list(itertools.chain.from_iterable(seg)))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
498
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
499 return ret
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
500
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
501 def simplify(self, precision):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
502 '''Simplify segment with precision:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
503 Remove any point which are ~aligned'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
504 ret = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
505 for seg in self.segments(precision):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
506 ret.append(simplify_segment(seg, precision))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
507
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
508 return ret
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
509
3
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
510
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
511 class Polygon(Transformable):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
512 '''SVG <polygon>'''
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
513 # class Path handles the <polygon> tag
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
514 tag = 'polygon'
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
515
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
516 def __init__(self, elt=None):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
517 Transformable.__init__(self, elt)
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
518 if elt is not None:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
519 self.style = elt.get('style')
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
520 self.parse(elt.get('points'))
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
521
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
522 def parse(self, pathstr):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
523 """Parse path string and build elements list"""
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
524
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
525 pathlst = re.findall(point_re, pathstr)
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
526
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
527 #pathlst.reverse()
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
528
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
529 current_pt = None
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
530 start_pt = None
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
531 while pathlst:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
532 coord = pathlst.pop().split(",")
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
533 pt = Point(coord[0], coord[1])
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
534
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
535 if start_pt:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
536 current_pt = pt
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
537 l = Segment(start_pt, current_pt)
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
538 self.items.append(l)
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
539 start_pt = current_pt
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
540 else:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
541 start_pt = pt
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
542 self.items.append(MoveTo(pt))
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
543
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
544 def __str__(self):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
545 return '\n'.join(str(x) for x in self.items)
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
546
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
547 def __repr__(self):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
548 return '<Polygon ' + self.id + '>'
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
549
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
550 def segments(self, precision=0):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
551 '''Return a list of segments, each segment is ended by a MoveTo.
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
552 A segment is a list of Points'''
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
553 ret = []
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
554 # group items separated by MoveTo
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
555 for moveTo, group in itertools.groupby(self.items,
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
556 lambda x: isinstance(x, MoveTo)):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
557 # Use only non MoveTo item
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
558 if not moveTo:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
559 # Generate segments for each relevant item
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
560 seg = [x.segments(precision) for x in group]
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
561 # Merge all segments into one
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
562 ret.append(list(itertools.chain.from_iterable(seg)))
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
563
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
564 return ret
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
565
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
566 def simplify(self, precision):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
567 '''Simplify segment with precision:
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
568 Remove any point which are ~aligned'''
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
569 ret = []
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
570 for seg in self.segments(precision):
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
571 ret.append(simplify_segment(seg, precision))
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
572
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
573 return ret
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
574
a519e3ac3849 added parser for polygon elements
mbayer
parents: 2
diff changeset
575
2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
576 class Ellipse(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
577 '''SVG <ellipse>'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
578 # class Ellipse handles the <ellipse> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
579 tag = 'ellipse'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
580
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
581 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
582 Transformable.__init__(self, elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
583 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
584 self.center = Point(self.xlength(elt.get('cx')),
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
585 self.ylength(elt.get('cy')))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
586 self.rx = self.length(elt.get('rx'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
587 self.ry = self.length(elt.get('ry'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
588 self.style = elt.get('style')
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
589
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
590 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
591 return '<Ellipse ' + self.id + '>'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
592
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
593 def bbox(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
594 '''Bounding box'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
595 pmin = self.center - Point(self.rx, self.ry)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
596 pmax = self.center + Point(self.rx, self.ry)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
597 return (pmin, pmax)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
598
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
599 def transform(self, matrix):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
600 self.center = self.matrix * self.center
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
601 self.rx = self.matrix.xlength(self.rx)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
602 self.ry = self.matrix.ylength(self.ry)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
603
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
604 def scale(self, ratio):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
605 self.center *= ratio
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
606 self.rx *= ratio
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
607 self.ry *= ratio
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
608 def translate(self, offset):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
609 self.center += offset
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
610 def rotate(self, angle):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
611 self.center = self.center.rot(angle)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
612
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
613 def P(self, t):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
614 '''Return a Point on the Ellipse for t in [0..1]'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
615 x = self.center.x + self.rx * math.cos(2 * math.pi * t)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
616 y = self.center.y + self.ry * math.sin(2 * math.pi * t)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
617 return Point(x,y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
618
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
619 def segments(self, precision=0):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
620 if max(self.rx, self.ry) < precision:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
621 return [[self.center]]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
622
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
623 p = [(0,self.P(0)), (1, self.P(1))]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
624 d = 2 * max(self.rx, self.ry)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
625
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
626 while d > precision:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
627 for (t1,p1),(t2,p2) in zip(p[:-1],p[1:]):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
628 t = t1 + (t2 - t1)/2.
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
629 d = Segment(p1, p2).pdistance(self.P(t))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
630 p.append((t, self.P(t)))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
631 p.sort(key=operator.itemgetter(0))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
632
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
633 ret = [x for t,x in p]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
634 return [ret]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
635
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
636 def simplify(self, precision):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
637 return self
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
638
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
639 # A circle is a special type of ellipse where rx = ry = radius
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
640 class Circle(Ellipse):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
641 '''SVG <circle>'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
642 # class Circle handles the <circle> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
643 tag = 'circle'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
644
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
645 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
646 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
647 elt.set('rx', elt.get('r'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
648 elt.set('ry', elt.get('r'))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
649 Ellipse.__init__(self, elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
650
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
651 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
652 return '<Circle ' + self.id + '>'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
653
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
654 class Rect(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
655 '''SVG <rect>'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
656 # class Rect handles the <rect> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
657 tag = 'rect'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
658
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
659 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
660 Transformable.__init__(self, elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
661 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
662 self.P1 = Point(self.xlength(elt.get('x')),
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
663 self.ylength(elt.get('y')))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
664
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
665 self.P2 = Point(self.P1.x + self.xlength(elt.get('width')),
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
666 self.P1.y + self.ylength(elt.get('height')))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
667
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
668 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
669 return '<Rect ' + self.id + '>'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
670
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
671 def bbox(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
672 '''Bounding box'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
673 xmin = min([p.x for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
674 xmax = max([p.x for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
675 ymin = min([p.y for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
676 ymax = max([p.y for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
677
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
678 return (Point(xmin,ymin), Point(xmax,ymax))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
679
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
680 def transform(self, matrix):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
681 self.P1 = self.matrix * self.P1
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
682 self.P2 = self.matrix * self.P2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
683
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
684 def segments(self, precision=0):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
685 # A rectangle is built with a segment going thru 4 points
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
686 ret = []
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
687 Pa = Point(self.P1.x, self.P2.y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
688 Pb = Point(self.P2.x, self.P1.y)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
689
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
690 ret.append([self.P1, Pa, self.P2, Pb, self.P1])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
691 return ret
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
692
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
693 def simplify(self, precision):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
694 return self.segments(precision)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
695
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
696 class Line(Transformable):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
697 '''SVG <line>'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
698 # class Line handles the <line> tag
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
699 tag = 'line'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
700
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
701 def __init__(self, elt=None):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
702 Transformable.__init__(self, elt)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
703 if elt is not None:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
704 self.P1 = Point(self.xlength(elt.get('x1')),
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
705 self.ylength(elt.get('y1')))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
706 self.P2 = Point(self.xlength(elt.get('x2')),
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
707 self.ylength(elt.get('y2')))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
708 self.segment = Segment(self.P1, self.P2)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
709
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
710 def __repr__(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
711 return '<Line ' + self.id + '>'
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
712
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
713 def bbox(self):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
714 '''Bounding box'''
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
715 xmin = min([p.x for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
716 xmax = max([p.x for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
717 ymin = min([p.y for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
718 ymax = max([p.y for p in (self.P1, self.P2)])
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
719
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
720 return (Point(xmin,ymin), Point(xmax,ymax))
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
721
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
722 def transform(self, matrix):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
723 self.P1 = self.matrix * self.P1
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
724 self.P2 = self.matrix * self.P2
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
725 self.segment = Segment(self.P1, self.P2)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
726
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
727 def segments(self, precision=0):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
728 return [self.segment.segments()]
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
729
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
730 def simplify(self, precision):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
731 return self.segments(precision)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
732
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
733 # overwrite JSONEncoder for svg classes which have defined a .json() method
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
734 class JSONEncoder(json.JSONEncoder):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
735 def default(self, obj):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
736 if not isinstance(obj, tuple(svgClass.values() + [Svg])):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
737 return json.JSONEncoder.default(self, obj)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
738
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
739 if not hasattr(obj, 'json'):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
740 return repr(obj)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
741
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
742 return obj.json()
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
743
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
744 ## Code executed on module load ##
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
745
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
746 # SVG tag handler classes are initialized here
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
747 # (classes must be defined before)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
748 import inspect
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
749 svgClass = {}
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
750 # Register all classes with attribute 'tag' in svgClass dict
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
751 for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
752 tag = getattr(cls, 'tag', None)
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
753 if tag:
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
754 svgClass[svg_ns + tag] = cls
660ce16822a9 added basic svg parser library
mbayer
parents:
diff changeset
755

mercurial