the icon rendering script from Joel had a function to invoke Inkscape; it seems this was a leftover from earlier attempts to render the icons. Now, we seem to rely on lib Cairor solely
183 lines
6.1 KiB
Python
Executable file
183 lines
6.1 KiB
Python
Executable file
#!/usr/bin/python
|
|
#
|
|
# IconSvgRenderer.py - Icon rendering utility script
|
|
#
|
|
# Copyright (C) Lumiera.org
|
|
# 2008, Joel Holdsworth <joel@airwebreathe.org.uk>
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License as
|
|
# published by the Free Software Foundation; either version 2 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
import os
|
|
import sys
|
|
import getopt
|
|
import shutil
|
|
from xml.dom import minidom
|
|
|
|
|
|
rsvgPath = "./rsvg-convert"
|
|
artworkLayerPrefix = "artwork:"
|
|
|
|
#
|
|
# 2/2011 some notes by Ichthyo
|
|
# The purpose of this python script is
|
|
# - to parse a SVG
|
|
# - to invoke Inkscape to render this SVG into a raster image (icon)
|
|
#
|
|
# For the actual Cairo based SVG rendering we rely on an executable 'rsvg-convert',
|
|
# which is built during the Lumiera build process.
|
|
#
|
|
# Judging from the code and the actual SVGs, this seems to work as follows:
|
|
# The SVG contains a design to be rendered into raster images of various sizes.
|
|
# These sizes are determined by special rectangles, which act as bounding box and
|
|
# are placed on a special 'plate' layer, which is a child layer of the main
|
|
# 'artwork:' layer. The grid of the SVG is setup such as to result in pixel sizes
|
|
# suitable for icon generation. The actual size of the generated icons are then
|
|
# parsed from the height and width attributes of the mentioned bounding box
|
|
# rectangles.
|
|
#
|
|
# The parser seems to be rather simplistic; the sizes and positions need to be
|
|
# integral numbers. In one instance we had a float number in the y coordinate,
|
|
# which resulted in an invalid, zero sized output icon
|
|
#
|
|
#
|
|
|
|
|
|
def createDirectory( name ):
|
|
try:
|
|
if os.path.isfile(name):
|
|
os.remove(name)
|
|
if not os.path.exists(name):
|
|
os.mkdir(name)
|
|
except:
|
|
print 'WARNING: createDirectory("%s") failed. Permission problems?' % name
|
|
|
|
|
|
def copyMergeDirectory( src, dst ):
|
|
listing = os.listdir(src)
|
|
for file_name in listing:
|
|
src_file_path = os.path.join(src, file_name)
|
|
dst_file_path = os.path.join(dst, file_name)
|
|
shutil.copyfile(src_file_path, dst_file_path)
|
|
|
|
def getDocumentSize( svg_element ):
|
|
width = float(svg_element.getAttribute("width"))
|
|
height = float(svg_element.getAttribute("height"))
|
|
return [width, height]
|
|
|
|
def findChildLayerElement( parent_element ):
|
|
for node in parent_element.childNodes:
|
|
if node.nodeType == minidom.Node.ELEMENT_NODE:
|
|
if node.tagName == "g":
|
|
if node.getAttribute("inkscape:groupmode") == "layer":
|
|
return node
|
|
return None
|
|
|
|
def parsePlateLayer( layer ):
|
|
rectangles = []
|
|
for node in layer.childNodes:
|
|
if node.nodeType == minidom.Node.ELEMENT_NODE:
|
|
if node.tagName == "rect":
|
|
x = float(node.getAttribute("x"))
|
|
y = float(node.getAttribute("y"))
|
|
width = float(node.getAttribute("width"))
|
|
height = float(node.getAttribute("height"))
|
|
rectangles.append([x, y, width, height])
|
|
return rectangles
|
|
|
|
def parseSVG( file_path ):
|
|
print "Parsing " + file_path
|
|
svgdoc = minidom.parse(file_path)
|
|
for root_node in svgdoc.childNodes:
|
|
if root_node.nodeType == minidom.Node.ELEMENT_NODE:
|
|
if root_node.tagName == "svg":
|
|
size = getDocumentSize( root_node )
|
|
layer = findChildLayerElement( root_node )
|
|
if layer != None:
|
|
layer_name = layer.getAttribute("inkscape:label")
|
|
if layer_name[:len(artworkLayerPrefix)] == artworkLayerPrefix:
|
|
artwork_name = layer_name[len(artworkLayerPrefix):]
|
|
plate = findChildLayerElement( layer )
|
|
if plate != None:
|
|
return artwork_name, size, parsePlateLayer( plate )
|
|
return None
|
|
|
|
def renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size):
|
|
# Prepare a Cairo context
|
|
width = int(rectangle[2])
|
|
height = int(rectangle[3])
|
|
|
|
if not os.path.exists(rsvgPath):
|
|
print "Error: executable %s not found." % rsvgPath
|
|
|
|
os.spawnlp(os.P_WAIT, rsvgPath, rsvgPath,
|
|
"--source-rect=%g:%g:%g:%g" % (rectangle[0], rectangle[1], rectangle[2], rectangle[3]),
|
|
"--output=" + os.path.join(out_dir, "%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name)),
|
|
file_path)
|
|
|
|
def renderSvgIcon(file_path, out_dir):
|
|
artwork_name, doc_size, rectangles = parseSVG(file_path)
|
|
for rectangle in rectangles:
|
|
renderSvgRsvg(file_path, out_dir, artwork_name, rectangle, doc_size)
|
|
|
|
def getTargetNames(file_path):
|
|
"""get a list of target names to be rendered from the given source SVG
|
|
usable to setup the build targets for SCons
|
|
"""
|
|
artwork_name, _ , rectangles = parseSVG(file_path)
|
|
return ["%gx%g/%s.png" % (rectangle[2], rectangle[3], artwork_name) for rectangle in rectangles ]
|
|
|
|
|
|
def printHelp():
|
|
print "render-icon.py SRCFILE.svg TARGETDIR"
|
|
print "An icon rendering utility script for lumiera"
|
|
|
|
def parseArguments(argv):
|
|
optlist, args = getopt.getopt(argv, "")
|
|
|
|
if len(args) == 2:
|
|
return args[0], args[1]
|
|
|
|
printHelp()
|
|
return None, None
|
|
|
|
def main(argv):
|
|
in_path, out_dir = parseArguments(argv)
|
|
|
|
if not (in_path and out_dir):
|
|
print "Missing arguments in_path and out_dir."
|
|
sys.exit(1)
|
|
|
|
if os.path.isfile(out_dir):
|
|
print "Unable to use '%s' as output directory, because it\'s a file." % out_dir
|
|
sys.exit(1)
|
|
if not os.path.isdir(out_dir):
|
|
print "Output directory '%s' not found." % out_dir
|
|
sys.exit(1)
|
|
|
|
# Create the icons folders
|
|
createDirectory(os.path.join(out_dir, "48x48"))
|
|
createDirectory(os.path.join(out_dir, "32x32"))
|
|
createDirectory(os.path.join(out_dir, "24x24"))
|
|
createDirectory(os.path.join(out_dir, "22x22"))
|
|
createDirectory(os.path.join(out_dir, "16x16"))
|
|
|
|
renderSvgIcon(in_path, out_dir)
|
|
|
|
# Copy in prerendered icons
|
|
#copyPrerenderedIcons()
|
|
|
|
if __name__=="__main__":
|
|
main(sys.argv[1:])
|
|
|