Merge pull request #1441 from anthrotype/varlib-load-ttx

[varLib] allow loading masters from TTX files as well
This commit is contained in:
Cosimo Lupo 2019-01-14 19:28:39 +00:00 committed by GitHub
commit 7cbb2da4df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 13 deletions

View File

@ -811,14 +811,36 @@ def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True):
return vf, model, master_ttfs return vf, model, master_ttfs
def _open_font(path, master_finder):
# load TTFont masters from given 'path': this can be either a .TTX or an
# OpenType binary font; or if neither of these, try use the 'master_finder'
# callable to resolve the path to a valid .TTX or OpenType font binary.
from fontTools.ttx import guessFileType
master_path = os.path.normpath(path)
tp = guessFileType(master_path)
if tp is None:
# not an OpenType binary/ttx, fall back to the master finder.
master_path = master_finder(master_path)
tp = guessFileType(master_path)
if tp in ("TTX", "OTX"):
font = TTFont()
font.importXML(master_path)
elif tp in ("TTF", "OTF", "WOFF", "WOFF2"):
font = TTFont(master_path)
else:
raise VarLibError("Invalid master path: %r" % master_path)
return font
def load_masters(designspace, master_finder=lambda s: s): def load_masters(designspace, master_finder=lambda s: s):
"""Ensure that all SourceDescriptor.font attributes have an appropriate TTFont """Ensure that all SourceDescriptor.font attributes have an appropriate TTFont
object loaded, or else open TTFont objects from the SourceDescriptor.path object loaded, or else open TTFont objects from the SourceDescriptor.path
attributes. attributes.
The paths can point to either an OpenType font or to a UFO. In the latter case, The paths can point to either an OpenType font, a TTX file, or a UFO. In the
use the provided master_finder callable to map from UFO paths to the respective latter case, use the provided master_finder callable to map from UFO paths to
master font binaries (e.g. .ttf or .otf). the respective master font binaries (e.g. .ttf, .otf or .ttx).
Return list of master TTFont objects in the same order they are listed in the Return list of master TTFont objects in the same order they are listed in the
DesignSpaceDocument. DesignSpaceDocument.
@ -845,15 +867,10 @@ def load_masters(designspace, master_finder=lambda s: s):
"Designspace source '%s' has neither 'font' nor 'path' " "Designspace source '%s' has neither 'font' nor 'path' "
"attributes" % (master.name or "<Unknown>") "attributes" % (master.name or "<Unknown>")
) )
# 2. A SourceDescriptor's path might point to a UFO or an OpenType # 2. A SourceDescriptor's path might point an OpenType binary, a
# binary. Find out the hard way. # TTX file, or another source file (e.g. UFO), in which case we
master_path = os.path.normpath(master.path) # resolve the path using 'master_finder' function
try: font = _open_font(master.path, master_finder)
font = TTFont(master_path)
except (IOError, TTLibError):
# 3. Not an OpenType binary, fall back to the master finder.
master_path = master_finder(master_path)
font = TTFont(master_path)
master_fonts.append(font) master_fonts.append(font)
return master_fonts return master_fonts

View File

@ -290,7 +290,7 @@ class BuildTest(unittest.TestCase):
expected_ttx_path = self.get_test_output('BuildMain.ttx') expected_ttx_path = self.get_test_output('BuildMain.ttx')
self.expect_ttx(varfont, expected_ttx_path, tables) self.expect_ttx(varfont, expected_ttx_path, tables)
def test_varlib_build_from_ds_object(self): def test_varlib_build_from_ds_object_in_memory_ttfonts(self):
ds_path = self.get_test_input("Build.designspace") ds_path = self.get_test_input("Build.designspace")
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf") ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
expected_ttx_path = self.get_test_output("BuildMain.ttx") expected_ttx_path = self.get_test_output("BuildMain.ttx")
@ -314,6 +314,44 @@ class BuildTest(unittest.TestCase):
tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"] tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"]
self.expect_ttx(varfont, expected_ttx_path, tables) self.expect_ttx(varfont, expected_ttx_path, tables)
def test_varlib_build_from_ttf_paths(self):
ds_path = self.get_test_input("Build.designspace")
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
expected_ttx_path = self.get_test_output("BuildMain.ttx")
self.temp_dir()
for path in self.get_file_list(ttx_dir, '.ttx', 'TestFamily-'):
self.compile_font(path, ".ttf", self.tempdir)
ds = DesignSpaceDocument.fromfile(ds_path)
for source in ds.sources:
source.path = os.path.join(
self.tempdir, os.path.basename(source.filename).replace(".ufo", ".ttf")
)
ds.updatePaths()
varfont, _, _ = build(ds)
varfont = reload_font(varfont)
tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"]
self.expect_ttx(varfont, expected_ttx_path, tables)
def test_varlib_build_from_ttx_paths(self):
ds_path = self.get_test_input("Build.designspace")
ttx_dir = self.get_test_input("master_ttx_interpolatable_ttf")
expected_ttx_path = self.get_test_output("BuildMain.ttx")
ds = DesignSpaceDocument.fromfile(ds_path)
for source in ds.sources:
source.path = os.path.join(
ttx_dir, os.path.basename(source.filename).replace(".ufo", ".ttx")
)
ds.updatePaths()
varfont, _, _ = build(ds)
varfont = reload_font(varfont)
tables = [table_tag for table_tag in varfont.keys() if table_tag != "head"]
self.expect_ttx(varfont, expected_ttx_path, tables)
def test_load_masters_layerName_without_required_font(): def test_load_masters_layerName_without_required_font():
ds = DesignSpaceDocument() ds = DesignSpaceDocument()