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