diff options
| -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 | ||||
| -rw-r--r-- | lib/extensions/params.py | 3 | ||||
| -rw-r--r-- | lib/extensions/select_elements.py | 20 | ||||
| -rw-r--r-- | lib/extensions/stroke_to_lpe_satin.py | 2 | ||||
| -rw-r--r-- | lib/extensions/zigzag_line_to_satin.py | 2 | ||||
| -rw-r--r-- | lib/svg/rendering.py | 2 | ||||
| -rw-r--r-- | lib/svg/tags.py | 1 | ||||
| -rw-r--r-- | templates/select_elements.xml | 2 |
10 files changed, 110 insertions, 129 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()) diff --git a/lib/extensions/params.py b/lib/extensions/params.py index 802086d8..bf01153b 100644 --- a/lib/extensions/params.py +++ b/lib/extensions/params.py @@ -672,8 +672,7 @@ class Params(InkstitchExtension): classes.append(FillStitch) if element.get_style("stroke") is not None: classes.append(Stroke) - if element.get_style("stroke-dasharray") is None: - classes.append(SatinColumn) + classes.append(SatinColumn) return classes def get_nodes_by_class(self): diff --git a/lib/extensions/select_elements.py b/lib/extensions/select_elements.py index 0d4ce5f1..8fa9ca9d 100644 --- a/lib/extensions/select_elements.py +++ b/lib/extensions/select_elements.py @@ -22,9 +22,9 @@ class SelectElements(InkstitchExtension): pars.add_argument("--select-running-stitch", type=Boolean, dest="running", default=False) 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-zigzag", type=Boolean, dest="zigzag", 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("--select-e", type=Boolean, dest="e", default=False) @@ -101,16 +101,13 @@ class SelectElements(InkstitchExtension): def _select_stroke(self, element): select = False method = element.stroke_method - manual = element.manual_stitch_mode - if self.options.ripples and method == 1: + if self.options.running and method == 'running_stitch': select = True - elif self.options.manual and manual: + if self.options.ripples and method == 'ripple_stitch': select = True - elif method == 1 or manual: - return False - elif self.options.zigzag and not element.dashed: + elif self.options.zigzag and method == 'zigzag_stitch': select = True - elif self.options.running and element.dashed: + elif self.options.manual and method == 'manual_stitch': select = True return select @@ -139,13 +136,12 @@ class SelectElements(InkstitchExtension): def _select_satin(self, element): select = False - if not (self.options.satin or self.options.e): - return False if not self._select_satin_underlay(element): return False - if self.options.e and element.e_stitch: + method = element.satin_method + if self.options.satin and method == "satin_column": select = True - elif self.options.satin and not element.e_stitch: + elif self.options.e and method == "e_stitch": select = True return select diff --git a/lib/extensions/stroke_to_lpe_satin.py b/lib/extensions/stroke_to_lpe_satin.py index 1e9813a6..4052207a 100644 --- a/lib/extensions/stroke_to_lpe_satin.py +++ b/lib/extensions/stroke_to_lpe_satin.py @@ -92,8 +92,6 @@ class StrokeToLpeSatin(InkstitchExtension): element.set_param('satin_column', 'true') element.node.style['stroke-width'] = self.svg.viewport_to_unit('0.756') - # remove running_stitch dashes if they are there - element.update_dash(False) def _process_satin_column(self, element): current_effects = element.node.get(PATH_EFFECT, None) diff --git a/lib/extensions/zigzag_line_to_satin.py b/lib/extensions/zigzag_line_to_satin.py index 94a901c0..7e5232a7 100644 --- a/lib/extensions/zigzag_line_to_satin.py +++ b/lib/extensions/zigzag_line_to_satin.py @@ -50,8 +50,6 @@ class ZigzagLineToSatin(InkstitchExtension): element.node.set('d', " ".join(d)) element.set_param('satin_column', True) - # remove dashes - element.update_dash(False) def _get_rails_and_rungs(self, point_list): if self.options.pattern == "sawtooth": diff --git a/lib/svg/rendering.py b/lib/svg/rendering.py index 64090554..5ee6d328 100644 --- a/lib/svg/rendering.py +++ b/lib/svg/rendering.py @@ -202,7 +202,7 @@ def color_block_to_paths(color_block, svg, destination, visual_commands): 'style': "stroke: %s; stroke-width: 0.4; fill: none;" % color, 'd': "M" + " ".join(" ".join(str(coord) for coord in point) for point in point_list), 'transform': get_correction_transform(svg), - INKSTITCH_ATTRIBS['manual_stitch']: 'true' + INKSTITCH_ATTRIBS['stroke_method']: 'manual_stitch' }) destination.append(path) diff --git a/lib/svg/tags.py b/lib/svg/tags.py index 5f87bee4..9b5a78fb 100644 --- a/lib/svg/tags.py +++ b/lib/svg/tags.py @@ -117,6 +117,7 @@ inkstitch_attribs = [ 'grid_size', # satin column 'satin_column', + 'satin_method', 'short_stitch_distance_mm', 'short_stitch_inset', 'running_stitch_length_mm', diff --git a/templates/select_elements.xml b/templates/select_elements.xml index d1130c20..fee1f467 100644 --- a/templates/select_elements.xml +++ b/templates/select_elements.xml @@ -10,9 +10,9 @@ <label>Stroke type</label> <param indent="1" name="select-running-stitch" type="boolean" gui-text="Running Stitch">false</param> <param indent="1" name="select-ripples" type="boolean" gui-text="Ripples">false</param> + <param indent="1" name="select-zigzag" type="boolean" gui-text="ZigZag Stitch">false</param> <param indent="1" name="select-manual" type="boolean" gui-text="Manual Stitch">false</param> <param indent="1" name="select-polyline" type="boolean" gui-text="Polyline">false</param> - <param indent="1" name="select-zigzag" type="boolean" gui-text="ZigZag Stitch">false</param> <label>Satin</label> <param indent="1" name="select-satin" type="boolean" gui-text="Satin Column">false</param> <param indent="1" name="select-e" type="boolean" gui-text="E-Stitch">false</param> |
