diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/elements/element.py | 27 | ||||
| -rw-r--r-- | lib/elements/fill_stitch.py | 15 | ||||
| -rw-r--r-- | lib/elements/satin_column.py | 2 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 2 | ||||
| -rw-r--r-- | lib/elements/utils.py | 4 | ||||
| -rw-r--r-- | lib/extensions/break_apart.py | 2 | ||||
| -rw-r--r-- | lib/extensions/gradient_blocks.py | 16 | ||||
| -rwxr-xr-x | lib/extensions/params.py | 4 | ||||
| -rw-r--r-- | lib/marker.py | 4 | ||||
| -rw-r--r-- | lib/sew_stack/stitch_layers/stitch_layer.py | 4 | ||||
| -rw-r--r-- | lib/stitches/guided_fill.py | 2 | ||||
| -rw-r--r-- | lib/stitches/linear_gradient_fill.py | 7 | ||||
| -rw-r--r-- | lib/tartan/palette.py | 9 | ||||
| -rw-r--r-- | lib/threads/color.py | 31 | ||||
| -rw-r--r-- | lib/update.py | 2 |
15 files changed, 90 insertions, 41 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py index 7b558506..1ca78b04 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -198,12 +198,35 @@ class EmbroideryElement(object): style = element_style.get(style_name, default) if style in ['none', 'None']: style = None - elif style == 'currentColor': - style = element_style(style_name) return style @property @cache + def fill_color(self): + try: + color = self.node.get_computed_style("fill") + except (inkex.ColorError, ValueError): + # SVG spec says the default fill is black + # A color error could show up, when an element has an unrecognized color name + # A value error could show up, when for example when an element links to a non-existent gradient + # TODO: This will also apply to currentcolor and alike which will render in black + return "black" + return color + + @property + @cache + def stroke_color(self): + try: + color = self.node.get_computed_style("stroke") + except (inkex.ColorError, ValueError): + # A color error could show up, when an element has an unrecognized color name + # A value error could show up, when for example when an element links to a non-existent gradient + # TODO: This will also apply to currentcolor and alike which will not render + return None + return color + + @property + @cache def stroke_scale(self): # How wide is the stroke, after the transforms are applied? # diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py index 555c7e09..7ce3188a 100644 --- a/lib/elements/fill_stitch.py +++ b/lib/elements/fill_stitch.py @@ -7,7 +7,7 @@ import math import re import numpy as np -from inkex import LinearGradient +from inkex import Color, ColorError, LinearGradient from shapely import geometry as shgeo from shapely import set_precision from shapely.errors import GEOSException @@ -632,14 +632,12 @@ class FillStitch(EmbroideryElement): @property def color(self): - # SVG spec says the default fill is black - return self.get_style("fill", "#000000") + return self.fill_color @property def gradient(self): - gradient = self.node.get_computed_style("fill") - if isinstance(gradient, LinearGradient): - return gradient + if isinstance(self.fill_color, LinearGradient): + return self.fill_color return None @property @@ -1032,7 +1030,10 @@ class FillStitch(EmbroideryElement): def do_underlay(self, shape, starting_point): color = self.color if self.gradient is not None and self.fill_method == 'linear_gradient_fill': - color = self.gradient.stops[0].get_computed_style('stop-color') + try: + color = self.gradient.stops[0].get_computed_style('stop-color') + except ColorError: + color = Color('black') stitch_groups = [] for i in range(len(self.fill_underlay_angle)): diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index ff5cfe86..3a29aca7 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -243,7 +243,7 @@ class SatinColumn(EmbroideryElement): @property def color(self): - return self.get_style("stroke") + return self.stroke_color @property @param('zigzag_spacing_mm', diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 6e01151d..3740371f 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -50,7 +50,7 @@ class Stroke(EmbroideryElement): @property def color(self): - color = self.get_style("stroke") + color = self.stroke_color if self.cutwork_needle is not None: color = ThreadColor(color, description=self.cutwork_needle, chart=self.cutwork_needle) return color diff --git a/lib/elements/utils.py b/lib/elements/utils.py index 6aec1cc2..43c2387d 100644 --- a/lib/elements/utils.py +++ b/lib/elements/utils.py @@ -47,9 +47,9 @@ def node_to_elements(node, clone_to_element=False) -> List[EmbroideryElement]: if not sew_stack.sew_stack_only: element = EmbroideryElement(node) - if element.get_style("fill", "black") and not element.get_style('fill-opacity', 1) == "0": + if element.fill_color is not None and not element.get_style('fill-opacity', 1) == "0": elements.append(FillStitch(node)) - if element.get_style("stroke"): + if element.stroke_color is not None: if element.get_boolean_param("satin_column") and len(element.path) > 1: elements.append(SatinColumn(node)) elif not is_command(element.node): diff --git a/lib/extensions/break_apart.py b/lib/extensions/break_apart.py index 21806251..05f9375a 100644 --- a/lib/extensions/break_apart.py +++ b/lib/extensions/break_apart.py @@ -39,7 +39,7 @@ class BreakApart(InkstitchExtension): elements.append(EmbroideryElement(node)) for element in elements: - if not element.get_style("fill", "black"): + if not element.fill_color: continue # we don't want to touch valid elements diff --git a/lib/extensions/gradient_blocks.py b/lib/extensions/gradient_blocks.py index 79665a10..364ff2b2 100644 --- a/lib/extensions/gradient_blocks.py +++ b/lib/extensions/gradient_blocks.py @@ -5,8 +5,8 @@ from math import degrees, pi -from inkex import (DirectedLineSegment, Group, LinearGradient, Path, - PathElement, Transform, errormsg) +from inkex import (Color, ColorError, DirectedLineSegment, Group, + LinearGradient, Path, PathElement, Transform, errormsg) from shapely import geometry as shgeo from shapely.affinity import rotate from shapely.ops import split @@ -67,7 +67,7 @@ class GradientBlocks(InkstitchExtension): for i, shape in enumerate(fill_shapes): if shape.area < 15: continue - color = attributes[i]['color'] + color = verify_color(attributes[i]['color']) style['fill'] = color is_gradient = attributes[i]['is_gradient'] angle = degrees(attributes[i]['angle']) @@ -146,7 +146,7 @@ def gradient_shapes_and_attributes(element, shape, unit_multiplier): split_line = rotate(split_line, angle, origin=split_point, use_radians=True) offset_line = split_line.parallel_offset(1, 'right') polygon = split(shape, split_line) - color = stop_styles[i]['stop-color'] + color = verify_color(stop_styles[i]['stop-color']) # does this gradient line split the shape offset_outside_shape = len(polygon.geoms) == 1 for poly in polygon.geoms: @@ -178,6 +178,14 @@ def gradient_shapes_and_attributes(element, shape, unit_multiplier): return polygons, attributes +def verify_color(color): + try: + Color(color) + except ColorError: + return "black" + return color + + if __name__ == '__main__': e = GradientBlocks() e.run() diff --git a/lib/extensions/params.py b/lib/extensions/params.py index cb38585e..0bba13fe 100755 --- a/lib/extensions/params.py +++ b/lib/extensions/params.py @@ -721,9 +721,9 @@ class Params(InkstitchExtension): 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": + if element.fill_color is not None and not element.get_style("fill-opacity", 1) == "0": classes.append(FillStitch) - if element.get_style("stroke") is not None: + if element.stroke_color is not None: classes.append(Stroke) if len(element.path) > 1: classes.append(SatinColumn) diff --git a/lib/marker.py b/lib/marker.py index a2b0965a..cd700674 100644 --- a/lib/marker.py +++ b/lib/marker.py @@ -72,8 +72,8 @@ def get_marker_elements(node, marker, get_fills=True, get_strokes=True, get_sati continue element = EmbroideryElement(marker) - fill = element.get_style('fill') - stroke = element.get_style('stroke') + fill = element.fill_color + stroke = element.stroke_color if get_fills and fill is not None: fill = FillStitch(marker).shape diff --git a/lib/sew_stack/stitch_layers/stitch_layer.py b/lib/sew_stack/stitch_layers/stitch_layer.py index 615a36e8..d9a985f6 100644 --- a/lib/sew_stack/stitch_layers/stitch_layer.py +++ b/lib/sew_stack/stitch_layers/stitch_layer.py @@ -74,11 +74,11 @@ class StitchLayer: @property def stroke_color(self): - return self.element.get_style("stroke") + return self.element.stroke_color @property def fill_color(self): - return self.element.get_style("stroke") + return self.element.fill_color def to_stitch_groups(self, *args): raise NotImplementedError(f"{self.__class__.__name__} must implement to_stitch_groups()!") diff --git a/lib/stitches/guided_fill.py b/lib/stitches/guided_fill.py index 5d9a6018..16f0f2e8 100644 --- a/lib/stitches/guided_fill.py +++ b/lib/stitches/guided_fill.py @@ -180,7 +180,7 @@ def apply_stitches(line, max_stitch_length, num_staggers, row_spacing, row_num, # corners. if not threshold: threshold = row_spacing / 2.0 - simplified_line = line.simplify(threshold, False) + simplified_line = line.simplify(threshold, preserve_topology=False) simplified_points = [shgeo.Point(x, y) for x, y in simplified_line.coords] extra_points = [] diff --git a/lib/stitches/linear_gradient_fill.py b/lib/stitches/linear_gradient_fill.py index 2fb03bf9..589a1f23 100644 --- a/lib/stitches/linear_gradient_fill.py +++ b/lib/stitches/linear_gradient_fill.py @@ -6,7 +6,7 @@ from math import ceil, floor, sqrt import numpy as np -from inkex import DirectedLineSegment, Transform +from inkex import Color, ColorError, DirectedLineSegment, Transform from networkx import is_empty from shapely import segmentize from shapely.affinity import rotate @@ -75,7 +75,10 @@ def _get_gradient_info(fill, bbox): # but inkex/tinycss fails on stop color styles when it is not in the style attribute, but in it's own stop-color attribute colors = [] for i, stop in enumerate(fill.gradient.stops): - color = stop.get_computed_style('stop-color') + try: + color = stop.get_computed_style('stop-color') + except ColorError: + color = Color('black') opacity = stop.get_computed_style('stop-opacity') if float(opacity) == 0: color = 'none' diff --git a/lib/tartan/palette.py b/lib/tartan/palette.py index 25bd2100..b8c36331 100644 --- a/lib/tartan/palette.py +++ b/lib/tartan/palette.py @@ -8,9 +8,10 @@ import re from typing import TYPE_CHECKING, List, cast import wx -from inkex import Color +from inkex import Color, ColorError from .colors import string_to_color + if TYPE_CHECKING: from ..gui.tartan.stripe_panel import StripePanel @@ -175,7 +176,11 @@ class Palette: color = wx.Colour(color).GetAsString(wx.C2S_HTML_SYNTAX) except wx.PyNoAppError: # however when we render an embroidery element we do not want to open wx.App - color = str(Color(color).to_named()) + try: + color = str(Color(color).to_named()) + except ColorError: + color = None + if not color: color = '#000000' render = 0 diff --git a/lib/threads/color.py b/lib/threads/color.py index 699f4448..335dc32b 100644 --- a/lib/threads/color.py +++ b/lib/threads/color.py @@ -5,19 +5,20 @@ import colorsys -from inkex import Color +from inkex import Color, ColorError + from pyembroidery.EmbThread import EmbThread class ThreadColor(object): def __init__(self, color, name=None, number=None, manufacturer=None, description=None, chart=None): - ''' - avoid error messages: - * set colors with a gradient to black - * currentColor/context-fill/context-stroke: should not just be black, but we want to avoid - error messages until inkex will be able to handle these css properties - ''' - if isinstance(color, str) and color.startswith(('url', 'currentColor', 'context')): + self.rgb = None + + if isinstance(color, str) and color.lower().startswith(('url', 'currentcolor', 'context')): + ''' + Avoid error messages for currentcolor, context-fill, context-stroke and every string starting with an url. + they should not just be black, but we want to avoid error messages + ''' color = None elif isinstance(color, str) and color.startswith('rgb'): color = tuple(int(value) for value in color[4:-1].split(',')) @@ -33,11 +34,19 @@ class ThreadColor(object): self.rgb = (color.get_red(), color.get_green(), color.get_blue()) return elif isinstance(color, str): - self.rgb = tuple(Color(color).to('rgb')) + try: + self.rgb = tuple(Color(color).to('rgb')) + except ColorError: + self.rgb = None elif isinstance(color, (list, tuple)): self.rgb = tuple(color) - else: - raise ValueError("Invalid color: " + repr(color)) + + if self.rgb is None: + ''' + Instead of erroring out, we want to set everything to black at this point. + This includes for example patterns and gradients + ''' + self.rgb = (0, 0, 0) self.name = name self.number = number diff --git a/lib/update.py b/lib/update.py index e1b62cab..2055da7d 100644 --- a/lib/update.py +++ b/lib/update.py @@ -170,7 +170,7 @@ def _update_to_one(element): # noqa: C901 element.set_param('running_stitch_length_mm', 1.5) # convert legacy stroke_method - if element.get_style("stroke") and not element.node.get('inkscape:connection-start', None): + if element.stroke_color and not element.node.get('inkscape:connection-start', None): # manual stitch legacy_manual_stitch = element.get_boolean_param('manual_stitch', False) if legacy_manual_stitch is True: |
