Mercurial > MadButterfly
comparison tools/svg2code.py @ 62:7d976d925431
Generate C header files for SVG files.
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Tue, 12 Aug 2008 08:48:16 +0800 |
parents | |
children | f4b792afa74e |
comparison
equal
deleted
inserted
replaced
61:db5f203d7c19 | 62:7d976d925431 |
---|---|
1 #! /usr/bin/env python | |
2 from xml.dom.minidom import parse | |
3 import sys | |
4 | |
5 svgns='http://www.w3.org/2000/svg' | |
6 xlinkns='http://www.w3.org/1999/xlink' | |
7 | |
8 def translate_stops(parent, codefo, parent_id): | |
9 for node in parent.childNodes: | |
10 if node.localName == 'stop' and node.namespaceURI == svgns: | |
11 style = node.getAttribute('style') | |
12 style_props = [prop.strip() for prop in style.split(';') | |
13 if prop.strip()] | |
14 style_kvpairs = [prop.split(':') for prop in style_props] | |
15 style_kvpairs = [(prop[0].strip(), prop[1].strip()) | |
16 for prop in style_kvpairs] | |
17 style_map = dict(style_kvpairs) | |
18 | |
19 color = style_map['stop-color'].strip() | |
20 if len(color) == 7 and color[0] == '#': | |
21 r = float(int(color[1:3], 16)) / 255.0 | |
22 g = float(int(color[3:5], 16)) / 255.0 | |
23 b = float(int(color[5:7], 16)) / 255.0 | |
24 else: | |
25 raise ValueError, '\'%s\' is invalid color value.' % (color) | |
26 | |
27 opacity = style_map['stop-opacity'] | |
28 offset = node.getAttribute('offset') | |
29 print >> codefo, 'ADD_STOP([%s], [%f, %f, %f, %f], [%f])dnl' % ( | |
30 parent_id, r, g, b, float(opacity), float(offset)) | |
31 pass | |
32 pass | |
33 pass | |
34 | |
35 def translate_linearGradient(linear, codefo, doc): | |
36 linear_id = linear.getAttribute('id') | |
37 if linear.hasAttribute('x1'): | |
38 x1 = float(linear.getAttribute('x1')) | |
39 y1 = float(linear.getAttribute('y1')) | |
40 x2 = float(linear.getAttribute('x2')) | |
41 y2 = float(linear.getAttribute('y2')) | |
42 else: | |
43 x1 = y1 = x2 = y2 = 0 | |
44 pass | |
45 print >> codefo, 'ADD_LINEAR_PAINT([%s], [%f, %f, %f, %f])dnl' % ( | |
46 linear_id, x1, y1, x2, y2) | |
47 translate_stops(linear, codefo, linear_id) | |
48 | |
49 href = linear.getAttributeNS(xlinkns, 'href').strip() | |
50 if href and href[0] == '#': | |
51 print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (linear_id, href[1:]) | |
52 pass | |
53 pass | |
54 | |
55 def translate_radialGradient(radial, codefo, doc): | |
56 radial_id = radial.getAttribute('id') | |
57 try: | |
58 cx = float(radial.getAttribute('cx')) | |
59 cy = float(radial.getAttribute('cy')) | |
60 except: | |
61 cx = cy = 0 | |
62 pass | |
63 try: | |
64 r = float(radial.getAttribute('r')) | |
65 except: | |
66 r = 0.5 | |
67 pass | |
68 print >> codefo, 'ADD_RADIAL_PAINT([%s], [%f, %f], %f)dnl' % ( | |
69 radial_id, cx, cy, r) | |
70 translate_stops(radial, codefo, radial_id) | |
71 | |
72 href = radial.getAttributeNS(xlinkns, 'href').strip() | |
73 if href[0] == '#': | |
74 print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (radial_id, href[1:]) | |
75 pass | |
76 pass | |
77 | |
78 def translate_defs(defs, codefo, doc): | |
79 for node in defs.childNodes: | |
80 if node.namespaceURI != svgns: | |
81 continue | |
82 if node.localName == 'linearGradient': | |
83 translate_linearGradient(node, codefo, doc) | |
84 pass | |
85 elif node.localName == 'radialGradient': | |
86 translate_radialGradient(node, codefo, doc) | |
87 pass | |
88 pass | |
89 pass | |
90 | |
91 def trans_color(code): | |
92 return int(code[1:3], 16) / 255.0, \ | |
93 int(code[3:5], 16) / 255.0, \ | |
94 int(code[5:7], 16) / 255.0 | |
95 | |
96 def translate_style(node, coord_id, codefo, doc): | |
97 node_id = node.getAttribute('id') | |
98 style_str = node.getAttribute('style') | |
99 prop_strs = [s.strip() for s in style_str.split(';')] | |
100 prop_kvs = [s.split(':') for s in prop_strs if s] | |
101 prop_kvs = [(k.strip(), v.strip()) for k, v in prop_kvs] | |
102 prop_map = dict(prop_kvs) | |
103 | |
104 try: | |
105 opacity = float(node.getAttribute('opacity')) | |
106 except: | |
107 opacity = 1.0 | |
108 pass | |
109 | |
110 if prop_map.has_key('fill'): | |
111 fill = prop_map['fill'].strip() | |
112 if fill.startswith('#') and len(fill) == 7: | |
113 r, g, b = trans_color(fill) | |
114 print >> codefo, 'FILL_SHAPE([%s], %f, %f, %f, %f)dnl' % ( | |
115 node_id, r, g, b, opacity) | |
116 elif fill.startswith('url(') and fill.endswith(')'): | |
117 paint_id = fill[5:-1] | |
118 print >> codefo, 'FILL_SHAPE_WITH_PAINT([%s], [%s])dnl' % ( | |
119 node_id, paint_id) | |
120 else: | |
121 raise ValueError, '\'%s\' is an invalid value for fill.' % (fill) | |
122 pass | |
123 | |
124 try: | |
125 stroke_opacity = float(node.getAttribute('stroke-opacity')) | |
126 except: | |
127 stroke_opacity = 1.0 | |
128 pass | |
129 | |
130 if prop_map.has_key('stroke'): | |
131 stroke = prop_map['stroke'].strip() | |
132 if stroke.startswith('#') and len(stroke) == 7: | |
133 r, g, b = trans_color(stroke) | |
134 print >> codefo, 'STROKE_SHAPE([%s], %f, %f, %f, %f)dnl' % ( | |
135 node_id, r, g, b, stroke_opacity) | |
136 elif stroke.startswith('url(') and stroke.endswith(')'): | |
137 paint_id = stroke[5:-1] | |
138 print >> codefo, 'STROKE_SHAPE_WITH_PAINT([%s], [%s])dnl' % ( | |
139 node_id, paint_id) | |
140 else: | |
141 raise ValueError, '\'%s\' is an invalid value for stroke.' \ | |
142 % (stroke) | |
143 pass | |
144 pass | |
145 | |
146 def translate_path(path, coord_id, codefo, doc): | |
147 path_id = path.getAttribute('id') | |
148 d = path.getAttribute('d') | |
149 print >> codefo, 'dnl' | |
150 print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id) | |
151 translate_style(path, coord_id, codefo, doc) | |
152 pass | |
153 | |
154 def translate_rect(rect, coord_id, codefo, doc): | |
155 rect_id = rect.getAttribute('id') | |
156 x = float(rect.getAttribute('x')) | |
157 y = float(rect.getAttribute('y')) | |
158 width = float(rect.getAttribute('width')) | |
159 height = float(rect.getAttribute('height')) | |
160 print >> codefo, 'dnl' | |
161 print >> codefo, 'ADD_RECT([%s], %f, %f, %f, %f, [%s])dnl' % ( | |
162 rect_id, x, y, width, height, coord_id) | |
163 translate_style(rect, coord_id, codefo, doc) | |
164 pass | |
165 | |
166 def translate_group(group, parent_id, codefo, doc): | |
167 group_id = group.getAttribute('id') | |
168 print >> codefo, 'dnl' | |
169 print >> codefo, 'ADD_COORD([%s], [%s])dnl' % (group_id, parent_id) | |
170 for node in group.childNodes: | |
171 if node.namespaceURI != svgns: | |
172 continue | |
173 if node.localName == 'g': | |
174 translate_group(node, group_id, codefo, doc) | |
175 elif node.localName == 'path': | |
176 translate_path(node, group_id, codefo, doc) | |
177 elif node.localName == 'rect': | |
178 translate_rect(node, group_id, codefo, doc) | |
179 pass | |
180 pass | |
181 pass | |
182 | |
183 def svg_2_code(dom, codefo): | |
184 for node in dom.childNodes: | |
185 if node.localName == 'svg' and node.namespaceURI == svgns: | |
186 break; | |
187 pass | |
188 else: | |
189 raise ValueErr, 'no any svg tag node.' | |
190 | |
191 svg = node | |
192 for node in svg.childNodes: | |
193 if node.localName == 'defs' and node.namespaceURI == svgns: | |
194 translate_defs(node, codefo, dom) | |
195 pass | |
196 elif node.localName == 'g' and node.namespaceURI == svgns: | |
197 translate_group(node, 'root_coord', codefo, dom) | |
198 pass | |
199 pass | |
200 pass | |
201 | |
202 if __name__ == '__main__': | |
203 from os import path | |
204 if len(sys.argv) == 3: | |
205 svgfn = sys.argv[1] | |
206 codefn = sys.argv[2] | |
207 elif len(sys.argv) == 2: | |
208 svgfn = sys.argv[1] | |
209 codefn = 'out.mb' | |
210 else: | |
211 print >> sys.stderr, '%s <SVG file> [<output>]' % (sys.argv[0]) | |
212 pass | |
213 | |
214 struct_name = path.basename(svgfn).split('.')[0] | |
215 | |
216 dom = parse(svgfn) | |
217 codefo = file(codefn, 'w+') | |
218 print >> codefo, 'MADBUTTERFLY([%s],[dnl' % (struct_name) | |
219 svg_2_code(dom, codefo) | |
220 print >> codefo, '])dnl' | |
221 pass | |
222 |