kopia lustrzana https://github.com/inkstitch/inkstitch
add commands framework
rodzic
c8fe52f136
commit
e29096ee13
|
@ -0,0 +1,89 @@
|
|||
import inkex
|
||||
import cubicsuperpath
|
||||
|
||||
from .svg import apply_transforms
|
||||
from .svg.tags import SVG_USE_TAG, SVG_SYMBOL_TAG, CONNECTION_START, CONNECTION_END, XLINK_HREF
|
||||
|
||||
|
||||
class Command(object):
|
||||
def __init__(self, connector):
|
||||
self.connector = connector
|
||||
self.svg = self.connector.getroottree().getroot()
|
||||
|
||||
self.parse_command()
|
||||
|
||||
def get_node_by_url(self, url):
|
||||
# url will be #path12345. Find the object at the other end.
|
||||
|
||||
if url is None:
|
||||
raise ValueError("url is None")
|
||||
|
||||
if not url.startswith('#'):
|
||||
raise ValueError("invalid connection url: %s" % url)
|
||||
|
||||
id = url[1:]
|
||||
|
||||
try:
|
||||
return self.svg.xpath(".//*[@id='%s']" % id)[0]
|
||||
except (IndexError, AttributeError):
|
||||
raise ValueError("could not find node by url %s" % id)
|
||||
|
||||
def parse_connector_path(self):
|
||||
path = cubicsuperpath.parsePath(self.connector.get('d'))
|
||||
return apply_transforms(path, self.connector)
|
||||
|
||||
def parse_command(self):
|
||||
path = self.parse_connector_path()
|
||||
|
||||
neighbors = [
|
||||
(self.get_node_by_url(self.connector.get(CONNECTION_START)), path[0][0][1]),
|
||||
(self.get_node_by_url(self.connector.get(CONNECTION_END)), path[0][-1][1])
|
||||
]
|
||||
|
||||
if neighbors[0][0].tag != SVG_USE_TAG:
|
||||
neighbors.reverse()
|
||||
|
||||
if neighbors[0][0].tag != SVG_USE_TAG:
|
||||
raise ValueError("connector does not point to a use tag")
|
||||
|
||||
self.symbol = self.get_node_by_url(neighbors[0][0].get(XLINK_HREF))
|
||||
|
||||
if self.symbol.tag != SVG_SYMBOL_TAG:
|
||||
raise ValueError("use points to non-symbol")
|
||||
|
||||
self.command = self.symbol.get('id')
|
||||
|
||||
if self.command.startswith('inkstitch_'):
|
||||
self.command = self.command[10:]
|
||||
else:
|
||||
raise ValueError("symbol is not an Ink/Stitch command")
|
||||
|
||||
self.target = neighbors[1][0]
|
||||
self.target_point = neighbors[1][1]
|
||||
|
||||
def __repr__(self):
|
||||
return "Command('%s', %s)" % (self.command, self.target_point)
|
||||
|
||||
def find_commands(node):
|
||||
"""Find the symbols this node is connected to and return them as Commands"""
|
||||
|
||||
# find all paths that have this object as a connection
|
||||
xpath = ".//*[@inkscape:connection-start='#%(id)s' or @inkscape:connection-end='#%(id)s']" % dict(id=node.get('id'))
|
||||
connectors = node.getroottree().getroot().xpath(xpath, namespaces=inkex.NSS)
|
||||
|
||||
# try to turn them into commands
|
||||
commands = []
|
||||
for connector in connectors:
|
||||
try:
|
||||
commands.append(Command(connector))
|
||||
except ValueError:
|
||||
import sys
|
||||
import traceback
|
||||
print >> sys.stderr, "not a Command:", connector.get('id'), traceback.format_exc()
|
||||
# Parsing the connector failed, meaning it's not actually an Ink/Stitch command.
|
||||
pass
|
||||
|
||||
return commands
|
||||
|
||||
def is_command(node):
|
||||
return CONNECTION_START in node.attrib or CONNECTION_END in node.attrib
|
|
@ -4,7 +4,8 @@ from shapely import geometry as shgeo
|
|||
|
||||
from ..i18n import _
|
||||
from ..utils import cache
|
||||
from ..svg import PIXELS_PER_MM, get_viewbox_transform, convert_length, get_doc_size
|
||||
from ..svg import PIXELS_PER_MM, convert_length, get_doc_size, apply_transforms
|
||||
from ..commands import find_commands
|
||||
|
||||
# inkscape-provided utilities
|
||||
import simpletransform
|
||||
|
@ -171,10 +172,6 @@ class EmbroideryElement(object):
|
|||
|
||||
@property
|
||||
def path(self):
|
||||
return cubicsuperpath.parsePath(self.node.get("d"))
|
||||
|
||||
@cache
|
||||
def parse_path(self):
|
||||
# A CSP is a "cubic superpath".
|
||||
#
|
||||
# A "path" is a sequence of strung-together bezier curves.
|
||||
|
@ -202,22 +199,16 @@ class EmbroideryElement(object):
|
|||
# In a path, each element in the 3-tuple is itself a tuple of (x, y).
|
||||
# Tuples all the way down. Hasn't anyone heard of using classes?
|
||||
|
||||
path = self.path
|
||||
return cubicsuperpath.parsePath(self.node.get("d"))
|
||||
|
||||
# start with the identity transform
|
||||
transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
|
||||
@cache
|
||||
def parse_path(self):
|
||||
return apply_transforms(self.path, self.node)
|
||||
|
||||
# combine this node's transform with all parent groups' transforms
|
||||
transform = simpletransform.composeParents(self.node, transform)
|
||||
|
||||
# add in the transform implied by the viewBox
|
||||
viewbox_transform = get_viewbox_transform(self.node.getroottree().getroot())
|
||||
transform = simpletransform.composeTransform(viewbox_transform, transform)
|
||||
|
||||
# apply the combined transform to this node's path
|
||||
simpletransform.applyTransformToPath(transform, path)
|
||||
|
||||
return path
|
||||
@property
|
||||
@cache
|
||||
def commands(self):
|
||||
return find_commands(self.node)
|
||||
|
||||
def strip_control_points(self, subpath):
|
||||
return [point for control_before, point, control_after in subpath]
|
||||
|
|
|
@ -4,6 +4,7 @@ from .element import param, EmbroideryElement, Patch
|
|||
from ..i18n import _
|
||||
from ..utils import cache, Point
|
||||
from ..stitches import running_stitch
|
||||
from ..svg import parse_length_with_units
|
||||
|
||||
warned_about_legacy_running_stitch = False
|
||||
|
||||
|
@ -57,7 +58,7 @@ class Stroke(EmbroideryElement):
|
|||
def is_running_stitch(self):
|
||||
# using stroke width <= 0.5 pixels to indicate running stitch is deprecated in favor of dashed lines
|
||||
|
||||
stroke_width = float(self.get_style("stroke-width", 1))
|
||||
stroke_width, units = parse_length_with_units(self.get_style("stroke-width", "1"))
|
||||
|
||||
if self.dashed:
|
||||
return True
|
||||
|
|
|
@ -7,6 +7,7 @@ from collections import MutableMapping
|
|||
from ..svg.tags import *
|
||||
from ..elements import AutoFill, Fill, Stroke, SatinColumn, Polyline, EmbroideryElement
|
||||
from ..utils import cache
|
||||
from ..commands import is_command
|
||||
|
||||
|
||||
SVG_METADATA_TAG = inkex.addNS("metadata", "svg")
|
||||
|
@ -165,7 +166,8 @@ class InkstitchExtension(inkex.Effect):
|
|||
classes.append(Fill)
|
||||
|
||||
if element.get_style("stroke"):
|
||||
classes.append(Stroke)
|
||||
if not is_command(element.node):
|
||||
classes.append(Stroke)
|
||||
|
||||
if element.get_boolean_param("stroke_first", False):
|
||||
classes.reverse()
|
||||
|
|
|
@ -19,6 +19,7 @@ from ..stitch_plan import patches_to_stitch_plan
|
|||
from ..elements import EmbroideryElement, Fill, AutoFill, Stroke, SatinColumn
|
||||
from ..utils import save_stderr, restore_stderr
|
||||
from ..simulator import EmbroiderySimulator
|
||||
from ..commands import is_command
|
||||
|
||||
|
||||
def presets_path():
|
||||
|
@ -655,7 +656,7 @@ class Params(InkstitchExtension):
|
|||
classes.append(AutoFill)
|
||||
classes.append(Fill)
|
||||
|
||||
if element.get_style("stroke"):
|
||||
if element.get_style("stroke") and not is_command(node):
|
||||
classes.append(Stroke)
|
||||
|
||||
if element.get_style("stroke-dasharray") is None:
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
from .svg import color_block_to_point_lists, render_stitch_plan
|
||||
from .units import *
|
||||
from .path import apply_transforms
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import simpletransform
|
||||
import cubicsuperpath
|
||||
|
||||
from .units import get_viewbox_transform
|
||||
|
||||
def apply_transforms(path, node):
|
||||
# start with the identity transform
|
||||
transform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
|
||||
|
||||
# combine this node's transform with all parent groups' transforms
|
||||
transform = simpletransform.composeParents(node, transform)
|
||||
|
||||
# add in the transform implied by the viewBox
|
||||
viewbox_transform = get_viewbox_transform(node.getroottree().getroot())
|
||||
transform = simpletransform.composeTransform(viewbox_transform, transform)
|
||||
|
||||
# apply the combined transform to this node's path
|
||||
simpletransform.applyTransformToPath(transform, path)
|
||||
|
||||
return path
|
|
@ -5,8 +5,13 @@ SVG_PATH_TAG = inkex.addNS('path', 'svg')
|
|||
SVG_POLYLINE_TAG = inkex.addNS('polyline', 'svg')
|
||||
SVG_DEFS_TAG = inkex.addNS('defs', 'svg')
|
||||
SVG_GROUP_TAG = inkex.addNS('g', 'svg')
|
||||
SVG_SYMBOL_TAG = inkex.addNS('symbol', 'svg')
|
||||
SVG_USE_TAG = inkex.addNS('use', 'svg')
|
||||
|
||||
INKSCAPE_LABEL = inkex.addNS('label', 'inkscape')
|
||||
INKSCAPE_GROUPMODE = inkex.addNS('groupmode', 'inkscape')
|
||||
CONNECTION_START = inkex.addNS('connection-start', 'inkscape')
|
||||
CONNECTION_END = inkex.addNS('connection-end', 'inkscape')
|
||||
XLINK_HREF = inkex.addNS('href', 'xlink')
|
||||
|
||||
EMBROIDERABLE_TAGS = (SVG_PATH_TAG, SVG_POLYLINE_TAG)
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 377.95276 377.95276"
|
||||
id="svg8375"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.3 (unknown)"
|
||||
sodipodi:docname="inkstitch.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="64.500275"
|
||||
inkscape:cy="322.07765"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="mm"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="705"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="-4"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:measure-start="128.23,226.536"
|
||||
inkscape:measure-end="114.217,226.536"
|
||||
inkscape:snap-global="false"
|
||||
showguides="false">
|
||||
<inkscape:grid
|
||||
empspacing="2"
|
||||
opacity="0.1254902"
|
||||
color="#f03fff"
|
||||
spacingy="18.897638"
|
||||
spacingx="18.897638"
|
||||
units="mm"
|
||||
id="grid5001"
|
||||
type="xygrid" />
|
||||
</sodipodi:namedview>
|
||||
<title
|
||||
id="title9425">Ink/Stitch Commands</title>
|
||||
<defs
|
||||
id="defs8377">
|
||||
<symbol
|
||||
id="inkstitch_end">
|
||||
<title
|
||||
id="title9427">Fill stitch starting point</title>
|
||||
<circle
|
||||
inkscape:label="outline"
|
||||
style="opacity:1;vector-effect:none;fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#003399;stroke-width:1.06501234;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.19503705, 3.19503705;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle13166"
|
||||
cx="47.235394"
|
||||
cy="105.91732"
|
||||
r="9.2465534" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect5371-2"
|
||||
d="m 42.691395,101.26765 h 9.140878 v 9.14087 h -9.140878 z"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60622311;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:4.81866985, 4.81866985;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||
</symbol>
|
||||
<symbol
|
||||
id="inkstitch_start">
|
||||
<title
|
||||
id="title9432">Fill stitch ending point</title>
|
||||
<circle
|
||||
inkscape:label="outline"
|
||||
style="opacity:1;vector-effect:none;fill:#fafafa;fill-opacity:1;fill-rule:evenodd;stroke:#003399;stroke-width:1.06501234;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.19503705, 3.19503705;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="circle13166-6"
|
||||
cx="85.223907"
|
||||
cy="106.13256"
|
||||
r="9.2465534" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4183"
|
||||
d="m 91.796747,106.13612 -10.4514,6.03412 v -12.06823 z"
|
||||
inkscape:transform-center-y="3.0183984e-06"
|
||||
inkscape:transform-center-x="-1.7419043"
|
||||
style="opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.74180555;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</symbol>
|
||||
</defs>
|
||||
<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" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
style="display:inline"
|
||||
transform="translate(0,-58.409503)"
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<use
|
||||
xlink:href="#inkstitch_end"
|
||||
id="use18860"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
xlink:href="#inkstitch_start"
|
||||
id="use18871"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
</svg>
|
Po Szerokość: | Wysokość: | Rozmiar: 4.4 KiB |
Ładowanie…
Reference in New Issue