fonttools/Tests/varLib/interpolate_layout_test.py
Khaled Hosny 000bf81700 Default to "\n" for newlinestr instead of None
If newlinestr is None, os.linesep is used, bu it is the third millennium
and we don’t need or want different line endings per-platform.
2021-07-30 04:12:33 +02:00

874 lines
33 KiB
Python

from fontTools.ttLib import TTFont
from fontTools.varLib import build
from fontTools.varLib.interpolate_layout import interpolate_layout
from fontTools.varLib.interpolate_layout import main as interpolate_layout_main
from fontTools.designspaceLib import DesignSpaceDocument, DesignSpaceDocumentError
from fontTools.feaLib.builder import addOpenTypeFeaturesFromString
import difflib
import os
import shutil
import sys
import tempfile
import unittest
class InterpolateLayoutTest(unittest.TestCase):
def __init__(self, methodName):
unittest.TestCase.__init__(self, methodName)
# Python 3 renamed assertRaisesRegexp to assertRaisesRegex,
# and fires deprecation warnings if a program uses the old name.
if not hasattr(self, "assertRaisesRegex"):
self.assertRaisesRegex = self.assertRaisesRegexp
def setUp(self):
self.tempdir = None
self.num_tempfiles = 0
def tearDown(self):
if self.tempdir:
shutil.rmtree(self.tempdir)
@staticmethod
def get_test_input(test_file_or_folder):
path, _ = os.path.split(__file__)
return os.path.join(path, "data", test_file_or_folder)
@staticmethod
def get_test_output(test_file_or_folder):
path, _ = os.path.split(__file__)
return os.path.join(path, "data", "test_results", test_file_or_folder)
@staticmethod
def get_file_list(folder, suffix, prefix=''):
all_files = os.listdir(folder)
file_list = []
for p in all_files:
if p.startswith(prefix) and p.endswith(suffix):
file_list.append(os.path.abspath(os.path.join(folder, p)))
return file_list
def temp_path(self, suffix):
self.temp_dir()
self.num_tempfiles += 1
return os.path.join(self.tempdir,
"tmp%d%s" % (self.num_tempfiles, suffix))
def temp_dir(self):
if not self.tempdir:
self.tempdir = tempfile.mkdtemp()
def read_ttx(self, path):
lines = []
with open(path, "r", encoding="utf-8") as ttx:
for line in ttx.readlines():
# Elide ttFont attributes because ttLibVersion may change.
if line.startswith("<ttFont "):
lines.append("<ttFont>\n")
else:
lines.append(line.rstrip() + "\n")
return lines
def expect_ttx(self, font, expected_ttx, tables):
path = self.temp_path(suffix=".ttx")
font.saveXML(path, tables=tables)
actual = self.read_ttx(path)
expected = self.read_ttx(expected_ttx)
if actual != expected:
for line in difflib.unified_diff(
expected, actual, fromfile=expected_ttx, tofile=path):
sys.stdout.write(line)
self.fail("TTX output is different from expected")
def check_ttx_dump(self, font, expected_ttx, tables, suffix):
"""Ensure the TTX dump is the same after saving and reloading the font."""
path = self.temp_path(suffix=suffix)
font.save(path)
self.expect_ttx(TTFont(path), expected_ttx, tables)
def compile_font(self, path, suffix, temp_dir, features=None):
ttx_filename = os.path.basename(path)
savepath = os.path.join(temp_dir, ttx_filename.replace('.ttx', suffix))
font = TTFont(recalcBBoxes=False, recalcTimestamp=False)
font.importXML(path)
if features:
addOpenTypeFeaturesFromString(font, features)
font.save(savepath, reorderTables=None)
return font, savepath
# -----
# Tests
# -----
def test_varlib_interpolate_layout_GSUB_only_ttf(self):
"""Only GSUB, and only in the base master.
The variable font will inherit the GSUB table from the
base master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GSUB']
expected_ttx_path = self.get_test_output('InterpolateLayout.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_no_GSUB_ttf(self):
"""The base master has no GSUB table.
The variable font will end up without a GSUB table.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout2.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for path in ttx_paths:
self.compile_font(path, suffix, self.tempdir)
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GSUB']
expected_ttx_path = self.get_test_output('InterpolateLayout2.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GSUB_only_no_axes_ttf(self):
"""Only GSUB, and only in the base master.
Designspace file has no <axes> element.
The variable font will inherit the GSUB table from the
base master.
"""
ds_path = self.get_test_input('InterpolateLayout3.designspace')
with self.assertRaisesRegex(DesignSpaceDocumentError, "No axes defined"):
instfont = interpolate_layout(ds_path, {'weight': 500})
def test_varlib_interpolate_layout_GPOS_only_size_feat_same_val_ttf(self):
"""Only GPOS; 'size' feature; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
feature size {
parameters 10.0 0;
} size;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_size_feat_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_same_val_ttf(self):
"""Only GPOS; LookupType 1; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
feature xxxx {
pos A <-80 0 -160 0>;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_diff_val_ttf(self):
"""Only GPOS; LookupType 1; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos A <-80 0 -160 0>;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos A <-97 0 -195 0>;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_1_diff2_val_ttf(self):
"""Only GPOS; LookupType 1; different values and items in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos A <-80 0 -160 0>;
pos a <-55 0 -105 0>;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos A <-97 0 -195 0>;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_1_diff2.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_same_val_ttf(self):
"""Only GPOS; LookupType 2 specific pairs; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
feature xxxx {
pos A a -53;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff_val_ttf(self):
"""Only GPOS; LookupType 2 specific pairs; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos A a -53;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos A a -27;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_spec_pairs_diff2_val_ttf(self):
"""Only GPOS; LookupType 2 specific pairs; different values and items in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos A a -53;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos A a -27;
pos a a 19;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_spec_diff2.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_same_val_ttf(self):
"""Only GPOS; LookupType 2 class pairs; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
feature xxxx {
pos [A] [a] -53;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff_val_ttf(self):
"""Only GPOS; LookupType 2 class pairs; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos [A] [a] -53;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos [A] [a] -27;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_2_class_pairs_diff2_val_ttf(self):
"""Only GPOS; LookupType 2 class pairs; different values and items in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos [A] [a] -53;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos [A] [a] -27;
pos [a] [a] 19;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_2_class_diff2.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_3_same_val_ttf(self):
"""Only GPOS; LookupType 3; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
feature xxxx {
pos cursive a <anchor 60 15> <anchor 405 310>;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_3_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_3_diff_val_ttf(self):
"""Only GPOS; LookupType 3; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
feature xxxx {
pos cursive a <anchor 60 15> <anchor 405 310>;
} xxxx;
"""
fea_str_1 = """
feature xxxx {
pos cursive a <anchor 38 42> <anchor 483 279>;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_3_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_4_same_val_ttf(self):
"""Only GPOS; LookupType 4; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
feature xxxx {
pos base a <anchor 260 500> mark @MARKS_ABOVE;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_4_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_4_diff_val_ttf(self):
"""Only GPOS; LookupType 4; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
feature xxxx {
pos base a <anchor 260 500> mark @MARKS_ABOVE;
} xxxx;
"""
fea_str_1 = """
markClass uni0303 <anchor 0 520> @MARKS_ABOVE;
feature xxxx {
pos base a <anchor 285 520> mark @MARKS_ABOVE;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_4_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_5_same_val_ttf(self):
"""Only GPOS; LookupType 5; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
markClass uni0330 <anchor 0 -50> @MARKS_BELOW;
feature xxxx {
pos ligature f_t <anchor 115 -50> mark @MARKS_BELOW
ligComponent <anchor 430 -50> mark @MARKS_BELOW;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_5_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_5_diff_val_ttf(self):
"""Only GPOS; LookupType 5; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
markClass uni0330 <anchor 0 -50> @MARKS_BELOW;
feature xxxx {
pos ligature f_t <anchor 115 -50> mark @MARKS_BELOW
ligComponent <anchor 430 -50> mark @MARKS_BELOW;
} xxxx;
"""
fea_str_1 = """
markClass uni0330 <anchor 0 -20> @MARKS_BELOW;
feature xxxx {
pos ligature f_t <anchor 173 -20> mark @MARKS_BELOW
ligComponent <anchor 577 -20> mark @MARKS_BELOW;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_5_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_6_same_val_ttf(self):
"""Only GPOS; LookupType 6; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
feature xxxx {
pos mark uni0308 <anchor 0 675> mark @MARKS_ABOVE;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_6_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_6_diff_val_ttf(self):
"""Only GPOS; LookupType 6; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
feature xxxx {
pos mark uni0308 <anchor 0 675> mark @MARKS_ABOVE;
} xxxx;
"""
fea_str_1 = """
markClass uni0303 <anchor 0 520> @MARKS_ABOVE;
feature xxxx {
pos mark uni0308 <anchor 0 730> mark @MARKS_ABOVE;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_6_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_7_same_val_ttf(self):
"""Only GPOS; LookupType 7; same values in all masters.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
lookup CNTXT_PAIR_POS {
pos A a -23;
} CNTXT_PAIR_POS;
lookup CNTXT_MARK_TO_BASE {
pos base a <anchor 260 500> mark @MARKS_ABOVE;
} CNTXT_MARK_TO_BASE;
feature xxxx {
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
} xxxx;
"""
features = [fea_str] * 2
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_7_same.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_GPOS_only_LookupType_7_diff_val_ttf(self):
"""Only GPOS; LookupType 7; different values in each master.
"""
suffix = '.ttf'
ds_path = self.get_test_input('InterpolateLayout.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
fea_str_0 = """
markClass uni0303 <anchor 0 500> @MARKS_ABOVE;
lookup CNTXT_PAIR_POS {
pos A a -23;
} CNTXT_PAIR_POS;
lookup CNTXT_MARK_TO_BASE {
pos base a <anchor 260 500> mark @MARKS_ABOVE;
} CNTXT_MARK_TO_BASE;
feature xxxx {
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
} xxxx;
"""
fea_str_1 = """
markClass uni0303 <anchor 0 520> @MARKS_ABOVE;
lookup CNTXT_PAIR_POS {
pos A a 57;
} CNTXT_PAIR_POS;
lookup CNTXT_MARK_TO_BASE {
pos base a <anchor 285 520> mark @MARKS_ABOVE;
} CNTXT_MARK_TO_BASE;
feature xxxx {
pos A' lookup CNTXT_PAIR_POS a' @MARKS_ABOVE' lookup CNTXT_MARK_TO_BASE;
} xxxx;
"""
features = [fea_str_0, fea_str_1]
self.temp_dir()
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily2-')
for i, path in enumerate(ttx_paths):
self.compile_font(path, suffix, self.tempdir, features[i])
finder = lambda s: s.replace(ufo_dir, self.tempdir).replace('.ufo', suffix)
instfont = interpolate_layout(ds_path, {'weight': 500}, finder)
tables = ['GPOS']
expected_ttx_path = self.get_test_output('InterpolateLayoutGPOS_7_diff.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
self.check_ttx_dump(instfont, expected_ttx_path, tables, suffix)
def test_varlib_interpolate_layout_main_ttf(self):
"""Mostly for testing varLib.interpolate_layout.main()
"""
suffix = '.ttf'
ds_path = self.get_test_input('Build.designspace')
ufo_dir = self.get_test_input('master_ufo')
ttx_dir = self.get_test_input('master_ttx_interpolatable_ttf')
self.temp_dir()
ttf_dir = os.path.join(self.tempdir, 'master_ttf_interpolatable')
os.makedirs(ttf_dir)
ttx_paths = self.get_file_list(ttx_dir, '.ttx', 'TestFamily-')
for path in ttx_paths:
self.compile_font(path, suffix, ttf_dir)
finder = lambda s: s.replace(ufo_dir, ttf_dir).replace('.ufo', suffix)
varfont, _, _ = build(ds_path, finder)
varfont_name = 'InterpolateLayoutMain'
varfont_path = os.path.join(self.tempdir, varfont_name + suffix)
varfont.save(varfont_path)
ds_copy = os.path.splitext(varfont_path)[0] + '.designspace'
shutil.copy2(ds_path, ds_copy)
args = [ds_copy, 'weight=500', 'contrast=50']
interpolate_layout_main(args)
instfont_path = os.path.splitext(varfont_path)[0] + '-instance' + suffix
instfont = TTFont(instfont_path)
tables = [table_tag for table_tag in instfont.keys() if table_tag != 'head']
expected_ttx_path = self.get_test_output(varfont_name + '.ttx')
self.expect_ttx(instfont, expected_ttx_path, tables)
if __name__ == "__main__":
sys.exit(unittest.main())