2016-08-17 20:39:14 -07:00
|
|
|
"""
|
|
|
|
Interpolate OpenType Layout tables (GDEF / GPOS / GSUB).
|
|
|
|
"""
|
|
|
|
from __future__ import print_function, division, absolute_import
|
|
|
|
from fontTools.misc.py23 import *
|
|
|
|
from fontTools.ttLib import TTFont
|
2017-05-22 19:40:20 -07:00
|
|
|
from fontTools.varLib import models, VarLibError, load_designspace
|
2017-01-25 20:11:35 -08:00
|
|
|
from fontTools.varLib.merger import InstancerMerger
|
2016-08-17 20:39:14 -07:00
|
|
|
import os.path
|
2017-05-22 19:40:20 -07:00
|
|
|
import logging
|
|
|
|
from pprint import pformat
|
2016-08-17 20:39:14 -07:00
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
log = logging.getLogger("fontTools.varLib.interpolate_layout")
|
2016-10-12 16:11:20 -07:00
|
|
|
|
2016-09-05 19:10:18 -07:00
|
|
|
|
2017-05-22 18:46:41 -07:00
|
|
|
def interpolate_layout(designspace_filename, loc, master_finder=lambda s:s):
|
|
|
|
"""
|
|
|
|
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).
|
|
|
|
"""
|
2016-08-17 20:39:14 -07:00
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
axes, internal_axis_supports, base_idx, normalized_master_locs, masters, instances = load_designspace(designspace_filename)
|
2017-02-26 07:49:44 -08:00
|
|
|
|
2016-08-17 20:39:14 -07:00
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
log.info("Building interpolated font")
|
|
|
|
log.info("Loading master fonts")
|
2016-08-17 20:39:14 -07:00
|
|
|
basedir = os.path.dirname(designspace_filename)
|
2017-05-22 18:46:41 -07:00
|
|
|
master_ttfs = [master_finder(os.path.join(basedir, m['filename'])) for m in masters]
|
2016-08-17 20:39:14 -07:00
|
|
|
master_fonts = [TTFont(ttf_path) for ttf_path in master_ttfs]
|
|
|
|
|
|
|
|
#font = master_fonts[base_idx]
|
|
|
|
font = TTFont(master_ttfs[base_idx])
|
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
log.info("Location: %s", pformat(loc))
|
|
|
|
loc = {name:axes[name].map_forward(v) for name,v in loc.items()}
|
|
|
|
log.info("Internal location: %s", pformat(loc))
|
|
|
|
loc = models.normalizeLocation(loc, internal_axis_supports)
|
|
|
|
log.info("Normalized location: %s", pformat(loc))
|
2016-08-17 20:39:14 -07:00
|
|
|
|
|
|
|
# Assume single-model for now.
|
2017-05-22 19:40:20 -07:00
|
|
|
model = models.VariationModel(normalized_master_locs)
|
2016-08-17 20:39:14 -07:00
|
|
|
assert 0 == model.mapping[base_idx]
|
|
|
|
|
2016-10-12 16:11:20 -07:00
|
|
|
merger = InstancerMerger(font, model, loc)
|
2016-08-21 23:53:09 -07:00
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
log.info("Building interpolated tables")
|
|
|
|
merger.mergeTables(font, master_fonts, ['GPOS'])
|
2016-10-06 17:33:07 -07:00
|
|
|
return font
|
|
|
|
|
|
|
|
|
|
|
|
def main(args=None):
|
2017-05-22 19:40:20 -07:00
|
|
|
from fontTools import configLogger
|
2016-10-06 17:33:07 -07:00
|
|
|
|
|
|
|
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'
|
|
|
|
|
2017-05-22 19:40:20 -07:00
|
|
|
# TODO: allow user to configure logging via command-line options
|
|
|
|
configLogger(level="INFO")
|
|
|
|
|
2016-10-06 17:33:07 -07:00
|
|
|
finder = lambda s: s.replace('master_ufo', 'master_ttf_interpolatable').replace('.ufo', '.ttf')
|
|
|
|
|
|
|
|
loc = {}
|
|
|
|
for arg in locargs:
|
|
|
|
tag,val = arg.split('=')
|
|
|
|
loc[tag] = float(val)
|
2016-08-17 20:39:14 -07:00
|
|
|
|
2016-10-06 17:33:07 -07:00
|
|
|
font = interpolate_layout(designspace_filename, loc, finder)
|
2017-05-22 19:40:20 -07:00
|
|
|
log.info("Saving font %s", outfile)
|
2016-08-17 20:39:14 -07:00
|
|
|
font.save(outfile)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
import sys
|
|
|
|
if len(sys.argv) > 1:
|
2017-01-11 12:10:58 +00:00
|
|
|
sys.exit(main())
|
2017-01-11 12:24:04 +00:00
|
|
|
import doctest
|
2016-08-17 20:39:14 -07:00
|
|
|
sys.exit(doctest.testmod().failed)
|