summaryrefslogtreecommitdiff
path: root/lib/elements
diff options
context:
space:
mode:
authorKaalleen <36401965+kaalleen@users.noreply.github.com>2024-03-29 10:25:02 +0100
committerGitHub <noreply@github.com>2024-03-29 10:25:02 +0100
commit2439adafa8592995d9acead47ef2802d5d95c373 (patch)
treebfa10aaf017bc48cf6c166c7adeb9afd5dc12922 /lib/elements
parentfb1ecd0badf5eb142f17cc7f0f7e8b347151b002 (diff)
Add "the tartan universe" (#2782)
Diffstat (limited to 'lib/elements')
-rw-r--r--lib/elements/element.py6
-rw-r--r--lib/elements/fill_stitch.py128
2 files changed, 124 insertions, 10 deletions
diff --git a/lib/elements/element.py b/lib/elements/element.py
index 071f8a90..4ea909ac 100644
--- a/lib/elements/element.py
+++ b/lib/elements/element.py
@@ -22,7 +22,7 @@ from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length,
get_node_transform)
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS
from ..utils import Point, cache
-from ..utils.cache import get_stitch_plan_cache, CacheKeyGenerator
+from ..utils.cache import CacheKeyGenerator, get_stitch_plan_cache
class Param(object):
@@ -557,6 +557,9 @@ class EmbroideryElement(object):
gradient['styles'] = [(style['stop-color'], style['stop-opacity']) for style in self.gradient.stop_styles]
return gradient
+ def _get_tartan_key_data(self):
+ return (self.node.get('inkstitch:tartan', None))
+
def get_cache_key_data(self, previous_stitch):
return []
@@ -572,6 +575,7 @@ class EmbroideryElement(object):
cache_key_generator.update(self._get_patterns_cache_key_data())
cache_key_generator.update(self._get_guides_cache_key_data())
cache_key_generator.update(self.get_cache_key_data(previous_stitch))
+ cache_key_generator.update(self._get_tartan_key_data())
cache_key = cache_key_generator.get_cache_key()
debug.log(f"cache key for {self.node.get('id')} {self.node.get(INKSCAPE_LABEL)} {previous_stitch}: {cache_key}")
diff --git a/lib/elements/fill_stitch.py b/lib/elements/fill_stitch.py
index 9ba649d7..cb1d5225 100644
--- a/lib/elements/fill_stitch.py
+++ b/lib/elements/fill_stitch.py
@@ -18,11 +18,13 @@ from ..i18n import _
from ..marker import get_marker_elements
from ..stitch_plan import StitchGroup
from ..stitches import (auto_fill, circular_fill, contour_fill, guided_fill,
- legacy_fill, linear_gradient_fill, meander_fill)
+ legacy_fill, linear_gradient_fill, meander_fill,
+ tartan_fill)
from ..stitches.linear_gradient_fill import gradient_angle
from ..svg import PIXELS_PER_MM, get_node_transform
from ..svg.clip import get_clip_path
from ..svg.tags import INKSCAPE_LABEL
+from ..tartan.utils import get_tartan_settings, get_tartan_stripes
from ..utils import cache
from ..utils.geometry import ensure_multi_polygon
from ..utils.param import ParamOption
@@ -112,6 +114,25 @@ class NoGradientWarning(ValidationWarning):
]
+class NoTartanStripeWarning(ValidationWarning):
+ name = _("No stripes to render")
+ description = _("Tartan fill: There is no active fill stripe to render")
+ steps_to_solve = [
+ _('Go to Extensions > Ink/Stitch > Fill Tools > Tartan and adjust stripe settings:'),
+ _('* Check if stripes are active'),
+ _('* Check the minimum stripe width setting and the scale factor')
+ ]
+
+
+class DefaultTartanStripeWarning(ValidationWarning):
+ name = _("No customized pattern")
+ description = _("Tartan fill: Using default pattern")
+ steps_to_solve = [
+ _('Go to Extensions > Ink/Stitch > Fill Tools > Tartan and adjust stripe settings:'),
+ _('* Customize your pattern')
+ ]
+
+
class InvalidShapeError(ValidationError):
name = _("This shape is invalid")
description = _('Fill: This shape cannot be stitched out. Please try to repair it with the "Break Apart Fill Objects" extension.')
@@ -129,11 +150,12 @@ class FillStitch(EmbroideryElement):
return self.get_boolean_param('auto_fill', True)
_fill_methods = [ParamOption('auto_fill', _("Auto Fill")),
+ ParamOption('circular_fill', _("Circular Fill")),
ParamOption('contour_fill', _("Contour Fill")),
ParamOption('guided_fill', _("Guided Fill")),
- ParamOption('meander_fill', _("Meander Fill")),
- ParamOption('circular_fill', _("Circular Fill")),
ParamOption('linear_gradient_fill', _("Linear Gradient Fill")),
+ ParamOption('meander_fill', _("Meander Fill")),
+ ParamOption('tartan_fill', _("Tartan Fill")),
ParamOption('legacy_fill', _("Legacy Fill"))]
@property
@@ -247,6 +269,7 @@ class FillStitch(EmbroideryElement):
('fill_method', 'guided_fill'),
('fill_method', 'meander_fill'),
('fill_method', 'circular_fill'),
+ ('fill_method', 'tartan_fill'),
('fill_method', 'linear_gradient_fill')])
def expand(self):
return self.get_float_param('expand_mm', 0)
@@ -265,6 +288,19 @@ class FillStitch(EmbroideryElement):
return math.radians(self.get_float_param('angle', 0))
@property
+ @param('tartan_angle',
+ _('Angle of lines of stitches'),
+ tooltip=_('Relative to the tartan stripe direction.'),
+ unit='deg',
+ type='float',
+ sort_index=21,
+ select_items=[('fill_method', 'tartan_fill')],
+ default=45)
+ @cache
+ def tartan_angle(self):
+ return self.get_float_param('tartan_angle', -45)
+
+ @property
@param('max_stitch_length_mm',
_('Maximum fill stitch length'),
tooltip=_(
@@ -276,6 +312,7 @@ class FillStitch(EmbroideryElement):
('fill_method', 'contour_fill'),
('fill_method', 'guided_fill'),
('fill_method', 'linear_gradient_fill'),
+ ('fill_method', 'tartan_fill'),
('fill_method', 'legacy_fill')],
default=3.0)
def max_stitch_length(self):
@@ -293,6 +330,7 @@ class FillStitch(EmbroideryElement):
('fill_method', 'guided_fill'),
('fill_method', 'circular_fill'),
('fill_method', 'linear_gradient_fill'),
+ ('fill_method', 'tartan_fill'),
('fill_method', 'legacy_fill')],
default=0.25)
def row_spacing(self):
@@ -323,6 +361,7 @@ class FillStitch(EmbroideryElement):
select_items=[('fill_method', 'auto_fill'),
('fill_method', 'guided_fill'),
('fill_method', 'linear_gradient_fill'),
+ ('fill_method', 'tartan_fill'),
('fill_method', 'legacy_fill')],
default=4)
def staggers(self):
@@ -359,6 +398,18 @@ class FillStitch(EmbroideryElement):
@property
@param(
+ 'reverse',
+ _('Reverse fill'),
+ tooltip=_('Reverses fill path.'),
+ type='boolean',
+ sort_index=28,
+ select_items=[('fill_method', 'legacy_fill')],
+ default=False)
+ def reverse(self):
+ return self.get_boolean_param("reverse", False)
+
+ @property
+ @param(
'stop_at_ending_point',
_('Stop at ending point'),
tooltip=_('If this option is disabled, the ending point will only be used to define a general direction for '
@@ -396,7 +447,8 @@ class FillStitch(EmbroideryElement):
('fill_method', 'guided_fill'),
('fill_method', 'meander_fill'),
('fill_method', 'circular_fill'),
- ('fill_method', 'linear_gradient_fill')],
+ ('fill_method', 'linear_gradient_fill'),
+ ('fill_method', 'tartan_fill')],
sort_index=31)
def running_stitch_length(self):
return max(self.get_float_param("running_stitch_length_mm", 2.5), 0.01)
@@ -434,7 +486,8 @@ class FillStitch(EmbroideryElement):
'A pattern with various repeats can be created with a list of values separated by a space.'),
type='str',
select_items=[('fill_method', 'meander_fill'),
- ('fill_method', 'circular_fill')],
+ ('fill_method', 'circular_fill'),
+ ('fill_method', 'tartan_fill')],
default=0,
sort_index=34)
def bean_stitch_repeats(self):
@@ -467,6 +520,31 @@ class FillStitch(EmbroideryElement):
return self.get_float_param("zigzag_width_mm", 3)
@property
+ @param(
+ 'rows_per_thread',
+ _("Rows per tartan thread"),
+ tooltip=_("Consecutive rows of the same color"),
+ type='int',
+ default="2",
+ select_items=[('fill_method', 'tartan_fill')],
+ sort_index=35
+ )
+ def rows_per_thread(self):
+ return max(1, self.get_int_param("rows_per_thread", 2))
+
+ @property
+ @param('herringbone_width_mm',
+ _('Herringbone width'),
+ tooltip=_('Defines width of a herringbone pattern. Use 0 for regular rows.'),
+ unit='mm',
+ type='int',
+ default=0,
+ select_items=[('fill_method', 'tartan_fill')],
+ sort_index=36)
+ def herringbone_width(self):
+ return self.get_float_param('herringbone_width_mm', 0)
+
+ @property
def color(self):
# SVG spec says the default fill is black
return self.get_style("fill", "#000000")
@@ -679,6 +757,15 @@ class FillStitch(EmbroideryElement):
# they may used a fill on a straight line
yield StrokeAndFillWarning(self.paths[0][0])
+ # tartan fill
+ if self.fill_method == 'tartan_fill':
+ settings = get_tartan_settings(self.node)
+ warp, weft = get_tartan_stripes(settings)
+ if not (warp or weft):
+ yield NoTartanStripeWarning(self.shape.representative_point())
+ if not self.node.get('inkstitch:tartan', ''):
+ yield DefaultTartanStripeWarning(self.shape.representative_point())
+
for warning in super(FillStitch, self).validation_warnings():
yield warning
@@ -778,19 +865,38 @@ class FillStitch(EmbroideryElement):
stitch_groups.extend(self.do_circular_fill(fill_shape, previous_stitch_group, start, end))
elif self.fill_method == 'linear_gradient_fill':
stitch_groups.extend(self.do_linear_gradient_fill(fill_shape, previous_stitch_group, start, end))
+ elif self.fill_method == 'tartan_fill':
+ stitch_groups.extend(self.do_tartan_fill(fill_shape, previous_stitch_group, start, end))
else:
# auto_fill
stitch_groups.extend(self.do_auto_fill(fill_shape, previous_stitch_group, start, end))
if stitch_groups:
previous_stitch_group = stitch_groups[-1]
- # sort colors of linear gradient (if multiple shapes)
- if self.fill_method == 'linear_gradient_fill':
- colors = [stitch_group.color for stitch_group in stitch_groups]
- stitch_groups.sort(key=lambda group: colors.index(group.color))
+ # sort colors of linear gradient
+ if len(shapes) > 1 and self.fill_method == 'linear_gradient_fill':
+ self.color_sort(stitch_groups)
+
+ # sort colors of tartan fill
+ if len(shapes) > 1 and self.fill_method == 'tartan_fill':
+ # while color sorting make sure stroke lines go still on top of the fills
+ fill_groups = []
+ stroke_groups = []
+ for stitch_group in stitch_groups:
+ if "tartan_run" in stitch_group.stitches[0].tags:
+ stroke_groups.append(stitch_group)
+ else:
+ fill_groups.append(stitch_group)
+ self.color_sort(fill_groups)
+ self.color_sort(stroke_groups)
+ stitch_groups = fill_groups + stroke_groups
return stitch_groups
+ def color_sort(self, stitch_groups):
+ colors = [stitch_group.color for stitch_group in stitch_groups]
+ stitch_groups.sort(key=lambda group: colors.index(group.color))
+
def do_legacy_fill(self):
stitch_lists = legacy_fill(
self.shape,
@@ -799,6 +905,7 @@ class FillStitch(EmbroideryElement):
self.end_row_spacing,
self.max_stitch_length,
self.flip,
+ self.reverse,
self.staggers,
self.skip_last
)
@@ -996,3 +1103,6 @@ class FillStitch(EmbroideryElement):
def do_linear_gradient_fill(self, shape, last_stitch_group, start, end):
return linear_gradient_fill(self, shape, start, end)
+
+ def do_tartan_fill(self, shape, last_stitch_group, start, end):
+ return tartan_fill(self, shape, start, end)