From 307d0d4c57ccbd1e4b72adc000764c9acd6fff74 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Fri, 25 Aug 2017 22:01:14 +0200 Subject: [PATCH] [AAT] Implement subsetting of baseline table --- Lib/fontTools/subset/__init__.py | 46 +++- Tests/subset/data/TestBSLN-0.ttx | 342 ++++++++++++++++++++++++++ Tests/subset/data/TestBSLN-1.ttx | 348 ++++++++++++++++++++++++++ Tests/subset/data/TestBSLN-2.ttx | 342 ++++++++++++++++++++++++++ Tests/subset/data/TestBSLN-3.ttx | 363 ++++++++++++++++++++++++++++ Tests/subset/data/expect_bsln_0.ttx | 43 ++++ Tests/subset/data/expect_bsln_1.ttx | 46 ++++ Tests/subset/data/expect_bsln_2.ttx | 44 ++++ Tests/subset/data/expect_bsln_3.ttx | 47 ++++ Tests/subset/subset_test.py | 78 ++++++ 10 files changed, 1688 insertions(+), 11 deletions(-) create mode 100644 Tests/subset/data/TestBSLN-0.ttx create mode 100644 Tests/subset/data/TestBSLN-1.ttx create mode 100644 Tests/subset/data/TestBSLN-2.ttx create mode 100644 Tests/subset/data/TestBSLN-3.ttx create mode 100644 Tests/subset/data/expect_bsln_0.ttx create mode 100644 Tests/subset/data/expect_bsln_1.ttx create mode 100644 Tests/subset/data/expect_bsln_2.ttx create mode 100644 Tests/subset/data/expect_bsln_3.ttx diff --git a/Lib/fontTools/subset/__init__.py b/Lib/fontTools/subset/__init__.py index b4ff4063a..3b23e9b01 100644 --- a/Lib/fontTools/subset/__init__.py +++ b/Lib/fontTools/subset/__init__.py @@ -1675,6 +1675,30 @@ def subset_glyphs(self, s): self.hdmx = {sz:_dict_subset(l, s.glyphs) for sz,l in self.hdmx.items()} return bool(self.hdmx) +@_add_method(ttLib.getTableClass('bsln')) +def closure_glyphs(self, s): + table = self.table.Baseline + if table.Format in (2, 3): + s.glyphs.add(table.StandardGlyph) + +@_add_method(ttLib.getTableClass('bsln')) +def subset_glyphs(self, s): + table = self.table.Baseline + if table.Format in (1, 3): + baselines = {glyph: table.BaselineValues.get(glyph, table.DefaultBaseline) + for glyph in s.glyphs} + if len(baselines) > 0: + mostCommon, _cnt = Counter(baselines.values()).most_common(1)[0] + table.DefaultBaseline = mostCommon + baselines = {glyph: b for glyph, b in baselines.items() + if b != mostCommon} + if len(baselines) > 0: + table.BaselineValues = baselines + else: + table.Format = {1: 0, 3: 2}[table.Format] + del table.BaselineValues + return True + @_add_method(ttLib.getTableClass('lcar')) def subset_glyphs(self, s): table = self.table.LigatureCarets @@ -2797,17 +2821,17 @@ class Subsetter(object): log.glyphs(self.glyphs, font=font) self.glyphs_mathed = frozenset(self.glyphs) - if 'COLR' in font: - with timer("close glyph list over 'COLR'"): - log.info("Closing glyph list over 'COLR': %d glyphs before", - len(self.glyphs)) - log.glyphs(self.glyphs, font=font) - font['COLR'].closure_glyphs(self) - self.glyphs.intersection_update(realGlyphs) - log.info("Closed glyph list over 'COLR': %d glyphs after", - len(self.glyphs)) - log.glyphs(self.glyphs, font=font) - self.glyphs_colred = frozenset(self.glyphs) + for table in ('COLR', 'bsln'): + if table in font: + with timer("close glyph list over '%s'" % table): + log.info("Closing glyph list over '%s': %d glyphs before", + table, len(self.glyphs)) + log.glyphs(self.glyphs, font=font) + font[table].closure_glyphs(self) + self.glyphs.intersection_update(realGlyphs) + log.info("Closed glyph list over '%s': %d glyphs after", + table, len(self.glyphs)) + log.glyphs(self.glyphs, font=font) if 'glyf' in font: with timer("close glyph list over 'glyf'"): diff --git a/Tests/subset/data/TestBSLN-0.ttx b/Tests/subset/data/TestBSLN-0.ttx new file mode 100644 index 000000000..9a446e1ac --- /dev/null +++ b/Tests/subset/data/TestBSLN-0.ttx @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TestBSLN-0 + + + Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/TestBSLN-1.ttx b/Tests/subset/data/TestBSLN-1.ttx new file mode 100644 index 000000000..3ad83a250 --- /dev/null +++ b/Tests/subset/data/TestBSLN-1.ttx @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TestBSLN-1 + + + Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/TestBSLN-2.ttx b/Tests/subset/data/TestBSLN-2.ttx new file mode 100644 index 000000000..7a005007f --- /dev/null +++ b/Tests/subset/data/TestBSLN-2.ttx @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TestBSLN-2 + + + Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/TestBSLN-3.ttx b/Tests/subset/data/TestBSLN-3.ttx new file mode 100644 index 000000000..4bba6b48d --- /dev/null +++ b/Tests/subset/data/TestBSLN-3.ttx @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TestBSLN-3 + + + Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/expect_bsln_0.ttx b/Tests/subset/data/expect_bsln_0.ttx new file mode 100644 index 000000000..89f68d426 --- /dev/null +++ b/Tests/subset/data/expect_bsln_0.ttx @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/expect_bsln_1.ttx b/Tests/subset/data/expect_bsln_1.ttx new file mode 100644 index 000000000..71e1df4cc --- /dev/null +++ b/Tests/subset/data/expect_bsln_1.ttx @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/expect_bsln_2.ttx b/Tests/subset/data/expect_bsln_2.ttx new file mode 100644 index 000000000..6d2da1820 --- /dev/null +++ b/Tests/subset/data/expect_bsln_2.ttx @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/data/expect_bsln_3.ttx b/Tests/subset/data/expect_bsln_3.ttx new file mode 100644 index 000000000..04f3f9a82 --- /dev/null +++ b/Tests/subset/data/expect_bsln_3.ttx @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/subset/subset_test.py b/Tests/subset/subset_test.py index 82673bb29..09aa83429 100644 --- a/Tests/subset/subset_test.py +++ b/Tests/subset/subset_test.py @@ -95,6 +95,84 @@ class SubsetTest(unittest.TestCase): subsetfont = TTFont(subsetpath) self.expect_ttx(subsetfont, self.getpath("expect_no_notdef_outline_ttf.ttx"), ["glyf", "hmtx"]) + def test_subset_bsln_format_0(self): + _, fontpath = self.compile_font(self.getpath("TestBSLN-0.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--glyphs=one", "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_0.ttx"), ["bsln"]) + + def test_subset_bsln_format_0_from_format_1(self): + # TestBSLN-1 defines the ideographic baseline to be the font's default, + # and specifies that glyphs {.notdef, zero, one, two} use the roman + # baseline instead of the default ideographic baseline. As we request + # a subsetted font with {zero, one} and the implicit .notdef, all + # glyphs in the resulting font use the Roman baseline. In this case, + # we expect a format 0 'bsln' table because it is the most compact. + _, fontpath = self.compile_font(self.getpath("TestBSLN-1.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--unicodes=U+0030-0031", + "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_0.ttx"), ["bsln"]) + + def test_subset_bsln_format_1(self): + # TestBSLN-1 defines the ideographic baseline to be the font's default, + # and specifies that glyphs {.notdef, zero, one, two} use the roman + # baseline instead of the default ideographic baseline. We request + # a subset where the majority of glyphs use the roman baseline, + # but one single glyph (uni2EA2) is ideographic. In the resulting + # subsetted font, we expect a format 1 'bsln' table whose default + # is Roman, but with an override that uses the ideographic baseline + # for uni2EA2. + _, fontpath = self.compile_font(self.getpath("TestBSLN-1.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--unicodes=U+0030-0031,U+2EA2", + "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_1.ttx"), ["bsln"]) + + def test_subset_bsln_format_2(self): + # The 'bsln' table in TestBSLN-2 refers to control points in glyph 'P' + # for defining its baselines. Therefore, the subsetted font should + # include this glyph even though it is not requested explicitly. + _, fontpath = self.compile_font(self.getpath("TestBSLN-2.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--glyphs=one", "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_2.ttx"), ["bsln"]) + + def test_subset_bsln_format_2_from_format_3(self): + # TestBSLN-3 defines the ideographic baseline to be the font's default, + # and specifies that glyphs {.notdef, zero, one, two, P} use the roman + # baseline instead of the default ideographic baseline. As we request + # a subsetted font with zero and the implicit .notdef and P for + # baseline measurement, all glyphs in the resulting font use the Roman + # baseline. In this case, we expect a format 2 'bsln' table because it + # is the most compact encoding. + _, fontpath = self.compile_font(self.getpath("TestBSLN-3.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--unicodes=U+0030", + "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_2.ttx"), ["bsln"]) + + def test_subset_bsln_format_3(self): + # TestBSLN-3 defines the ideographic baseline to be the font's default, + # and specifies that glyphs {.notdef, zero, one, two} use the roman + # baseline instead of the default ideographic baseline. We request + # a subset where the majority of glyphs use the roman baseline, + # but one single glyph (uni2EA2) is ideographic. In the resulting + # subsetted font, we expect a format 1 'bsln' table whose default + # is Roman, but with an override that uses the ideographic baseline + # for uni2EA2. + _, fontpath = self.compile_font(self.getpath("TestBSLN-3.ttx"), ".ttf") + subsetpath = self.temp_path(".ttf") + subset.main([fontpath, "--unicodes=U+0030-0031,U+2EA2", + "--output-file=%s" % subsetpath]) + subsetfont = TTFont(subsetpath) + self.expect_ttx(subsetfont, self.getpath("expect_bsln_3.ttx"), ["bsln"]) + def test_subset_clr(self): _, fontpath = self.compile_font(self.getpath("TestCLR-Regular.ttx"), ".ttf") subsetpath = self.temp_path(".ttf")