00001
00002 from xml.dom.minidom import parse
00003 import sys
00004 import re
00005
00006 svgns='http://www.w3.org/2000/svg'
00007 xlinkns='http://www.w3.org/1999/xlink'
00008
00009 re_rgb = re.compile('rgb\\( *([0-9]+(\\.[0-9]+)?) *, *([0-9]+(\\.[0-9]+)?) *, *([0-9]+(\\.[0-9]+)?) *\\)')
00010 def translate_stops(parent, codefo, parent_id):
00011 stops = []
00012 for node in parent.childNodes:
00013 if node.localName == 'stop' and node.namespaceURI == svgns:
00014 style = node.getAttribute('style')
00015 style_props = [prop.strip() for prop in style.split(';')
00016 if prop.strip()]
00017 style_kvpairs = [prop.split(':') for prop in style_props]
00018 style_kvpairs = [(prop[0].strip(), prop[1].strip())
00019 for prop in style_kvpairs]
00020 style_map = dict(style_kvpairs)
00021
00022 color = style_map['stop-color'].strip()
00023 if len(color) == 7 and color[0] == '#':
00024 r = float(int(color[1:3], 16)) / 255.0
00025 g = float(int(color[3:5], 16)) / 255.0
00026 b = float(int(color[5:7], 16)) / 255.0
00027 elif color.lower() == 'white':
00028 r, g, b = 1, 1, 1
00029 elif color.lower() == 'black':
00030 r, g, b = 0, 0, 0
00031 else:
00032 mo = re_rgb.match(color)
00033 if mo:
00034 r = float(mo.group(1))
00035 g = float(mo.group(3))
00036 b = float(mo.group(5))
00037 else:
00038 raise ValueError, '\'%s\' is invalid color value.' % (color)
00039 pass
00040
00041 try:
00042 opacity = style_map['stop-opacity']
00043 except:
00044 opacity = 1
00045 pass
00046 offset = node.getAttribute('offset')
00047 stops.append('[COLOR_STOP([%s], %f, %f, %f, %f, %f)]' % (
00048 parent_id, r, g, b, float(opacity), float(offset)))
00049 pass
00050 pass
00051 print >> codefo, '%sdnl' % (', '.join(stops))
00052 pass
00053
00054 def translate_linearGradient(linear, codefo, doc):
00055 linear_id = linear.getAttribute('id')
00056 if linear.hasAttribute('x1'):
00057 x1 = float(linear.getAttribute('x1'))
00058 y1 = float(linear.getAttribute('y1'))
00059 x2 = float(linear.getAttribute('x2'))
00060 y2 = float(linear.getAttribute('y2'))
00061 else:
00062 x1 = y1 = x2 = y2 = 0
00063 pass
00064 print >> codefo, 'ADD_LINEAR_PAINT([%s], %f, %f, %f, %f, [' % (
00065 linear_id, x1, y1, x2, y2)
00066 translate_stops(linear, codefo, linear_id)
00067 print >> codefo, '])dnl'
00068
00069 href = linear.getAttributeNS(xlinkns, 'href').strip()
00070 if href and href[0] == '#':
00071 print >> codefo, 'REF_STOPS_LINEAR([%s], [%s])dnl' % (
00072 linear_id, href[1:])
00073 pass
00074 pass
00075
00076 def translate_radialGradient(radial, codefo, doc):
00077 radial_id = radial.getAttribute('id')
00078 try:
00079 cx = float(radial.getAttribute('cx'))
00080 cy = float(radial.getAttribute('cy'))
00081 except:
00082 cx = cy = 0
00083 pass
00084 try:
00085 r = float(radial.getAttribute('r'))
00086 except:
00087 r = 0.5
00088 pass
00089 print >> codefo, 'ADD_RADIAL_PAINT([%s], %f, %f, %f, [' % (
00090 radial_id, cx, cy, r)
00091 translate_stops(radial, codefo, radial_id)
00092 print >>codefo, '])dnl'
00093
00094 href = radial.getAttributeNS(xlinkns, 'href').strip()
00095 if href[0] == '#':
00096 print >> codefo, 'REF_STOPS_RADIAL([%s], [%s])dnl' % (
00097 radial_id, href[1:])
00098 pass
00099 pass
00100
00101 def translate_defs(defs, codefo, doc):
00102 for node in defs.childNodes:
00103 if node.namespaceURI != svgns:
00104 continue
00105 if node.localName == 'linearGradient':
00106 translate_linearGradient(node, codefo, doc)
00107 pass
00108 elif node.localName == 'radialGradient':
00109 translate_radialGradient(node, codefo, doc)
00110 pass
00111 pass
00112 pass
00113
00114 def trans_color(code):
00115 return int(code[1:3], 16) / 255.0, \
00116 int(code[3:5], 16) / 255.0, \
00117 int(code[5:7], 16) / 255.0
00118
00119 def get_style_map(style_str):
00120 prop_strs = [s.strip() for s in style_str.split(';')]
00121 prop_kvs = [s.split(':') for s in prop_strs if s]
00122 prop_kvs = [(k.strip(), v.strip()) for k, v in prop_kvs]
00123 prop_map = dict(prop_kvs)
00124 return prop_map
00125
00126 def translate_style(node, coord_id, codefo, doc, prefix):
00127 node_id = node.getAttribute('id')
00128 style_str = node.getAttribute('style')
00129 prop_map = get_style_map(style_str)
00130
00131 try:
00132 opacity = float(node.getAttribute('opacity'))
00133 except:
00134 opacity = 1.0
00135 pass
00136
00137 if prop_map.has_key('fill'):
00138 fill = prop_map['fill'].strip()
00139 if fill.startswith('#') and len(fill) == 7:
00140 r, g, b = trans_color(fill)
00141 print >> codefo, 'FILL_SHAPE([%s], %f, %f, %f, %f)dnl' % (
00142 node_id, r, g, b, opacity)
00143 elif fill.startswith('url(') and fill.endswith(')'):
00144 paint_id = fill[5:-1]
00145 print >> codefo, 'FILL_SHAPE_WITH_PAINT([%s], [%s])dnl' % (
00146 node_id, paint_id)
00147 elif fill.lower() == 'none':
00148 pass
00149 else:
00150 raise ValueError, '\'%s\' is an invalid value for fill.' % (fill)
00151 pass
00152
00153 try:
00154 stroke_opacity = float(node.getAttribute('stroke-opacity'))
00155 except:
00156 stroke_opacity = 1.0
00157 pass
00158
00159 if prop_map.has_key('stroke'):
00160 stroke = prop_map['stroke'].strip()
00161 if stroke.startswith('#') and len(stroke) == 7:
00162 r, g, b = trans_color(stroke)
00163 print >> codefo, 'STROKE_SHAPE([%s], %f, %f, %f, %f)dnl' % (
00164 node_id, r, g, b, stroke_opacity)
00165 elif stroke.startswith('url(') and stroke.endswith(')'):
00166 paint_id = stroke[5:-1]
00167 print >> codefo, 'STROKE_SHAPE_WITH_PAINT([%s], [%s])dnl' % (
00168 node_id, paint_id)
00169 elif stroke.lower() == 'none':
00170 pass
00171 else:
00172 raise ValueError, '\'%s\' is an invalid value for stroke.' \
00173 % (stroke)
00174 pass
00175
00176 if prop_map.has_key('stroke-width'):
00177 if prop_map['stroke-width'].endswith('px'):
00178 stroke_width = float(prop_map['stroke-width'][:-2])
00179 else:
00180 stroke_width = float(prop_map['stroke-width'])
00181 pass
00182 print >> codefo, 'STROKE_WIDTH([%s], %f)dnl' % (
00183 node_id, stroke_width)
00184 pass
00185
00186 if prop_map.has_key('display'):
00187 display = prop_map['display'].strip().lower()
00188 if display == 'none':
00189 print >> codefo, '%sHIDE([%s])dnl' % (prefix, node_id)
00190 pass
00191 pass
00192 pass
00193
00194 def translate_shape_transform(shape, coord_id, codefo):
00195 shape_id = shape.getAttribute('id')
00196
00197 if shape.hasAttribute('transform'):
00198 shape_coord_id = shape_id + '_coord'
00199
00200
00201
00202
00203
00204 print >> codefo, 'dnl'
00205 print >> codefo, 'ADD_COORD([%s], [%s])dnl' % (
00206 shape_coord_id, coord_id)
00207 transform = shape.getAttribute('transform')
00208 translate_transform(shape_coord_id, transform, codefo, 'SHAPE_')
00209 coord_id = shape_coord_id
00210 pass
00211 return coord_id
00212
00213 def translate_path(path, coord_id, codefo, doc):
00214 coord_id = translate_shape_transform(path, coord_id, codefo)
00215
00216 path_id = path.getAttribute('id')
00217 d = path.getAttribute('d')
00218 print >> codefo, 'dnl'
00219 print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id)
00220
00221 translate_style(path, coord_id, codefo, doc, 'PATH_')
00222 pass
00223
00224 def translate_rect(rect, coord_id, codefo, doc):
00225 coord_id = translate_shape_transform(rect, coord_id, codefo)
00226
00227 rect_id = rect.getAttribute('id')
00228 x = float(rect.getAttribute('x'))
00229 y = float(rect.getAttribute('y'))
00230 rx = 0.0
00231 if rect.hasAttribute('rx'):
00232 rx = float(rect.getAttribute('rx'))
00233 pass
00234 ry = 0.0
00235 if rect.hasAttribute('ry'):
00236 ry = float(rect.getAttribute('ry'))
00237 pass
00238 width = float(rect.getAttribute('width'))
00239 height = float(rect.getAttribute('height'))
00240 print >> codefo, 'dnl'
00241 print >> codefo, 'ADD_RECT([%s], %f, %f, %f, %f, %f, %f, [%s])dnl' % (
00242 rect_id, x, y, width, height, rx, ry, coord_id)
00243 translate_style(rect, coord_id, codefo, doc, 'RECT_')
00244 pass
00245
00246 def translate_font_style(text, codefo):
00247 text_id = text.getAttribute('id')
00248 style_str = text.getAttribute('style')
00249 style_map = get_style_map(style_str)
00250
00251 font_sz = 10.0
00252 if style_map.has_key('font-size'):
00253 if style_map['font-size'].endswith('px'):
00254 font_sz = float(style_map['font-size'][:-2])
00255 print >> codefo, 'define([MB_FONT_SZ], %f)dnl' % (font_sz)
00256 pass
00257 pass
00258
00259 font_style = 'normal'
00260 if style_map.has_key('font-style'):
00261 font_style = style_map['font-style'].lower()
00262 pass
00263
00264 font_family = 'Roman'
00265 if style_map.has_key('font-family'):
00266 font_family = style_map['font-family'].lower()
00267 pass
00268 pass
00269
00270 def translate_text(text, coord_id, codefo, doc):
00271 translate_font_style(text, codefo)
00272
00273 txt_strs = []
00274 for node in text.childNodes:
00275 if node.localName == None:
00276 txt_strs.append(node.data)
00277 elif node.localName == 'tspan':
00278 node.setAttribute('style', text.getAttribute('style'))
00279 translate_text(node, coord_id, codefo, doc)
00280 pass
00281 pass
00282 if txt_strs:
00283 text_id = text.getAttribute('id')
00284 x = float(text.getAttribute('x'))
00285 y = float(text.getAttribute('y'))
00286 print >> codefo, 'dnl'
00287 print >> codefo, \
00288 'ADD_TEXT([%s], [%s], %f, %f, MB_FONT_SZ, [%s])dnl' % (
00289 text_id.encode('utf8'), u''.join(txt_strs).encode('utf8'),
00290 x, y, coord_id.encode('utf8'))
00291 translate_style(text, coord_id, codefo, doc, 'TEXT_')
00292 pass
00293 pass
00294
00295 reo_func = re.compile('([a-zA-Z]+)\\([^\\)]*\\)')
00296 reo_translate = re.compile('translate\\(([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)\\)')
00297 reo_matrix = re.compile('matrix\\(([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?),([-+]?[0-9]+(\\.[0-9]+)?)\\)')
00298 def translate_transform(coord_id, transform, codefo, prefix):
00299 transform = transform.strip()
00300 mo = reo_func.match(transform)
00301 if not mo:
00302 return
00303 name = mo.group(1)
00304 if name == 'translate':
00305 mo = reo_translate.match(transform)
00306 if mo:
00307 x = float(mo.group(1))
00308 y = float(mo.group(3))
00309 print >> codefo, '%sTRANSLATE([%s], %f, %f)dnl' % (
00310 prefix, coord_id, x, y)
00311 pass
00312 elif name == 'matrix':
00313 mo = reo_matrix.match(transform)
00314 if mo:
00315 r10, r11, r12 = \
00316 float(mo.group(1)), float(mo.group(3)), float(mo.group(5))
00317 r20, r21, r22 = \
00318 float(mo.group(7)), float(mo.group(9)), float(mo.group(11))
00319 print >> codefo, \
00320 '%sMATRIX([%s], %f, %f, %f, %f, %f, %f)dnl' % (
00321 prefix, coord_id, r10, r11, r12, r20, r21, r22)
00322 pass
00323 pass
00324 pass
00325
00326 def translate_group(group, parent_id, codefo, doc):
00327 group_id = group.getAttribute('id')
00328 print >> codefo, 'dnl'
00329 print >> codefo, 'ADD_COORD([%s], [%s])dnl' % (group_id, parent_id)
00330
00331 if group.hasAttribute('transform'):
00332 transform = group.getAttribute('transform')
00333 translate_transform(group_id, transform, codefo, 'COORD_')
00334 pass
00335
00336 translate_style(group, group_id, codefo, doc, 'GROUP_')
00337 for node in group.childNodes:
00338 if node.namespaceURI != svgns:
00339 continue
00340 if node.localName == 'g':
00341 translate_group(node, group_id, codefo, doc)
00342 elif node.localName == 'path':
00343 translate_path(node, group_id, codefo, doc)
00344 elif node.localName == 'rect':
00345 translate_rect(node, group_id, codefo, doc)
00346 elif node.localName == 'text':
00347 translate_text(node, group_id, codefo, doc)
00348 pass
00349 pass
00350 pass
00351
00352 def svg_2_code(dom, codefo):
00353 for node in dom.childNodes:
00354 if node.localName == 'svg' and node.namespaceURI == svgns:
00355 break;
00356 pass
00357 else:
00358 raise ValueErr, 'no any svg tag node.'
00359
00360 svg = node
00361 for node in svg.childNodes:
00362 if node.localName == 'defs' and node.namespaceURI == svgns:
00363 translate_defs(node, codefo, dom)
00364 pass
00365 elif node.localName == 'g' and node.namespaceURI == svgns:
00366 translate_group(node, 'root_coord', codefo, dom)
00367 pass
00368 pass
00369 pass
00370
00371 if __name__ == '__main__':
00372 from os import path
00373 if len(sys.argv) == 3:
00374 svgfn = sys.argv[1]
00375 codefn = sys.argv[2]
00376 elif len(sys.argv) == 2:
00377 svgfn = sys.argv[1]
00378 codefn = 'out.mb'
00379 else:
00380 print >> sys.stderr, '%s <SVG file> [<output>]' % (sys.argv[0])
00381 pass
00382
00383 struct_name = path.basename(codefn).split('.')[0]
00384
00385 dom = parse(svgfn)
00386 codefo = file(codefn, 'w+')
00387 print >> codefo, 'MADBUTTERFLY([%s],[dnl' % (struct_name)
00388 svg_2_code(dom, codefo)
00389 print >> codefo, '])dnl'
00390 pass
00391