add commands framework

pull/212/head
Lex Neva 2018-06-21 15:41:06 -04:00
rodzic c8fe52f136
commit e29096ee13
9 zmienionych plików z 259 dodań i 22 usunięć

89
lib/commands.py 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -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]

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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:

Wyświetl plik

@ -1,2 +1,3 @@
from .svg import color_block_to_point_lists, render_stitch_plan
from .units import *
from .path import apply_transforms

20
lib/svg/path.py 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -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)

Wyświetl plik

@ -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