aboutsummaryrefslogtreecommitdiff
path: root/Lib/fontTools/pens/svgPathPen.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/fontTools/pens/svgPathPen.py')
-rw-r--r--Lib/fontTools/pens/svgPathPen.py79
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())