Fix lettering scale, etc. (#1620)

* fix lettering scale
* adapt to updated inkex:  transform operator, selections
* fix #1597
* no traceback error message on broken satin columns
* highlight troubleshoot "steps to solve" through additional headline
* set a minimum value for running stitch repeats
* rename "import" thread list to "apply" thread list
pull/1644/head
Kaalleen 2022-04-24 08:27:42 +02:00 zatwierdzone przez GitHub
rodzic 4058712139
commit f9d57f6ea5
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
30 zmienionych plików z 131 dodań i 108 usunięć

Wyświetl plik

@ -5,8 +5,6 @@
from math import atan, degrees from math import atan, degrees
import inkex
from ..commands import is_command, is_command_symbol from ..commands import is_command, is_command_symbol
from ..i18n import _ from ..i18n import _
from ..svg.path import get_node_transform from ..svg.path import get_node_transform
@ -128,7 +126,7 @@ class Clone(EmbroideryElement):
return patches return patches
def get_clone_style(self, style_name, node, default=None): def get_clone_style(self, style_name, node, default=None):
style = inkex.styles.AttrFallbackStyle(node).get(style_name) or default style = node.style[style_name] or default
return style return style
def center(self, source_node): def center(self, source_node):

Wyświetl plik

@ -6,17 +6,18 @@
from copy import deepcopy from copy import deepcopy
from itertools import chain from itertools import chain
from inkex import paths
from shapely import affinity as shaffinity from shapely import affinity as shaffinity
from shapely import geometry as shgeo from shapely import geometry as shgeo
from shapely.ops import nearest_points from shapely.ops import nearest_points
from .element import EmbroideryElement, param from inkex import paths
from .validation import ValidationError, ValidationWarning
from ..i18n import _ from ..i18n import _
from ..stitch_plan import StitchGroup from ..stitch_plan import StitchGroup
from ..svg import line_strings_to_csp, point_lists_to_csp from ..svg import line_strings_to_csp, point_lists_to_csp
from ..utils import Point, cache, collapse_duplicate_point, cut from ..utils import Point, cache, collapse_duplicate_point, cut
from .element import EmbroideryElement, param
from .validation import ValidationError, ValidationWarning
class SatinHasFillError(ValidationError): class SatinHasFillError(ValidationError):
@ -51,6 +52,15 @@ class UnequalPointsError(ValidationError):
] ]
class NotStitchableError(ValidationError):
name = _("Not stitchable satin column")
description = _("A satin column consists out of two rails and one or more rungs. This satin column may have a different setup.")
steps_to_solve = [
_('Make sure your satin column is not a combination of multiple satin columns.'),
_('Go to our website and read how a satin column should look like https://inkstitch.org/docs/stitches/satin-column/'),
]
rung_message = _("Each rung should intersect both rails once.") rung_message = _("Each rung should intersect both rails once.")
@ -422,6 +432,9 @@ class SatinColumn(EmbroideryElement):
if not intersection.is_empty and not isinstance(intersection, shgeo.Point): if not intersection.is_empty and not isinstance(intersection, shgeo.Point):
yield TooManyIntersectionsError(rung.interpolate(0.5, normalized=True)) yield TooManyIntersectionsError(rung.interpolate(0.5, normalized=True))
if not self.to_stitch_groups():
yield NotStitchableError(self.shape.centroid)
def reverse(self): def reverse(self):
"""Return a new SatinColumn like this one but in the opposite direction. """Return a new SatinColumn like this one but in the opposite direction.
@ -859,7 +872,7 @@ class SatinColumn(EmbroideryElement):
points.append(Point(split_point.x, split_point.y)) points.append(Point(split_point.x, split_point.y))
return [points, split_count] return [points, split_count]
def to_stitch_groups(self, last_patch): def to_stitch_groups(self, last_patch=None):
# Stitch a variable-width satin column, zig-zagging between two paths. # Stitch a variable-width satin column, zig-zagging between two paths.
# The algorithm will draw zigzags between each consecutive pair of # The algorithm will draw zigzags between each consecutive pair of
@ -884,4 +897,7 @@ class SatinColumn(EmbroideryElement):
else: else:
patch += self.do_satin() patch += self.do_satin()
if not patch.stitches:
return []
return [patch] return [patch]

