summaryrefslogtreecommitdiff
path: root/lib/svg/svg.py
blob: 852215f23f35139f09ed6ea11c6d5ed1ef70dd69 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import simpletransform, simplestyle, inkex

from .units import get_viewbox_transform
from .tags import SVG_GROUP_TAG, INKSCAPE_LABEL, INKSCAPE_GROUPMODE, SVG_PATH_TAG
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_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):
    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)})
        group.extend(color_block_to_paths(color_block, svg))

    svg.append(layer)