summaryrefslogtreecommitdiff
path: root/lib/marker.py
blob: 56a43c3bc81314d4f63eced4f3a95635299826e1 (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
# 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

import inkex
from shapely import geometry as shgeo

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):
    from .elements import EmbroideryElement
    from .elements.stroke import Stroke

    fills = []
    strokes = []
    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 = Stroke(marker).paths
            linear_rings = [shgeo.LinearRing(path) for path in fill]
            for ring in linear_rings:
                fills.append(shgeo.Polygon(ring))

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

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


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