diff --git a/Lib/fontTools/cffLib/width.py b/Lib/fontTools/cffLib/width.py index 909f1267d..fefae3aa8 100644 --- a/Lib/fontTools/cffLib/width.py +++ b/Lib/fontTools/cffLib/width.py @@ -146,16 +146,30 @@ def optimizeWidths(widths): return default, nominal -def main(): +def main(args=None): """Calculate optimum defaultWidthX/nominalWidthX values""" - for fontfile in sys.argv[1:]: + + import argparse + parser = argparse.ArgumentParser( + "fonttools cffLib.width", + description=main.__doc__, + ) + parser.add_argument('inputs', metavar='FILE', type=str, nargs='+', + help="Input TTF files") + parser.add_argument('-b', '--brute-force', dest="brute", action="store_true", + help="Use brute-force approach (VERY slow)") + + args = parser.parse_args(args) + + for fontfile in args.inputs: font = TTFont(fontfile) hmtx = font['hmtx'] widths = [m[0] for m in hmtx.metrics.values()] - default, nominal = optimizeWidths(widths) + if args.brute: + default, nominal = optimizeWidthsBruteforce(widths) + else: + default, nominal = optimizeWidths(widths) print("glyphs=%d default=%d nominal=%d byteCost=%d" % (len(widths), default, nominal, byteCost(widths, default, nominal))) - #default, nominal = optimizeWidthsBruteforce(widths) - #print("glyphs=%d default=%d nominal=%d byteCost=%d" % (len(widths), default, nominal, byteCost(widths, default, nominal))) if __name__ == '__main__': import sys diff --git a/Lib/fontTools/mtiLib/__init__.py b/Lib/fontTools/mtiLib/__init__.py index cf264a85c..4176fb253 100644 --- a/Lib/fontTools/mtiLib/__init__.py +++ b/Lib/fontTools/mtiLib/__init__.py @@ -1164,17 +1164,31 @@ def main(args=None, font=None): # comment this out to enable debug messages from mtiLib's logger # log.setLevel(logging.DEBUG) - if font is None: - font = MockFont() + import argparse + parser = argparse.ArgumentParser( + "fonttools mtiLib", + description=main.__doc__, + ) - tableTag = None - if args[0].startswith('-t'): - tableTag = args[0][2:] - del args[0] - for f in args: + parser.add_argument('--font', '-f', metavar='FILE', dest="font", + help="Input TTF files (used for glyph classes and sorting coverage tables)") + parser.add_argument('--table', '-t', metavar='TABLE', dest="tableTag", + help="Table to fill (sniffed from input file if not provided)") + parser.add_argument('inputs', metavar='FILE', type=str, nargs='+', + help="Input FontDame .txt files") + + args = parser.parse_args(args) + + if font is None: + if args.font: + font = ttLib.TTFont(args.font) + else: + font = MockFont() + + for f in args.inputs: log.debug("Processing %s", f) with open(f, 'rt', encoding="utf-8") as f: - table = build(f, font, tableTag=tableTag) + table = build(f, font, tableTag=args.tableTag) blob = table.compile(font) # Make sure it compiles decompiled = table.__class__() decompiled.decompile(blob, font) # Make sure it decompiles! diff --git a/Lib/fontTools/ttLib/woff2.py b/Lib/fontTools/ttLib/woff2.py index b56355923..e77ad9a4d 100644 --- a/Lib/fontTools/ttLib/woff2.py +++ b/Lib/fontTools/ttLib/woff2.py @@ -1395,6 +1395,17 @@ def main(args=None): from fontTools import configLogger from fontTools.ttx import makeOutputFileName + class _HelpAction(argparse._HelpAction): + + def __call__(self, parser, namespace, values, option_string=None): + subparsers_actions = [ + action for action in parser._actions + if isinstance(action, argparse._SubParsersAction)] + for subparsers_action in subparsers_actions: + for choice, subparser in subparsers_action.choices.items(): + print(subparser.format_help()) + parser.exit() + class _NoGlyfTransformAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): namespace.transform_tables.difference_update({"glyf", "loca"}) @@ -1405,12 +1416,18 @@ def main(args=None): parser = argparse.ArgumentParser( prog="fonttools ttLib.woff2", - description=main.__doc__ + description=main.__doc__, + add_help = False ) + parser.add_argument('-h', '--help', action=_HelpAction, + help='show this help message and exit') + parser_group = parser.add_subparsers(title="sub-commands") - parser_compress = parser_group.add_parser("compress") - parser_decompress = parser_group.add_parser("decompress") + parser_compress = parser_group.add_parser("compress", + description = "Compress a TTF or OTF font to WOFF2") + parser_decompress = parser_group.add_parser("decompress", + description = "Decompress a WOFF2 font to OTF") for subparser in (parser_compress, parser_decompress): group = subparser.add_mutually_exclusive_group(required=False) diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py index acc929b00..1bf586f70 100644 --- a/Lib/fontTools/varLib/__init__.py +++ b/Lib/fontTools/varLib/__init__.py @@ -1011,7 +1011,7 @@ def main(args=None): from argparse import ArgumentParser from fontTools import configLogger - parser = ArgumentParser(prog='varLib') + parser = ArgumentParser(prog='varLib', description = main.__doc__) parser.add_argument('designspace') parser.add_argument( '-o', diff --git a/Lib/fontTools/varLib/interpolatable.py b/Lib/fontTools/varLib/interpolatable.py index 1e326c9b0..6488022f6 100644 --- a/Lib/fontTools/varLib/interpolatable.py +++ b/Lib/fontTools/varLib/interpolatable.py @@ -157,23 +157,31 @@ def test(glyphsets, glyphs=None, names=None): #for x in hist: # print(x) -def main(args): +def main(args=None): """Test for interpolatability issues between fonts""" - filenames = args + import argparse + parser = argparse.ArgumentParser( + "fonttools varLib.interpolatable", + description=main.__doc__, + ) + parser.add_argument('inputs', metavar='FILE', type=str, nargs='+', + help="Input TTF files") + + args = parser.parse_args(args) glyphs = None #glyphs = ['uni08DB', 'uniFD76'] #glyphs = ['uni08DE', 'uni0034'] #glyphs = ['uni08DE', 'uni0034', 'uni0751', 'uni0753', 'uni0754', 'uni08A4', 'uni08A4.fina', 'uni08A5.fina'] from os.path import basename - names = [basename(filename).rsplit('.', 1)[0] for filename in filenames] + names = [basename(filename).rsplit('.', 1)[0] for filename in args.inputs] from fontTools.ttLib import TTFont - fonts = [TTFont(filename) for filename in filenames] + fonts = [TTFont(filename) for filename in args.inputs] glyphsets = [font.getGlyphSet() for font in fonts] test(glyphsets, glyphs=glyphs, names=names) if __name__ == '__main__': import sys - main(sys.argv[1:]) + main() diff --git a/Lib/fontTools/varLib/interpolate_layout.py b/Lib/fontTools/varLib/interpolate_layout.py index 1403818c8..6d0385dd7 100644 --- a/Lib/fontTools/varLib/interpolate_layout.py +++ b/Lib/fontTools/varLib/interpolate_layout.py @@ -60,28 +60,40 @@ def interpolate_layout(designspace, loc, master_finder=lambda s:s, mapped=False) def main(args=None): """Interpolate GDEF/GPOS/GSUB tables for a point on a designspace""" from fontTools import configLogger - + import argparse import sys - if args is None: - args = sys.argv[1:] - designspace_filename = args[0] - locargs = args[1:] - outfile = os.path.splitext(designspace_filename)[0] + '-instance.ttf' + parser = argparse.ArgumentParser( + "fonttools varLib.interpolate_layout", + description=main.__doc__, + ) + parser.add_argument('designspace_filename', metavar='DESIGNSPACE', + help="Input TTF files") + parser.add_argument('locations', metavar='LOCATION', type=str, nargs='+', + help="Axis locations (e.g. wdth=120") + parser.add_argument('-o', '--output', metavar='OUTPUT', + help="Output font file (defaults to -instance.ttf)") + parser.add_argument('-l', '--loglevel', metavar='LEVEL', default="INFO", + help="Logging level (defaults to INFO)") - # TODO: allow user to configure logging via command-line options - configLogger(level="INFO") + + args = parser.parse_args(args) + + if not args.output: + args.output = os.path.splitext(args.designspace_filename)[0] + '-instance.ttf' + + configLogger(level=args.loglevel) finder = lambda s: s.replace('master_ufo', 'master_ttf_interpolatable').replace('.ufo', '.ttf') loc = {} - for arg in locargs: + for arg in args.locations: tag,val = arg.split('=') loc[tag] = float(val) - font = interpolate_layout(designspace_filename, loc, finder) - log.info("Saving font %s", outfile) - font.save(outfile) + font = interpolate_layout(args.designspace_filename, loc, finder) + log.info("Saving font %s", args.output) + font.save(args.output) if __name__ == "__main__": diff --git a/Lib/fontTools/varLib/models.py b/Lib/fontTools/varLib/models.py index aa181bb22..eddf3b218 100644 --- a/Lib/fontTools/varLib/models.py +++ b/Lib/fontTools/varLib/models.py @@ -422,27 +422,32 @@ def piecewiseLinearMap(v, mapping): return va + (vb - va) * (v - a) / (b - a) -def main(args): +def main(args=None): """Normalize locations on a given designspace""" from fontTools import configLogger + import argparse - args = args[1:] + parser = argparse.ArgumentParser( + "fonttools varLib.models", + description=main.__doc__, + ) + parser.add_argument('--loglevel', metavar='LEVEL', default="INFO", + help="Logging level (defaults to INFO)") - # TODO: allow user to configure logging via command-line options - configLogger(level="INFO") + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-d', '--designspace',metavar="DESIGNSPACE",type=str) + group.add_argument('-l', '--locations', metavar='LOCATION', nargs='+', + help="Master locations as comma-separate coordinates. One must be all zeros.") - if len(args) < 1: - print("usage: fonttools varLib.models source.designspace", file=sys.stderr) - print(" or") - print("usage: fonttools varLib.models location1 location2 ...", file=sys.stderr) - sys.exit(1) + args = parser.parse_args(args) + configLogger(level=args.loglevel) from pprint import pprint - if len(args) == 1 and args[0].endswith('.designspace'): + if args.designspacefile: from fontTools.designspaceLib import DesignSpaceDocument doc = DesignSpaceDocument() - doc.read(args[0]) + doc.read(args.designspacefile) locs = [s.location for s in doc.sources] print("Original locations:") pprint(locs) @@ -452,7 +457,7 @@ def main(args): pprint(locs) else: axes = [chr(c) for c in range(ord('A'), ord('Z')+1)] - locs = [dict(zip(axes, (float(v) for v in s.split(',')))) for s in args] + locs = [dict(zip(axes, (float(v) for v in s.split(',')))) for s in args.locations] model = VariationModel(locs) print("Sorted locations:") @@ -464,6 +469,6 @@ if __name__ == "__main__": import doctest, sys if len(sys.argv) > 1: - sys.exit(main(sys.argv)) + sys.exit(main()) sys.exit(doctest.testmod().failed) diff --git a/Lib/fontTools/varLib/varStore.py b/Lib/fontTools/varLib/varStore.py index de114b19d..3d9566a1c 100644 --- a/Lib/fontTools/varLib/varStore.py +++ b/Lib/fontTools/varLib/varStore.py @@ -551,7 +551,7 @@ def main(args=None): from fontTools.ttLib import TTFont from fontTools.ttLib.tables.otBase import OTTableWriter - parser = ArgumentParser(prog='varLib.varStore') + parser = ArgumentParser(prog='varLib.varStore', description= main.__doc__) parser.add_argument('fontfile') parser.add_argument('outfile', nargs='?') options = parser.parse_args(args)