Wyświetl plik

@ -77,7 +77,8 @@ class Stroke(EmbroideryElement):
default="1", default="1",
sort_index=1) sort_index=1)
def repeats(self): def repeats(self):
return self.get_int_param("repeats", 1) repeats = self.get_int_param("repeats", 1)
return max(1, repeats)
@property @property
def paths(self): def paths(self):

Wyświetl plik

@ -5,6 +5,7 @@
from lib.extensions.troubleshoot import Troubleshoot from lib.extensions.troubleshoot import Troubleshoot
from .apply_threadlist import ApplyThreadlist
from .auto_satin import AutoSatin from .auto_satin import AutoSatin
from .break_apart import BreakApart from .break_apart import BreakApart
from .cleanup import Cleanup from .cleanup import Cleanup
@ -18,7 +19,6 @@ from .embroider_settings import EmbroiderSettings
from .flip import Flip from .flip import Flip
from .generate_palette import GeneratePalette from .generate_palette import GeneratePalette
from .global_commands import GlobalCommands from .global_commands import GlobalCommands
from .import_threadlist import ImportThreadlist
from .input import Input from .input import Input
from .install import Install from .install import Install
from .install_custom_palette import InstallCustomPalette from .install_custom_palette import InstallCustomPalette
@ -71,7 +71,7 @@ __all__ = extensions = [StitchPlanPreview,
RemoveEmbroiderySettings, RemoveEmbroiderySettings,
Cleanup, Cleanup,
BreakApart, BreakApart,
ImportThreadlist, ApplyThreadlist,
InstallCustomPalette, InstallCustomPalette,
GeneratePalette, GeneratePalette,
PaletteSplitText, PaletteSplitText,

Wyświetl plik

@ -14,7 +14,12 @@ from ..threads import ThreadCatalog
from .base import InkstitchExtension from .base import InkstitchExtension
class ImportThreadlist(InkstitchExtension): class ApplyThreadlist(InkstitchExtension):
'''
Applies colors of a thread list to elements
Count of colors and elements should fit together
Use case: reapply colors to e.g. a dst file
'''
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self, *args, **kwargs) InkstitchExtension.__init__(self, *args, **kwargs)
self.arg_parser.add_argument("-f", "--filepath", type=str, default="", dest="filepath") self.arg_parser.add_argument("-f", "--filepath", type=str, default="", dest="filepath")
@ -23,7 +28,7 @@ class ImportThreadlist(InkstitchExtension):
def effect(self): def effect(self):
# Remove selection, we want all the elements in the document # Remove selection, we want all the elements in the document
self.svg.selected.clear() self.svg.selection.clear()
if not self.get_elements(): if not self.get_elements():
return return

Wyświetl plik

