diff --git a/Lib/fontTools/subset/__init__.py b/Lib/fontTools/subset/__init__.py
index 9b7c3e937..4da48c73a 100644
--- a/Lib/fontTools/subset/__init__.py
+++ b/Lib/fontTools/subset/__init__.py
@@ -13,6 +13,7 @@ import sys
import struct
import array
import logging
+from collections import Counter
from types import MethodType
__usage__ = "pyftsubset font-file [glyph...] [--option=value]..."
@@ -1704,6 +1705,26 @@ def subset_glyphs(self, s):
self.extraNames = [] # This seems to do it
return True # Required table
+@_add_method(ttLib.getTableClass('prop'))
+def subset_glyphs(self, s):
+ prop = self.table.GlyphProperties
+ if prop.Format == 0:
+ return prop.DefaultProperties != 0
+ elif prop.Format == 1:
+ prop.Properties = {g: prop.Properties.get(g, prop.DefaultProperties)
+ for g in s.glyphs}
+ mostCommon, _cnt = Counter(prop.Properties.values()).most_common(1)[0]
+ prop.DefaultProperties = mostCommon
+ prop.Properties = {g: prop for g, prop in prop.Properties.items()
+ if prop != mostCommon}
+ if len(prop.Properties) == 0:
+ del prop.Properties
+ prop.Format = 0
+ return prop.DefaultProperties != 0
+ return True
+ else:
+ assert False, "unknown 'prop' format %s" % prop.Format
+
@_add_method(ttLib.getTableClass('COLR'))
def closure_glyphs(self, s):
decompose = s.glyphs
diff --git a/Tests/subset/data/TestPROP.ttx b/Tests/subset/data/TestPROP.ttx
new file mode 100644
index 000000000..c783fced0
--- /dev/null
+++ b/Tests/subset/data/TestPROP.ttx
@@ -0,0 +1,322 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TestPROP
+
+
+ Regular
+
+
+ TestPROP
+
+
+ TestPROP-Regular
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/subset/data/expect_prop_0.ttx b/Tests/subset/data/expect_prop_0.ttx
new file mode 100644
index 000000000..f8ca15093
--- /dev/null
+++ b/Tests/subset/data/expect_prop_0.ttx
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/subset/data/expect_prop_1.ttx b/Tests/subset/data/expect_prop_1.ttx
new file mode 100644
index 000000000..f7f2d23c6
--- /dev/null
+++ b/Tests/subset/data/expect_prop_1.ttx
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/subset/subset_test.py b/Tests/subset/subset_test.py
index 938bd8585..0faba5047 100644
--- a/Tests/subset/subset_test.py
+++ b/Tests/subset/subset_test.py
@@ -123,6 +123,41 @@ class SubsetTest(unittest.TestCase):
subsetfont = TTFont(subsetpath)
self.expect_ttx(subsetfont, self.getpath("expect_keep_math.ttx"), ["GlyphOrder", "CFF ", "MATH", "hmtx"])
+ def test_subset_prop_remove_default_zero(self):
+ # If all glyphs have an AAT glyph property with value 0,
+ # the "prop" table should be removed from the subsetted font.
+ _, fontpath = self.compile_font(self.getpath("TestPROP.ttx"), ".ttf")
+ subsetpath = self.temp_path(".ttf")
+ subset.main([fontpath, "--unicodes=U+0041",
+ "--output-file=%s" % subsetpath])
+ subsetfont = TTFont(subsetpath)
+ self.assertNotIn("prop", subsetfont)
+
+ def test_subset_prop_0(self):
+ # If all glyphs share the same AAT glyph properties, the "prop" table
+ # in the subsetted font should use format 0.
+ #
+ # Unless the shared value is zero, in which case the subsetted font
+ # should have no "prop" table at all. But that case has already been
+ # tested above in test_subset_prop_remove_default_zero().
+ _, fontpath = self.compile_font(self.getpath("TestPROP.ttx"), ".ttf")
+ subsetpath = self.temp_path(".ttf")
+ subset.main([fontpath, "--unicodes=U+0030-0032", "--no-notdef-glyph",
+ "--output-file=%s" % subsetpath])
+ subsetfont = TTFont(subsetpath)
+ self.expect_ttx(subsetfont, self.getpath("expect_prop_0.ttx"), ["prop"])
+
+ def test_subset_prop_1(self):
+ # If not all glyphs share the same AAT glyph properties, the subsetted
+ # font should contain a "prop" table in format 1. To save space, the
+ # DefaultProperties should be set to the most frequent value.
+ _, fontpath = self.compile_font(self.getpath("TestPROP.ttx"), ".ttf")
+ subsetpath = self.temp_path(".ttf")
+ subset.main([fontpath, "--unicodes=U+0030-0032", "--notdef-outline",
+ "--output-file=%s" % subsetpath])
+ subsetfont = TTFont(subsetpath)
+ self.expect_ttx(subsetfont, self.getpath("expect_prop_1.ttx"), ["prop"])
+
def test_options(self):
# https://github.com/behdad/fonttools/issues/413
opt1 = subset.Options()