kopia lustrzana https://github.com/inkstitch/inkstitch
125 wiersze
4.3 KiB
Python
125 wiersze
4.3 KiB
Python
# 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 lxml.etree import Comment
|
|
from typing import List, Optional
|
|
from inkex import BaseElement
|
|
|
|
from ..commands import is_command, layer_commands
|
|
from ..marker import has_marker
|
|
from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE,
|
|
NOT_EMBROIDERABLE_TAGS, SVG_CLIPPATH_TAG, SVG_DEFS_TAG,
|
|
SVG_GROUP_TAG, SVG_MASK_TAG, SVG_IMAGE_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 .satin_column import SatinColumn
|
|
from .stroke import Stroke
|
|
from .text import TextObject
|
|
|
|
|
|
def node_to_elements(node, clone_to_element=False) -> List[EmbroideryElement]: # noqa: C901
|
|
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 in EMBROIDERABLE_TAGS and not node.get_path():
|
|
return [EmptyDObject(node)]
|
|
|
|
elif has_marker(node):
|
|
return [MarkerObject(node)]
|
|
|
|
elif node.tag in EMBROIDERABLE_TAGS or is_clone(node):
|
|
element = EmbroideryElement(node)
|
|
|
|
elements = []
|
|
if element.get_style("fill", "black") and not element.get_style('fill-opacity', 1) == "0":
|
|
elements.append(FillStitch(node))
|
|
if element.get_style("stroke"):
|
|
if element.get_boolean_param("satin_column") and len(element.path) > 1:
|
|
elements.append(SatinColumn(node))
|
|
elif not is_command(element.node):
|
|
elements.append(Stroke(node))
|
|
if element.get_boolean_param("stroke_first", False):
|
|
elements.reverse()
|
|
return elements
|
|
|
|
elif node.tag == SVG_IMAGE_TAG:
|
|
return [ImageObject(node)]
|
|
|
|
elif node.tag == SVG_TEXT_TAG:
|
|
return [TextObject(node)]
|
|
|
|
else:
|
|
return []
|
|
|
|
|
|
def nodes_to_elements(nodes):
|
|
elements = []
|
|
for node in nodes:
|
|
elements.extend(node_to_elements(node))
|
|
|
|
return elements
|
|
|
|
|
|
def iterate_nodes(node: BaseElement, # noqa: C901
|
|
selection: Optional[List[BaseElement]] = None,
|
|
troubleshoot=False) -> List[BaseElement]:
|
|
# Postorder traversal of selected nodes and their descendants.
|
|
# Returns all nodes if there is no selection.
|
|
def walk(node: BaseElement, selected: bool) -> List[BaseElement]:
|
|
nodes = []
|
|
|
|
if node.tag == Comment:
|
|
return []
|
|
|
|
element = EmbroideryElement(node)
|
|
|
|
if element.has_command('ignore_object'):
|
|
return []
|
|
|
|
if node.tag == SVG_GROUP_TAG and node.get(INKSCAPE_GROUPMODE) == "layer":
|
|
if len(list(layer_commands(node, "ignore_layer"))):
|
|
return []
|
|
|
|
if (node.tag in EMBROIDERABLE_TAGS or node.tag == SVG_GROUP_TAG) and element.get_style('display', 'inline') is None:
|
|
return []
|
|
|
|
# defs, masks and clippaths can contain embroiderable elements
|
|
# but should never be rendered directly.
|
|
if node.tag in [SVG_DEFS_TAG, SVG_MASK_TAG, SVG_CLIPPATH_TAG]:
|
|
return []
|
|
|
|
# command connectors with a fill color set, will glitch into the elements list
|
|
if is_command(node) or node.get(CONNECTOR_TYPE):
|
|
return []
|
|
|
|
if not selected:
|
|
if selection:
|
|
if node in selection:
|
|
selected = True
|
|
else:
|
|
# if the user didn't select anything that means we process everything
|
|
selected = True
|
|
|
|
for child in node:
|
|
nodes.extend(walk(child, selected))
|
|
|
|
if selected:
|
|
if node.tag == SVG_GROUP_TAG:
|
|
pass
|
|
elif (node.tag in EMBROIDERABLE_TAGS or is_clone(node)) and not has_marker(node):
|
|
nodes.append(node)
|
|
# add images, text and elements with a marker for the troubleshoot extension
|
|
elif troubleshoot and (node.tag in NOT_EMBROIDERABLE_TAGS or has_marker(node)):
|
|
nodes.append(node)
|
|
|
|
return nodes
|
|
|
|
return walk(node, False)
|