예제 #1
0
def main(args=None):
    """Merge multiple fonts into one"""
    from fontemon_blender_addon.fontTools import configLogger

    if args is None:
        args = sys.argv[1:]

    options = Options()
    args = options.parse_opts(args)

    if len(args) < 1:
        print("usage: pyftmerge font...", file=sys.stderr)
        return 1

    configLogger(level=logging.INFO if options.verbose else logging.WARNING)
    if options.timing:
        timer.logger.setLevel(logging.DEBUG)
    else:
        timer.logger.disabled = True

    merger = Merger(options=options)
    font = merger.merge(args)
    outfile = 'merged.ttf'
    with timer("compile and save font"):
        font.save(outfile)
예제 #2
0
def main(args=None):
    """Convert OpenType fonts to XML and back"""
    from fontemon_blender_addon.fontTools import configLogger

    if args is None:
        args = sys.argv[1:]
    try:
        jobs, options = parseOptions(args)
    except getopt.GetoptError as e:
        print("%s\nERROR: %s" % (__doc__, e), file=sys.stderr)
        sys.exit(2)

    configLogger(level=options.logLevel)

    try:
        process(jobs, options)
    except KeyboardInterrupt:
        log.error("(Cancelled.)")
        sys.exit(1)
    except SystemExit:
        if sys.platform == "win32":
            waitForKeyPress()
        raise
    except TTLibError as e:
        log.error(e)
        sys.exit(1)
    except:
        log.exception('Unhandled exception has occurred')
        if sys.platform == "win32":
            waitForKeyPress()
        sys.exit(1)
예제 #3
0
def main(args=None):
    """Normalize locations on a given designspace"""
    from fontemon_blender_addon.fontTools import configLogger
    import argparse

    parser = argparse.ArgumentParser(
        "fontemon_blender_addon.fontTools varLib.models",
        description=main.__doc__,
    )
    parser.add_argument('--loglevel',
                        metavar='LEVEL',
                        default="INFO",
                        help="Logging level (defaults to 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."
    )

    args = parser.parse_args(args)

    configLogger(level=args.loglevel)
    from pprint import pprint

    if args.designspace:
        from fontemon_blender_addon.fontTools.designspaceLib import DesignSpaceDocument
        doc = DesignSpaceDocument()
        doc.read(args.designspace)
        locs = [s.location for s in doc.sources]
        print("Original locations:")
        pprint(locs)
        doc.normalize()
        print("Normalized locations:")
        locs = [s.location for s in doc.sources]
        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.locations
        ]

    model = VariationModel(locs)
    print("Sorted locations:")
    pprint(model.locations)
    print("Supports:")
    pprint(model.supports)
예제 #4
0
def main(args=None):
    """Interpolate GDEF/GPOS/GSUB tables for a point on a designspace"""
    from fontemon_blender_addon.fontTools import configLogger
    import argparse
    import sys

    parser = argparse.ArgumentParser(
        "fontemon_blender_addon.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)")

    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 args.locations:
        tag, val = arg.split('=')
        loc[tag] = float(val)

    font = interpolate_layout(args.designspace_filename, loc, finder)
    log.info("Saving font %s", args.output)
    font.save(args.output)
def main(args=None):
    """Optimize a font's GDEF variation store"""
    from argparse import ArgumentParser
    from fontemon_blender_addon.fontTools import configLogger
    from fontemon_blender_addon.fontTools.ttLib import TTFont
    from fontemon_blender_addon.fontTools.ttLib.tables.otBase import OTTableWriter

    parser = ArgumentParser(prog='varLib.varStore', description=main.__doc__)
    parser.add_argument('fontfile')
    parser.add_argument('outfile', nargs='?')
    options = parser.parse_args(args)

    # TODO: allow user to configure logging via command-line options
    configLogger(level="INFO")

    fontfile = options.fontfile
    outfile = options.outfile

    font = TTFont(fontfile)
    gdef = font['GDEF']
    store = gdef.table.VarStore

    writer = OTTableWriter()
    store.compile(writer, font)
    size = len(writer.getAllData())
    print("Before: %7d bytes" % size)

    varidx_map = store.optimize()

    gdef.table.remap_device_varidxes(varidx_map)
    if 'GPOS' in font:
        font['GPOS'].table.remap_device_varidxes(varidx_map)

    writer = OTTableWriter()
    store.compile(writer, font)
    size = len(writer.getAllData())
    print("After:  %7d bytes" % size)

    if outfile is not None:
        font.save(outfile)
