123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- """
- Interpolate OpenType Layout tables (GDEF / GPOS / GSUB).
- """
- from fontTools.ttLib import TTFont
- from fontTools.varLib import models, VarLibError, load_designspace, load_masters
- from fontTools.varLib.merger import InstancerMerger
- import os.path
- import logging
- from copy import deepcopy
- from pprint import pformat
- log = logging.getLogger("fontTools.varLib.interpolate_layout")
- def interpolate_layout(designspace, loc, master_finder=lambda s: s, mapped=False):
- """
- Interpolate GPOS from a designspace file and location.
- If master_finder is set, it should be a callable that takes master
- filename as found in designspace file and map it to master font
- binary as to be opened (eg. .ttf or .otf).
- If mapped is False (default), then location is mapped using the
- map element of the axes in designspace file. If mapped is True,
- it is assumed that location is in designspace's internal space and
- no mapping is performed.
- """
- if hasattr(designspace, "sources"): # Assume a DesignspaceDocument
- pass
- else: # Assume a file path
- from fontTools.designspaceLib import DesignSpaceDocument
- designspace = DesignSpaceDocument.fromfile(designspace)
- ds = load_designspace(designspace)
- log.info("Building interpolated font")
- log.info("Loading master fonts")
- master_fonts = load_masters(designspace, master_finder)
- font = deepcopy(master_fonts[ds.base_idx])
- log.info("Location: %s", pformat(loc))
- if not mapped:
- loc = {name: ds.axes[name].map_forward(v) for name, v in loc.items()}
- log.info("Internal location: %s", pformat(loc))
- loc = models.normalizeLocation(loc, ds.internal_axis_supports)
- log.info("Normalized location: %s", pformat(loc))
- # Assume single-model for now.
- model = models.VariationModel(ds.normalized_master_locs)
- assert 0 == model.mapping[ds.base_idx]
- merger = InstancerMerger(font, model, loc)
- log.info("Building interpolated tables")
- # TODO GSUB/GDEF
- merger.mergeTables(font, master_fonts, ["GPOS"])
- return font
- def main(args=None):
- """Interpolate GDEF/GPOS/GSUB tables for a point on a designspace"""
- from fontTools import configLogger
- import argparse
- import sys
- 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)",
- )
- 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)
- if __name__ == "__main__":
- import sys
- if len(sys.argv) > 1:
- sys.exit(main())
- import doctest
- sys.exit(doctest.testmod().failed)
|