• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2Interpolate OpenType Layout tables (GDEF / GPOS / GSUB).
3"""
4from __future__ import print_function, division, absolute_import
5from fontTools.misc.py23 import *
6from fontTools.ttLib import TTFont
7from fontTools.varLib import models, VarLibError, load_designspace, load_masters
8from fontTools.varLib.merger import InstancerMerger
9import os.path
10import logging
11from copy import deepcopy
12from pprint import pformat
13
14log = logging.getLogger("fontTools.varLib.interpolate_layout")
15
16
17def interpolate_layout(designspace, loc, master_finder=lambda s:s, mapped=False):
18	"""
19	Interpolate GPOS from a designspace file and location.
20
21	If master_finder is set, it should be a callable that takes master
22	filename as found in designspace file and map it to master font
23	binary as to be opened (eg. .ttf or .otf).
24
25	If mapped is False (default), then location is mapped using the
26	map element of the axes in designspace file.  If mapped is True,
27	it is assumed that location is in designspace's internal space and
28	no mapping is performed.
29	"""
30	if hasattr(designspace, "sources"):  # Assume a DesignspaceDocument
31		pass
32	else:  # Assume a file path
33		from fontTools.designspaceLib import DesignSpaceDocument
34		designspace = DesignSpaceDocument.fromfile(designspace)
35
36	ds = load_designspace(designspace)
37	log.info("Building interpolated font")
38
39	log.info("Loading master fonts")
40	master_fonts = load_masters(designspace, master_finder)
41	font = deepcopy(master_fonts[ds.base_idx])
42
43	log.info("Location: %s", pformat(loc))
44	if not mapped:
45		loc = {name: ds.axes[name].map_forward(v) for name,v in loc.items()}
46	log.info("Internal location: %s", pformat(loc))
47	loc = models.normalizeLocation(loc, ds.internal_axis_supports)
48	log.info("Normalized location: %s", pformat(loc))
49
50	# Assume single-model for now.
51	model = models.VariationModel(ds.normalized_master_locs)
52	assert 0 == model.mapping[ds.base_idx]
53
54	merger = InstancerMerger(font, model, loc)
55
56	log.info("Building interpolated tables")
57	# TODO GSUB/GDEF
58	merger.mergeTables(font, master_fonts, ['GPOS'])
59	return font
60
61
62def main(args=None):
63	from fontTools import configLogger
64
65	import sys
66	if args is None:
67		args = sys.argv[1:]
68
69	designspace_filename = args[0]
70	locargs = args[1:]
71	outfile = os.path.splitext(designspace_filename)[0] + '-instance.ttf'
72
73	# TODO: allow user to configure logging via command-line options
74	configLogger(level="INFO")
75
76	finder = lambda s: s.replace('master_ufo', 'master_ttf_interpolatable').replace('.ufo', '.ttf')
77
78	loc = {}
79	for arg in locargs:
80		tag,val = arg.split('=')
81		loc[tag] = float(val)
82
83	font = interpolate_layout(designspace_filename, loc, finder)
84	log.info("Saving font %s", outfile)
85	font.save(outfile)
86
87
88if __name__ == "__main__":
89	import sys
90	if len(sys.argv) > 1:
91		sys.exit(main())
92	import doctest
93	sys.exit(doctest.testmod().failed)
94