From 890c5061b5058c5de08b12a5bf54c161bac3d25e Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Mon, 11 May 2020 13:32:18 +0100 Subject: [PATCH 1/2] subset: fix issue subsetting Context{Subst,Pos}Format3 Fixes https://github.com/fonttools/fonttools/issues/1879 In ChainContext{Subst,Pos}Format3, the array of input coverages is called InputCoverage, whereas in non-Chain Context{Subst,Pos}Format3 subtables it is called simply Coverage. --- Lib/fontTools/subset/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/fontTools/subset/__init__.py b/Lib/fontTools/subset/__init__.py index 0119a92bd..701c1aa25 100644 --- a/Lib/fontTools/subset/__init__.py +++ b/Lib/fontTools/subset/__init__.py @@ -894,6 +894,8 @@ def __subset_classify_context(self): self.ClassDef = 'InputClassDef' if Chain else 'ClassDef' self.ClassDefIndex = 1 if Chain else 0 self.Input = 'Input' if Chain else 'Class' + elif Format == 3: + self.Input = 'InputCoverage' if Chain else 'Coverage' if self.Format not in [1, 2, 3]: return None # Don't shoot the messenger; let it go @@ -976,6 +978,7 @@ def closure_glyphs(self, s, cur_glyphs): if not all(x.intersect(s.glyphs) for x in c.RuleData(self)): return [] r = self + input_coverages = getattr(r, c.Input) chaos = set() for ll in getattr(r, c.LookupRecord): if not ll: continue @@ -987,11 +990,11 @@ def closure_glyphs(self, s, cur_glyphs): if seqi == 0: pos_glyphs = frozenset(cur_glyphs) else: - pos_glyphs = frozenset(r.InputCoverage[seqi].intersect_glyphs(s.glyphs)) + pos_glyphs = frozenset(input_coverages[seqi].intersect_glyphs(s.glyphs)) lookup = s.table.LookupList.Lookup[ll.LookupListIndex] chaos.add(seqi) if lookup.may_have_non_1to1(): - chaos.update(range(seqi, len(r.InputCoverage)+1)) + chaos.update(range(seqi, len(input_coverages)+1)) lookup.closure_glyphs(s, cur_glyphs=pos_glyphs) else: assert 0, "unknown format: %s" % self.Format From 8bbf30d569c716f4cae701d3cdd02eddee3e0b17 Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Mon, 11 May 2020 18:32:32 +0100 Subject: [PATCH 2/2] subset_test: add subset of Iosekva-Medium.ttf with ContextSubstFormat3 --- LICENSE.external | 4 + Tests/subset/data/TestContextSubstFormat3.ttx | 610 ++++++++++++++++++ Tests/subset/subset_test.py | 13 +- 3 files changed, 626 insertions(+), 1 deletion(-) create mode 100644 Tests/subset/data/TestContextSubstFormat3.ttx diff --git a/LICENSE.external b/LICENSE.external index 88a0272f5..2bc4dab3e 100644 --- a/LICENSE.external +++ b/LICENSE.external @@ -26,6 +26,10 @@ XITS font project This Font Software is licensed under the SIL Open Font License, Version 1.1. +Iosevka + Copyright (c) 2015-2020 Belleve Invis (belleve@typeof.net). + This Font Software is licensed under the SIL Open Font License, Version 1.1. + This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL diff --git a/Tests/subset/data/TestContextSubstFormat3.ttx b/Tests/subset/data/TestContextSubstFormat3.ttx new file mode 100644 index 000000000..899b037e3 --- /dev/null +++ b/Tests/subset/data/TestContextSubstFormat3.ttx @@ -0,0 +1,610 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Copyright (c) 2015-2019 Belleve Invis. + + + Iosevka Medium + + + Regular + + + Iosevka Medium Version 3.0.0-rc.8 + + + Iosevka Medium + + + Version 3.0.0-rc.8; ttfautohint (v1.8.3) + + + Iosevka-Medium + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/subset_test.py b/Tests/subset/subset_test.py index 2493daff1..2cce9baf5 100644 --- a/Tests/subset/subset_test.py +++ b/Tests/subset/subset_test.py @@ -56,7 +56,7 @@ class SubsetTest(unittest.TestCase): lines.append(line.rstrip() + os.linesep) return lines - def expect_ttx(self, font, expected_ttx, tables): + def expect_ttx(self, font, expected_ttx, tables=None): path = self.temp_path(suffix=".ttx") font.saveXML(path, tables=tables) actual = self.read_ttx(path) @@ -732,6 +732,17 @@ class SubsetTest(unittest.TestCase): self.assertEqual(ttf.flavor, None) + def test_subset_context_subst_format_3(self): + # https://github.com/fonttools/fonttools/issues/1879 + # Test font contains 'calt' feature with Format 3 ContextSubst lookup subtables + ttx = self.getpath("TestContextSubstFormat3.ttx") + font, fontpath = self.compile_font(ttx, ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--unicodes=*", "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + # check all glyphs are kept via GSUB closure, no changes expected + self.expect_ttx(subsetfont, ttx) + @pytest.fixture def featureVarsTestFont():