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