summaryrefslogtreecommitdiff
path: root/lib/marker.py
blob: 977475b02e222814115421137ef9d69c7fc2ea31 (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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Authors: see git history
#
# Copyright (c) 2022 Authors
# Licensed under the GNU GPL version 3.0 or later.  See the file LICENSE for details.

from copy import deepcopy
from os import path

from shapely import geometry as shgeo

import inkex

from .svg.tags import EMBROIDERABLE_TAGS
from .utils import cache, get_bundled_dir

MARKER = ['pattern', 'guide-line']


def ensure_marker(svg, marker):
    marker_path = ".//*[@id='inkstitch-%s-marker']" % marker
    if svg.defs.find(marker_path) is None:
        svg.defs.append(deepcopy(_marker_svg().defs.find(marker_path)))


@cache
def _marker_svg():
    marker_path = path.join(get_bundled_dir("symbols"), "marker.svg")
    with open(marker_path) as marker_file:
        return inkex.load_svg(marker_file).getroot()


def set_marker(node, position, marker):
    ensure_marker(node.getroottree().getroot(), marker)

    # attach marker to node
    style = node.get('style') or ''
    style = style.split(";")
    style = [i for i in style if not i.startswith('marker-%s' % position)]
    style.append('marker-%s:url(#inkstitch-%s-marker)' % (position, marker))
    node.set('style', ";".join(style))


def get_marker_elements(node, marker, get_fills=True, get_strokes=True, get_satins=False):
    from .elements import EmbroideryElement
    from .elements.fill_stitch import FillStitch
    from .elements.satin_column import SatinColumn
    from .elements.stroke import Stroke

    fills = []
    strokes = []
    satins = []
    # do not close marker-start:url(
    # if the marker group has been copied and pasted in Inkscape it may have been duplicated with an updated id (e.g. -4)
    xpath = "./parent::svg:g/*[contains(@style, 'marker-start:url(#inkstitch-%s-marker')]" % marker
    markers = node.xpath(xpath, namespaces=inkex.NSS)
    for marker in markers:
        if marker.tag not in EMBROIDERABLE_TAGS:
            continue

        element = EmbroideryElement(marker)
        fill = element.get_style('fill')
        stroke = element.get_style('stroke')

        if get_fills and fill is not None:
            fill = FillStitch(marker).shape
            fills.append(fill)

        if get_strokes and stroke is not None:
            stroke = Stroke(marker).paths
            line_strings = [shgeo.LineString(path) for path in stroke]
            strokes.append(shgeo.MultiLineString(line_strings))

        if get_satins and stroke is not None:
            satin = SatinColumn(marker)
            if len(satin.rails) == 2:
                satins.append(satin)

    return {'fill': fills, 'stroke': strokes, 'satin': satins}


def get_marker_elements_cache_key_data(node, marker):
    marker_elements = get_marker_elements(node, marker, True, True, True)

    marker_elements['fill'] = [shape.wkt for shape in marker_elements['fill']]
    marker_elements['stroke'] = [shape.wkt for shape in marker_elements['stroke']]
    marker_elements['satin'] = [satin.csp for satin in marker_elements['satin']]

    return marker_elements


def has_marker(node, marker=list()):
    if not marker:
        marker = MARKER
    for m in marker:
        style = node.get('style') or ''
        if "marker-start:url(#inkstitch-%s-marker" % m in style:
            return True
    return False