@ -44,7 +44,7 @@ class AutoSatin(CommandsExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
# L10N auto-route satin columns extension # L10N auto-route satin columns extension
inkex.errormsg(_("Please select one or more satin columns.")) inkex.errormsg(_("Please select one or more satin columns."))
return False return False

Wyświetl plik

@ -121,7 +121,7 @@ class InkstitchExtension(inkex.Effect):
return current_layer return current_layer
def no_elements_error(self): def no_elements_error(self):
if self.svg.selected: if self.svg.selection:
# l10n This was previously: "No embroiderable paths selected." # l10n This was previously: "No embroiderable paths selected."
inkex.errormsg(_("Ink/Stitch doesn't know how to work with any of the objects you've selected.") + "\n") inkex.errormsg(_("Ink/Stitch doesn't know how to work with any of the objects you've selected.") + "\n")
else: else:
@ -156,8 +156,8 @@ class InkstitchExtension(inkex.Effect):
if is_command(node) or node.get(CONNECTOR_TYPE): if is_command(node) or node.get(CONNECTOR_TYPE):
return [] return []
if self.svg.selected: if self.svg.selection:
if node.get("id") in self.svg.selected: if node.get("id") in self.svg.selection:
selected = True selected = True
else: else:
# if the user didn't select anything that means we process everything # if the user didn't select anything that means we process everything
@ -188,14 +188,6 @@ class InkstitchExtension(inkex.Effect):
self.no_elements_error() self.no_elements_error()
return False return False
def get_selected_in_order(self):
selected = []
for i in self.options.ids:
path = '//*[@id="%s"]' % i
for node in self.document.xpath(path, namespaces=inkex.NSS):
selected.append(node)
return selected
def elements_to_stitch_groups(self, elements): def elements_to_stitch_groups(self, elements):
patches = [] patches = []
for element in elements: for element in elements:

Wyświetl plik

@ -27,7 +27,7 @@ class BreakApart(InkstitchExtension):
self.minimum_size = 5 self.minimum_size = 5
def effect(self): # noqa: C901 def effect(self): # noqa: C901
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select one or more fill areas to break apart.")) inkex.errormsg(_("Please select one or more fill areas to break apart."))
return return

Wyświetl plik

@ -24,7 +24,7 @@ class Cleanup(InkstitchExtension):
self.fill_threshold = self.options.fill_threshold self.fill_threshold = self.options.fill_threshold
self.stroke_threshold = self.options.stroke_threshold self.stroke_threshold = self.options.stroke_threshold
self.svg.selected.clear() self.svg.selection.clear()
count = 0 count = 0
svg = self.document.getroot() svg = self.document.getroot()

Wyświetl plik

@ -31,7 +31,7 @@ class ConvertToSatin(InkstitchExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select at least one line to convert to a satin column.")) inkex.errormsg(_("Please select at least one line to convert to a satin column."))
return return

Wyświetl plik

@ -21,7 +21,7 @@ class ConvertToStroke(InkstitchExtension):
self.arg_parser.add_argument("-k", "--keep_satin", type=inkex.Boolean, default=False, dest="keep_satin") self.arg_parser.add_argument("-k", "--keep_satin", type=inkex.Boolean, default=False, dest="keep_satin")
def effect(self): def effect(self):
if not self.svg.selected or not self.get_elements(): if not self.svg.selection or not self.get_elements():
inkex.errormsg(_("Please select at least one satin column to convert to a running stitch.")) inkex.errormsg(_("Please select at least one satin column to convert to a running stitch."))
return return

Wyświetl plik

@ -16,7 +16,7 @@ class CutSatin(InkstitchExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select one or more satin columns to cut.")) inkex.errormsg(_("Please select one or more satin columns to cut."))
return return

Wyświetl plik

@ -43,7 +43,7 @@ class CutworkSegmentation(InkstitchExtension):
self.arg_parser.add_argument("-k", "--keep_original", type=inkex.Boolean, default=False, dest="keep_original") self.arg_parser.add_argument("-k", "--keep_original", type=inkex.Boolean, default=False, dest="keep_original")
def effect(self): def effect(self):
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select one or more stroke elements.")) inkex.errormsg(_("Please select one or more stroke elements."))
return return

Wyświetl plik

@ -3,10 +3,9 @@
# Copyright (c) 2021 Authors # Copyright (c) 2021 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import inkex from inkex import NSS, ShapeElement, errormsg
from ..i18n import _ from ..i18n import _
from ..svg.tags import EMBROIDERABLE_TAGS, SVG_GROUP_TAG
from .base import InkstitchExtension from .base import InkstitchExtension
@ -14,36 +13,29 @@ class DuplicateParams(InkstitchExtension):
# Transfer inkstitch namespaced attributes from the first selected element to the rest of selection # Transfer inkstitch namespaced attributes from the first selected element to the rest of selection
def effect(self): def effect(self):
objects = self.get_selected_in_order() objects = self.svg.selection.get(ShapeElement)
if len(objects) < 2: if len(objects) < 2:
inkex.errormsg(_("This function copies Ink/Stitch parameters from the first selected element to the rest of the selection. " errormsg(_("This function copies Ink/Stitch parameters from the first selected element to the rest of the selection. "
"Please select at least two elements.")) "Please select at least two elements."))
return return
copy_from = objects[0] copy_from = objects.first()
copy_from_attribs = self.get_inkstitch_attributes(copy_from) copy_from_attribs = self.get_inkstitch_attributes(copy_from)
copy_to_selection = objects[1:] copy_to = objects
self.copy_to = []
# extract copy_to group elements
for element in copy_to_selection:
if element.tag == SVG_GROUP_TAG:
for descendant in element.iterdescendants(EMBROIDERABLE_TAGS):
self.copy_to.append(descendant)
elif element.tag in EMBROIDERABLE_TAGS:
self.copy_to.append(element)
# remove inkstitch params from copy_to elements # remove inkstitch params from copy_to elements
for element in self.copy_to: for element in copy_to:
if element == copy_to.first():
continue
copy_to_attribs = self.get_inkstitch_attributes(element) copy_to_attribs = self.get_inkstitch_attributes(element)
for attrib in copy_to_attribs: for attrib in copy_to_attribs:
element.pop(attrib) element.pop(attrib)
# paste inkstitch params from copy_from element to copy_to elements # paste inkstitch params from copy_from element to copy_to elements
for attrib in copy_from_attribs: for attrib in copy_from_attribs:
for element in self.copy_to: for element in copy_to:
element.attrib[attrib] = copy_from_attribs[attrib] element.attrib[attrib] = copy_from_attribs[attrib]
def get_inkstitch_attributes(self, node): def get_inkstitch_attributes(self, node):
return {k: v for k, v in node.attrib.iteritems() if inkex.NSS['inkstitch'] in k} return {k: v for k, v in node.attrib.iteritems() if NSS['inkstitch'] in k}

Wyświetl plik

@ -24,7 +24,7 @@ class Flip(InkstitchExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select one or more satin columns to flip.")) inkex.errormsg(_("Please select one or more satin columns to flip."))
return return

Wyświetl plik

@ -9,10 +9,11 @@ import sys
from base64 import b64decode from base64 import b64decode
import appdirs import appdirs
import inkex
import wx import wx
import wx.adv import wx.adv
import inkex
from ..elements import nodes_to_elements from ..elements import nodes_to_elements
from ..gui import PresetsPanel, SimulatorPreview, info_dialog from ..gui import PresetsPanel, SimulatorPreview, info_dialog
from ..i18n import _ from ..i18n import _
@ -272,12 +273,15 @@ class LetteringFrame(wx.Frame):
font.render_text(self.settings.text, destination_group, back_and_forth=self.settings.back_and_forth, trim=self.settings.trim) font.render_text(self.settings.text, destination_group, back_and_forth=self.settings.back_and_forth, trim=self.settings.trim)
except FontError as e: except FontError as e:
if raise_error: if raise_error:
inkex.errormsg("Error: Text cannot be applied to the document.\n%s" % e) inkex.errormsg(_("Error: Text cannot be applied to the document.\n%s") % e)
return return
else: else:
pass pass
if self.settings.scale != 100: # destination_group isn't always the text scaling group (but also the parent group)
# the text scaling group label is dependend on the user language, so it would break in international file exchange if we used it
# scaling (correction transform) on the parent group is already applied, so let's use that for recognition
if self.settings.scale != 100 and not destination_group.get('transform', None):
destination_group.attrib['transform'] = 'scale(%s)' % (self.settings.scale / 100.0) destination_group.attrib['transform'] = 'scale(%s)' % (self.settings.scale / 100.0)
def generate_patches(self, abort_early=None): def generate_patches(self, abort_early=None):
@ -395,10 +399,10 @@ class Lettering(CommandsExtension):
self.cancelled = True self.cancelled = True
def get_or_create_group(self): def get_or_create_group(self):
if self.svg.selected: if self.svg.selection:
groups = set() groups = set()
for node in self.svg.selected.values(): for node in self.svg.selection:
if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib: if node.tag == SVG_GROUP_TAG and INKSTITCH_LETTERING in node.attrib:
groups.add(node) groups.add(node)

Wyświetl plik

@ -17,7 +17,7 @@ class ObjectCommands(CommandsExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select one or more objects to which to attach commands.")) inkex.errormsg(_("Please select one or more objects to which to attach commands."))
return return

Wyświetl plik

@ -22,22 +22,21 @@ class PaletteSplitText(InkstitchExtension):
line_height = self.options.line_height line_height = self.options.line_height
for text in self.svg.selected: for text in self.svg.selection.get(inkex.elements.TextElement):
if type(text) == inkex.elements.TextElement: parent = text.getparent()
parent = text.getparent() content = text.get_text()
content = text.get_text() lines = content.split('\n')
lines = content.split('\n') lines.reverse()
lines.reverse() style = text.get('style')
style = text.get('style') x = text.get('x')
x = text.get('x') y = text.get('y')
y = text.get('y') y = float(y) + (len(lines) - 1) * line_height
y = float(y) + (len(lines) - 1) * line_height for line in lines:
for line in lines: element = inkex.TextElement()
element = inkex.TextElement() element.text = line
element.text = line element.set('style', style)
element.set('style', style) element.set('x', x)
element.set('x', x) element.set('y', str(y))
element.set('y', str(y)) y = float(y) - line_height
y = float(y) - line_height parent.insert(0, element)
parent.insert(0, element) parent.remove(text)
parent.remove(text)

Wyświetl plik

@ -301,7 +301,7 @@ class Print(InkstitchExtension):
# objects. It's almost certain they meant to print the whole design. # objects. It's almost certain they meant to print the whole design.
# If they really wanted to print just a few objects, they could set # If they really wanted to print just a few objects, they could set
# the rest invisible temporarily. # the rest invisible temporarily.
self.svg.selected.clear() self.svg.selection.clear()
if not self.get_elements(): if not self.get_elements():
return return

Wyświetl plik

@ -3,11 +3,10 @@
# Copyright (c) 2010 Authors # Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from inkex import NSS, Boolean from inkex import NSS, Boolean, ShapeElement
from ..commands import find_commands from ..commands import find_commands
from ..svg.svg import find_elements from ..svg.svg import find_elements
from ..svg.tags import EMBROIDERABLE_TAGS, SVG_GROUP_TAG
from .base import InkstitchExtension from .base import InkstitchExtension
@ -36,7 +35,7 @@ class RemoveEmbroiderySettings(InkstitchExtension):
self.remove_element(print_setting) self.remove_element(print_setting)
def remove_params(self): def remove_params(self):
if not self.svg.selected: if not self.svg.selection:
xpath = ".//svg:path|.//svg:circle|.//svg:rect|.//svg:ellipse" xpath = ".//svg:path|.//svg:circle|.//svg:rect|.//svg:ellipse"
elements = find_elements(self.svg, xpath) elements = find_elements(self.svg, xpath)
self.remove_inkstitch_attributes(elements) self.remove_inkstitch_attributes(elements)
@ -45,7 +44,7 @@ class RemoveEmbroiderySettings(InkstitchExtension):
self.remove_inkstitch_attributes(elements) self.remove_inkstitch_attributes(elements)
def remove_commands(self): def remove_commands(self):
if not self.svg.selected: if not self.svg.selection:
# remove intact command groups # remove intact command groups
xpath = ".//svg:g[starts-with(@id,'command_group')]" xpath = ".//svg:g[starts-with(@id,'command_group')]"
groups = find_elements(self.svg, xpath) groups = find_elements(self.svg, xpath)
@ -58,7 +57,7 @@ class RemoveEmbroiderySettings(InkstitchExtension):
group = command.connector.getparent() group = command.connector.getparent()
group.getparent().remove(group) group.getparent().remove(group)
if not self.svg.selected: if not self.svg.selection:
# remove standalone commands and ungrouped object commands # remove standalone commands and ungrouped object commands
standalone_commands = ".//svg:use[starts-with(@xlink:href, '#inkstitch_')]|.//svg:path[starts-with(@id, 'command_connector')]" standalone_commands = ".//svg:use[starts-with(@xlink:href, '#inkstitch_')]|.//svg:path[starts-with(@id, 'command_connector')]"
self.remove_elements(standalone_commands) self.remove_elements(standalone_commands)
@ -68,14 +67,7 @@ class RemoveEmbroiderySettings(InkstitchExtension):
self.remove_elements(symbols) self.remove_elements(symbols)
def get_selected_elements(self): def get_selected_elements(self):
elements = [] return self.svg.selection.get(ShapeElement)
for node in self.svg.selected.values():
if node.tag == SVG_GROUP_TAG:
for child in node.iterdescendants(EMBROIDERABLE_TAGS):
elements.append(child)
else:
elements.append(node)
return elements
def remove_elements(self, xpath): def remove_elements(self, xpath):
elements = find_elements(self.svg, xpath) elements = find_elements(self.svg, xpath)

Wyświetl plik

@ -3,6 +3,9 @@
# Copyright (c) 2010 Authors # Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from inkex import errormsg
from ..i18n import _
from .base import InkstitchExtension from .base import InkstitchExtension
@ -11,10 +14,15 @@ class Reorder(InkstitchExtension):
# were selected. # were selected.
def effect(self): def effect(self):
objects = self.get_selected_in_order() objects = self.svg.selection
for obj in objects[1:]: if not objects:
obj.getparent().remove(obj) errormsg(_("Please select at least to elements to reorder."))
return
for obj in objects:
if not obj == objects.first():
obj.getparent().remove(obj)
insert_parent = objects[0].getparent() insert_parent = objects[0].getparent()
insert_pos = insert_parent.index(objects[0]) insert_pos = insert_parent.index(objects[0])

Wyświetl plik

@ -17,7 +17,7 @@ class SelectionToPattern(InkstitchExtension):
if not self.get_elements(): if not self.get_elements():
return return
if not self.svg.selected: if not self.svg.selection:
inkex.errormsg(_("Please select at least one object to be marked as a pattern.")) inkex.errormsg(_("Please select at least one object to be marked as a pattern."))
return return

Wyświetl plik

@ -128,7 +128,7 @@ class Troubleshoot(InkstitchExtension):
self.warning_group = warning_group self.warning_group = warning_group
self.type_warning_group = type_warning_group self.type_warning_group = type_warning_group
def add_descriptions(self, problem_types): def add_descriptions(self, problem_types): # noqa: C901
svg = self.document.getroot() svg = self.document.getroot()
# We could use svg.viewport_width, but then we would need to do unit conversions, # We could use svg.viewport_width, but then we would need to do unit conversions,
@ -174,6 +174,8 @@ class Troubleshoot(InkstitchExtension):
text.append([problem.name, "font-weight: bold; fill: %s;" % text_color]) text.append([problem.name, "font-weight: bold; fill: %s;" % text_color])
text.append([problem.description, "font-size: 3px;"]) text.append([problem.description, "font-size: 3px;"])
text.append(["", ""]) text.append(["", ""])
if problem.steps_to_solve:
text.append([_("Possible solutions"), "font-weight: bold; text-decoration: underline; font-size: 4px;"])
for step in problem.steps_to_solve: for step in problem.steps_to_solve:
text.append([step, "font-size: 4px;"]) text.append([step, "font-size: 4px;"])
text.append(["", ""]) text.append(["", ""])

Wyświetl plik

@ -87,14 +87,14 @@ class Font(object):
def _load_metadata(self): def _load_metadata(self):
try: try:
with open(os.path.join(self.path, "font.json"), encoding="utf-8") as metadata_file: with open(os.path.join(self.path, "font.json"), encoding="utf-8-sig") as metadata_file:
self.metadata = json.load(metadata_file) self.metadata = json.load(metadata_file)
except IOError: except IOError:
pass pass
def _load_license(self): def _load_license(self):
try: try:
with open(os.path.join(self.path, "LICENSE"), encoding="utf-8") as license_file: with open(os.path.join(self.path, "LICENSE"), encoding="utf-8-sig") as license_file:
self.license = license_file.read() self.license = license_file.read()
except IOError: except IOError:
pass pass

Wyświetl plik

@ -3,9 +3,14 @@
# Copyright (c) 2010 Authors # Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from .ties import add_ties from sys import exit
from .color_block import ColorBlock
from inkex import errormsg
from ..i18n import _
from ..svg import PIXELS_PER_MM from ..svg import PIXELS_PER_MM
from .color_block import ColorBlock
from .ties import add_ties
def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=False): # noqa: C901 def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=False): # noqa: C901
@ -17,6 +22,11 @@ def stitch_groups_to_stitch_plan(stitch_groups, collapse_len=None, disable_ties=
* adds jump-stitches between stitch_group if necessary * adds jump-stitches between stitch_group if necessary
""" """
if not stitch_groups:
errormsg(_("There is no selected stitchable element. Please run "
"Extensions > Ink/Stitch > Troubleshoot > Troubleshoot objects in case you have expected a stitchout."))
exit(1)
if collapse_len is None: if collapse_len is None:
collapse_len = 3.0 collapse_len = 3.0
collapse_len = collapse_len * PIXELS_PER_MM collapse_len = collapse_len * PIXELS_PER_MM

Wyświetl plik

@ -24,7 +24,7 @@ def compose_parent_transforms(node, mat):
trans = node.get('transform') trans = node.get('transform')
if trans: if trans:
mat = inkex.transforms.Transform(trans) * mat mat = inkex.transforms.Transform(trans) @ mat
if node.getparent() is not None: if node.getparent() is not None:
if node.getparent().tag in [SVG_GROUP_TAG, SVG_LINK_TAG]: if node.getparent().tag in [SVG_GROUP_TAG, SVG_LINK_TAG]:
mat = compose_parent_transforms(node.getparent(), mat) mat = compose_parent_transforms(node.getparent(), mat)
@ -47,7 +47,7 @@ def get_node_transform(node):
# add in the transform implied by the viewBox # add in the transform implied by the viewBox
viewbox_transform = get_viewbox_transform(node.getroottree().getroot()) viewbox_transform = get_viewbox_transform(node.getroottree().getroot())
transform = viewbox_transform * transform transform = viewbox_transform @ transform
return transform return transform

Wyświetl plik

@ -149,7 +149,7 @@ def get_viewbox_transform(node):
sx = sy = max(sx, sy) if 'slice' in aspect_ratio else min(sx, sy) sx = sy = max(sx, sy) if 'slice' in aspect_ratio else min(sx, sy)
scale_transform = inkex.transforms.Transform("scale(%f, %f)" % (sx, sy)) scale_transform = inkex.transforms.Transform("scale(%f, %f)" % (sx, sy))
transform = transform * scale_transform transform = transform @ scale_transform
except ZeroDivisionError: except ZeroDivisionError:
pass pass

Wyświetl plik

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension"> <inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Import Threadlist</name> <name>Apply Threadlist</name>
<id>org.inkstitch.import_threadlist</id> <id>org.inkstitch.apply_threadlist</id>
<param name="extension" type="string" gui-hidden="true">import_threadlist</param> <param name="extension" type="string" gui-hidden="true">apply_threadlist</param>
<param name="filepath" type="path" gui-text="Choose file" mode="file" filetypes="txt"/> <param name="filepath" type="path" gui-text="Choose file" mode="file" filetypes="txt"/>
<param name="method" type="optiongroup" gui-text="Choose method"> <param name="method" type="optiongroup" gui-text="Choose method">
<option value="1">Import Ink/Stitch threadlist</option> <option value="1">Apply Ink/Stitch threadlist</option>
<option value="2">Import other threadlist*</option> <option value="2">Apply other threadlist*</option>
</param> </param>
<param name="palette" type="enum" gui-text="*Choose color palette"> <param name="palette" type="enum" gui-text="*Choose color palette">
{%- for item in threadcatalog %} {%- for item in threadcatalog %}

Wyświetl plik

@ -8,7 +8,9 @@
<object-type>all</object-type> <object-type>all</object-type>
<effects-menu> <effects-menu>
<submenu name="Ink/Stitch" translatable="no"> <submenu name="Ink/Stitch" translatable="no">
<submenu name="Commands" /> <submenu name="Commands">
<submenu name="View" />
</submenu>
</submenu> </submenu>
</effects-menu> </effects-menu>
</effect> </effect>

Wyświetl plik

@ -7,7 +7,9 @@
<object-type>all</object-type> <object-type>all</object-type>
<effects-menu> <effects-menu>
<submenu name="Ink/Stitch" translatable="no"> <submenu name="Ink/Stitch" translatable="no">
<submenu name="Commands" /> <submenu name="Commands">
<submenu name="View" />
</submenu>
</submenu> </submenu>
</effects-menu> </effects-menu>
</effect> </effect>