Ensure all fonttools CLI tools have help documentation (#1948)
Note UI change : `fonttools varLib.models` now takes prefixed options `-d` or `-l` instead of guessing the intended feature from the number of arguments. We have a number of command line tools which are somewhat opaque. (varLib.models in particular was very confusing.) This ensures that they all use argparse to have a consistent interface, and all have --help documentation which at least details their parameters, and hopefully therefore gives more of a clue about what they do. Those which use logging have had a command-line logging parameter added.
This commit is contained in:
parent
a114ec2c20
commit
089f24da6b
@ -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()]
|
||||
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
|
||||
|
@ -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)
|
||||
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(
|
||||
"fonttools mtiLib",
|
||||
description=main.__doc__,
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
tableTag = None
|
||||
if args[0].startswith('-t'):
|
||||
tableTag = args[0][2:]
|
||||
del args[0]
|
||||
for f in args:
|
||||
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!
|
||||
|
@ -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)
|
||||
|
@ -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',
|
||||
|
@ -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()
|
||||
|
@ -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 <designspacename>-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__":
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user