2017-09-12 22:21:20 -04:00
|
|
|
from fontTools.pens.transformPen import TransformPen
|
2018-10-18 19:50:26 +01:00
|
|
|
from fontTools.misc import etree
|
2021-08-20 00:45:43 +02:00
|
|
|
from fontTools.misc.textTools import tostr
|
2017-09-12 22:21:20 -04:00
|
|
|
from .parser import parse_path
|
2019-02-08 11:37:00 -08:00
|
|
|
from .shapes import PathBuilder
|
2017-09-12 22:21:20 -04:00
|
|
|
|
|
|
|
|
|
|
|
__all__ = [tostr(s) for s in ("SVGPath", "parse_path")]
|
|
|
|
|
|
|
|
|
|
|
|
class SVGPath(object):
|
2022-12-13 11:26:36 +00:00
|
|
|
"""Parse SVG ``path`` elements from a file or string, and draw them
|
2017-09-12 22:21:20 -04:00
|
|
|
onto a glyph object that supports the FontTools Pen protocol.
|
|
|
|
|
|
|
|
For example, reading from an SVG file and drawing to a Defcon Glyph:
|
|
|
|
|
2024-09-03 17:52:59 +01:00
|
|
|
.. code-block::
|
|
|
|
|
2017-09-12 22:21:20 -04:00
|
|
|
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):
|
|
|
|
|
2024-09-03 17:52:59 +01:00
|
|
|
.. code-block::
|
|
|
|
|
2017-09-12 22:21:20 -04:00
|
|
|
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:
|
2018-10-18 19:50:26 +01:00
|
|
|
self.root = etree.ElementTree()
|
2017-09-12 22:21:20 -04:00
|
|
|
else:
|
2018-10-18 19:50:26 +01:00
|
|
|
tree = etree.parse(filename)
|
2017-09-12 22:21:20 -04:00
|
|
|
self.root = tree.getroot()
|
|
|
|
self.transform = transform
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def fromstring(cls, data, transform=None):
|
|
|
|
self = cls(transform=transform)
|
2018-10-18 19:50:26 +01:00
|
|
|
self.root = etree.fromstring(data)
|
2017-09-12 22:21:20 -04:00
|
|
|
return self
|
|
|
|
|
|
|
|
def draw(self, pen):
|
|
|
|
if self.transform:
|
|
|
|
pen = TransformPen(pen, self.transform)
|
2019-02-08 11:37:00 -08:00
|
|
|
pb = PathBuilder()
|
|
|
|
# xpath | doesn't seem to reliable work so just walk it
|
|
|
|
for el in self.root.iter():
|
2019-02-12 11:53:27 -08:00
|
|
|
pb.add_path_from_element(el)
|
2019-04-02 00:30:09 -07:00
|
|
|
original_pen = pen
|
2019-02-17 21:23:11 -08:00
|
|
|
for path, transform in zip(pb.paths, pb.transforms):
|
2019-04-02 00:30:09 -07:00
|
|
|
if transform:
|
|
|
|
pen = TransformPen(original_pen, transform)
|
|
|
|
else:
|
|
|
|
pen = original_pen
|
2019-02-08 11:37:00 -08:00
|
|
|
parse_path(path, pen)
|