diff --git a/lib/elements/clone.py b/lib/elements/clone.py index 6adfc5b3e..d5c146ef0 100644 --- a/lib/elements/clone.py +++ b/lib/elements/clone.py @@ -4,11 +4,10 @@ # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. from math import degrees -from copy import deepcopy from contextlib import contextmanager from typing import Generator, List -from inkex import Transform, BaseElement, Style +from inkex import Transform, BaseElement from shapely import MultiLineString from ..stitch_plan.stitch_group import StitchGroup @@ -43,7 +42,7 @@ class Clone(EmbroideryElement): @property @param('clone', _("Clone"), type='toggle', inverse=False, default=True) def clone(self): - return self.get_boolean_param("clone") + return self.get_boolean_param("clone", True) @property @param('angle', @@ -81,6 +80,9 @@ class Clone(EmbroideryElement): return elements def to_stitch_groups(self, last_stitch_group=None) -> List[StitchGroup]: + if not self.clone: + return [] + with self.clone_elements() as elements: stitch_groups = [] @@ -123,22 +125,18 @@ class Clone(EmbroideryElement): parent: BaseElement = self.node.getparent() source_node: BaseElement = self.node.href source_parent: BaseElement = source_node.getparent() - cloned_node = deepcopy(source_node) + cloned_node = source_node.copy() if recursive: # Recursively resolve all clones as if the clone was in the same place as its source source_parent.add(cloned_node) if is_clone(cloned_node): - resolved_cloned_node = Clone(cloned_node).resolve_clone() - cloned_node.getparent().remove(cloned_node) - # Replace the cloned_node with its resolved version - cloned_node = resolved_cloned_node + cloned_node = cloned_node.replace_with(Clone(cloned_node).resolve_clone()) else: clones: List[BaseElement] = [n for n in cloned_node.iterdescendants() if is_clone(n)] for clone in clones: - Clone(clone).resolve_clone() - clone.getparent().remove(clone) + clone.replace_with(Clone(clone).resolve_clone()) source_parent.remove(cloned_node) @@ -146,14 +144,10 @@ class Clone(EmbroideryElement): parent.add(cloned_node) # The transform of a resolved clone is based on the clone's transform as well as the source element's transform. # This makes intuitive sense: The clone of a scaled item is also scaled, the clone of a rotated item is also rotated, etc. - cloned_node.set('transform', Transform(self.node.get('transform')) @ Transform(cloned_node.get('transform'))) + cloned_node.transform = self.node.transform @ cloned_node.transform # Merge the style, if any: Note that the source node's style applies on top of the use's, not the other way around. - clone_style = self.node.get('style') - if clone_style: - merged_style = Style(clone_style) - merged_style.update(cloned_node.get('style')) - cloned_node.set('style', merged_style) + cloned_node.style = self.node.style + cloned_node.style # Compute angle transform: # Effectively, this is (local clone transform) * (to parent space) * (from clone's parent space) @@ -174,7 +168,6 @@ class Clone(EmbroideryElement): # Otherwise we'd have to calculate the transform of (0,0) and subtract it from the transform of (1,0) angle_transform = Transform((transform.a, transform.b, transform.c, transform.d, 0.0, 0.0)) - elements = self.clone_to_elements(cloned_node) for node in cloned_node.iter(): # Only need to adjust angles on embroiderable nodes if node.tag not in EMBROIDERABLE_TAGS: @@ -195,8 +188,6 @@ class Clone(EmbroideryElement): node.set(INKSTITCH_ATTRIBS['angle'], round(element_angle, 6)) - return elements - @property def shape(self): path = self.node.get_path() diff --git a/tests/test_clone.py b/tests/test_clone.py index d8e64c9c7..6ebb07968 100644 --- a/tests/test_clone.py +++ b/tests/test_clone.py @@ -34,6 +34,22 @@ class CloneElementTest(TestCase): stitch_groups = clone.to_stitch_groups(None) self.assertEqual(len(stitch_groups), 0) + def test_not_clone(self): + root: SvgDocumentElement = svg() + rect = root.add(Rectangle(attrib={ + "width": "10", + "height": "10", + INKSTITCH_ATTRIBS["angle"]: "30" + })) + use = root.add(Use(attrib={ + INKSTITCH_ATTRIBS["clone"]: "false" + })) + use.href = rect + + clone = Clone(use) + stitch_groups = clone.to_stitch_groups(None) + self.assertEqual(len(stitch_groups), 0) + # These tests make sure the element cloning works as expected, using the `clone_elements` method. def test_basic(self):