From b496df017de1fc96614fe384b67acae053109015 Mon Sep 17 00:00:00 2001 From: leyghisbb Date: Fri, 9 Apr 2021 19:13:32 +0200 Subject: [PATCH] added open closed path and export selection as svg --- .../fablabchemnitz/export_selection.inx | 19 ++++ extensions/fablabchemnitz/export_selection.py | 100 ++++++++++++++++++ extensions/fablabchemnitz/openClosedPath.inx | 15 +++ extensions/fablabchemnitz/openClosedPath.py | 37 +++++++ 4 files changed, 171 insertions(+) create mode 100644 extensions/fablabchemnitz/export_selection.inx create mode 100644 extensions/fablabchemnitz/export_selection.py create mode 100644 extensions/fablabchemnitz/openClosedPath.inx create mode 100644 extensions/fablabchemnitz/openClosedPath.py diff --git a/extensions/fablabchemnitz/export_selection.inx b/extensions/fablabchemnitz/export_selection.inx new file mode 100644 index 00000000..78e188bf --- /dev/null +++ b/extensions/fablabchemnitz/export_selection.inx @@ -0,0 +1,19 @@ + + + <_name>Export selection as SVG + fablabchemnitz.de.export_selection_as_svg + false + ./inkscape_export/ + + all + Export selection to separate SVG file. + + + + + + + + diff --git a/extensions/fablabchemnitz/export_selection.py b/extensions/fablabchemnitz/export_selection.py new file mode 100644 index 00000000..e3692440 --- /dev/null +++ b/extensions/fablabchemnitz/export_selection.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +from copy import deepcopy +from pathlib import Path +import logging +import math +import os + +import inkex +import inkex.command +from lxml import etree +from scour.scour import scourString + + +logger = logging.getLogger(__name__) + + +GROUP_ID = 'export_selection_transform' + + +class ExportObject(inkex.EffectExtension): + def add_arguments(self, pars): + pars.add_argument("--wrap_transform", type=inkex.Boolean, default=False, help="Wrap final document in transform") + pars.add_argument("--export_dir", default="~/inkscape_export/", help="Location to save exported documents") + + def effect(self): + if not self.svg.selected: + return + + export_dir = Path(self.absolute_href(self.options.export_dir)) + os.makedirs(export_dir, exist_ok=True) + + bbox = inkex.BoundingBox() + for elem in self.svg.selected.values(): + transform = inkex.Transform() + parent = elem.getparent() + if parent is not None and isinstance(parent, inkex.ShapeElement): + transform = parent.composed_transform() + try: + bbox += elem.bounding_box(transform) + except Exception: + logger.exception("Bounding box not computed") + logger.info("Skipping bounding box") + transform = elem.composed_transform() + x1, y1 = transform.apply_to_point([0, 0]) + x2, y2 = transform.apply_to_point([1, 1]) + bbox += inkex.BoundingBox((x1, x2), (y1, y2)) + + template = self.create_document() + filename = None + + group = etree.SubElement(template, '{http://www.w3.org/2000/svg}g') + group.attrib['id'] = GROUP_ID + group.attrib['transform'] = str(inkex.Transform(((1, 0, -bbox.left), (0, 1, -bbox.top)))) + + for elem in self.svg.selected.values(): + + elem_copy = deepcopy(elem) + elem_copy.attrib['transform'] = str(elem.composed_transform()) + group.append(elem_copy) + + width = math.ceil(bbox.width) + height = math.ceil(bbox.height) + template.attrib['viewBox'] = f'0 0 {width} {height}' + template.attrib['width'] = f'{width}' + template.attrib['height'] = f'{height}' + + if filename is None: + filename = elem.attrib.get('id', None) + if filename: + filename = filename.replace(os.sep, '_') + '.svg' + if not filename: + filename = 'element.svg' + + template.append(group) + + if not self.options.wrap_transform: + self.load(inkex.command.inkscape_command(template.tostring(), select=GROUP_ID, verbs=['SelectionUnGroup'])) + template = self.svg + for child in template.getchildren(): + if child.tag == '{http://www.w3.org/2000/svg}metadata': + template.remove(child) + + self.save_document(template, export_dir / filename) + + def create_document(self): + document = self.svg.copy() + for child in document.getchildren(): + if child.tag == '{http://www.w3.org/2000/svg}defs': + continue + document.remove(child) + return document + + def save_document(self, document, filename): + with open(filename, 'wb') as fp: + document = document.tostring() + fp.write(scourString(document).encode('utf8')) + + +if __name__ == '__main__': + ExportObject().run() \ No newline at end of file diff --git a/extensions/fablabchemnitz/openClosedPath.inx b/extensions/fablabchemnitz/openClosedPath.inx new file mode 100644 index 00000000..0233808a --- /dev/null +++ b/extensions/fablabchemnitz/openClosedPath.inx @@ -0,0 +1,15 @@ + + + Open closed Path + fablabchemnitz.de.openClosedPath + + + + + + + + + \ No newline at end of file diff --git a/extensions/fablabchemnitz/openClosedPath.py b/extensions/fablabchemnitz/openClosedPath.py new file mode 100644 index 00000000..1afb0335 --- /dev/null +++ b/extensions/fablabchemnitz/openClosedPath.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# coding=utf-8 +# +# Copyright (C) 2020 Ellen Wasboe, ellen@wasbo.net +# +# 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. +""" +Remove all z-s from all selected paths +My purpose: to open paths of single line fonts with a temporary closing to fit into .ttf/.otf format files +""" + +import inkex, re +from inkex import PathElement + +class OpenClosedPath(inkex.EffectExtension): +# Extension to open a closed path by z or by last node + + def effect(self): + elements = self.svg.selection.filter(PathElement).values() + for elem in elements: + pp=elem.path.to_absolute() #remove transformation matrix + elem.path = re.sub(r"Z","",str(pp)) + +if __name__ == '__main__': + OpenClosedPath().run()