diff options
| author | Nicolas Dufour <nicoduf@yahoo.fr> | 2010-08-25 04:43:37 +0000 |
|---|---|---|
| committer | JazzyNico <nicoduf@yahoo.fr> | 2010-08-25 04:43:37 +0000 |
| commit | fa68c532a42cd07a563b38594be2ce20ee97ef6b (patch) | |
| tree | f8d0e6a35907b65480454b5e5738dd19b0b0fcd9 | |
| parent | Doc. Keys and mouse reference, bugtracker link fix (from SF to LP). (diff) | |
| download | inkscape-fa68c532a42cd07a563b38594be2ce20ee97ef6b.tar.gz inkscape-fa68c532a42cd07a563b38594be2ce20ee97ef6b.zip | |
Extensions. New guillotine extension (testing).
(bzr r9725)
| -rw-r--r-- | po/POTFILES.in | 2 | ||||
| -rw-r--r-- | share/extensions/Makefile.am | 2 | ||||
| -rw-r--r-- | share/extensions/guillotine.inx | 26 | ||||
| -rw-r--r-- | share/extensions/guillotine.py | 248 |
4 files changed, 278 insertions, 0 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in index 0fdec6a4e..ab7222d17 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -58,6 +58,7 @@ [type: gettext/xml] share/extensions/grid_cartesian.inx [type: gettext/xml] share/extensions/grid_polar.inx [type: gettext/xml] share/extensions/guides_creator.inx +[type: gettext/xml] share/extensions/guillotine.inx [type: gettext/xml] share/extensions/handles.inx [type: gettext/xml] share/extensions/hpgl_output.inx [type: gettext/xml] share/extensions/inkscape_help_askaquestion.inx @@ -510,6 +511,7 @@ share/extensions/web-transmit-att.py [type: gettext/xml] share/extensions/grid_cartesian.inx [type: gettext/xml] share/extensions/grid_polar.inx [type: gettext/xml] share/extensions/guides_creator.inx +[type: gettext/xml] share/extensions/guillotine.inx [type: gettext/xml] share/extensions/handles.inx [type: gettext/xml] share/extensions/hpgl_output.inx [type: gettext/xml] share/extensions/inkscape_help_askaquestion.inx diff --git a/share/extensions/Makefile.am b/share/extensions/Makefile.am index 78532f939..36a25d56f 100644 --- a/share/extensions/Makefile.am +++ b/share/extensions/Makefile.am @@ -67,6 +67,7 @@ extensions = \ grid_cartesian.py \ grid_polar.py \ guides_creator.py \ + guillotine.py \ handles.py \ hpgl_output.py \ ill2svg.pl \ @@ -221,6 +222,7 @@ modules = \ grid_cartesian.inx \ grid_polar.inx \ guides_creator.inx \ + guillotine.inx \ handles.inx \ hpgl_output.inx \ inkscape_help_askaquestion.inx \ diff --git a/share/extensions/guillotine.inx b/share/extensions/guillotine.inx new file mode 100644 index 000000000..ba88f668c --- /dev/null +++ b/share/extensions/guillotine.inx @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <_name>Guillotine</_name>
+ <id>org.inkscape.guillotine</id>
+
+ <dependency type="extension">org.inkscape.output.svg.inkscape</dependency>
+
+ <dependency type="executable" location="extensions">guillotine.py</dependency>
+ <dependency type="executable" location="extensions">inkex.py</dependency>
+
+ <param name="directory" type="string" _gui-text="Directory to save images to">~/</param>
+ <param name="image" type="string" _gui-text="Image name (without extension)">guillotined</param>
+ <param name="ignore" type="boolean" _gui-text="Ignore these settings and use export hints?">false</param>
+
+ <effect needs-live-preview="false">
+ <object-type>all</object-type>
+ <effects-menu>
+ <submenu _name="Export"/>
+ </effects-menu>
+ </effect>
+
+ <script>
+ <command reldir="extensions" interpreter="python">guillotine.py</command>
+ </script>
+
+</inkscape-extension>
diff --git a/share/extensions/guillotine.py b/share/extensions/guillotine.py new file mode 100644 index 000000000..7c43daa6d --- /dev/null +++ b/share/extensions/guillotine.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python
+'''
+guillotine.py
+
+Copyright (C) 2010 Craig Marshall, craig9 [at] gmail.com
+
+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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+-----------------------
+
+This script slices an inkscape drawing along the guides, similarly to
+the GIMP plugin called "guillotine". It can optionally export to the
+same directory as the SVG file with the same name, but with a number
+suffix. e.g.
+
+/home/foo/drawing.svg
+
+will export to:
+
+/home/foo/drawing0.png
+/home/foo/drawing1.png
+/home/foo/drawing2.png
+/home/foo/drawing3.png
+
+etc.
+
+'''
+
+import os
+import sys
+import inkex
+import simplestyle
+import locale
+
+locale.setlocale(locale.LC_ALL, '')
+
+try:
+ from subprocess import Popen, PIPE
+ bsubprocess = True
+except:
+ bsubprocess = False
+
+def float_sort(a, b):
+ '''
+ This is used to sort the horizontal and vertical guide positions,
+ which are floating point numbers, but which are held as text.
+ '''
+ return cmp(float(a), float(b))
+
+class Guillotine(inkex.Effect):
+ """Exports slices made using guides"""
+ def __init__(self):
+ inkex.Effect.__init__(self)
+ self.OptionParser.add_option("--directory", action="store",
+ type="string", dest="directory",
+ default=None, help="")
+
+ self.OptionParser.add_option("--image", action="store",
+ type="string", dest="image",
+ default=None, help="")
+
+ self.OptionParser.add_option("--ignore", action="store",
+ type="inkbool", dest="ignore",
+ default=None, help="")
+
+ def get_guides(self):
+ '''
+ Returns all guide elements as an iterable collection
+ '''
+ root = self.document.getroot()
+ guides = []
+ xpath = self.document.xpath("//sodipodi:guide",
+ namespaces=inkex.NSS)
+ for g in xpath:
+ guide = {}
+ (x, y) = g.attrib['position'].split(',')
+ if g.attrib['orientation'] == '0,1':
+ guide['orientation'] = 'horizontal'
+ guide['position'] = y
+ guides.append(guide)
+ elif g.attrib['orientation'] == '1,0':
+ guide['orientation'] = 'vertical'
+ guide['position'] = x
+ guides.append(guide)
+ return guides
+
+ def get_all_horizontal_guides(self):
+ '''
+ Returns all horizontal guides as a list of floats stored as
+ strings. Each value is the position from 0 in pixels.
+ '''
+ guides = []
+ for g in self.get_guides():
+ if g['orientation'] == 'horizontal':
+ guides.append(g['position'])
+ return guides
+
+ def get_all_vertical_guides(self):
+ '''
+ Returns all vertical guides as a list of floats stored as
+ strings. Each value is the position from 0 in pixels.
+ '''
+ guides = []
+ for g in self.get_guides():
+ if g['orientation'] == 'vertical':
+ guides.append(g['position'])
+ return guides
+
+ def get_horizontal_slice_positions(self):
+ '''
+ Make a sorted list of all horizontal guide positions,
+ including 0 and the document height, but not including
+ those outside of the canvas
+ '''
+ root = self.document.getroot()
+ horizontals = ['0']
+ height = inkex.unittouu(root.attrib['height'])
+ for h in self.get_all_horizontal_guides():
+ if h >= 0 and float(h) <= float(height):
+ horizontals.append(h)
+ horizontals.append(height)
+ horizontals.sort(cmp=float_sort)
+ return horizontals
+
+ def get_vertical_slice_positions(self):
+ '''
+ Make a sorted list of all vertical guide positions,
+ including 0 and the document width, but not including
+ those outside of the canvas.
+ '''
+ root = self.document.getroot()
+ verticals = ['0']
+ width = inkex.unittouu(root.attrib['width'])
+ for v in self.get_all_vertical_guides():
+ if v >= 0 and float(v) <= float(width):
+ verticals.append(v)
+ verticals.append(width)
+ verticals.sort(cmp=float_sort)
+ return verticals
+
+ def get_slices(self):
+ '''
+ Returns a list of all "slices" as denoted by the guides
+ on the page. Each slice is really just a 4 element list of
+ floats (stored as strings), consisting of the X and Y start
+ position and the X and Y end position.
+ '''
+ hs = self.get_horizontal_slice_positions()
+ vs = self.get_vertical_slice_positions()
+ slices = []
+ for i in range(len(hs)-1):
+ for j in range(len(vs)-1):
+ slices.append([vs[j], hs[i], vs[j+1], hs[i+1]])
+ return slices
+
+ def get_filename_parts(self):
+ '''
+ Attempts to get directory and image as passed in by the inkscape
+ dialog. If the boolean ignore flag is set, then it will ignore
+ these settings and try to use the settings from the export
+ filename.
+ '''
+
+ if self.options.ignore == False:
+ return (self.options.directory, self.options.image)
+ else:
+ '''
+ First get the export-filename from the document, if the
+ document has been exported before (TODO: Will not work if it
+ hasn't been exported yet), then uses this to return a tuple
+ consisting of the directory to export to, and the filename
+ without extension.
+ '''
+ svg = self.document.getroot()
+ att = '{http://www.inkscape.org/namespaces/inkscape}export-filename'
+ try:
+ export_file = svg.attrib[att]
+ except KeyError:
+ inkex.errormsg("To use the export hints option, you " +
+ "need to have previously exported the document. " +
+ "Otherwise no export hints exist!")
+ sys.exit(-1)
+ dirname, filename = os.path.split(export_file)
+ filename = filename.rsplit(".", 1)[0] # Without extension
+ return (dirname, filename)
+
+ def check_dir_exists(self, dir):
+ if not os.path.isdir(dir):
+ os.makedirs(dir)
+
+ def get_localised_string(self, str):
+ return locale.format("%.f", float(str), 0)
+
+ def export_slice(self, s, filename):
+ '''
+ Runs inkscape's command line interface and exports the image
+ slice from the 4 coordinates in s, and saves as the filename
+ given.
+ '''
+ svg_file = self.args[-1]
+ command = "inkscape -a %s:%s:%s:%s -e \"%s\" \"%s\" " % (self.get_localised_string(s[0]), self.get_localised_string(s[1]), self.get_localised_string(s[2]), self.get_localised_string(s[3]), filename, svg_file)
+ if bsubprocess:
+ p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
+ return_code = p.wait()
+ f = p.stdout
+ err = p.stderr
+ else:
+ _, f, err = os.open3(command)
+ f.close()
+
+ def export_slices(self, slices):
+ '''
+ Takes the slices list and passes each one with a calculated
+ filename/directory into export_slice.
+ '''
+ dirname, filename = self.get_filename_parts()
+ if dirname == '' or dirname == None:
+ dirname = './'
+ inkex.errormsg(dirname)
+ dirname = os.path.expanduser(dirname)
+ dirname = os.path.expandvars(dirname)
+ self.check_dir_exists(dirname)
+ i = 0
+ for s in slices:
+ f = dirname + os.path.sep + filename + str(i) + ".png"
+ self.export_slice(s, f)
+ i += 1
+
+ def effect(self):
+ slices = self.get_slices()
+ self.export_slices(slices)
+
+if __name__ == "__main__":
+ e = Guillotine()
+ e.affect()
+
|
