diff --git a/lib/elements/__init__.py b/lib/elements/__init__.py index 00933f36f..bcb341e11 100644 --- a/lib/elements/__init__.py +++ b/lib/elements/__init__.py @@ -8,7 +8,6 @@ from .element import EmbroideryElement from .empty_d_object import EmptyDObject from .fill_stitch import FillStitch from .image import ImageObject -from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke from .text import TextObject diff --git a/lib/elements/polyline.py b/lib/elements/polyline.py deleted file mode 100644 index 9d17132a5..000000000 --- a/lib/elements/polyline.py +++ /dev/null @@ -1,103 +0,0 @@ -# Authors: see git history -# -# Copyright (c) 2010 Authors -# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. - -from inkex import Path -from shapely import geometry as shgeo - -from ..i18n import _ -from ..stitch_plan import StitchGroup -from ..utils import cache -from ..utils.geometry import Point -from .element import EmbroideryElement, param -from .validation import ValidationWarning - - -class PolylineWarning(ValidationWarning): - name = _("Polyline Object") - description = _("This object is an SVG PolyLine. Ink/Stitch can work with this shape, " - "but you can't edit it in Inkscape. Convert it to a manual stitch path " - "to allow editing.") - steps_to_solve = [ - _("* Select this object."), - _("* Do Path > Object to Path."), - _('* Optional: Run the Params extension and check the "manual stitch" box.') - ] - - -class Polyline(EmbroideryElement): - # Handle a element, which is treated as a set of points to - # stitch exactly. - # - # elements are pretty rare in SVG, from what I can tell. - # Anything you can do with a can also be done with a

