diff options
Diffstat (limited to 'lib/elements')
| -rw-r--r-- | lib/elements/element.py | 33 | ||||
| -rw-r--r-- | lib/elements/satin_column.py | 49 | ||||
| -rw-r--r-- | lib/elements/stroke.py | 125 |
3 files changed, 98 insertions, 109 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py index c0b7ee0f..d3690b4c 100644 --- a/lib/elements/element.py +++ b/lib/elements/element.py @@ -58,13 +58,16 @@ def param(*args, **kwargs): class EmbroideryElement(object): def __init__(self, node): self.node = node + self._update_legacy_params() + def _update_legacy_params(self): # noqa: C901 # update legacy embroider_ attributes to namespaced attributes legacy_attribs = False for attrib in self.node.attrib: if attrib.startswith('embroider_'): self.replace_legacy_param(attrib) legacy_attribs = True + # convert legacy tie setting legacy_tie = self.get_param('ties', None) if legacy_tie == "True": @@ -83,10 +86,36 @@ class EmbroideryElement(object): elif legacy_fill_method == 3: self.set_param('fill_method', 'legacy_fill') + # legacy satin method + if self.get_boolean_param('e_stitch', False) is True: + self.remove_param('e_stitch') + self.set_param('satin_method', 'e_stitch') + # default setting for fill_underlay has changed if legacy_attribs and not self.get_param('fill_underlay', ""): self.set_param('fill_underlay', False) + # convert legacy stroke_method + if self.get_style("stroke"): + # manual stitch + legacy_manual_stitch = self.get_boolean_param('manual_stitch', False) + if legacy_manual_stitch is True: + self.remove_param('manual_stitch') + self.set_param('stroke_method', 'manual_stitch') + # stroke_method + legacy_stroke_method = self.get_int_param('stroke_method', None) + if legacy_stroke_method == 0: + self.set_param('stroke_method', 'running_stitch') + elif legacy_stroke_method == 1: + self.set_param('stroke_method', 'ripple_stitch') + if (not self.get_param('stroke_method', None) and + self.get_param('satin_column', False) is False and + not self.node.style('stroke-dasharray')): + self.set_param('stroke_method', 'zigzag_stitch') + # if the stroke method is a zigzag-stitch but we are receiving a dashed line, set it to running stitch + if self.get_param('stroke_method', None) == 'zigzag_stitch' and self.node.style('stroke-dasharray'): + self.set_param('stroke_method', 'running_stitch') + @property def id(self): return self.node.get('id') @@ -193,6 +222,10 @@ class EmbroideryElement(object): param = INKSTITCH_ATTRIBS[name] self.node.set(param, str(value)) + def remove_param(self, name): + param = INKSTITCH_ATTRIBS[name] + del self.node.attrib[param] + @cache def _get_specified_style(self): # We want to cache this, because it's quite expensive to generate. diff --git a/lib/elements/satin_column.py b/lib/elements/satin_column.py index 7af64382..887aec01 100644 --- a/lib/elements/satin_column.py +++ b/lib/elements/satin_column.py @@ -19,9 +19,10 @@ from ..stitch_plan import StitchGroup from ..stitches import running_stitch from ..svg import line_strings_to_csp, point_lists_to_csp from ..utils import Point, cache, cut, cut_multiple, prng +from ..utils.param import ParamOption +from ..utils.threading import check_stop_flag from .element import PIXELS_PER_MM, EmbroideryElement, param from .validation import ValidationError, ValidationWarning -from ..utils.threading import check_stop_flag class TooFewPathsError(ValidationError): @@ -77,17 +78,26 @@ class SatinColumn(EmbroideryElement): def satin_column(self): return self.get_boolean_param("satin_column") - # I18N: "E" stitch is so named because it looks like the letter E. + _satin_methods = [ParamOption('satin_column', _('Satin Column')), + ParamOption('e_stitch', _('"E" Stitch'))] + @property - @param('e_stitch', _('"E" stitch'), type='boolean', default='false') - def e_stitch(self): - return self.get_boolean_param("e_stitch") + @param('satin_method', + _('Method'), + type='combo', + default=0, + options=_satin_methods, + sort_index=0) + def satin_method(self): + return self.get_param('satin_method', 'satin_column') @property @param('max_stitch_length_mm', _('Maximum stitch length'), tooltip=_('Maximum stitch length for split stitches.'), - type='float', unit="mm") + type='float', + unit="mm", + sort_index=1) def max_stitch_length_px(self): return self.get_float_param("max_stitch_length_mm") or None @@ -150,8 +160,10 @@ class SatinColumn(EmbroideryElement): @param('short_stitch_inset', _('Short stitch inset'), tooltip=_('Stitches in areas with high density will be inset by this amount.'), - type='float', unit="%", - default=15) + type='float', + unit="%", + default=15, + sort_index=3) def short_stitch_inset(self): return self.get_float_param("short_stitch_inset", 15) / 100 @@ -159,8 +171,10 @@ class SatinColumn(EmbroideryElement): @param('short_stitch_distance_mm', _('Short stitch distance'), tooltip=_('Inset stitches if the distance between stitches is smaller than this.'), - type='float', unit="mm", - default=0.25) + type='float', + unit="mm", + default=0.25, + sort_index=4) def short_stitch_distance(self): return self.get_float_param("short_stitch_distance_mm", 0.25) @@ -174,7 +188,8 @@ class SatinColumn(EmbroideryElement): tooltip=_('Peak-to-peak distance between zig-zags. This is double the mm/stitch measurement used by most mechanical machines.'), unit='mm/cycle', type='float', - default=0.4) + default=0.4, + sort_index=5) def zigzag_spacing(self): # peak-to-peak distance between zigzags return max(self.get_float_param("zigzag_spacing_mm", 0.4), 0.01) @@ -187,7 +202,8 @@ class SatinColumn(EmbroideryElement): 'Two values separated by a space may be used for an aysmmetric effect.'), unit='% (each side)', type='float', - default=0) + default=0, + sort_index=6) @cache def pull_compensation_percent(self): # pull compensation as a percentage of the width @@ -202,7 +218,8 @@ class SatinColumn(EmbroideryElement): 'Two values separated by a space may be used for an aysmmetric effect.'), unit='mm (each side)', type='float', - default=0) + default=0, + sort_index=7) @cache def pull_compensation_px(self): # In satin stitch, the stitches have a tendency to pull together and @@ -250,7 +267,9 @@ class SatinColumn(EmbroideryElement): _('Inset distance (fixed)'), tooltip=_('Shrink the outline by a fixed length, to prevent the underlay from showing around the outside of the satin column.'), group=_('Contour Underlay'), - unit='mm (each side)', type='float', default=0.4, + unit='mm (each side)', + type='float', + default=0.4, sort_index=2) @cache def contour_underlay_inset_px(self): @@ -1125,7 +1144,7 @@ class SatinColumn(EmbroideryElement): # zigzags sit on the contour walk underlay like rail ties on rails. patch += self.do_zigzag_underlay() - if self.e_stitch: + if self.satin_method == 'e_stitch': patch += self.do_e_stitch() else: patch += self.do_satin() diff --git a/lib/elements/stroke.py b/lib/elements/stroke.py index 8f5a6347..258bf737 100644 --- a/lib/elements/stroke.py +++ b/lib/elements/stroke.py @@ -3,8 +3,6 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -import sys - import shapely.geometry from inkex import Transform @@ -16,6 +14,7 @@ from ..stitches.running_stitch import bean_stitch, running_stitch from ..svg import get_node_transform, parse_length_with_units from ..threads import ThreadColor from ..utils import Point, cache +from ..utils.param import ParamOption from .element import EmbroideryElement, param from .validation import ValidationWarning @@ -39,14 +38,6 @@ class MultipleGuideLineWarning(ValidationWarning): ] -class SmallZigZagWarning(ValidationWarning): - name = _("Small ZigZag") - description = _("This zig zag stitch has a stroke width smaller than 0.5 units.") - steps_to_solve = [ - _("Set your stroke to be dashed to indicate running stitch. Any kind of dash will work.") - ] - - class Stroke(EmbroideryElement): element_name = _("Stroke") @@ -69,46 +60,27 @@ class Stroke(EmbroideryElement): needle = f'Cut {needle}' return needle - @property - def dashed(self): - return self.get_style("stroke-dasharray") is not None - - def update_dash(self, to_dash): - if self.dashed == to_dash: - return - if to_dash is False: - del self.node.style['stroke-dasharray'] - else: - self.node.style['stroke-dasharray'] = "1,0.5" + _stroke_methods = [ParamOption('running_stitch', _("Running Stitch / Bean Stitch")), + ParamOption('ripple_stitch', _("Ripple Stitch")), + ParamOption('zigzag_stitch', _("ZigZag Stitch")), + ParamOption('manual_stitch', _("Manual Stitch"))] @property @param('stroke_method', _('Method'), - type='dropdown', + type='combo', default=0, - # 0: run/simple satin, 1: manual, 2: ripple - options=[_("Running Stitch"), _("Ripple")], + options=_stroke_methods, sort_index=0) def stroke_method(self): - return self.get_int_param('stroke_method', 0) - - @property - @param('manual_stitch', - _('Manual stitch placement'), - tooltip=_("Stitch every node in the path. All options other than stop and trim are ignored. " - "Lock stitches will be added only if force lock stitches is checked."), - type='boolean', - default=False, - select_items=[('stroke_method', 0)], - sort_index=1) - def manual_stitch_mode(self): - return self.get_boolean_param('manual_stitch') + return self.get_param('stroke_method', 'running_stitch') @property @param('repeats', _('Repeats'), tooltip=_('Defines how many times to run down and back along the path.'), type='int', + select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch'), ('stroke_method', 'zigzag_stitch')], default="1", sort_index=2) def repeats(self): @@ -123,6 +95,7 @@ class Stroke(EmbroideryElement): 'A value of 2 would quintuple each stitch, etc.\n\n' 'A pattern with various repeats can be created with a list of values separated by a space.'), type='str', + select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch')], default=0, sort_index=3) def bean_stitch_repeats(self): @@ -134,6 +107,7 @@ class Stroke(EmbroideryElement): tooltip=_('Length of stitches in running stitch mode.'), unit='mm', type='float', + select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch')], default=1.5, sort_index=4) def running_stitch_length(self): @@ -147,6 +121,7 @@ class Stroke(EmbroideryElement): 'A higher tolerance means sharp corners may be rounded.'), unit='mm', type='float', + select_items=[('stroke_method', 'running_stitch'), ('stroke_method', 'ripple_stitch')], default=0.2, sort_index=4) def running_stitch_tolerance(self): @@ -159,7 +134,7 @@ class Stroke(EmbroideryElement): unit='mm', type='float', default=0.4, - select_items=[('stroke_method', 0)], + select_items=[('stroke_method', 'zigzag_stitch')], sort_index=5) @cache def zigzag_spacing(self): @@ -171,7 +146,7 @@ class Stroke(EmbroideryElement): tooltip=_('Number of lines from start to finish'), type='int', default=10, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=5) @cache def line_count(self): @@ -188,7 +163,7 @@ class Stroke(EmbroideryElement): tooltip=_('Skip this number of lines at the beginning.'), type='int', default=0, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=6) @cache def skip_start(self): @@ -200,7 +175,7 @@ class Stroke(EmbroideryElement): tooltip=_('Skip this number of lines at the end'), type='int', default=0, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=7) @cache def skip_end(self): @@ -224,7 +199,7 @@ class Stroke(EmbroideryElement): tooltip=_('Increase density towards one side.'), type='float', default=1, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=8) @cache def exponent(self): @@ -236,7 +211,7 @@ class Stroke(EmbroideryElement): tooltip=_('Reverse exponent effect.'), type='boolean', default=False, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=9) @cache def flip_exponent(self): @@ -248,7 +223,7 @@ class Stroke(EmbroideryElement): tooltip=_('Flip start and end point'), type='boolean', default=False, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=10) @cache def reverse(self): @@ -261,7 +236,7 @@ class Stroke(EmbroideryElement): type='float', default=0, unit='mm', - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=11) @cache def grid_size(self): @@ -275,7 +250,7 @@ class Stroke(EmbroideryElement): default=0, # 0: xy, 1: x, 2: y, 3: none options=["X Y", "X", "Y", _("None")], - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=12) def scale_axis(self): return self.get_int_param('scale_axis', 0) @@ -287,7 +262,7 @@ class Stroke(EmbroideryElement): type='float', unit='%', default=100, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=13) def scale_start(self): return self.get_float_param('scale_start', 100.0) @@ -299,7 +274,7 @@ class Stroke(EmbroideryElement): type='float', unit='%', default=0.0, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=14) def scale_end(self): return self.get_float_param('scale_end', 0.0) @@ -310,7 +285,7 @@ class Stroke(EmbroideryElement): tooltip=_('Rotate satin guided ripple stitches'), type='boolean', default=True, - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=15) @cache def rotate_ripples(self): @@ -323,7 +298,7 @@ class Stroke(EmbroideryElement): type='dropdown', default=0, options=(_("flat"), _("point")), - select_items=[('stroke_method', 1)], + select_items=[('stroke_method', 'ripple_stitch')], sort_index=16) @cache def join_style(self): @@ -349,7 +324,7 @@ class Stroke(EmbroideryElement): if len(flattened[0]) == 1: return [[[flattened[0][0][0], flattened[0][0][1]], [flattened[0][0][0] + 1.0, flattened[0][0][1]]]] - if self.manual_stitch_mode: + if self.stroke_method == 'manual_stitch': return [self.strip_control_points(subpath) for subpath in path] else: return flattened @@ -374,42 +349,6 @@ class Stroke(EmbroideryElement): else: return self.shape.centroid - def is_running_stitch(self): - # using stroke width <= 0.5 pixels to indicate running stitch is deprecated in favor of dashed lines - - stroke_width, units = parse_length_with_units(self.get_style("stroke-width", "1")) - - if self.dashed: - return True - elif stroke_width <= 0.5 and self.get_float_param('running_stitch_length_mm', None) is not None: - # if they use a stroke width less than 0.5 AND they specifically set a running stitch - # length, then assume they intend to use the deprecated <= 0.5 method to set running - # stitch. - # - # Note that we use self.get_style("stroke_width") _not_ self.stroke_width above. We - # explicitly want the stroke width in "user units" ("document units") -- that is, what - # the user sees in inkscape's stroke settings. - # - # Also note that we don't use self.running_stitch_length_mm above. This is because we - # want to see if they set a running stitch length at all, and the property will apply - # a default value. - # - # This is so tricky, and and intricate that's a major reason that we deprecated the - # 0.5 units rule. - - # Warn them the first time. - global warned_about_legacy_running_stitch - if not warned_about_legacy_running_stitch: - warned_about_legacy_running_stitch = True - print(_("Legacy running stitch setting detected!\n\nIt looks like you're using a stroke " + - "smaller than 0.5 units to indicate a running stitch, which is deprecated. Instead, please set " + - "your stroke to be dashed to indicate running stitch. Any kind of dash will work."), file=sys.stderr) - - # still allow the deprecated setting to work in order to support old files - return True - else: - return False - def simple_satin(self, path, zigzag_spacing, stroke_width): "zig-zag along the path at the specified spacing and wdith" @@ -468,11 +407,11 @@ class Stroke(EmbroideryElement): def do_bean_repeats(self, stitches): return bean_stitch(stitches, self.bean_stitch_repeats) - def to_stitch_groups(self, last_patch): + def to_stitch_groups(self, last_patch): # noqa: C901 patches = [] # ripple stitch - if self.stroke_method == 1: + if self.stroke_method == 'ripple_stitch': patch = self.ripple_stitch() if patch: if any(self.bean_stitch_repeats): @@ -482,7 +421,7 @@ class Stroke(EmbroideryElement): for path in self.paths: path = [Point(x, y) for x, y in path] # manual stitch - if self.manual_stitch_mode: + if self.stroke_method == 'manual_stitch': if self.force_lock_stitches: lock_stitches = self.lock_stitches else: @@ -493,13 +432,13 @@ class Stroke(EmbroideryElement): lock_stitches=lock_stitches, force_lock_stitches=self.force_lock_stitches) # running stitch - elif self.is_running_stitch(): + elif self.stroke_method == 'running_stitch': patch = self.running_stitch(path, self.running_stitch_length, self.running_stitch_tolerance) # bean stitch if any(self.bean_stitch_repeats): patch.stitches = self.do_bean_repeats(patch.stitches) # simple satin - else: + elif self.stroke_method == 'zigzag_stitch': patch = self.simple_satin(path, self.zigzag_spacing, self.stroke_width) if patch: @@ -541,5 +480,3 @@ class Stroke(EmbroideryElement): yield MultipleGuideLineWarning(self._representative_point()) stroke_width, units = parse_length_with_units(self.get_style("stroke-width", "1")) - if not self.dashed and stroke_width <= 0.5: - yield SmallZigZagWarning(self._representative_point()) |
