[gnome-icon-theme/one-canvas] Add one canvas conversion script (to remove it again in the next commit).
- From: Jakub Steiner <jimmac src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-icon-theme/one-canvas] Add one canvas conversion script (to remove it again in the next commit).
- Date: Mon, 6 Jul 2009 16:55:32 +0000 (UTC)
commit e231de4735edbf208876c6b042d4a6d314d6711a
Author: Benjamin Berg <benjamin sipsolutions net>
Date: Sun Jul 5 20:14:16 2009 +0100
Add one canvas conversion script (to remove it again in the next commit).
find_icons.py | 54 ++++++++++
icon_builder.py | 298 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
template.svg | 199 +++++++++++++++++++++++++++++++++++++
3 files changed, 551 insertions(+), 0 deletions(-)
---
diff --git a/find_icons.py b/find_icons.py
new file mode 100755
index 0000000..18b211a
--- /dev/null
+++ b/find_icons.py
@@ -0,0 +1,54 @@
+#! /usr/bin/env python
+"""
+License: Public Domain
+
+This scans the directory to find all icon files in an icon theme. It has an
+hardcoded list of directories to search. The scalable directory (if found)
+is assumed to contain 48x48 icons.
+"""
+
+import os
+import os.path
+import sys
+
+
+def find_icons(theme_path):
+ icons = {}
+
+ for size_dir in ['16x16', '22x22', '32x32', 'scalable', '48x48']:
+ size = size_dir
+ if size_dir == 'scalable':
+ size = "48x48"
+
+ if not os.path.exists(os.path.join(theme_path, size_dir)):
+ continue
+
+ for context in os.listdir(os.path.join(theme_path, size_dir)):
+ dir = os.path.join(theme_path, size_dir, context)
+
+ if not os.path.isdir(dir):
+ continue
+
+ for icon in os.listdir(dir):
+ if icon[-4:] == ".svg":
+ if not icons.has_key((icon[0:-4], context)):
+ icons[(icon[0:-4], context)] = {}
+
+ icons[(icon[0:-4], context)][size] = os.path.join(dir, icon)
+
+ if icon[-4:] == ".png":
+ if not icons.has_key((icon[0:-4], context)):
+ icons[(icon[0:-4], context)] = {}
+
+ if not size in icons[(icon[0:-4], context)]:
+ icons[(icon[0:-4], context)][size] = os.path.join(dir, icon)
+
+ return icons
+
+
+if __name__ == '__main__':
+ import pprint
+ icons = find_icons(sys.argv[1])
+ pprint.pprint(icons)
+ print "Number: %i" % len(icons)
+
diff --git a/icon_builder.py b/icon_builder.py
new file mode 100755
index 0000000..22f2c9a
--- /dev/null
+++ b/icon_builder.py
@@ -0,0 +1,298 @@
+#! /usr/bin/env python
+"""
+License: Public Domain
+
+This script aggregates icons onto one canvas. It is supposed to facilitate the
+conversion of icon themes to the one canvas workflow.
+
+The copyright on the template.svg belongs to Jacub Steiner.
+"""
+
+import os
+from find_icons import find_icons
+import sys
+import xml.dom.minidom
+
+icons = find_icons(sys.argv[1])
+
+
+def nodes_differ(node1, node2):
+ collision = False
+
+
+ if node1.attributes is None and node2.attributes is None:
+ return False
+ if node1.attributes is None or node2.attributes is None:
+ return True
+
+ if dict(node1.attributes).keys() != dict(node2.attributes).keys():
+ for key in dict(node1.attributes).keys():
+ if node1.getAttribute(key) != node2.getAttribute(node2):
+ return True
+
+ child1 = node1.firstChild
+ child2 = node2.firstChild
+ while child1 and child2:
+ if child1.nodeType != node1.ELEMENT_NODE:
+ child1.nextSibling
+ if child2.nodeType != node1.ELEMENT_NODE:
+ child2.nextSibling
+
+ if nodes_differ(child1, child2):
+ return True
+
+ return False
+
+ return False
+
+def parse_defs(node, defs):
+ collision = False
+ child = node.firstChild
+ while child:
+ if child.nodeType == node.ELEMENT_NODE:
+ id = child.getAttribute('id')
+
+ next_child = child.nextSibling
+ node.removeChild(child)
+ found = False
+ for def_id, definition in defs:
+ if def_id == id:
+ found = True
+ break
+ if not found:
+ defs.append((id, child))
+ else:
+ if nodes_differ(child, definition):
+ collision = True
+ child = next_child
+
+ continue
+
+ child = child.nextSibling
+ return collision
+
+def build_icon_data(icon, size, data):
+ collision = False
+ dom = xml.dom.minidom.parse(icon)
+ child = dom.firstChild
+ while child:
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "svg":
+ node = child
+ break
+ child = child.nextSibling
+
+ objects = []
+
+ pxsize = float(size.split('x')[0])
+ data["scales"][size] = (pxsize / float(node.getAttribute("width").strip('px')), \
+ pxsize / float(node.getAttribute("height").strip('px')))
+
+ child = node.firstChild
+ while child:
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "metadata":
+ sfw = child.firstChild
+ while sfw:
+ if sfw.nodeType != dom.ELEMENT_NODE or sfw.tagName != "ns:sfw":
+ sfw = sfw.nextSibling
+ continue
+
+ sliceSourceBounds = sfw.firstChild
+ while sliceSourceBounds:
+ if sliceSourceBounds.nodeType != dom.ELEMENT_NODE or sliceSourceBounds.tagName != "ns:sliceSourceBounds":
+ sliceSourceBounds = sliceSourceBounds.nextSibling
+ continue
+
+ if sliceSourceBounds.hasAttribute("y"):
+ y = float(sliceSourceBounds.getAttribute("y").strip("px"))
+ else:
+ y = 0
+ if sliceSourceBounds.hasAttribute("x"):
+ x = float(sliceSourceBounds.getAttribute("x").strip("px"))
+ else:
+ x = 0
+
+ if y != 0 or x != 0:
+ data["translates"][size] = (x, y)
+
+ sliceSourceBounds = sliceSourceBounds.nextSibling
+
+ sfw = sfw.nextSibling
+
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "defs":
+ ret = parse_defs(child, data["defs"])
+ collision = ret or collision
+
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName.find(':') == -1 \
+ and not child.tagName in ["metadata", "defs"]:
+
+ include = True
+ if child.tagName == "g":
+ group_child = child.firstChild
+ include = False
+ while group_child:
+ if group_child.nodeType == dom.ELEMENT_NODE:
+ include = True
+ break
+ group_child = group_child.nextSibling
+
+ if include:
+ next_child = child.nextSibling
+ node.removeChild(child)
+ objects.append(child)
+ child = next_child
+
+ continue
+
+ child = child.nextSibling
+
+ data["icons"][size] = objects
+ return collision
+
+
+import base64
+
+def build_size_objects(doc, node, scales, translates, icon_objects):
+ child = node.firstChild
+
+ while child:
+ if child.nodeType == node.ELEMENT_NODE and child.tagName == "g":
+ id = child.getAttribute("id")
+ size = id[1:]+"x"+id[1:]
+
+ if size in scales:
+ transform = child.getAttribute("transform")
+ transform += " scale(%f,%f)" % scales[size]
+ child.setAttribute("transform", transform)
+
+ if size in translates:
+ transform = child.getAttribute("transform")
+ transform += " translate(%f,%f)" % translates[size]
+ child.setAttribute("transform", transform)
+
+ if size in icon_objects:
+ data = icon_objects[size]
+ if isinstance(data, type("")):
+ # embed an image
+
+ image = open(data)
+ image_data = base64.b64encode(image.read())
+
+ image_node = doc.createElement("svg:image")
+ image_node.setAttribute("id", "image"+id[1:])
+ image_node.setAttribute("x", "0")
+ image_node.setAttribute("y", "0")
+ image_node.setAttribute("width", id[1:])
+ image_node.setAttribute("height", id[1:])
+ image_node.setAttribute("xlink:href", "data:image/png;base64,"+image_data)
+
+ child.appendChild(image_node)
+ else:
+ objects = data
+ for obj in objects:
+ if obj.tagName.startswith('i:'):
+ # Ignore anything from the illustrator namespace ...
+ continue
+
+ if obj.tagName != "g" and obj.hasAttribute("style") or obj.hasAttribute("transform"):
+ clone = obj.cloneNode(True)
+ child.appendChild(clone)
+
+ continue
+
+ group_child = obj.firstChild
+ while group_child:
+ clone = group_child.cloneNode(True)
+ child.appendChild(clone)
+
+ group_child = group_child.nextSibling
+
+ child = child.nextSibling
+
+def build_icon(name, context, data):
+
+ dom = xml.dom.minidom.parse(os.path.join(os.path.dirname(__file__), "template.svg"))
+
+ child = dom.firstChild
+ while child:
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "svg":
+ node = child
+ break
+ child = child.nextSibling
+
+ child = node.firstChild
+ while child:
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "defs":
+ for def_id, definition in data["defs"]:
+ child.appendChild(definition)
+
+ if child.nodeType == dom.ELEMENT_NODE and child.tagName == "g":
+ id = child.getAttribute("id")
+ if id == "layer6":
+ rect = child.firstChild
+ while rect:
+ if rect.nodeType != dom.ELEMENT_NODE or rect.tagName != "rect":
+ rect = rect.nextSibling
+ continue
+ size = rect.getAttribute("inkscape:label")
+ if not data["icons"].has_key(size):
+ next = rect.nextSibling
+
+ child.removeChild(rect)
+
+ rect = next
+ continue
+ rect = rect.nextSibling
+ else:
+ #child.setAttribute("inkscape:label", "artwork:"+ name)
+ build_size_objects(dom, child, data["scales"], data["translates"], data["icons"])
+
+
+ child = child.nextSibling
+
+
+ # Replace the strings
+ for in_node in node.getElementsByTagName("text"):
+ if in_node.getAttribute("inkscape:label") == "icon-name":
+ span = in_node.getElementsByTagName("tspan")[0]
+ text = span.firstChild
+ assert text.nodeType == dom.TEXT_NODE
+
+ text.data = name
+
+
+ if in_node.getAttribute("inkscape:label") == "context":
+ span = in_node.getElementsByTagName("tspan")[0]
+ text = span.firstChild
+ assert text.nodeType == dom.TEXT_NODE
+
+ text.data = context
+
+ if not os.path.exists(os.path.join('.', 'svgs', context)):
+ os.mkdir(os.path.join('.', 'svgs', context))
+ file = open(os.path.join('.', 'svgs', context, name+".svg"), "w")
+ file.write(dom.toxml(encoding="utf-8"))
+ file.close()
+
+for icon_info, sizes in icons.iteritems():
+ data = {}
+ data["defs"] = []
+ data["icons"] = {}
+ data["scales"] = {}
+ data["translates"] = {}
+
+ if True:
+ collision = False
+ for size, file in sizes.iteritems():
+ if file[-4:] == ".svg":
+ collision = build_icon_data(file, size, data) or collision
+ else:
+ data["icons"][size] = file
+
+ if collision:
+ print "Possible def collision in icon %s" % icon_info[0]
+
+ build_icon(icon_info[0], icon_info[1], data)
+ else:
+ print "Failed for icon %s" % icon_info[0]
+ sys.exit(1)
+
diff --git a/template.svg b/template.svg
new file mode 100644
index 0000000..4da5975
--- /dev/null
+++ b/template.svg
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ height="300"
+ id="svg11300"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-ydpi="90.000000"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:version="0.46"
+ sodipodi:docname="template.svg"
+ sodipodi:version="0.32"
+ style="display:inline;enable-background:new"
+ version="1.0"
+ width="400">
+ <title
+ id="title8836">Optical Drive</title>
+ <metadata
+ id="metadata154">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ <dc:source />
+ <cc:license
+ rdf:resource="" />
+ <dc:subject>
+ <rdf:Bag />
+ </dc:subject>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ fill="#f57900"
+ gridtolerance="12"
+ guidetolerance="13"
+ height="300px"
+ id="base"
+ inkscape:current-layer="layer6"
+ inkscape:cx="144.68008"
+ inkscape:cy="87.105301"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:showpageshadow="false"
+ inkscape:snap-bbox="true"
+ inkscape:snap-nodes="true"
+ inkscape:window-height="876"
+ inkscape:window-width="968"
+ inkscape:window-x="132"
+ inkscape:window-y="8"
+ inkscape:zoom="1"
+ objecttolerance="7"
+ pagecolor="#ffffff"
+ showgrid="false"
+ stroke="#ef2929"
+ width="400px"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <inkscape:grid
+ enabled="true"
+ id="grid5883"
+ spacingx="0.5px"
+ spacingy="0.5px"
+ type="xygrid"
+ visible="true"
+ empspacing="2" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3" />
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ height="48"
+ id="rect6284"
+ inkscape:label="48x48"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="48"
+ x="296"
+ y="50" />
+ <rect
+ height="32"
+ id="rect6592"
+ inkscape:label="32x32"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="32"
+ x="303"
+ y="126" />
+ <rect
+ height="22"
+ id="rect6749"
+ inkscape:label="22x22"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="22"
+ x="303"
+ y="177" />
+ <rect
+ height="16"
+ id="rect6833"
+ inkscape:label="16x16"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="16"
+ x="303"
+ y="219" />
+ <rect
+ height="24"
+ id="rect8104"
+ inkscape:label="24x24"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="24"
+ x="302"
+ y="176" />
+ <rect
+ height="256"
+ id="rect6282"
+ inkscape:label="256x256"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ width="256"
+ x="16"
+ y="28" />
+ <text
+ id="context"
+ inkscape:label="context"
+ style="font-size:18.30070686px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Bitstream Vera Sans"
+ x="20.970737"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan2716"
+ sodipodi:role="line"
+ x="20.970737"
+ y="21.513618">icon-type</tspan></text>
+ <text
+ id="icon-name"
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ style="font-size:18.30070686px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Droid Sans;-inkscape-font-specification:Droid Sans Bold"
+ x="191.97073"
+ xml:space="preserve"
+ y="21.513618"><tspan
+ id="tspan3023"
+ sodipodi:role="line"
+ x="191.97073"
+ y="21.513618">icon-name</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="small sizes"
+ style="display:inline">
+ <g
+ style="display:inline;enable-background:new"
+ id="g48"
+ transform="translate(296,50)" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g32"
+ transform="translate(303,126)" />
+ <g
+ style="display:inline;enable-background:new"
+ transform="translate(303,177)"
+ id="g22" />
+ <g
+ style="display:inline;enable-background:new"
+ id="g16"
+ transform="translate(303,219)" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="hires"
+ style="display:inline" />
+</svg>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]