, and - # much more. - # - # Notably, EmbroiderModder2 uses elements when converting from - # common machine embroidery file formats to SVG. Handling those here lets - # users use File -> Import to pull in existing designs they may have - # obtained, for example purchased fonts. - - element_name = "Polyline" - - @property - @param('polyline', _('Manual stitch along path'), type='toggle', inverse=True) - def polyline(self): - return self.get_boolean_param("polyline") - - @property - @cache - def shape(self): - return shgeo.MultiLineString(self.csp[0]) - - @property - def path(self): - # A polyline is a series of connected line segments described by their - # points. In order to make use of the existing logic for incorporating - # svg transforms that is in our superclass, we'll convert the polyline - # to a degenerate cubic superpath in which the bezier handles are on - # the segment endpoints. - if self.node.get('points', None): - path = self.node.get_path() - else: - # Set path to (0, 0) for empty polylines - path = 'M 0 0' - path = Path(path).to_superpath() - return path - - @property - @cache - def csp(self): - csp = self.parse_path() - - return csp - - @property - def color(self): - # EmbroiderModder2 likes to use the `stroke` property directly instead - # of CSS. - return self.get_style("stroke", "#000000") - - @property - def stitches(self): - # For a , we'll stitch the points exactly as they exist in - # the SVG, with no stitch spacing interpolation, flattening, etc. - - # See the comments in the parent class's parse_path method for a - # description of the CSP data structure. - - stitches = [point for handle_before, point, handle_after in self.csp[0]] - - return stitches - - def validation_warnings(self): - yield PolylineWarning(self.path[0][0][0]) - - def to_stitch_groups(self, last_stitch_group): - stitch_group = StitchGroup(color=self.color, lock_stitches=(None, None)) - - for stitch in self.stitches: - stitch_group.add_stitch(Point(*stitch)) - - return [stitch_group] diff --git a/lib/elements/utils.py b/lib/elements/utils.py index d5122e3f9..fde66afc0 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -5,30 +5,24 @@ from ..commands import is_command from ..marker import has_marker -from ..svg.tags import (EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG, - SVG_POLYGON_TAG, SVG_POLYLINE_TAG, SVG_TEXT_TAG) +from ..svg.tags import EMBROIDERABLE_TAGS, SVG_IMAGE_TAG, SVG_PATH_TAG, SVG_TEXT_TAG from .clone import Clone, is_clone from .element import EmbroideryElement from .empty_d_object import EmptyDObject from .fill_stitch import FillStitch from .image import ImageObject from .marker import MarkerObject -from .polyline import Polyline from .satin_column import SatinColumn from .stroke import Stroke from .text import TextObject def node_to_elements(node, clone_to_element=False): # noqa: C901 - if node.tag == SVG_POLYLINE_TAG: - return [Polyline(node)] - - elif is_clone(node) and not clone_to_element: + if is_clone(node) and not clone_to_element: # clone_to_element: get an actual embroiderable element once a clone has been defined as a clone return [Clone(node)] - elif ((node.tag == SVG_PATH_TAG and not node.get('d', None)) or - (node.tag in [SVG_POLYLINE_TAG, SVG_POLYGON_TAG] and not node.get('points', None))): + elif node.tag in EMBROIDERABLE_TAGS and not node.get_path(): return [EmptyDObject(node)] elif has_marker(node): diff --git a/lib/extensions/params.py b/lib/extensions/params.py index 076ed301d..dc6cd147a 100644 --- a/lib/extensions/params.py +++ b/lib/extensions/params.py @@ -16,15 +16,15 @@ import wx from wx.lib.scrolledpanel import ScrolledPanel from ..commands import is_command, is_command_symbol -from ..elements import (Clone, EmbroideryElement, FillStitch, Polyline, - SatinColumn, Stroke) +from ..elements import (Clone, EmbroideryElement, FillStitch, SatinColumn, + Stroke) from ..elements.clone import is_clone from ..exceptions import InkstitchException, format_uncaught_exception from ..gui import PresetsPanel, PreviewRenderer, WarningPanel from ..gui.simulator import SplitSimulatorWindow from ..i18n import _ from ..stitch_plan import stitch_groups_to_stitch_plan -from ..svg.tags import SVG_POLYLINE_TAG +from ..svg.tags import EMBROIDERABLE_TAGS from ..utils import get_resource_dir from ..utils.param import ParamOption from ..utils.svg_data import get_pagecolor @@ -658,10 +658,10 @@ class Params(InkstitchExtension): classes = [] if not is_command(node) and not is_command_symbol(node): - if node.tag == SVG_POLYLINE_TAG: - classes.append(Polyline) - elif is_clone(node): + if is_clone(node): classes.append(Clone) + elif node.tag in EMBROIDERABLE_TAGS and not node.get_path(): + pass else: if element.get_style("fill", 'black') and not element.get_style("fill-opacity", 1) == "0": classes.append(FillStitch) diff --git a/lib/extensions/select_elements.py b/lib/extensions/select_elements.py index c1b948a36..59e3d06d4 100644 --- a/lib/extensions/select_elements.py +++ b/lib/extensions/select_elements.py @@ -9,7 +9,7 @@ import sys from inkex import Boolean, errormsg -from ..elements import Clone, FillStitch, Polyline, SatinColumn, Stroke +from ..elements import Clone, FillStitch, SatinColumn, Stroke from ..i18n import _ from ..utils import get_bundled_dir from .base import InkstitchExtension @@ -27,7 +27,6 @@ class SelectElements(InkstitchExtension): pars.add_argument("--select-ripples", type=Boolean, dest="ripples", default=False) pars.add_argument("--select-zigzag", type=Boolean, dest="zigzag", default=False) pars.add_argument("--select-manual", type=Boolean, dest="manual", default=False) - pars.add_argument("--select-polyline", type=Boolean, dest="poly", default=False) pars.add_argument("--select-satin", type=Boolean, dest="satin", default=False) pars.add_argument("--satin-underlay", type=str, dest="satin_underlay", default="all") pars.add_argument("--rung-count", type=str, dest="rung_count", default="all") @@ -115,8 +114,6 @@ class SelectElements(InkstitchExtension): for element in self.elements: if isinstance(element, Stroke) and self._select_stroke(element): ids.add(element.id) - elif isinstance(element, Polyline) and self.options.poly: - ids.add(element.id) elif isinstance(element, FillStitch) and self._select_fill(element): ids.add(element.id) elif isinstance(element, SatinColumn) and self._select_satin(element): diff --git a/lib/extensions/update_svg.py b/lib/extensions/update_svg.py index 0f0609be3..f620af2d4 100644 --- a/lib/extensions/update_svg.py +++ b/lib/extensions/update_svg.py @@ -14,8 +14,11 @@ class UpdateSvg(InkstitchExtension): def __init__(self, *args, **kwargs): InkstitchExtension.__init__(self, *args, **kwargs) + # inkstitch_svg_version history: + # 1 -> v3.0.0, May 2023 + # 2 -> v.3.1.0 May 2024 + # TODO: When there are more legacy versions than only one, this can be transformed into a user input - # inkstitch_svg_version history: 1 -> v3.0.0, May 2023 self.update_from = 0 def effect(self): diff --git a/lib/update.py b/lib/update.py index b0bfcdfaa..84522934b 100644 --- a/lib/update.py +++ b/lib/update.py @@ -6,7 +6,7 @@ from .metadata import InkStitchMetadata from .svg import PIXELS_PER_MM from .svg.tags import EMBROIDERABLE_TAGS, INKSTITCH_ATTRIBS -INKSTITCH_SVG_VERSION = 1 +INKSTITCH_SVG_VERSION = 2 def update_inkstitch_document(svg, selection=None): @@ -67,6 +67,13 @@ def update_legacy_params(element, file_version, inkstitch_svg_version): def _update_to(version, element): if version == 1: _update_to_one(element) + elif version == 2: + _update_to_two(element) + + +def _update_to_two(element): + if element.node.TAG == "polyline" and element.node.style("stroke") is not None: + element.set_param('stroke_method', 'manual_stitch') def _update_to_one(element): # noqa: C901 diff --git a/templates/select_elements.xml b/templates/select_elements.xml index 4d8823e58..8ade3c674 100644 --- a/templates/select_elements.xml +++ b/templates/select_elements.xml @@ -22,7 +22,6 @@ false false false - false