예제 #6
0
def main(args=None):
    from fontemon_blender_addon.fontTools import configLogger

    if args is None:
        args = sys.argv[1:]

    # configure the library logger (for >= WARNING)
    configLogger()
    # comment this out to enable debug messages from logger
    # log.setLevel(logging.DEBUG)

    if len(args) < 1:
        print(
            "usage: fontemon_blender_addon.fontTools varLib.plot source.designspace",
            file=sys.stderr)
        print("  or")
        print(
            "usage: fontemon_blender_addon.fontTools varLib.plot location1 location2 ...",
            file=sys.stderr)
        sys.exit(1)

    fig = pyplot.figure()
    fig.set_tight_layout(True)

    if len(args) == 1 and args[0].endswith('.designspace'):
        doc = DesignSpaceDocument()
        doc.read(args[0])
        plotDocument(doc, fig)
    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
        ]
        plotLocations(locs, fig)

    pyplot.show()
def main(args=None):
    """Add features from a feature file (.fea) into a OTF font"""
    parser = argparse.ArgumentParser(
        description=
        "Use fontemon_blender_addon.fontTools to compile OpenType feature files (*.fea)."
    )
    parser.add_argument("input_fea",
                        metavar="FEATURES",
                        help="Path to the feature file")
    parser.add_argument("input_font",
                        metavar="INPUT_FONT",
                        help="Path to the input font")
    parser.add_argument(
        "-o",
        "--output",
        dest="output_font",
        metavar="OUTPUT_FONT",
        help="Path to the output font.",
    )
    parser.add_argument(
        "-t",
        "--tables",
        metavar="TABLE_TAG",
        choices=Builder.supportedTables,
        nargs="+",
        help="Specify the table(s) to be built.",
    )
    parser.add_argument(
        "-d",
        "--debug",
        action="store_true",
        help="Add source-level debugging information to font.",
    )
    parser.add_argument(
        "-v",
        "--verbose",
        help="increase the logger verbosity. Multiple -v "
        "options are allowed.",
        action="count",
        default=0,
    )
    parser.add_argument("--traceback",
                        help="show traceback for exceptions.",
                        action="store_true")
    options = parser.parse_args(args)

    levels = ["WARNING", "INFO", "DEBUG"]
    configLogger(level=levels[min(len(levels) - 1, options.verbose)])

    output_font = options.output_font or makeOutputFileName(options.input_font)
    log.info("Compiling features to '%s'" % (output_font))

    font = TTFont(options.input_font)
    try:
        addOpenTypeFeatures(font,
                            options.input_fea,
                            tables=options.tables,
                            debug=options.debug)
    except FeatureLibError as e:
        if options.traceback:
            raise
        log.error(e)
    font.save(output_font)
