kopia lustrzana https://github.com/inkstitch/inkstitch
115 wiersze
3.8 KiB
Python
115 wiersze
3.8 KiB
Python
import simpletransform, simplestyle, inkex
|
|
|
|
from .units import get_viewbox_transform
|
|
from .tags import SVG_GROUP_TAG, INKSCAPE_LABEL, INKSCAPE_GROUPMODE, SVG_PATH_TAG, SVG_DEFS_TAG
|
|
from .realistic_rendering import realistic_stitch, realistic_filter
|
|
from ..i18n import _
|
|
from ..utils import cache
|
|
|
|
|
|
def color_block_to_point_lists(color_block):
|
|
point_lists = [[]]
|
|
|
|
for stitch in color_block:
|
|
if stitch.trim:
|
|
if point_lists[-1]:
|
|
point_lists.append([])
|
|
continue
|
|
|
|
if not stitch.jump and not stitch.color_change:
|
|
point_lists[-1].append(stitch.as_tuple())
|
|
|
|
return point_lists
|
|
|
|
|
|
@cache
|
|
def get_correction_transform(svg):
|
|
transform = get_viewbox_transform(svg)
|
|
|
|
# we need to correct for the viewbox
|
|
transform = simpletransform.invertTransform(transform)
|
|
transform = simpletransform.formatTransform(transform)
|
|
|
|
return transform
|
|
|
|
|
|
def color_block_to_realistic_stitches(color_block, svg):
|
|
paths = []
|
|
|
|
for point_list in color_block_to_point_lists(color_block):
|
|
color = color_block.color.visible_on_white.darker.to_hex_str()
|
|
start = point_list[0]
|
|
for point in point_list[1:]:
|
|
paths.append(inkex.etree.Element(
|
|
SVG_PATH_TAG,
|
|
{'style': simplestyle.formatStyle(
|
|
{
|
|
'fill': color,
|
|
'stroke': 'none',
|
|
'filter': 'url(#realistic-stitch-filter)'
|
|
}),
|
|
'd': realistic_stitch(start, point),
|
|
'transform': get_correction_transform(svg)
|
|
}))
|
|
start = point
|
|
|
|
return paths
|
|
|
|
def color_block_to_paths(color_block, svg):
|
|
paths = []
|
|
# We could emit just a single path with one subpath per point list, but
|
|
# emitting multiple paths makes it easier for the user to manipulate them.
|
|
for point_list in color_block_to_point_lists(color_block):
|
|
color = color_block.color.visible_on_white.to_hex_str()
|
|
paths.append(inkex.etree.Element(
|
|
SVG_PATH_TAG,
|
|
{'style': simplestyle.formatStyle(
|
|
{'stroke': color,
|
|
'stroke-width': "0.4",
|
|
'fill': 'none'}),
|
|
'd': "M" + " ".join(" ".join(str(coord) for coord in point) for point in point_list),
|
|
'transform': get_correction_transform(svg),
|
|
'embroider_manual_stitch': 'true',
|
|
'embroider_trim_after': 'true',
|
|
}))
|
|
|
|
# no need to trim at the end of a thread color
|
|
if paths:
|
|
paths[-1].attrib.pop('embroider_trim_after')
|
|
|
|
return paths
|
|
|
|
def render_stitch_plan(svg, stitch_plan, realistic=False):
|
|
layer = svg.find(".//*[@id='__inkstitch_stitch_plan__']")
|
|
if layer is None:
|
|
layer = inkex.etree.Element(SVG_GROUP_TAG,
|
|
{'id': '__inkstitch_stitch_plan__',
|
|
INKSCAPE_LABEL: _('Stitch Plan'),
|
|
INKSCAPE_GROUPMODE: 'layer'})
|
|
else:
|
|
# delete old stitch plan
|
|
del layer[:]
|
|
|
|
# make sure the layer is visible
|
|
layer.set('style', 'display:inline')
|
|
|
|
for i, color_block in enumerate(stitch_plan):
|
|
group = inkex.etree.SubElement(layer,
|
|
SVG_GROUP_TAG,
|
|
{'id': '__color_block_%d__' % i,
|
|
INKSCAPE_LABEL: "color block %d" % (i + 1)})
|
|
if realistic:
|
|
group.extend(color_block_to_realistic_stitches(color_block, svg))
|
|
else:
|
|
group.extend(color_block_to_paths(color_block, svg))
|
|
|
|
svg.append(layer)
|
|
|
|
if realistic:
|
|
defs = svg.find(SVG_DEFS_TAG)
|
|
|
|
if defs is None:
|
|
defs = inkex.etree.SubElement(svg, SVG_DEFS_TAG)
|
|
|
|
defs.append(inkex.etree.fromstring(realistic_filter))
|