diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /share/extensions/media_zip.py | |
parent | Initial commit. (diff) | |
download | inkscape-cca66b9ec4e494c1d919bff0f71a820d8afab1fa.tar.xz inkscape-cca66b9ec4e494c1d919bff0f71a820d8afab1fa.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rwxr-xr-x | share/extensions/media_zip.py | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/share/extensions/media_zip.py b/share/extensions/media_zip.py new file mode 100755 index 0000000..82fb25d --- /dev/null +++ b/share/extensions/media_zip.py @@ -0,0 +1,209 @@ +#!/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 tempfile +import zipfile + +from typing import List, Tuple +from urllib.parse import urlparse +from urllib.request import url2pathname + +import inkex +from inkex import TextElement, Tspan, FlowRoot, FlowPara, FlowSpan +from inkex.localization import inkex_gettext as _ + + +class CompressedMedia(inkex.OutputExtension): + """Output a compressed file""" + + def __init__(self): + super().__init__() + self.path_dict = {} + + def add_arguments(self, pars): + pars.add_argument("--image_dir", help="Image directory", default="images") + pars.add_argument("--font_list", type=inkex.Boolean, help="Add font list") + + def process_path(self, path: str) -> Tuple[str, bool]: + """Processes an absolute path and returns + (unique filename, exists).""" + + if path in self.path_dict: + return os.path.split(path)[1], True + + index = 0 + pth, ext = os.path.splitext(path) + _, filename = os.path.split(pth) + trypath = filename + ext + while True: + if trypath in list(self.path_dict.values()): + index += 1 + trypath = f"{filename}{index}{ext}" + else: + self.path_dict[path] = trypath + return trypath, False + + def collect_images(self, docname, z: zipfile.ZipFile): + """ + 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": + url = urlparse(xlink) + href = url2pathname(url.path) + + image_path = self.absolute_href(href or "") + + # Backup directory where we can find the image + if not os.path.isfile(image_path): + image_path = node.get("sodipodi:absref", image_path) + + if not os.path.isfile(image_path): + inkex.errormsg( + _('File not found "{}". Unable to embed image.').format( + image_path + ) + ) + continue + else: + zippath, exists = self.process_path(image_path) + if not exists: + z.write(image_path, os.path.join(imgdir, zippath)) + + node.set("xlink:href", f"{imgdir}/{zippath}") + + def collect_svg(self, docstripped, z: zipfile.ZipFile): + """ + 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: zipfile.ZipFile): + """ + 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: List[inkex.BaseElement] = [] + items = self.svg.iterdescendants() + 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() |