Sat, 23 Sep 2017 10:27:49 +0200
Added more default options
Code cleanup
16 | 1 | #!/usr/bin/env python |
2 | ||
3 | import logging | |
4 | import traceback | |
5 | import xml.etree.ElementTree as ET | |
6 | import simplepath | |
7 | import simpletransform | |
8 | import cubicsuperpath | |
9 | import cspsubdiv | |
10 | from bezmisc import beziersplitatt | |
11 | ||
12 | ||
13 | class svgshape(object): | |
14 | ||
15 | def __init__(self, xml_node): | |
16 | self.xml_node = xml_node | |
17 | ||
18 | def d_path(self): | |
19 | raise NotImplementedError | |
20 | ||
21 | def transformation_matrix(self): | |
22 | t = self.xml_node.get('transform') | |
23 | return simpletransform.parseTransform(t) if t is not None else None | |
24 | ||
25 | def svg_path(self): | |
26 | return "<path d=\"" + self.d_path() + "\"/>" | |
27 | ||
28 | def __str__(self): | |
29 | return self.xml_node | |
30 | ||
31 | class path(svgshape): | |
32 | def __init__(self, xml_node): | |
33 | super(path, self).__init__(xml_node) | |
34 | ||
35 | if not self.xml_node == None: | |
36 | path_el = self.xml_node | |
37 | self.d = path_el.get('d') | |
38 | else: | |
39 | self.d = None | |
40 | logging.error("path: Unable to get the attributes for %s", self.xml_node) | |
41 | ||
42 | def d_path(self): | |
43 | return self.d | |
44 | ||
45 | class rect(svgshape): | |
46 | ||
47 | def __init__(self, xml_node): | |
48 | super(rect, self).__init__(xml_node) | |
49 | ||
50 | if not self.xml_node == None: | |
51 | rect_el = self.xml_node | |
52 | self.x = float(rect_el.get('x')) if rect_el.get('x') else 0 | |
53 | self.y = float(rect_el.get('y')) if rect_el.get('y') else 0 | |
54 | self.rx = float(rect_el.get('rx')) if rect_el.get('rx') else 0 | |
55 | self.ry = float(rect_el.get('ry')) if rect_el.get('ry') else 0 | |
56 | self.width = float(rect_el.get('width')) if rect_el.get('width') else 0 | |
57 | self.height = float(rect_el.get('height')) if rect_el.get('height') else 0 | |
58 | else: | |
59 | self.x = self.y = self.rx = self.ry = self.width = self.height = 0 | |
60 | logging.error("rect: Unable to get the attributes for %s", self.xml_node) | |
61 | ||
62 | def d_path(self): | |
63 | a = list() | |
64 | a.append( ['M ', [self.x, self.y]] ) | |
65 | a.append( [' l ', [self.width, 0]] ) | |
66 | a.append( [' l ', [0, self.height]] ) | |
67 | a.append( [' l ', [-self.width, 0]] ) | |
68 | #a.append( [' l ', [self.x, self.y]] ) # CLOSE RECTANGLE! | |
69 | a.append( [' Z', []] ) | |
70 | return simplepath.formatPath(a) | |
71 | ||
72 | class ellipse(svgshape): | |
73 | ||
74 | def __init__(self, xml_node): | |
75 | super(ellipse, self).__init__(xml_node) | |
76 | ||
77 | if not self.xml_node == None: | |
78 | ellipse_el = self.xml_node | |
79 | self.cx = float(ellipse_el.get('cx')) if ellipse_el.get('cx') else 0 | |
80 | self.cy = float(ellipse_el.get('cy')) if ellipse_el.get('cy') else 0 | |
81 | self.rx = float(ellipse_el.get('rx')) if ellipse_el.get('rx') else 0 | |
82 | self.ry = float(ellipse_el.get('ry')) if ellipse_el.get('ry') else 0 | |
83 | else: | |
84 | self.cx = self.cy = self.rx = self.ry = 0 | |
85 | logging.error("ellipse: Unable to get the attributes for %s", self.xml_node) | |
86 | ||
87 | def d_path(self): | |
88 | x1 = self.cx - self.rx | |
89 | x2 = self.cx + self.rx | |
90 | p = 'M %f,%f ' % ( x1, self.cy ) + \ | |
91 | 'A %f,%f ' % ( self.rx, self.ry ) + \ | |
92 | '0 1 0 %f,%f ' % ( x2, self.cy ) + \ | |
93 | 'A %f,%f ' % ( self.rx, self.ry ) + \ | |
94 | '0 1 0 %f,%f' % ( x1, self.cy ) | |
95 | return p | |
96 | ||
97 | class circle(ellipse): | |
98 | def __init__(self, xml_node): | |
99 | super(ellipse, self).__init__(xml_node) | |
100 | ||
101 | if not self.xml_node == None: | |
102 | circle_el = self.xml_node | |
103 | self.cx = float(circle_el.get('cx')) if circle_el.get('cx') else 0 | |
104 | self.cy = float(circle_el.get('cy')) if circle_el.get('cy') else 0 | |
105 | self.rx = float(circle_el.get('r')) if circle_el.get('r') else 0 | |
106 | self.ry = self.rx | |
107 | else: | |
108 | self.cx = self.cy = self.r = 0 | |
109 | logging.error("Circle: Unable to get the attributes for %s", self.xml_node) | |
110 | ||
111 | class line(svgshape): | |
112 | ||
113 | def __init__(self, xml_node): | |
114 | super(line, self).__init__(xml_node) | |
115 | ||
116 | if not self.xml_node == None: | |
117 | line_el = self.xml_node | |
118 | self.x1 = float(line_el.get('x1')) if line_el.get('x1') else 0 | |
119 | self.y1 = float(line_el.get('y1')) if line_el.get('y1') else 0 | |
120 | self.x2 = float(line_el.get('x2')) if line_el.get('x2') else 0 | |
121 | self.y2 = float(line_el.get('y2')) if line_el.get('y2') else 0 | |
122 | else: | |
123 | self.x1 = self.y1 = self.x2 = self.y2 = 0 | |
124 | logging.error("line: Unable to get the attributes for %s", self.xml_node) | |
125 | ||
126 | def d_path(self): | |
127 | a = [] | |
128 | a.append( ['M ', [self.x1, self.y1]] ) | |
129 | a.append( ['L ', [self.x2, self.y2]] ) | |
130 | return simplepath.formatPath(a) | |
131 | ||
132 | class polycommon(svgshape): | |
133 | ||
134 | def __init__(self, xml_node, polytype): | |
135 | super(polycommon, self).__init__(xml_node) | |
136 | self.points = list() | |
137 | if not self.xml_node == None: | |
138 | polycommon_el = self.xml_node | |
139 | points = polycommon_el.get('points') if polycommon_el.get('points') else list() | |
140 | points = points.split() | |
141 | for pa in points: | |
142 | self.points.append(pa) | |
143 | else: | |
144 | logging.error("polycommon: Unable to get the attributes for %s", self.xml_node) | |
145 | ||
146 | ||
147 | class polygon(polycommon): | |
148 | ||
149 | def __init__(self, xml_node): | |
150 | super(polygon, self).__init__(xml_node, 'polygon') | |
151 | ||
152 | def d_path(self): | |
153 | d = "M " + self.points[0] | |
154 | for i in range( 1, len(self.points) ): | |
155 | d += " L " + self.points[i] | |
156 | d += " Z" | |
157 | return d | |
158 | ||
159 | class polyline(polycommon): | |
160 | ||
161 | def __init__(self, xml_node): | |
162 | super(polyline, self).__init__(xml_node, 'polyline') | |
163 | ||
164 | def d_path(self): | |
165 | d = "M " + self.points[0] | |
166 | for i in range( 1, len(self.points) ): | |
167 | d += " L " + self.points[i] | |
168 | return d | |
169 | ||
170 | def point_generator(path, mat, flatness): | |
171 | simple_path = simplepath.parsePath(path) | |
172 | ||
173 | if len(simple_path) == 0: | |
174 | return | |
175 | ||
176 | startX,startY = float(simple_path[0][1][0]), float(simple_path[0][1][1]) | |
177 | yield startX, startY, False | |
178 | ||
179 | p = cubicsuperpath.parsePath(path) | |
180 | ||
181 | if mat: | |
182 | simpletransform.applyTransformToPath(mat, p) | |
183 | ||
184 | for sp in p: | |
185 | cspsubdiv.subdiv( sp, flatness) | |
186 | pen = False | |
187 | for csp in sp: | |
188 | ctrl_pt1 = csp[0] | |
189 | ctrl_pt2 = csp[1] | |
190 | end_pt = csp[2] | |
191 | yield end_pt[0], end_pt[1], pen | |
192 | if not pen: pen = True |