kopia lustrzana https://github.com/inkstitch/inkstitch
Force lock stitches option/extension and some typos (#1471)
rodzic
41ace3a9e5
commit
36f7610cc0
2
Makefile
2
Makefile
|
@ -15,7 +15,7 @@ inx: version locales
|
|||
messages.po: inx
|
||||
rm -f messages.po
|
||||
xgettext inx/*.inx --its=its/inx.its -o messages-inx.po
|
||||
# There seems to be no propper way to set the charset to utf-8
|
||||
# There seems to be no proper way to set the charset to utf-8
|
||||
sed -i 's/charset=CHARSET/charset=UTF-8/g' messages-inx.po
|
||||
bin/pyembroidery-gettext > pyembroidery-format-descriptions.py
|
||||
bin/inkstitch-fonts-gettext > inkstitch-fonts-metadata.py
|
||||
|
|
|
@ -207,6 +207,18 @@ class EmbroideryElement(object):
|
|||
def ties(self):
|
||||
return self.get_int_param("ties", 0)
|
||||
|
||||
@property
|
||||
@param('force_lock_stitches',
|
||||
_('Force lock stitches'),
|
||||
tooltip=_('Sew lock stitches after sewing this element, '
|
||||
'even if the distance to the next object is shorter than defined by the collapse length value in the Ink/Stitch preferences.'),
|
||||
type='boolean',
|
||||
default=False,
|
||||
sort_index=5)
|
||||
@cache
|
||||
def force_lock_stitches(self):
|
||||
return self.get_boolean_param('force_lock_stitches', False)
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
# A CSP is a "cubic superpath".
|
||||
|
@ -312,6 +324,7 @@ class EmbroideryElement(object):
|
|||
|
||||
for patch in patches:
|
||||
patch.tie_modus = self.ties
|
||||
patch.force_lock_stitches = self.force_lock_stitches
|
||||
|
||||
if patches:
|
||||
patches[-1].trim_after = self.has_command("trim") or self.trim_after
|
||||
|
|
|
@ -24,6 +24,7 @@ from .lettering import Lettering
|
|||
from .lettering_custom_font_dir import LetteringCustomFontDir
|
||||
from .lettering_generate_json import LetteringGenerateJson
|
||||
from .lettering_remove_kerning import LetteringRemoveKerning
|
||||
from .lettering_force_lock_stitches import LetteringForceLockStitches
|
||||
from .letters_to_font import LettersToFont
|
||||
from .object_commands import ObjectCommands
|
||||
from .output import Output
|
||||
|
@ -56,6 +57,7 @@ __all__ = extensions = [StitchPlanPreview,
|
|||
LetteringGenerateJson,
|
||||
LetteringRemoveKerning,
|
||||
LetteringCustomFontDir,
|
||||
LetteringForceLockStitches,
|
||||
LettersToFont,
|
||||
Troubleshoot,
|
||||
RemoveEmbroiderySettings,
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
# Authors: see git history
|
||||
#
|
||||
# Copyright (c) 2021 Authors
|
||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import inkex
|
||||
from shapely.geometry import Point
|
||||
|
||||
from ..i18n import _
|
||||
from ..svg import PIXELS_PER_MM
|
||||
from ..svg.tags import INKSTITCH_ATTRIBS
|
||||
from .base import InkstitchExtension
|
||||
|
||||
|
||||
class LetteringForceLockStitches(InkstitchExtension):
|
||||
'''
|
||||
This extension helps font creators to add the force lock stitches attribute to the last objects of each glyph
|
||||
Font creators to add forced lock stitches on glyphs with accents / spaces.
|
||||
'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
InkstitchExtension.__init__(self, *args, **kwargs)
|
||||
self.arg_parser.add_argument("-a", "--max_distance", type=float, default=3, dest="max_distance")
|
||||
self.arg_parser.add_argument("-i", "--min_distance", type=float, default=1, dest="min_distance")
|
||||
self.arg_parser.add_argument("-l", "--last_element", type=inkex.Boolean, dest="last_element")
|
||||
|
||||
def effect(self):
|
||||
if self.options.max_distance < self.options.min_distance:
|
||||
inkex.errormssg(_("The maximum value is smaller than the minimum value."))
|
||||
|
||||
# Set glyph layers to be visible. We don't want them to be ignored by self.elements
|
||||
self._update_layer_visibility('inline')
|
||||
|
||||
# mark last elements of a glyph
|
||||
xpath = ".//svg:g[@inkscape:groupmode='layer']//svg:path[last()]"
|
||||
last_elements = self.document.xpath(xpath, namespaces=inkex.NSS)
|
||||
for last_element in last_elements:
|
||||
last_element.set('lastglyphelement', str(True))
|
||||
|
||||
# find last point of an element
|
||||
if not self.get_elements():
|
||||
return
|
||||
|
||||
previous_element = None
|
||||
last_stitch = None
|
||||
for element in self.elements:
|
||||
stitch_group = element.to_stitch_groups(None)
|
||||
# if the distance of the last stitch of the previous object to the first stitch of this objects
|
||||
# lies within the user defined distance range, set the force_lock_stitches-attribute.
|
||||
if last_stitch:
|
||||
first_stitch = stitch_group[0].stitches[0]
|
||||
first_stitch = Point(first_stitch.x, first_stitch.y)
|
||||
self._set_force_attribute(first_stitch, last_stitch, previous_element)
|
||||
|
||||
# if this is the last element of a glyph, we don't want to compare it to the next element
|
||||
if element.node.get('lastglyphelement', False):
|
||||
previous_element = None
|
||||
last_stitch = None
|
||||
else:
|
||||
previous_element = element
|
||||
last_stitch = stitch_group[-1].stitches[-1]
|
||||
last_stitch = Point(last_stitch.x, last_stitch.y)
|
||||
|
||||
# remove last element attributes again
|
||||
# set force lock stitches attribute if needed
|
||||
for last_element in last_elements:
|
||||
last_element.attrib.pop('lastglyphelement')
|
||||
if self.options.last_element:
|
||||
last_element.set(INKSTITCH_ATTRIBS['force_lock_stitches'], True)
|
||||
|
||||
# hide glyph layers again
|
||||
self._update_layer_visibility('none')
|
||||
|
||||
def _set_force_attribute(self, first_stitch, last_stitch, previous_element):
|
||||
distance_mm = first_stitch.distance(last_stitch) / PIXELS_PER_MM
|
||||
|
||||
if distance_mm < self.options.max_distance and distance_mm > self.options.min_distance:
|
||||
previous_element.node.set(INKSTITCH_ATTRIBS['force_lock_stitches'], True)
|
||||
|
||||
def _update_layer_visibility(self, display):
|
||||
xpath = ".//svg:g[@inkscape:groupmode='layer']"
|
||||
layers = self.document.xpath(xpath, namespaces=inkex.NSS)
|
||||
for layer in layers:
|
||||
display_style = 'display:%s' % display
|
||||
style = inkex.Style(layer.get('style', '')) + inkex.Style(display_style)
|
||||
layer.set('style', style)
|
|
@ -7,7 +7,7 @@ from .base import InkstitchExtension
|
|||
|
||||
|
||||
class Reorder(InkstitchExtension):
|
||||
# Remove selected objects from the document and readd them in the order they
|
||||
# Remove selected objects from the document and re-add them in the order they
|
||||
# were selected.
|
||||
|
||||
def effect(self):
|
||||
|
|
|
@ -41,7 +41,7 @@ class StitchPlanPreview(InkstitchExtension):
|
|||
# apply options
|
||||
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
|
||||
|
||||
# update layer visibilty 0 = unchanged, 1 = hidden, 2 = lower opacity
|
||||
# update layer visibility 0 = unchanged, 1 = hidden, 2 = lower opacity
|
||||
if self.options.layer_visibility == 1:
|
||||
self.hide_all_layers()
|
||||
layer.set('style', None)
|
||||
|
|
|
@ -88,7 +88,7 @@ class Glyph(object):
|
|||
self.min_x = left
|
||||
|
||||
def _process_commands(self):
|
||||
# Save object ids with commmands in a dictionary: {object_id: [connector_id, symbol_id]}
|
||||
# Save object ids with commands in a dictionary: {object_id: [connector_id, symbol_id]}
|
||||
self.commands = {}
|
||||
|
||||
for node in self.node.iter(SVG_USE_TAG):
|
||||
|
|
|
@ -10,7 +10,8 @@ from copy import deepcopy
|
|||
class Stitch(Point):
|
||||
"""A stitch is a Point with extra information telling how to sew it."""
|
||||
|
||||
def __init__(self, x, y=None, color=None, jump=False, stop=False, trim=False, color_change=False, tie_modus=0, no_ties=False, tags=None):
|
||||
def __init__(self, x, y=None, color=None, jump=False, stop=False, trim=False, color_change=False,
|
||||
tie_modus=0, force_lock_stitches=False, no_ties=False, tags=None):
|
||||
if isinstance(x, Stitch):
|
||||
# Allow creating a Stitch from another Stitch. Attributes passed as
|
||||
# arguments will override any existing attributes.
|
||||
|
@ -28,6 +29,7 @@ class Stitch(Point):
|
|||
self.trim = trim
|
||||
self.stop = stop
|
||||
self.color_change = color_change
|
||||
self.force_lock_stitches = force_lock_stitches
|
||||
self.tie_modus = tie_modus
|
||||
self.no_ties = no_ties
|
||||
self.tags = set()
|
||||
|
@ -35,15 +37,16 @@ class Stitch(Point):
|
|||
self.add_tags(tags or [])
|
||||
|
||||
def __repr__(self):
|
||||
return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.x,
|
||||
self.y,
|
||||
self.color,
|
||||
"JUMP" if self.jump else " ",
|
||||
"TRIM" if self.trim else " ",
|
||||
"STOP" if self.stop else " ",
|
||||
"TIE MODUS" if self.tie_modus else " ",
|
||||
"NO TIES" if self.no_ties else " ",
|
||||
"COLOR CHANGE" if self.color_change else " ")
|
||||
return "Stitch(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.x,
|
||||
self.y,
|
||||
self.color,
|
||||
"JUMP" if self.jump else " ",
|
||||
"TRIM" if self.trim else " ",
|
||||
"STOP" if self.stop else " ",
|
||||
"TIE MODUS" if self.tie_modus else " ",
|
||||
"FORCE LOCK STITCHES" if self.force_lock_stitches else " ",
|
||||
"NO TIES" if self.no_ties else " ",
|
||||
"COLOR CHANGE" if self.color_change else " ")
|
||||
|
||||
def add_tags(self, tags):
|
||||
for tag in tags:
|
||||
|
@ -68,7 +71,8 @@ class Stitch(Point):
|
|||
return tag in self.tags
|
||||
|
||||
def copy(self):
|
||||
return Stitch(self.x, self.y, self.color, self.jump, self.stop, self.trim, self.color_change, self.tie_modus, self.no_ties, self.tags)
|
||||
return Stitch(self.x, self.y, self.color, self.jump, self.stop, self.trim, self.color_change,
|
||||
self.tie_modus, self.force_lock_stitches, self.no_ties, self.tags)
|
||||
|
||||
def __json__(self):
|
||||
attributes = dict(vars(self))
|
||||
|
|
|
@ -17,11 +17,13 @@ class StitchGroup:
|
|||
between them by the stitch plan generation code.
|
||||
"""
|
||||
|
||||
def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False, tie_modus=0, stitch_as_is=False, tags=None):
|
||||
def __init__(self, color=None, stitches=None, trim_after=False, stop_after=False,
|
||||
tie_modus=0, force_lock_stitches=False, stitch_as_is=False, tags=None):
|
||||
self.color = color
|
||||
self.trim_after = trim_after
|
||||
self.stop_after = stop_after
|
||||
self.tie_modus = tie_modus
|
||||
self.force_lock_stitches = force_lock_stitches
|
||||
self.stitch_as_is = stitch_as_is
|
||||
self.stitches = []
|
||||
|
||||
|
|
|
@ -42,10 +42,13 @@ def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=
|
|||
# always start a color with a JUMP to the first stitch position
|
||||
color_block.add_stitch(stitch_group.stitches[0], jump=True)
|
||||
else:
|
||||
if len(color_block) and (stitch_group.stitches[0] - color_block.stitches[-1]).length() > collapse_len:
|
||||
if (len(color_block) and
|
||||
((stitch_group.stitches[0] - color_block.stitches[-1]).length() > collapse_len or
|
||||
color_block.stitches[-1].force_lock_stitches)):
|
||||
color_block.add_stitch(stitch_group.stitches[0], jump=True)
|
||||
|
||||
color_block.add_stitches(stitches=stitch_group.stitches, tie_modus=stitch_group.tie_modus, no_ties=stitch_group.stitch_as_is)
|
||||
color_block.add_stitches(stitches=stitch_group.stitches, tie_modus=stitch_group.tie_modus,
|
||||
force_lock_stitches=stitch_group.force_lock_stitches, no_ties=stitch_group.stitch_as_is)
|
||||
|
||||
if stitch_group.trim_after:
|
||||
color_block.add_stitch(trim=True)
|
||||
|
|
|
@ -37,7 +37,7 @@ def add_tie(stitches, tie_path):
|
|||
|
||||
def add_tie_off(stitches):
|
||||
# tie_modus: 0 = both | 1 = before | 2 = after | 3 = neither
|
||||
if stitches[-1].tie_modus not in [1, 3]:
|
||||
if stitches[-1].tie_modus not in [1, 3] or stitches[-1].force_lock_stitches:
|
||||
add_tie(stitches, stitches[-1:-3:-1])
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ SVG_OBJECT_TAGS = (SVG_ELLIPSE_TAG, SVG_CIRCLE_TAG, SVG_RECT_TAG)
|
|||
INKSTITCH_ATTRIBS = {}
|
||||
inkstitch_attribs = [
|
||||
'ties',
|
||||
'force_lock_stitches',
|
||||
# clone
|
||||
'clone',
|
||||
# polyline
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Force lock stitches</name>
|
||||
<id>org.inkstitch.force_lock_stitches</id>
|
||||
<param name="extension" type="string" gui-hidden="true">lettering_force_lock_stitches</param>
|
||||
<effect needs-live-preview="false">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="Ink/Stitch" translatable="no">
|
||||
<submenu name="Font Management" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<param name="force-lock-stitches" type="description" indent="1" >
|
||||
Small fonts will sometimes unravel if threads are cut after the embroidery machine has finished the work.
|
||||
Therefore it is important that also diacritics with a smaller distance to the font body than defined by the collapse length value (default: 3mm) have lock stitches.
|
||||
This can be achieved by adding a forced lock stitch attribute to them.
|
||||
</param>
|
||||
<separator />
|
||||
<param name="extension-description" type="description" indent="1">
|
||||
This extension has been build to help font authors to define "force lock stitches"-attributes automatically if they are placed in a predefined distance to the next object.
|
||||
</param>
|
||||
<param indent="1" name="min_distance" type="float" gui-text="Minimum distance (mm)" min="0" max="3">1</param>
|
||||
<param indent="1" name="max_distance" type="float" gui-text="Minimum distance (mm)" min="1" max="10">3</param>
|
||||
<separator />
|
||||
<param indent="1" name="last_element" type="boolean" gui-text="Add force lock stitches attribute to the last element of each glyph">false</param>
|
||||
<script>
|
||||
{{ command_tag | safe }}
|
||||
</script>
|
||||
</inkscape-extension>
|
|
@ -12,7 +12,7 @@
|
|||
</effects-menu>
|
||||
</effect>
|
||||
<param name="move-to-side" type="boolean" gui-text="Move stitch plan beside the canvas">true</param>
|
||||
<param name="layer-visibility" type="optiongroup" appearance="combo" gui-text="Design layer visibity">
|
||||
<param name="layer-visibility" type="optiongroup" appearance="combo" gui-text="Design layer visibility">
|
||||
<option value="0">Unchanged</option>
|
||||
<option value="1">Hidden</option>
|
||||
<option value="2">Lower opacity</option>
|
||||
|
|
Ładowanie…
Reference in New Issue