diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/svg2code.py	Tue Aug 12 08:48:16 2008 +0800
@@ -0,0 +1,222 @@
+#! /usr/bin/env python
+from xml.dom.minidom import parse
+import sys
+
+svgns='http://www.w3.org/2000/svg'
+xlinkns='http://www.w3.org/1999/xlink'
+
+def translate_stops(parent, codefo, parent_id):
+    for node in parent.childNodes:
+        if node.localName == 'stop' and node.namespaceURI == svgns:
+            style = node.getAttribute('style')
+            style_props = [prop.strip() for prop in style.split(';')
+                           if prop.strip()]
+            style_kvpairs = [prop.split(':') for prop in style_props]
+            style_kvpairs = [(prop[0].strip(), prop[1].strip())
+                             for prop in style_kvpairs]
+            style_map = dict(style_kvpairs)
+
+            color = style_map['stop-color'].strip()
+            if len(color) == 7 and color[0] == '#':
+                r = float(int(color[1:3], 16)) / 255.0
+                g = float(int(color[3:5], 16)) / 255.0
+                b = float(int(color[5:7], 16)) / 255.0
+            else:
+                raise ValueError, '\'%s\' is invalid color value.' % (color)
+
+            opacity = style_map['stop-opacity']
+            offset = node.getAttribute('offset')
+            print >> codefo, 'ADD_STOP([%s], [%f, %f, %f, %f], [%f])dnl' % (
+                parent_id, r, g, b, float(opacity), float(offset))
+            pass
+        pass
+    pass
+
+def translate_linearGradient(linear, codefo, doc):
+    linear_id = linear.getAttribute('id')
+    if linear.hasAttribute('x1'):
+        x1 = float(linear.getAttribute('x1'))
+        y1 = float(linear.getAttribute('y1'))
+        x2 = float(linear.getAttribute('x2'))
+        y2 = float(linear.getAttribute('y2'))
+    else:
+        x1 = y1 = x2 = y2 = 0
+        pass
+    print >> codefo, 'ADD_LINEAR_PAINT([%s], [%f, %f, %f, %f])dnl' % (
+        linear_id, x1, y1, x2, y2)
+    translate_stops(linear, codefo, linear_id)
+
+    href = linear.getAttributeNS(xlinkns, 'href').strip()
+    if href and href[0] == '#':
+        print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (linear_id, href[1:])
+        pass
+    pass
+
+def translate_radialGradient(radial, codefo, doc):
+    radial_id = radial.getAttribute('id')
+    try:
+        cx = float(radial.getAttribute('cx'))
+        cy = float(radial.getAttribute('cy'))
+    except:
+        cx = cy = 0
+        pass
+    try:
+        r = float(radial.getAttribute('r'))
+    except:
+        r = 0.5
+        pass
+    print >> codefo, 'ADD_RADIAL_PAINT([%s], [%f, %f], %f)dnl' % (
+        radial_id, cx, cy, r)
+    translate_stops(radial, codefo, radial_id)
+
+    href = radial.getAttributeNS(xlinkns, 'href').strip()
+    if href[0] == '#':
+        print >> codefo, 'REF_STOPS([%s], [%s])dnl' % (radial_id, href[1:])
+        pass
+    pass
+
+def translate_defs(defs, codefo, doc):
+    for node in defs.childNodes:
+        if node.namespaceURI != svgns:
+            continue
+        if node.localName == 'linearGradient':
+            translate_linearGradient(node, codefo, doc)
+            pass
+        elif node.localName == 'radialGradient':
+            translate_radialGradient(node, codefo, doc)
+            pass
+        pass
+    pass
+
+def trans_color(code):
+    return int(code[1:3], 16) / 255.0, \
+        int(code[3:5], 16) / 255.0, \
+        int(code[5:7], 16) / 255.0
+
+def translate_style(node, coord_id, codefo, doc):
+    node_id = node.getAttribute('id')
+    style_str = node.getAttribute('style')
+    prop_strs = [s.strip() for s in style_str.split(';')]
+    prop_kvs = [s.split(':') for s in prop_strs if s]
+    prop_kvs = [(k.strip(), v.strip()) for k, v in prop_kvs]
+    prop_map = dict(prop_kvs)
+
+    try:
+        opacity = float(node.getAttribute('opacity'))
+    except:
+        opacity = 1.0
+        pass
+
+    if prop_map.has_key('fill'):
+        fill = prop_map['fill'].strip()
+        if fill.startswith('#') and len(fill) == 7:
+            r, g, b = trans_color(fill)
+            print >> codefo, 'FILL_SHAPE([%s], %f, %f, %f, %f)dnl' % (
+                node_id, r, g, b, opacity)
+        elif fill.startswith('url(') and fill.endswith(')'):
+            paint_id = fill[5:-1]
+            print >> codefo, 'FILL_SHAPE_WITH_PAINT([%s], [%s])dnl' % (
+                node_id, paint_id)
+        else:
+            raise ValueError, '\'%s\' is an invalid value for fill.' % (fill)
+        pass
+
+    try:
+        stroke_opacity = float(node.getAttribute('stroke-opacity'))
+    except:
+        stroke_opacity = 1.0
+        pass
+
+    if prop_map.has_key('stroke'):
+        stroke = prop_map['stroke'].strip()
+        if stroke.startswith('#') and len(stroke) == 7:
+            r, g, b = trans_color(stroke)
+            print >> codefo, 'STROKE_SHAPE([%s], %f, %f, %f, %f)dnl' % (
+                node_id, r, g, b, stroke_opacity)
+        elif stroke.startswith('url(') and stroke.endswith(')'):
+            paint_id = stroke[5:-1]
+            print >> codefo, 'STROKE_SHAPE_WITH_PAINT([%s], [%s])dnl' % (
+                node_id, paint_id)
+        else:
+            raise ValueError, '\'%s\' is an invalid value for stroke.' \
+                % (stroke)
+        pass
+    pass
+
+def translate_path(path, coord_id, codefo, doc):
+    path_id = path.getAttribute('id')
+    d = path.getAttribute('d')
+    print >> codefo, 'dnl'
+    print >> codefo, 'ADD_PATH([%s], [%s], [%s])dnl' % (path_id, d, coord_id)
+    translate_style(path, coord_id, codefo, doc)
+    pass
+
+def translate_rect(rect, coord_id, codefo, doc):
+    rect_id = rect.getAttribute('id')
+    x = float(rect.getAttribute('x'))
+    y = float(rect.getAttribute('y'))
+    width = float(rect.getAttribute('width'))
+    height = float(rect.getAttribute('height'))
+    print >> codefo, 'dnl'
+    print >> codefo, 'ADD_RECT([%s], %f, %f, %f, %f, [%s])dnl' % (
+        rect_id, x, y, width, height, coord_id)
+    translate_style(rect, coord_id, codefo, doc)
+    pass
+
+def translate_group(group, parent_id, codefo, doc):
+    group_id = group.getAttribute('id')
+    print >> codefo, 'dnl'
+    print >> codefo, 'ADD_COORD([%s], [%s])dnl' % (group_id, parent_id)
+    for node in group.childNodes:
+        if node.namespaceURI != svgns:
+            continue
+        if node.localName == 'g':
+            translate_group(node, group_id, codefo, doc)
+        elif node.localName == 'path':
+            translate_path(node, group_id, codefo, doc)
+        elif node.localName == 'rect':
+            translate_rect(node, group_id, codefo, doc)
+            pass
+        pass
+    pass
+
+def svg_2_code(dom, codefo):
+    for node in dom.childNodes:
+        if node.localName == 'svg' and node.namespaceURI == svgns:
+            break;
+        pass
+    else:
+        raise ValueErr, 'no any svg tag node.'
+    
+    svg = node
+    for node in svg.childNodes:
+        if node.localName == 'defs' and node.namespaceURI == svgns:
+            translate_defs(node, codefo, dom)
+            pass
+        elif node.localName == 'g' and node.namespaceURI == svgns:
+            translate_group(node, 'root_coord', codefo, dom)
+            pass
+        pass
+    pass
+
+if __name__ == '__main__':
+    from os import path
+    if len(sys.argv) == 3:
+        svgfn = sys.argv[1]
+        codefn = sys.argv[2]
+    elif len(sys.argv) == 2:
+        svgfn = sys.argv[1]
+        codefn = 'out.mb'
+    else:
+        print >> sys.stderr, '%s <SVG file> [<output>]' % (sys.argv[0])
+        pass
+    
+    struct_name = path.basename(svgfn).split('.')[0]
+
+    dom = parse(svgfn)
+    codefo = file(codefn, 'w+')
+    print >> codefo, 'MADBUTTERFLY([%s],[dnl' % (struct_name)
+    svg_2_code(dom, codefo)
+    print >> codefo, '])dnl'
+    pass
+