diff options
Diffstat (limited to 'share/extensions/media_zip.py')
-rwxr-xr-x | share/extensions/media_zip.py | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/share/extensions/media_zip.py b/share/extensions/media_zip.py new file mode 100755 index 0000000..9881bff --- /dev/null +++ b/share/extensions/media_zip.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 Pim Snel, pim@lingewoud.com +# Copyright (C) 2008 Aaron Spike, aaron@ekips.org +# Copyright (C) 2011 Nicolas Dufour, nicoduf@yahoo.fr +# +# * Fix for a bug related to special characters in the path (LP #456248). +# * Fix for Windows support (LP #391307 ). +# * Font list and image directory features. +# +# this is the first Python script ever created +# its based on embedimage.py +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# TODOs +# - fix bug: not saving existing .zip after a Collect for Output is run +# this bug occurs because after running an effect extension the inkscape:output_extension is reset to svg.inkscape +# the file name is still xxx.zip. after saving again the file xxx.zip is written with a plain .svg which +# looks like a corrupt zip +# - maybe add better extension +# - consider switching to lzma in order to allow cross platform compression with no encoding problem... +# +""" +An extension which collects all images to the documents directory and +creates a zip archive containing all images and the document +""" + +import os +import shutil +import tempfile +import zipfile + +import inkex +from inkex import TextElement, Tspan, FlowRoot, FlowPara, FlowSpan + +try: # PY2 + from urllib import url2pathname + from urlparse import urlparse +except ImportError: # PY3 + from urllib.parse import urlparse + from urllib.request import url2pathname + +ENCODING = "cp437" if os.name == 'nt' else "latin-1" + +class CompressedMedia(inkex.OutputExtension): + """Output a compressed file""" + def add_arguments(self, pars): + pars.add_argument("--image_dir", help="Image directory") + pars.add_argument("--font_list", type=inkex.Boolean, help="Add font list") + + def collect_images(self, docname, z): + """ + Collects all images in the document + and copy them to the temporary directory. + """ + imgdir = self.options.image_dir + + for node in self.svg.xpath('//svg:image'): + xlink = node.get('xlink:href') + if xlink[:4] != 'data': + absref = node.get('sodipodi:absref') + url = urlparse(xlink) + href = url2pathname(url.path) + + if href is not None and os.path.isfile(href): + absref = os.path.realpath(href) + + image_path = os.path.join(imgdir, os.path.basename(absref)) + + if os.path.isfile(absref): + shutil.copy(absref, self.tmp_dir) + z.write(absref, image_path.encode(ENCODING)) + elif os.path.isfile(os.path.join(self.tmp_dir, absref)): + # TODO: please explain why this clause is necessary + shutil.copy(os.path.join(self.tmp_dir, absref), self.tmp_dir) + z.write(os.path.join(self.tmp_dir, absref), image_path.encode(ENCODING)) + else: + inkex.errormsg('Could not locate file: %s' % absref) + + node.set('xlink:href', image_path) + + def collect_svg(self, docstripped, z): + """ + Copy SVG document to the temporary directory + and add it to the temporary compressed file + """ + dst_file = os.path.join(self.tmp_dir, docstripped) + with open(dst_file, 'wb') as stream: + self.document.write(stream) + z.write(dst_file, docstripped + '.svg') + + def is_text(self, node): + """ + Returns true if the tag in question is an element that + can hold text. + """ + return isinstance(node, (TextElement, Tspan, FlowRoot, FlowPara, FlowSpan)) + + def get_fonts(self, node): + """ + Given a node, returns a list containing all the fonts that + the node is using. + """ + fonts = [] + s = '' + if 'style' in node.attrib: + s = dict(inkex.Style.parse_str(node.attrib['style'])) + if not s: + return fonts + + if 'font-family' in s: + if 'font-weight' in s: + fonts.append(s['font-family'] + ' ' + s['font-weight']) + else: + fonts.append(s['font-family']) + elif '-inkscape-font-specification' in s: + fonts.append(s['-inkscape-font-specification']) + return fonts + + def list_fonts(self, z): + """ + Walks through nodes, building a list of all fonts found, then + reports to the user with that list. + Based on Craig Marshall's replace_font.py + """ + nodes = [] + items = self.document.getroot().getiterator() + nodes.extend(filter(self.is_text, items)) + fonts_found = [] + for node in nodes: + for f in self.get_fonts(node): + if not f in fonts_found: + fonts_found.append(f) + findings = sorted(fonts_found) + # Write list to the temporary compressed file + filename = 'fontlist.txt' + dst_file = os.path.join(self.tmp_dir, filename) + with open(dst_file, 'w') as stream: + if len(findings) == 0: + stream.write("Didn't find any fonts in this document/selection.") + else: + if len(findings) == 1: + stream.write("Found the following font only: %s" % findings[0]) + else: + stream.write("Found the following fonts:\n%s" % '\n'.join(findings)) + z.write(dst_file, filename) + + def save(self, stream): + docname = self.svg.get('sodipodi:docname') + + if docname is None: + docname = self.options.input_file + + # TODO: replace whatever extension + docstripped = os.path.basename(docname.replace('.zip', '')) + docstripped = docstripped.replace('.svg', '') + docstripped = docstripped.replace('.svgz', '') + + # Create os temp dir + self.tmp_dir = tempfile.mkdtemp() + + # Create destination zip in same directory as the document + with zipfile.ZipFile(stream, 'w') as z: + self.collect_images(docname, z) + self.collect_svg(docstripped, z) + if self.options.font_list: + self.list_fonts(z) + +if __name__ == '__main__': + CompressedMedia().run() |