diff options
Diffstat (limited to 'Lib/fontTools/pens/svgPathPen.py')
-rw-r--r-- | Lib/fontTools/pens/svgPathPen.py | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/Lib/fontTools/pens/svgPathPen.py b/Lib/fontTools/pens/svgPathPen.py index e92737e3..106e33b7 100644 --- a/Lib/fontTools/pens/svgPathPen.py +++ b/Lib/fontTools/pens/svgPathPen.py @@ -23,6 +23,18 @@ class SVGPathPen(BasePen): used to resolve component references in composite glyphs. ntos: a callable that takes a number and returns a string, to customize how numbers are formatted (default: str). + + Note: + Fonts have a coordinate system where Y grows up, whereas in SVG, + Y grows down. As such, rendering path data from this pen in + SVG typically results in upside-down glyphs. You can fix this + by wrapping the data from this pen in an SVG group element with + transform, or wrap this pen in a transform pen. For example: + + spen = svgPathPen.SVGPathPen(glyphset) + pen= TransformPen(spen , (1, 0, 0, -1, 0, 0)) + glyphset[glyphname].draw(pen) + print(tpen.getCommands()) """ def __init__(self, glyphSet, ntos: Callable[[float], str] = str): BasePen.__init__(self, glyphSet) @@ -193,7 +205,70 @@ class SVGPathPen(BasePen): return "".join(self._commands) +def main(args=None): + """Generate per-character SVG from font and text""" + + if args is None: + import sys + args = sys.argv[1:] + + from fontTools.ttLib import TTFont + import argparse + + parser = argparse.ArgumentParser( + "fonttools pens.svgPathPen", description="Generate SVG from text") + parser.add_argument( + "font", metavar="font.ttf", help="Font file.") + parser.add_argument( + "text", metavar="text", help="Text string.") + parser.add_argument( + "--variations", metavar="AXIS=LOC", default='', + help="List of space separated locations. A location consist in " + "the name of a variation axis, followed by '=' and a number. E.g.: " + "wght=700 wdth=80. The default is the location of the base master.") + + options = parser.parse_args(args) + + font = TTFont(options.font) + text = options.text + + location = {} + for tag_v in options.variations.split(): + fields = tag_v.split('=') + tag = fields[0].strip() + v = int(fields[1]) + location[tag] = v + + hhea = font['hhea'] + ascent, descent = hhea.ascent, hhea.descent + + glyphset = font.getGlyphSet(location=location) + cmap = font['cmap'].getBestCmap() + + s = '' + width = 0 + for u in text: + g = cmap[ord(u)] + glyph = glyphset[g] + + pen = SVGPathPen(glyphset) + glyph.draw(pen) + commands = pen.getCommands() + + s += '<g transform="translate(%d %d) scale(1 -1)"><path d="%s"/></g>\n' % (width, ascent, commands) + + width += glyph.width + + print('<?xml version="1.0" encoding="UTF-8"?>') + print('<svg width="%d" height="%d" xmlns="http://www.w3.org/2000/svg">' % (width, ascent-descent)) + print(s, end='') + print('</svg>') + + if __name__ == "__main__": import sys - import doctest - sys.exit(doctest.testmod().failed) + if len(sys.argv) == 1: + import doctest + sys.exit(doctest.testmod().failed) + + sys.exit(main()) |