aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/svgLib/path/__init__.py
blob: 017ff57e63bb0b65a72e23f60d181d550119b5f2 (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
from __future__ import (
    print_function, division, absolute_import, unicode_literals)
from fontTools.misc.py23 import *

from fontTools.pens.transformPen import TransformPen
from fontTools.misc import etree
from .parser import parse_path
from .shapes import PathBuilder


__all__ = [tostr(s) for s in ("SVGPath", "parse_path")]


class SVGPath(object):
    """ Parse SVG ``path`` elements from a file or string, and draw them
    onto a glyph object that supports the FontTools Pen protocol.

    For example, reading from an SVG file and drawing to a Defcon Glyph:

        import defcon
        glyph = defcon.Glyph()
        pen = glyph.getPen()
        svg = SVGPath("path/to/a.svg")
        svg.draw(pen)

    Or reading from a string containing SVG data, using the alternative
    'fromstring' (a class method):

        data = '<?xml version="1.0" ...'
        svg = SVGPath.fromstring(data)
        svg.draw(pen)

    Both constructors can optionally take a 'transform' matrix (6-float
    tuple, or a FontTools Transform object) to modify the draw output.
    """

    def __init__(self, filename=None, transform=None):
        if filename is None:
            self.root = etree.ElementTree()
        else:
            tree = etree.parse(filename)
            self.root = tree.getroot()
        self.transform = transform

    @classmethod
    def fromstring(cls, data, transform=None):
        self = cls(transform=transform)
        self.root = etree.fromstring(data)
        return self

    def draw(self, pen):
        if self.transform:
            pen = TransformPen(pen, self.transform)
        pb = PathBuilder()
        # xpath | doesn't seem to reliable work so just walk it
        for el in self.root.iter():
            pb.add_path_from_element(el)
        for path in pb.paths:
            parse_path(path, pen)