#!/usr/bin/env python """ Convert SVG paths to UFO glyphs. """ from __future__ import print_function, absolute_import __requires__ = ["FontTools", "ufoLib"] from fontTools.misc.py23 import SimpleNamespace from fontTools.svgLib import SVGPath from fontTools.pens.pointPen import SegmentToPointPen from fontTools.ufoLib.glifLib import writeGlyphToString __all__ = ["svg2glif"] def svg2glif(svg, name, width=0, height=0, unicodes=None, transform=None, version=2): """ Convert an SVG outline to a UFO glyph with given 'name', advance 'width' and 'height' (int), and 'unicodes' (list of int). Return the resulting string in GLIF format (default: version 2). If 'transform' is provided, apply a transformation matrix before the conversion (must be tuple of 6 floats, or a FontTools Transform object). """ glyph = SimpleNamespace(width=width, height=height, unicodes=unicodes) outline = SVGPath.fromstring(svg, transform=transform) # writeGlyphToString takes a callable (usually a glyph's drawPoints # method) that accepts a PointPen, however SVGPath currently only has # a draw method that accepts a segment pen. We need to wrap the call # with a converter pen. def drawPoints(pointPen): pen = SegmentToPointPen(pointPen) outline.draw(pen) return writeGlyphToString(name, glyphObject=glyph, drawPointsFunc=drawPoints, formatVersion=version) def parse_args(args): import argparse def split(arg): return arg.replace(",", " ").split() def unicode_hex_list(arg): try: return [int(unihex, 16) for unihex in split(arg)] except ValueError: msg = "Invalid unicode hexadecimal value: %r" % arg raise argparse.ArgumentTypeError(msg) def transform_list(arg): try: return [float(n) for n in split(arg)] except ValueError: msg = "Invalid transformation matrix: %r" % arg raise argparse.ArgumentTypeError(msg) parser = argparse.ArgumentParser( description="Convert SVG outlines to UFO glyphs (.glif)") parser.add_argument( "infile", metavar="INPUT.svg", help="Input SVG file containing " '<path> elements with "d" attributes.') parser.add_argument( "outfile", metavar="OUTPUT.glif", help="Output GLIF file (default: " "print to stdout)", nargs='?') parser.add_argument( "-n", "--name", help="The glyph name (default: input SVG file " "basename, without the .svg extension)") parser.add_argument( "-w", "--width", help="The glyph advance width (default: 0)", type=int, default=0) parser.add_argument( "-H", "--height", help="The glyph vertical advance (optional if " '"width" is defined)', type=int, default=0) parser.add_argument( "-u", "--unicodes", help="List of Unicode code points as hexadecimal " 'numbers (e.g. -u "0041 0042")', type=unicode_hex_list) parser.add_argument( "-t", "--transform", help="Transformation matrix as a list of six " 'float values (e.g. -t "0.1 0 0 -0.1 -50 200")', type=transform_list) parser.add_argument( "-f", "--format", help="UFO GLIF format version (default: 2)", type=int, choices=(1, 2), default=2) return parser.parse_args(args) def main(args=None): from io import open options = parse_args(args) svg_file = options.infile if options.name: name = options.name else: import os name = os.path.splitext(os.path.basename(svg_file))[0] with open(svg_file, "r", encoding="utf-8") as f: svg = f.read() glif = svg2glif(svg, name, width=options.width, height=options.height, unicodes=options.unicodes, transform=options.transform, version=options.format) if options.outfile is None: print(glif) else: with open(options.outfile, 'w', encoding='utf-8') as f: f.write(glif) if __name__ == "__main__": import sys sys.exit(main())