예제 #8
0
def main(args=None, font=None):
    """Convert a FontDame OTL file to TTX XML.

	Writes XML output to stdout.

	Args:
		args: Command line arguments (``--font``, ``--table``, input files).
	"""
    import sys
    from fontemon_blender_addon.fontTools import configLogger
    from fontemon_blender_addon.fontTools.misc.testTools import MockFont

    if args is None:
        args = sys.argv[1:]

    # configure the library logger (for >= WARNING)
    configLogger()
    # comment this out to enable debug messages from mtiLib's logger
    # log.setLevel(logging.DEBUG)

    import argparse
    parser = argparse.ArgumentParser(
        "fontemon_blender_addon.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()

    for f in args.inputs:
        log.debug("Processing %s", f)
        with open(f, 'rt', encoding="utf-8") as f:
            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!

        #continue
        from fontemon_blender_addon.fontTools.misc import xmlWriter
        tag = table.tableTag
        writer = xmlWriter.XMLWriter(sys.stdout)
        writer.begintag(tag)
        writer.newline()
        #table.toXML(writer, font)
        decompiled.toXML(writer, font)
        writer.endtag(tag)
        writer.newline()
예제 #9
0
def main(args=None):
    """Instantiate a variation font"""
    from fontemon_blender_addon.fontTools import configLogger
    import argparse

    parser = argparse.ArgumentParser(
        "fontemon_blender_addon.fontTools varLib.mutator",
        description="Instantiate a variable font")
    parser.add_argument("input",
                        metavar="INPUT.ttf",
                        help="Input variable TTF file.")
    parser.add_argument(
        "locargs",
        metavar="AXIS=LOC",
        nargs="*",
        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.")
    parser.add_argument(
        "-o",
        "--output",
        metavar="OUTPUT.ttf",
        default=None,
        help="Output instance TTF file (default: INPUT-instance.ttf).")
    logging_group = parser.add_mutually_exclusive_group(required=False)
    logging_group.add_argument("-v",
                               "--verbose",
                               action="store_true",
                               help="Run more verbosely.")
    logging_group.add_argument("-q",
                               "--quiet",
                               action="store_true",
                               help="Turn verbosity off.")
    parser.add_argument(
        "--no-overlap",
        dest="overlap",
        action="store_false",
        help="Don't set OVERLAP_SIMPLE/OVERLAP_COMPOUND glyf flags.")
    options = parser.parse_args(args)

    varfilename = options.input
    outfile = (os.path.splitext(varfilename)[0] +
               '-instance.ttf' if not options.output else options.output)
    configLogger(level=(
        "DEBUG" if options.verbose else "ERROR" if options.quiet else "INFO"))

    loc = {}
    for arg in options.locargs:
        try:
            tag, val = arg.split('=')
            assert len(tag) <= 4
            loc[tag.ljust(4)] = float(val)
        except (ValueError, AssertionError):
            parser.error("invalid location argument format: %r" % arg)
    log.info("Location: %s", loc)

    log.info("Loading variable font")
    varfont = TTFont(varfilename)

    instantiateVariableFont(varfont,
                            loc,
                            inplace=True,
                            overlap=options.overlap)

    log.info("Saving instance font %s", outfile)
    varfont.save(outfile)
예제 #10
0
def main(args=None):
	"""Build a variable font from a designspace file and masters"""
	from argparse import ArgumentParser
	from fontemon_blender_addon.fontTools import configLogger

	parser = ArgumentParser(prog='varLib', description = main.__doc__)
	parser.add_argument('designspace')
	parser.add_argument(
		'-o',
		metavar='OUTPUTFILE',
		dest='outfile',
		default=None,
		help='output file'
	)
	parser.add_argument(
		'-x',
		metavar='TAG',
		dest='exclude',
		action='append',
		default=[],
		help='exclude table'
	)
	parser.add_argument(
		'--disable-iup',
		dest='optimize',
		action='store_false',
		help='do not perform IUP optimization'
	)
	parser.add_argument(
		'--master-finder',
		default='master_ttf_interpolatable/{stem}.ttf',
		help=(
			'templated string used for finding binary font '
			'files given the source file names defined in the '
			'designspace document. The following special strings '
			'are defined: {fullname} is the absolute source file '
			'name; {basename} is the file name without its '
			'directory; {stem} is the basename without the file '
			'extension; {ext} is the source file extension; '
			'{dirname} is the directory of the absolute file '
			'name. The default value is "%(default)s".'
		)
	)
	logging_group = parser.add_mutually_exclusive_group(required=False)
	logging_group.add_argument(
		"-v", "--verbose",
                action="store_true",
                help="Run more verbosely.")
	logging_group.add_argument(
		"-q", "--quiet",
                action="store_true",
                help="Turn verbosity off.")
	options = parser.parse_args(args)

	configLogger(level=(
		"DEBUG" if options.verbose else
		"ERROR" if options.quiet else
		"INFO"))

	designspace_filename = options.designspace
	finder = MasterFinder(options.master_finder)

	vf, _, _ = build(
		designspace_filename,
		finder,
		exclude=options.exclude,
		optimize=options.optimize
	)

	outfile = options.outfile
	if outfile is None:
		ext = "otf" if vf.sfntVersion == "OTTO" else "ttf"
		outfile = os.path.splitext(designspace_filename)[0] + '-VF.' + ext

	log.info("Saving variation font %s", outfile)
	vf.save(outfile)