• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from fontTools.misc.py23 import tostr
2
3from fontTools.pens.transformPen import TransformPen
4from fontTools.misc import etree
5from .parser import parse_path
6from .shapes import PathBuilder
7
8
9__all__ = [tostr(s) for s in ("SVGPath", "parse_path")]
10
11
12class SVGPath(object):
13    """ Parse SVG ``path`` elements from a file or string, and draw them
14    onto a glyph object that supports the FontTools Pen protocol.
15
16    For example, reading from an SVG file and drawing to a Defcon Glyph:
17
18        import defcon
19        glyph = defcon.Glyph()
20        pen = glyph.getPen()
21        svg = SVGPath("path/to/a.svg")
22        svg.draw(pen)
23
24    Or reading from a string containing SVG data, using the alternative
25    'fromstring' (a class method):
26
27        data = '<?xml version="1.0" ...'
28        svg = SVGPath.fromstring(data)
29        svg.draw(pen)
30
31    Both constructors can optionally take a 'transform' matrix (6-float
32    tuple, or a FontTools Transform object) to modify the draw output.
33    """
34
35    def __init__(self, filename=None, transform=None):
36        if filename is None:
37            self.root = etree.ElementTree()
38        else:
39            tree = etree.parse(filename)
40            self.root = tree.getroot()
41        self.transform = transform
42
43    @classmethod
44    def fromstring(cls, data, transform=None):
45        self = cls(transform=transform)
46        self.root = etree.fromstring(data)
47        return self
48
49    def draw(self, pen):
50        if self.transform:
51            pen = TransformPen(pen, self.transform)
52        pb = PathBuilder()
53        # xpath | doesn't seem to reliable work so just walk it
54        for el in self.root.iter():
55            pb.add_path_from_element(el)
56        original_pen = pen
57        for path, transform in zip(pb.paths, pb.transforms):
58            if transform:
59                pen = TransformPen(original_pen, transform)
60            else:
61                pen = original_pen
62            parse_path(path, pen)
63