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