kopia lustrzana https://github.com/inkstitch/inkstitch
rodzic
36815f977d
commit
2f35a4a192
|
@ -152,7 +152,7 @@ jobs:
|
|||
pip install git+https://github.com/gtaylor/python-colormath
|
||||
|
||||
pip install -r requirements.txt
|
||||
pip install pyinstaller
|
||||
pip install pyinstaller==4.3
|
||||
|
||||
echo "${{ env.pythonLocation }}/bin" >> $GITHUB_PATH
|
||||
- shell: bash
|
||||
|
|
2
Makefile
2
Makefile
|
@ -55,4 +55,4 @@ version:
|
|||
|
||||
.PHONY: style
|
||||
style:
|
||||
flake8 . --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py,electron,build
|
||||
flake8 . --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py,electron,build,src
|
||||
|
|
|
@ -10,6 +10,12 @@ import traceback
|
|||
from argparse import ArgumentParser
|
||||
from io import StringIO
|
||||
|
||||
if getattr(sys, 'frozen', None) is None:
|
||||
# When running in development mode, we want to use the inkex installed by
|
||||
# pip install, not the one bundled with Inkscape which is not new enough.
|
||||
sys.path.remove('/usr/share/inkscape/extensions')
|
||||
sys.path.append('/usr/share/inkscape/extensions')
|
||||
|
||||
from inkex import errormsg
|
||||
from lxml.etree import XMLSyntaxError
|
||||
|
||||
|
@ -27,7 +33,6 @@ formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
|
|||
ch.setFormatter(formatter)
|
||||
logger.addHandler(ch)
|
||||
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--extension")
|
||||
my_args, remaining_args = parser.parse_known_args()
|
||||
|
|
122
lib/commands.py
122
lib/commands.py
|
@ -9,15 +9,13 @@ from copy import deepcopy
|
|||
from random import random
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
from shapely import geometry as shgeo
|
||||
|
||||
from .i18n import N_, _
|
||||
from .svg import (apply_transforms, generate_unique_id,
|
||||
get_correction_transform, get_document, get_node_transform)
|
||||
from .svg.tags import (CONNECTION_END, CONNECTION_START, CONNECTOR_TYPE,
|
||||
INKSCAPE_LABEL, INKSTITCH_ATTRIBS, SVG_DEFS_TAG,
|
||||
SVG_GROUP_TAG, SVG_PATH_TAG, SVG_SYMBOL_TAG,
|
||||
INKSCAPE_LABEL, INKSTITCH_ATTRIBS, SVG_SYMBOL_TAG,
|
||||
SVG_USE_TAG, XLINK_HREF)
|
||||
from .utils import Point, cache, get_bundled_dir
|
||||
|
||||
|
@ -259,42 +257,36 @@ def symbols_path():
|
|||
@cache
|
||||
def symbols_svg():
|
||||
with open(symbols_path()) as symbols_file:
|
||||
return etree.parse(symbols_file)
|
||||
return inkex.load_svg(symbols_file).getroot()
|
||||
|
||||
|
||||
@cache
|
||||
def symbol_defs():
|
||||
return get_defs(symbols_svg())
|
||||
return symbols_svg().defs
|
||||
|
||||
|
||||
@cache
|
||||
def get_defs(document):
|
||||
defs = document.find(SVG_DEFS_TAG)
|
||||
|
||||
if defs is None:
|
||||
defs = etree.SubElement(document, SVG_DEFS_TAG)
|
||||
|
||||
return defs
|
||||
|
||||
|
||||
def ensure_symbol(document, command):
|
||||
def ensure_symbol(svg, command):
|
||||
"""Make sure the command's symbol definition exists in the <svg:defs> tag."""
|
||||
|
||||
# using @cache really just makes sure that we don't bother ensuring the
|
||||
# same symbol is there twice, which would be wasted work
|
||||
|
||||
path = "./*[@id='inkstitch_%s']" % command
|
||||
defs = get_defs(document)
|
||||
defs = svg.defs
|
||||
if defs.find(path) is None:
|
||||
defs.append(deepcopy(symbol_defs().find(path)))
|
||||
|
||||
|
||||
def add_group(document, node, command):
|
||||
group = etree.Element(
|
||||
SVG_GROUP_TAG,
|
||||
{
|
||||
"id": generate_unique_id(document, "command_group"),
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command),
|
||||
"transform": get_correction_transform(node)
|
||||
})
|
||||
node.getparent().insert(node.getparent().index(node) + 1, group)
|
||||
parent = node.getparent()
|
||||
group = inkex.Group(attrib={
|
||||
"id": generate_unique_id(document, "command_group"),
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command),
|
||||
"transform": get_correction_transform(node)
|
||||
})
|
||||
parent.insert(parent.index(node) + 1, group)
|
||||
|
||||
return group
|
||||
|
||||
|
||||
|
@ -308,35 +300,36 @@ def add_connector(document, symbol, element):
|
|||
if element.node.get('id') is None:
|
||||
element.node.set('id', generate_unique_id(document, "object"))
|
||||
|
||||
path = etree.Element(SVG_PATH_TAG,
|
||||
{
|
||||
"id": generate_unique_id(document, "command_connector"),
|
||||
"d": "M %s,%s %s,%s" % (start_pos[0], start_pos[1], end_pos.x, end_pos.y),
|
||||
"style": "stroke:#000000;stroke-width:1px;stroke-opacity:0.5;fill:none;",
|
||||
CONNECTION_START: "#%s" % symbol.get('id'),
|
||||
CONNECTION_END: "#%s" % element.node.get('id'),
|
||||
CONNECTOR_TYPE: "polyline",
|
||||
path = inkex.PathElement(attrib={
|
||||
"id": generate_unique_id(document, "command_connector"),
|
||||
"d": "M %s,%s %s,%s" % (start_pos[0], start_pos[1], end_pos.x, end_pos.y),
|
||||
"style": "stroke:#000000;stroke-width:1px;stroke-opacity:0.5;fill:none;",
|
||||
CONNECTION_START: "#%s" % symbol.get('id'),
|
||||
CONNECTION_END: "#%s" % element.node.get('id'),
|
||||
CONNECTOR_TYPE: "polyline",
|
||||
|
||||
# l10n: the name of the line that connects a command to the object it applies to
|
||||
INKSCAPE_LABEL: _("connector")
|
||||
})
|
||||
# l10n: the name of the line that connects a command to the object it applies to
|
||||
INKSCAPE_LABEL: _("connector")
|
||||
})
|
||||
|
||||
symbol.getparent().insert(0, path)
|
||||
|
||||
|
||||
def add_symbol(document, group, command, pos):
|
||||
return etree.SubElement(group, SVG_USE_TAG,
|
||||
{
|
||||
"id": generate_unique_id(document, "command_use"),
|
||||
XLINK_HREF: "#inkstitch_%s" % command,
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"x": str(pos.x),
|
||||
"y": str(pos.y),
|
||||
symbol = inkex.Use(attrib={
|
||||
"id": generate_unique_id(document, "command_use"),
|
||||
XLINK_HREF: "#inkstitch_%s" % command,
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"x": str(pos.x),
|
||||
"y": str(pos.y),
|
||||
|
||||
# l10n: the name of a command symbol (example: scissors icon for trim command)
|
||||
INKSCAPE_LABEL: _("command marker"),
|
||||
})
|
||||
# l10n: the name of a command symbol (example: scissors icon for trim command)
|
||||
INKSCAPE_LABEL: _("command marker"),
|
||||
})
|
||||
group.append(symbol)
|
||||
|
||||
return symbol
|
||||
|
||||
|
||||
def get_command_pos(element, index, total):
|
||||
|
@ -383,32 +376,31 @@ def remove_legacy_param(element, command):
|
|||
|
||||
|
||||
def add_commands(element, commands):
|
||||
document = get_document(element.node)
|
||||
svg = get_document(element.node)
|
||||
|
||||
for i, command in enumerate(commands):
|
||||
ensure_symbol(document, command)
|
||||
ensure_symbol(svg, command)
|
||||
remove_legacy_param(element, command)
|
||||
|
||||
group = add_group(document, element.node, command)
|
||||
group = add_group(svg, element.node, command)
|
||||
pos = get_command_pos(element, i, len(commands))
|
||||
symbol = add_symbol(document, group, command, pos)
|
||||
add_connector(document, symbol, element)
|
||||
symbol = add_symbol(svg, group, command, pos)
|
||||
add_connector(svg, symbol, element)
|
||||
|
||||
|
||||
def add_layer_commands(layer, commands):
|
||||
document = get_document(layer)
|
||||
svg = layer.root()
|
||||
correction_transform = get_correction_transform(layer)
|
||||
|
||||
for command in commands:
|
||||
ensure_symbol(document, command)
|
||||
etree.SubElement(layer, SVG_USE_TAG,
|
||||
{
|
||||
"id": generate_unique_id(document, "use"),
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command),
|
||||
XLINK_HREF: "#inkstitch_%s" % command,
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"x": "0",
|
||||
"y": "-10",
|
||||
"transform": correction_transform
|
||||
})
|
||||
for i, command in enumerate(commands):
|
||||
ensure_symbol(svg, command)
|
||||
layer.append(inkex.Use(attrib={
|
||||
"id": generate_unique_id(svg, "use"),
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command),
|
||||
XLINK_HREF: "#inkstitch_%s" % command,
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"x": str(i * 20),
|
||||
"y": "-10",
|
||||
"transform": correction_transform
|
||||
}))
|
||||
|
|
|
@ -7,15 +7,13 @@ import sys
|
|||
from copy import deepcopy
|
||||
|
||||
import inkex
|
||||
import tinycss2
|
||||
from inkex import bezier
|
||||
|
||||
from ..commands import find_commands
|
||||
from ..i18n import _
|
||||
from ..svg import (PIXELS_PER_MM, apply_transforms, convert_length,
|
||||
get_node_transform)
|
||||
from ..svg.tags import (EMBROIDERABLE_TAGS, INKSCAPE_LABEL, INKSTITCH_ATTRIBS,
|
||||
SVG_GROUP_TAG, SVG_LINK_TAG, SVG_USE_TAG)
|
||||
from ..svg.tags import INKSCAPE_LABEL, INKSTITCH_ATTRIBS
|
||||
from ..utils import Point, cache
|
||||
|
||||
|
||||
|
@ -165,37 +163,12 @@ class EmbroideryElement(object):
|
|||
self.node.set(param, str(value))
|
||||
|
||||
@cache
|
||||
def parse_style(self, node=None):
|
||||
if node is None:
|
||||
node = self.node
|
||||
element_style = node.get("style", "")
|
||||
if element_style is None:
|
||||
return None
|
||||
declarations = tinycss2.parse_declaration_list(node.get("style", ""))
|
||||
style = {declaration.lower_name: declaration.value[0].serialize() for declaration in declarations}
|
||||
return style
|
||||
|
||||
@cache
|
||||
def _get_style_raw(self, style_name):
|
||||
if self.node is None:
|
||||
return None
|
||||
if self.node.tag not in [SVG_GROUP_TAG, SVG_LINK_TAG, SVG_USE_TAG] and self.node.tag not in EMBROIDERABLE_TAGS:
|
||||
return None
|
||||
|
||||
style = self.parse_style()
|
||||
if style:
|
||||
style = style.get(style_name) or self.node.get(style_name)
|
||||
parent = self.node.getparent()
|
||||
# style not found, get inherited style elements
|
||||
while not style and parent is not None:
|
||||
style = self.parse_style(parent)
|
||||
if style:
|
||||
style = style.get(style_name) or parent.get(style_name)
|
||||
parent = parent.getparent()
|
||||
return style
|
||||
def _get_specified_style(self):
|
||||
# We want to cache this, because it's quite expensive to generate.
|
||||
return self.node.specified_style()
|
||||
|
||||
def get_style(self, style_name, default=None):
|
||||
style = self._get_style_raw(style_name) or default
|
||||
style = self._get_specified_style().get(style_name, default)
|
||||
if style == 'none':
|
||||
style = None
|
||||
return style
|
||||
|
|
|
@ -49,19 +49,7 @@ class InkStitchMetadata(MutableMapping):
|
|||
|
||||
def __init__(self, document):
|
||||
self.document = document
|
||||
self.metadata = self._get_or_create_metadata()
|
||||
|
||||
def _get_or_create_metadata(self):
|
||||
metadata = self.document.find(SVG_METADATA_TAG)
|
||||
|
||||
if metadata is None:
|
||||
metadata = etree.SubElement(self.document.getroot(), SVG_METADATA_TAG)
|
||||
|
||||
# move it so that it goes right after the first element, sodipodi:namedview
|
||||
self.document.getroot().remove(metadata)
|
||||
self.document.getroot().insert(1, metadata)
|
||||
|
||||
return metadata
|
||||
self.metadata = document.metadata
|
||||
|
||||
# Because this class inherints from MutableMapping, all we have to do is
|
||||
# implement these five methods and we get a full dict-like interface.
|
||||
|
@ -149,7 +137,8 @@ class InkstitchExtension(inkex.Effect):
|
|||
if len(list(layer_commands(node, "ignore_layer"))):
|
||||
return []
|
||||
|
||||
if element.has_style('display') and element.get_style('display') is None:
|
||||
if (node.tag in [EMBROIDERABLE_TAGS, SVG_GROUP_TAG] and
|
||||
element.get_style('display', 'inline') is None):
|
||||
return []
|
||||
|
||||
if node.tag == SVG_DEFS_TAG:
|
||||
|
@ -211,7 +200,7 @@ class InkstitchExtension(inkex.Effect):
|
|||
return patches
|
||||
|
||||
def get_inkstitch_metadata(self):
|
||||
return InkStitchMetadata(self.document)
|
||||
return InkStitchMetadata(self.svg)
|
||||
|
||||
def get_base_file_name(self):
|
||||
svg_filename = self.document.getroot().get(inkex.addNS('docname', 'sodipodi'), "embroidery.svg")
|
||||
|
|
|
@ -9,16 +9,15 @@ from itertools import chain, groupby
|
|||
|
||||
import inkex
|
||||
import numpy
|
||||
from lxml import etree
|
||||
from numpy import diff, setdiff1d, sign
|
||||
from shapely import geometry as shgeo
|
||||
|
||||
from .base import InkstitchExtension
|
||||
from ..elements import Stroke
|
||||
from ..i18n import _
|
||||
from ..svg import PIXELS_PER_MM, get_correction_transform
|
||||
from ..svg.tags import INKSTITCH_ATTRIBS, SVG_PATH_TAG
|
||||
from ..svg.tags import INKSTITCH_ATTRIBS
|
||||
from ..utils import Point
|
||||
from .base import InkstitchExtension
|
||||
|
||||
|
||||
class SelfIntersectionError(Exception):
|
||||
|
@ -317,11 +316,10 @@ class ConvertToSatin(InkstitchExtension):
|
|||
d += "%s,%s " % (x, y)
|
||||
d += " "
|
||||
|
||||
return etree.Element(SVG_PATH_TAG,
|
||||
{
|
||||
"id": self.uniqueId("path"),
|
||||
"style": path_style,
|
||||
"transform": correction_transform,
|
||||
"d": d,
|
||||
INKSTITCH_ATTRIBS['satin_column']: "true",
|
||||
})
|
||||
return inkex.PathElement(attrib={
|
||||
"id": self.uniqueId("path"),
|
||||
"style": path_style,
|
||||
"transform": correction_transform,
|
||||
"d": d,
|
||||
INKSTITCH_ATTRIBS['satin_column']: "true",
|
||||
})
|
||||
|
|
|
@ -47,7 +47,7 @@ class Input(object):
|
|||
del stitch_plan.last_color_block[-1]
|
||||
|
||||
extents = stitch_plan.extents
|
||||
svg = etree.Element("svg", nsmap=inkex.NSS, attrib={
|
||||
svg = inkex.SvgDocumentElement("svg", nsmap=inkex.NSS, attrib={
|
||||
"width": str(extents[0] * 2),
|
||||
"height": str(extents[1] * 2),
|
||||
"viewBox": "0 0 %s %s" % (extents[0] * 2, extents[1] * 2),
|
||||
|
|
|
@ -4,12 +4,9 @@
|
|||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
|
||||
from ..commands import LAYER_COMMANDS, ensure_symbol, get_command_description
|
||||
from ..commands import LAYER_COMMANDS, add_layer_commands
|
||||
from ..i18n import _
|
||||
from ..svg import get_correction_transform
|
||||
from ..svg.tags import INKSCAPE_LABEL, SVG_USE_TAG, XLINK_HREF
|
||||
from .commands import CommandsExtension
|
||||
|
||||
|
||||
|
@ -23,19 +20,4 @@ class LayerCommands(CommandsExtension):
|
|||
inkex.errormsg(_("Please choose one or more commands to add."))
|
||||
return
|
||||
|
||||
correction_transform = get_correction_transform(self.svg.get_current_layer(), child=True)
|
||||
|
||||
for i, command in enumerate(commands):
|
||||
ensure_symbol(self.document, command)
|
||||
|
||||
etree.SubElement(self.svg.get_current_layer(), SVG_USE_TAG,
|
||||
{
|
||||
"id": self.uniqueId("use"),
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Command") + ": %s" % get_command_description(command),
|
||||
XLINK_HREF: "#inkstitch_%s" % command,
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
"x": str(i * 20),
|
||||
"y": "-10",
|
||||
"transform": correction_transform
|
||||
})
|
||||
add_layer_commands(self.svg.get_current_layer(), commands)
|
||||
|
|
|
@ -12,8 +12,9 @@ import appdirs
|
|||
import inkex
|
||||
import wx
|
||||
import wx.adv
|
||||
from lxml import etree
|
||||
|
||||
from .commands import CommandsExtension
|
||||
from .lettering_custom_font_dir import get_custom_font_dir
|
||||
from ..elements import nodes_to_elements
|
||||
from ..gui import PresetsPanel, SimulatorPreview, info_dialog
|
||||
from ..i18n import _
|
||||
|
@ -22,8 +23,6 @@ from ..svg import get_correction_transform
|
|||
from ..svg.tags import (INKSCAPE_LABEL, INKSTITCH_LETTERING, SVG_GROUP_TAG,
|
||||
SVG_PATH_TAG)
|
||||
from ..utils import DotDict, cache, get_bundled_dir
|
||||
from .commands import CommandsExtension
|
||||
from .lettering_custom_font_dir import get_custom_font_dir
|
||||
|
||||
|
||||
class LetteringFrame(wx.Frame):
|
||||
|
@ -258,12 +257,13 @@ class LetteringFrame(wx.Frame):
|
|||
if self.settings.scale == 100:
|
||||
destination_group = self.group
|
||||
else:
|
||||
destination_group = etree.SubElement(self.group, SVG_GROUP_TAG, {
|
||||
destination_group = inkex.Group(attrib={
|
||||
# L10N The user has chosen to scale the text by some percentage
|
||||
# (50%, 200%, etc). If you need to use the percentage symbol,
|
||||
# make sure to double it (%%).
|
||||
INKSCAPE_LABEL: _("Text scale %s%%") % self.settings.scale
|
||||
})
|
||||
self.group.append(destination_group)
|
||||
|
||||
font = self.fonts.get(self.font_chooser.GetValue(), self.default_font)
|
||||
try:
|
||||
|
@ -414,10 +414,12 @@ class Lettering(CommandsExtension):
|
|||
else:
|
||||
return list(groups)[0]
|
||||
else:
|
||||
return etree.SubElement(self.get_current_layer(), SVG_GROUP_TAG, {
|
||||
group = inkex.Group(attrib={
|
||||
INKSCAPE_LABEL: _("Ink/Stitch Lettering"),
|
||||
"transform": get_correction_transform(self.get_current_layer(), child=True)
|
||||
})
|
||||
self.get_current_layer().append(group)
|
||||
return group
|
||||
|
||||
def effect(self):
|
||||
app = wx.App()
|
||||
|
|
|
@ -5,18 +5,15 @@
|
|||
|
||||
import textwrap
|
||||
|
||||
from inkex import errormsg
|
||||
from lxml import etree
|
||||
import inkex
|
||||
|
||||
from .base import InkstitchExtension
|
||||
from ..commands import add_layer_commands
|
||||
from ..elements.validation import (ObjectTypeWarning, ValidationError,
|
||||
ValidationWarning)
|
||||
from ..i18n import _
|
||||
from ..svg.path import get_correction_transform
|
||||
from ..svg.tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL, SODIPODI_ROLE,
|
||||
SVG_GROUP_TAG, SVG_PATH_TAG, SVG_TEXT_TAG,
|
||||
SVG_TSPAN_TAG)
|
||||
from .base import InkstitchExtension
|
||||
from ..svg.tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL, SODIPODI_ROLE)
|
||||
|
||||
|
||||
class Troubleshoot(InkstitchExtension):
|
||||
|
@ -49,7 +46,7 @@ class Troubleshoot(InkstitchExtension):
|
|||
message += "\n\n"
|
||||
message += _("If you are still having trouble with a shape not being embroidered, "
|
||||
"check if it is in a layer with an ignore command.")
|
||||
errormsg(message)
|
||||
inkex.errormsg(message)
|
||||
|
||||
def insert_pointer(self, problem):
|
||||
correction_transform = get_correction_transform(self.troubleshoot_layer)
|
||||
|
@ -67,31 +64,25 @@ class Troubleshoot(InkstitchExtension):
|
|||
pointer_style = "stroke:#000000;stroke-width:0.2;fill:%s;" % (fill_color)
|
||||
text_style = "fill:%s;stroke:#000000;stroke-width:0.2;font-size:8px;text-align:center;text-anchor:middle" % (fill_color)
|
||||
|
||||
path = etree.Element(
|
||||
SVG_PATH_TAG,
|
||||
{
|
||||
"id": self.uniqueId("inkstitch__invalid_pointer__"),
|
||||
"d": "m %s,%s 4,20 h -8 l 4,-20" % (problem.position.x, problem.position.y),
|
||||
"style": pointer_style,
|
||||
INKSCAPE_LABEL: _('Invalid Pointer'),
|
||||
"transform": correction_transform
|
||||
}
|
||||
)
|
||||
path = inkex.PathElement(attrib={
|
||||
"id": self.uniqueId("inkstitch__invalid_pointer__"),
|
||||
"d": "m %s,%s 4,20 h -8 l 4,-20" % (problem.position.x, problem.position.y),
|
||||
"style": pointer_style,
|
||||
INKSCAPE_LABEL: _('Invalid Pointer'),
|
||||
"transform": correction_transform
|
||||
})
|
||||
layer.insert(0, path)
|
||||
|
||||
text = etree.Element(
|
||||
SVG_TEXT_TAG,
|
||||
{
|
||||
INKSCAPE_LABEL: _('Description'),
|
||||
"x": str(problem.position.x),
|
||||
"y": str(float(problem.position.y) + 30),
|
||||
"transform": correction_transform,
|
||||
"style": text_style
|
||||
}
|
||||
)
|
||||
text = inkex.TextElement(attrib={
|
||||
INKSCAPE_LABEL: _('Description'),
|
||||
"x": str(problem.position.x),
|
||||
"y": str(float(problem.position.y) + 30),
|
||||
"transform": correction_transform,
|
||||
"style": text_style
|
||||
})
|
||||
layer.append(text)
|
||||
|
||||
tspan = etree.Element(SVG_TSPAN_TAG)
|
||||
tspan = inkex.Tspan()
|
||||
tspan.text = problem.name
|
||||
if problem.label:
|
||||
tspan.text += " (%s)" % problem.label
|
||||
|
@ -102,46 +93,34 @@ class Troubleshoot(InkstitchExtension):
|
|||
layer = svg.find(".//*[@id='__validation_layer__']")
|
||||
|
||||
if layer is None:
|
||||
layer = etree.Element(
|
||||
SVG_GROUP_TAG,
|
||||
{
|
||||
'id': '__validation_layer__',
|
||||
INKSCAPE_LABEL: _('Troubleshoot'),
|
||||
INKSCAPE_GROUPMODE: 'layer',
|
||||
})
|
||||
layer = inkex.Group(attrib={
|
||||
'id': '__validation_layer__',
|
||||
INKSCAPE_LABEL: _('Troubleshoot'),
|
||||
INKSCAPE_GROUPMODE: 'layer',
|
||||
})
|
||||
svg.append(layer)
|
||||
|
||||
else:
|
||||
# Clear out everything from the last run
|
||||
del layer[:]
|
||||
|
||||
add_layer_commands(layer, ["ignore_layer"])
|
||||
|
||||
error_group = etree.SubElement(
|
||||
layer,
|
||||
SVG_GROUP_TAG,
|
||||
{
|
||||
"id": '__validation_errors__',
|
||||
INKSCAPE_LABEL: _("Errors"),
|
||||
})
|
||||
error_group = inkex.Group(attrib={
|
||||
"id": '__validation_errors__',
|
||||
INKSCAPE_LABEL: _("Errors"),
|
||||
})
|
||||
layer.append(error_group)
|
||||
|
||||
warning_group = etree.SubElement(
|
||||
layer,
|
||||
SVG_GROUP_TAG,
|
||||
{
|
||||
"id": '__validation_warnings__',
|
||||
INKSCAPE_LABEL: _("Warnings"),
|
||||
})
|
||||
warning_group = inkex.Group(attrib={
|
||||
"id": '__validation_warnings__',
|
||||
INKSCAPE_LABEL: _("Warnings"),
|
||||
})
|
||||
layer.append(warning_group)
|
||||
|
||||
type_warning_group = etree.SubElement(
|
||||
layer,
|
||||
SVG_GROUP_TAG,
|
||||
{
|
||||
"id": '__validation_ignored__',
|
||||
INKSCAPE_LABEL: _("Type Warnings"),
|
||||
})
|
||||
type_warning_group = inkex.Group(attrib={
|
||||
"id": '__validation_ignored__',
|
||||
INKSCAPE_LABEL: _("Type Warnings"),
|
||||
})
|
||||
layer.append(type_warning_group)
|
||||
|
||||
self.troubleshoot_layer = layer
|
||||
|
@ -153,14 +132,11 @@ class Troubleshoot(InkstitchExtension):
|
|||
svg = self.document.getroot()
|
||||
text_x = str(float(svg.get('viewBox', '0 0 800 0').split(' ')[2]) + 5.0)
|
||||
|
||||
text_container = etree.Element(
|
||||
SVG_TEXT_TAG,
|
||||
{
|
||||
"x": text_x,
|
||||
"y": str(5),
|
||||
"style": "fill:#000000;font-size:5px;line-height:1;"
|
||||
}
|
||||
)
|
||||
text_container = inkex.TextElement(attrib={
|
||||
"x": text_x,
|
||||
"y": str(5),
|
||||
"style": "fill:#000000;font-size:5px;line-height:1;"
|
||||
})
|
||||
self.troubleshoot_layer.append(text_container)
|
||||
|
||||
text = [
|
||||
|
@ -209,13 +185,10 @@ class Troubleshoot(InkstitchExtension):
|
|||
text = self.split_text(text)
|
||||
|
||||
for text_line in text:
|
||||
tspan = etree.Element(
|
||||
SVG_TSPAN_TAG,
|
||||
{
|
||||
SODIPODI_ROLE: "line",
|
||||
"style": text_line[1]
|
||||
}
|
||||
)
|
||||
tspan = inkex.Tspan(attrib={
|
||||
SODIPODI_ROLE: "line",
|
||||
"style": text_line[1]
|
||||
})
|
||||
tspan.text = text_line[0]
|
||||
text_container.append(tspan)
|
||||
|
||||
|
|
|
@ -7,16 +7,15 @@ import json
|
|||
import os
|
||||
from copy import deepcopy
|
||||
|
||||
from inkex import styles
|
||||
from lxml import etree
|
||||
import inkex
|
||||
|
||||
from .font_variant import FontVariant
|
||||
from ..elements import nodes_to_elements
|
||||
from ..exceptions import InkstitchException
|
||||
from ..i18n import _, get_languages
|
||||
from ..stitches.auto_satin import auto_satin
|
||||
from ..svg.tags import INKSCAPE_LABEL, SVG_GROUP_TAG, SVG_PATH_TAG
|
||||
from ..svg.tags import INKSCAPE_LABEL, SVG_PATH_TAG
|
||||
from ..utils import Point
|
||||
from .font_variant import FontVariant
|
||||
|
||||
|
||||
class FontError(InkstitchException):
|
||||
|
@ -190,7 +189,7 @@ class Font(object):
|
|||
for element in destination_group.iterdescendants(SVG_PATH_TAG):
|
||||
dash_array = ""
|
||||
stroke_width = ""
|
||||
style = styles.Style(element.get('style'))
|
||||
style = inkex.styles.Style(element.get('style'))
|
||||
|
||||
if style.get('fill') == 'none':
|
||||
stroke_width = ";stroke-width:1px"
|
||||
|
@ -224,7 +223,7 @@ class Font(object):
|
|||
An svg:g element containing the rendered text.
|
||||
"""
|
||||
|
||||
group = etree.Element(SVG_GROUP_TAG, {
|
||||
group = inkex.Group(attrib={
|
||||
INKSCAPE_LABEL: line
|
||||
})
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import os
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
|
||||
from ..svg.tags import INKSCAPE_GROUPMODE, INKSCAPE_LABEL
|
||||
from .glyph import Glyph
|
||||
|
@ -61,8 +60,7 @@ class FontVariant(object):
|
|||
|
||||
def _load_glyphs(self):
|
||||
svg_path = os.path.join(self.path, "%s.svg" % self.variant)
|
||||
with open(svg_path, encoding="utf-8") as svg_file:
|
||||
svg = etree.parse(svg_file)
|
||||
svg = inkex.load_svg(svg_path)
|
||||
|
||||
glyph_layers = svg.xpath(".//svg:g[starts-with(@inkscape:label, 'GlyphLayer-')]", namespaces=inkex.NSS)
|
||||
for layer in glyph_layers:
|
||||
|
@ -76,14 +74,10 @@ class FontVariant(object):
|
|||
# glyph.
|
||||
del group.attrib[INKSCAPE_GROUPMODE]
|
||||
|
||||
style_text = group.get('style')
|
||||
|
||||
if style_text:
|
||||
# The layer may be marked invisible, so we'll clear the 'display'
|
||||
# style.
|
||||
style = dict(inkex.Style.parse_str(group.get('style')))
|
||||
style.pop('display')
|
||||
group.set('style', str(inkex.Style(style)))
|
||||
# The layer may be marked invisible, so we'll clear the 'display'
|
||||
# style and presentation attribute.
|
||||
group.style.pop('display', None)
|
||||
group.attrib.pop('display', None)
|
||||
|
||||
def __getitem__(self, character):
|
||||
if character in self.glyphs:
|
||||
|
|
|
@ -8,7 +8,6 @@ from copy import copy
|
|||
from inkex import paths, transforms
|
||||
|
||||
from ..svg import get_guides
|
||||
from ..svg.path import get_correction_transform
|
||||
from ..svg.tags import SVG_GROUP_TAG, SVG_PATH_TAG
|
||||
|
||||
|
||||
|
@ -53,9 +52,7 @@ class Glyph(object):
|
|||
node_copy = copy(node)
|
||||
|
||||
if "d" in node.attrib:
|
||||
transform = -transforms.Transform(get_correction_transform(node, True))
|
||||
path = paths.Path(node.get("d")).transform(transform).to_absolute()
|
||||
node_copy.set("d", str(path))
|
||||
node_copy.path = node.path.transform(node.composed_transform()).to_absolute()
|
||||
|
||||
# Delete transforms from paths and groups, since we applied
|
||||
# them to the paths already.
|
||||
|
|
|
@ -8,7 +8,6 @@ from itertools import chain
|
|||
|
||||
import inkex
|
||||
import networkx as nx
|
||||
from lxml import etree
|
||||
from shapely import geometry as shgeo
|
||||
from shapely.geometry import Point as ShapelyPoint
|
||||
|
||||
|
@ -17,8 +16,7 @@ from ..elements import SatinColumn, Stroke
|
|||
from ..i18n import _
|
||||
from ..svg import (PIXELS_PER_MM, generate_unique_id, get_correction_transform,
|
||||
line_strings_to_csp)
|
||||
from ..svg.tags import (INKSCAPE_LABEL, INKSTITCH_ATTRIBS, SVG_GROUP_TAG,
|
||||
SVG_PATH_TAG)
|
||||
from ..svg.tags import (INKSCAPE_LABEL, INKSTITCH_ATTRIBS)
|
||||
from ..utils import Point as InkstitchPoint
|
||||
from ..utils import cache, cut
|
||||
|
||||
|
@ -219,14 +217,13 @@ class RunningStitch(object):
|
|||
original_element.node.get(INKSTITCH_ATTRIBS['contour_underlay_stitch_length_mm'], '')
|
||||
|
||||
def to_element(self):
|
||||
node = etree.Element(SVG_PATH_TAG)
|
||||
node = inkex.PathElement()
|
||||
d = str(inkex.paths.CubicSuperPath(line_strings_to_csp([self.path])))
|
||||
node.set("d", d)
|
||||
|
||||
style = self.original_element.parse_style()
|
||||
style['stroke-dasharray'] = "0.5,0.5"
|
||||
style = str(inkex.Style(style))
|
||||
node.set("style", style)
|
||||
dasharray = inkex.Style("stroke-dasharray:0.5,0.5;")
|
||||
style = inkex.Style(self.original_element.node.get('style', '')) + dasharray
|
||||
node.set("style", str(style))
|
||||
node.set(INKSTITCH_ATTRIBS['running_stitch_length_mm'], self.running_stitch_length)
|
||||
|
||||
stroke = Stroke(node)
|
||||
|
@ -658,7 +655,7 @@ def preserve_original_groups(elements, original_parent_nodes):
|
|||
|
||||
|
||||
def create_new_group(parent, insert_index):
|
||||
group = etree.Element(SVG_GROUP_TAG, {
|
||||
group = inkex.Group(attrib={
|
||||
INKSCAPE_LABEL: _("Auto-Satin"),
|
||||
"transform": get_correction_transform(parent, child=True)
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
|
||||
from .tags import SVG_GROUP_TAG, SVG_LINK_TAG
|
||||
from .units import get_viewbox_transform
|
||||
|
@ -96,6 +95,6 @@ def point_lists_to_csp(point_lists):
|
|||
def line_strings_to_path(line_strings):
|
||||
csp = line_strings_to_csp(line_strings)
|
||||
|
||||
return etree.Element("path", {
|
||||
return inkex.PathElement(attrib={
|
||||
"d": str(inkex.paths.CubicSuperPath(csp))
|
||||
})
|
||||
|
|
|
@ -4,16 +4,14 @@
|
|||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import math
|
||||
|
||||
import inkex
|
||||
from lxml import etree
|
||||
from math import pi
|
||||
|
||||
import inkex
|
||||
|
||||
from .tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL, INKSTITCH_ATTRIBS)
|
||||
from .units import PIXELS_PER_MM, get_viewbox_transform
|
||||
from ..i18n import _
|
||||
from ..utils import Point, cache
|
||||
from .tags import (INKSCAPE_GROUPMODE, INKSCAPE_LABEL, INKSTITCH_ATTRIBS,
|
||||
SVG_DEFS_TAG, SVG_GROUP_TAG, SVG_PATH_TAG)
|
||||
from .units import PIXELS_PER_MM, get_viewbox_transform
|
||||
|
||||
# The stitch vector path looks like this:
|
||||
# _______
|
||||
|
@ -174,7 +172,7 @@ def color_block_to_realistic_stitches(color_block, svg, destination):
|
|||
color = color_block.color.visible_on_white.darker.to_hex_str()
|
||||
start = point_list[0]
|
||||
for point in point_list[1:]:
|
||||
destination.append(etree.Element(SVG_PATH_TAG, {
|
||||
destination.append(inkex.PathElement(attrib={
|
||||
'style': "fill: %s; stroke: none; filter: url(#realistic-stitch-filter);" % color,
|
||||
'd': realistic_stitch(start, point),
|
||||
'transform': get_correction_transform(svg)
|
||||
|
@ -200,7 +198,7 @@ def color_block_to_paths(color_block, svg, destination, visual_commands):
|
|||
|
||||
color = color_block.color.visible_on_white.to_hex_str()
|
||||
|
||||
path = etree.Element(SVG_PATH_TAG, {
|
||||
path = inkex.PathElement(attrib={
|
||||
'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),
|
||||
|
@ -219,10 +217,11 @@ def color_block_to_paths(color_block, svg, destination, visual_commands):
|
|||
def render_stitch_plan(svg, stitch_plan, realistic=False, visual_commands=True):
|
||||
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
|
||||
if layer is None:
|
||||
layer = etree.Element(SVG_GROUP_TAG,
|
||||
{'id': '__inkstitch_stitch_plan__',
|
||||
INKSCAPE_LABEL: _('Stitch Plan'),
|
||||
INKSCAPE_GROUPMODE: 'layer'})
|
||||
layer = inkex.Group(attrib={
|
||||
'id': '__inkstitch_stitch_plan__',
|
||||
INKSCAPE_LABEL: _('Stitch Plan'),
|
||||
INKSCAPE_GROUPMODE: 'layer'
|
||||
})
|
||||
else:
|
||||
# delete old stitch plan
|
||||
del layer[:]
|
||||
|
@ -233,19 +232,16 @@ def render_stitch_plan(svg, stitch_plan, realistic=False, visual_commands=True):
|
|||
svg.append(layer)
|
||||
|
||||
for i, color_block in enumerate(stitch_plan):
|
||||
group = etree.SubElement(layer,
|
||||
SVG_GROUP_TAG,
|
||||
{'id': '__color_block_%d__' % i,
|
||||
INKSCAPE_LABEL: "color block %d" % (i + 1)})
|
||||
group = inkex.Group(attrib={
|
||||
'id': '__color_block_%d__' % i,
|
||||
INKSCAPE_LABEL: "color block %d" % (i + 1)
|
||||
})
|
||||
layer.append(group)
|
||||
if realistic:
|
||||
color_block_to_realistic_stitches(color_block, svg, group)
|
||||
else:
|
||||
color_block_to_paths(color_block, svg, group, visual_commands)
|
||||
|
||||
if realistic:
|
||||
defs = svg.find(SVG_DEFS_TAG)
|
||||
|
||||
if defs is None:
|
||||
defs = etree.SubElement(svg, SVG_DEFS_TAG)
|
||||
|
||||
defs.append(etree.fromstring(realistic_filter))
|
||||
filter_document = inkex.load_svg(realistic_filter)
|
||||
svg.defs.append(filter_document.getroot())
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
./pyembroidery
|
||||
inkex
|
||||
|
||||
# This installs inkex, the Inkscape python extension library.
|
||||
# We need the new style handling that was added after the inkex version bundled
|
||||
# with Inkscape 1.1. That's why we're installing from Git.
|
||||
-e git+https://gitlab.com/inkscape/extensions.git@139d71470e7d6bbe9fcd869f385fc73e3a8a8bea#egg=inkscape-core-extensions
|
||||
|
||||
backports.functools_lru_cache
|
||||
wxPython
|
||||
networkx
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 377.95276 377.95276"
|
||||
id="svg8375"
|
||||
version="1.1"
|
||||
inkscape:version="1.1 (1:1.1+202105261517+ce6663b3b7)"
|
||||
sodipodi:docname="style_cascade_and_inheritance.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<style
|
||||
id="style2">
|
||||
.greenstroke {
|
||||
stroke: green;
|
||||
stroke-width: 10px;
|
||||
fill: none;
|
||||
}
|
||||
.bluefill {
|
||||
fill: blue;
|
||||
}
|
||||
</style>
|
||||
<defs
|
||||
id="defs8377" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.979899"
|
||||
inkscape:cx="303.55084"
|
||||
inkscape:cy="244.96199"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="mm"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="705"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="-4"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:lockguides="true" />
|
||||
<metadata
|
||||
id="metadata8380">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
fill="none"
|
||||
style="stroke:#ff0000"
|
||||
id="g858">
|
||||
<path
|
||||
d="m 48.538989,130.3934 c 3.326181,-8.42241 9.209428,-14.93056 15.256084,-21.44505 67.367287,-72.579537 58.649627,29.08478 99.857957,35.46681 49.83745,7.71844 71.22003,-40.00458 105.12825,-62.410584"
|
||||
id="path855" />
|
||||
</g>
|
||||
<path
|
||||
d="m 48.538989,96.942485 c 3.326181,8.422415 9.209428,14.930565 15.256084,21.445055 67.367287,72.57953 58.649627,-29.084785 99.857957,-35.466815 49.83745,-7.71844 71.22003,40.004585 105.12825,62.410585"
|
||||
id="path855-6"
|
||||
transform="translate(0,80)"
|
||||
class="greenstroke" />
|
||||
<g
|
||||
style="stroke:#ffff00"
|
||||
id="g98473">
|
||||
<path
|
||||
d="m 91.07929,256.94248 c 2.38168,8.42242 6.59431,14.93057 10.92395,21.44506 48.23758,72.57953 41.9954,-29.08479 71.50215,-35.46682 35.68554,-7.71843 50.99629,40.00459 75.27589,62.41059"
|
||||
id="path855-6-3"
|
||||
class="greenstroke"
|
||||
sodipodi:nodetypes="cssc" />
|
||||
</g>
|
||||
<g
|
||||
class="bluefill"
|
||||
id="g12">
|
||||
<path
|
||||
d="m 271.07929,316.94248 c 6.30625,17.64804 17.75622,33.53816 32.08917,45.49885 10.71785,6.11302 19.63778,-5.0749 22.62041,-14.31971 6.7262,-14.65667 9.98208,-31.76158 22.29605,-43.1292 7.42851,0.83153 13.85966,-9.52025 2.61436,-9.26942 -3.7666,-37.59816 -44.38889,-14.02914 -72.24439,-4.7814 -11.41463,2.62143 -1.42076,18.19844 -7.3756,26.00088 z"
|
||||
id="path855-6-3-6"
|
||||
style="stroke:#800080;stroke-width:5px"
|
||||
sodipodi:nodetypes="csscccc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Po Szerokość: | Wysokość: | Rozmiar: 3.3 KiB |
Ładowanie…
Reference in New Issue