Drop GPOS Device tables / anchor contour points if not hinting
diff --git a/pyotlss.py b/pyotlss.py
index 3b07ab3..8a6a6af 100755
--- a/pyotlss.py
+++ b/pyotlss.py
@@ -41,6 +41,10 @@
def wrapper(method):
for clazz in clazzes:
assert clazz.__name__ != 'DefaultTable', 'Oops, table class not found.'
+ assert not hasattr(clazz, method.func_name) or \
+ len([c for c in clazzes if c == clazz or c in clazz.__bases__]) > 1, \
+ "Oops, class '%s' has method '%s'." % (clazz.__name__,
+ method.func_name)
setattr(clazz, method.func_name, method)
return None
return wrapper
@@ -231,6 +235,13 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.SinglePos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ # Drop device tables
+ self.ValueFormat &= ~0x00F0
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.PairPos)
def subset_glyphs(self, s):
if self.Format == 1:
@@ -257,6 +268,14 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.PairPos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ # Drop device tables
+ self.ValueFormat1 &= ~0x00F0
+ self.ValueFormat2 &= ~0x00F0
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.CursivePos)
def subset_glyphs(self, s):
if self.Format == 1:
@@ -267,6 +286,19 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.Anchor)
+def prune_hints(self):
+ # Drop device tables / contour anchor point
+ self.Format = 1
+
+@_add_method(fontTools.ttLib.tables.otTables.CursivePos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ for rec in self.EntryExitRecord:
+ if rec.EntryAnchor: rec.EntryAnchor.prune_hints()
+ if rec.ExitAnchor: rec.ExitAnchor.prune_hints()
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.MarkBasePos)
def subset_glyphs(self, s):
if self.Format == 1:
@@ -291,6 +323,16 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.MarkBasePos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ for m in self.MarkArray.MarkRecord:
+ m.MarkAnchor.prune_hints()
+ for b in self.BaseArray.BaseRecord:
+ for a in b.BaseAnchor:
+ a.prune_hints()
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.MarkLigPos)
def subset_glyphs(self, s):
if self.Format == 1:
@@ -316,6 +358,17 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.MarkLigPos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ for m in self.MarkArray.MarkRecord:
+ m.MarkAnchor.prune_hints()
+ for l in self.LigatureArray.LigatureAttach:
+ for c in l.ComponentRecord:
+ for a in c.LigatureAnchor:
+ a.prune_hints()
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.MarkMarkPos)
def subset_glyphs(self, s):
if self.Format == 1:
@@ -340,6 +393,17 @@
else:
assert 0, "unknown format: %s" % self.Format
+@_add_method(fontTools.ttLib.tables.otTables.MarkMarkPos)
+def prune_post_subset(self, options):
+ if not options.hinting:
+ # Drop device tables or contour anchor point
+ for m in self.Mark1Array.MarkRecord:
+ m.MarkAnchor.prune_hints()
+ for b in self.Mark2Array.Mark2Record:
+ for m in rec.Mark2Anchor:
+ m.prune_hints()
+ return True
+
@_add_method(fontTools.ttLib.tables.otTables.SingleSubst,
fontTools.ttLib.tables.otTables.MultipleSubst,
fontTools.ttLib.tables.otTables.AlternateSubst,
@@ -369,6 +433,36 @@
return []
@_add_method(fontTools.ttLib.tables.otTables.SingleSubst,
+ fontTools.ttLib.tables.otTables.MultipleSubst,
+ fontTools.ttLib.tables.otTables.AlternateSubst,
+ fontTools.ttLib.tables.otTables.LigatureSubst,
+ fontTools.ttLib.tables.otTables.ContextSubst,
+ fontTools.ttLib.tables.otTables.ChainContextSubst,
+ fontTools.ttLib.tables.otTables.ReverseChainSingleSubst,
+ fontTools.ttLib.tables.otTables.SinglePos,
+ fontTools.ttLib.tables.otTables.PairPos,
+ fontTools.ttLib.tables.otTables.CursivePos,
+ fontTools.ttLib.tables.otTables.MarkBasePos,
+ fontTools.ttLib.tables.otTables.MarkLigPos,
+ fontTools.ttLib.tables.otTables.MarkMarkPos,
+ fontTools.ttLib.tables.otTables.ContextPos,
+ fontTools.ttLib.tables.otTables.ChainContextPos)
+def prune_pre_subset(self, options):
+ return True
+
+@_add_method(fontTools.ttLib.tables.otTables.SingleSubst,
+ fontTools.ttLib.tables.otTables.MultipleSubst,
+ fontTools.ttLib.tables.otTables.AlternateSubst,
+ fontTools.ttLib.tables.otTables.LigatureSubst,
+ fontTools.ttLib.tables.otTables.ReverseChainSingleSubst,
+ fontTools.ttLib.tables.otTables.ContextSubst,
+ fontTools.ttLib.tables.otTables.ChainContextSubst,
+ fontTools.ttLib.tables.otTables.ContextPos,
+ fontTools.ttLib.tables.otTables.ChainContextPos)
+def prune_post_subset(self, options):
+ return True
+
+@_add_method(fontTools.ttLib.tables.otTables.SingleSubst,
fontTools.ttLib.tables.otTables.AlternateSubst,
fontTools.ttLib.tables.otTables.ReverseChainSingleSubst)
def may_have_non_1to1(self):
@@ -677,6 +771,14 @@
@_add_method(fontTools.ttLib.tables.otTables.ExtensionSubst,
fontTools.ttLib.tables.otTables.ExtensionPos)
+def prune_pre_subset(self, options):
+ if self.Format == 1:
+ return self.ExtSubTable.prune_pre_subset(options)
+ else:
+ assert 0, "unknown format: %s" % self.Format
+
+@_add_method(fontTools.ttLib.tables.otTables.ExtensionSubst,
+ fontTools.ttLib.tables.otTables.ExtensionPos)
def subset_glyphs(self, s):
if self.Format == 1:
return self.ExtSubTable.subset_glyphs(s)
@@ -685,6 +787,14 @@
@_add_method(fontTools.ttLib.tables.otTables.ExtensionSubst,
fontTools.ttLib.tables.otTables.ExtensionPos)
+def prune_post_subset(self, options):
+ if self.Format == 1:
+ return self.ExtSubTable.prune_post_subset(options)
+ else:
+ assert 0, "unknown format: %s" % self.Format
+
+@_add_method(fontTools.ttLib.tables.otTables.ExtensionSubst,
+ fontTools.ttLib.tables.otTables.ExtensionPos)
def subset_lookups(self, lookup_indices):
if self.Format == 1:
return self.ExtSubTable.subset_lookups(lookup_indices)
@@ -706,12 +816,28 @@
st.closure_glyphs(s, cur_glyphs)
@_add_method(fontTools.ttLib.tables.otTables.Lookup)
+def prune_pre_subset(self, options):
+ ret = False
+ for st in self.SubTable:
+ if not st: continue
+ if st.prune_pre_subset(options): ret = True
+ return ret
+
+@_add_method(fontTools.ttLib.tables.otTables.Lookup)
def subset_glyphs(self, s):
self.SubTable = [st for st in self.SubTable if st and st.subset_glyphs(s)]
self.SubTableCount = len(self.SubTable)
return bool(self.SubTableCount)
@_add_method(fontTools.ttLib.tables.otTables.Lookup)
+def prune_post_subset(self, options):
+ ret = False
+ for st in self.SubTable:
+ if not st: continue
+ if st.prune_post_subset(options): ret = True
+ return ret
+
+@_add_method(fontTools.ttLib.tables.otTables.Lookup)
def subset_lookups(self, lookup_indices):
for s in self.SubTable:
s.subset_lookups(lookup_indices)
@@ -726,11 +852,27 @@
return any(st.may_have_non_1to1() for st in self.SubTable if st)
@_add_method(fontTools.ttLib.tables.otTables.LookupList)
+def prune_pre_subset(self, options):
+ ret = False
+ for l in self.Lookup:
+ if not l: continue
+ if l.prune_pre_subset(options): ret = True
+ return ret
+
+@_add_method(fontTools.ttLib.tables.otTables.LookupList)
def subset_glyphs(self, s):
"Returns the indices of nonempty lookups."
return [i for i,l in enumerate(self.Lookup) if l and l.subset_glyphs(s)]
@_add_method(fontTools.ttLib.tables.otTables.LookupList)
+def prune_post_subset(self, options):
+ ret = False
+ for l in self.Lookup:
+ if not l: continue
+ if l.prune_post_subset(options): ret = True
+ return ret
+
+@_add_method(fontTools.ttLib.tables.otTables.LookupList)
def subset_lookups(self, lookup_indices):
self.Lookup = [self.Lookup[i] for i in lookup_indices
if i < self.LookupCount]
@@ -895,6 +1037,13 @@
if '*' not in options.layout_features:
self.subset_feature_tags(options.layout_features)
self.prune_lookups()
+ self.table.LookupList.prune_pre_subset(options);
+ return True
+
+@_add_method(fontTools.ttLib.getTableClass('GSUB'),
+ fontTools.ttLib.getTableClass('GPOS'))
+def prune_post_subset(self, options):
+ self.table.LookupList.prune_post_subset(options);
return True
@_add_method(fontTools.ttLib.getTableClass('GDEF'))
@@ -1333,7 +1482,6 @@
# TODO(behdad) Avoid recursing too much (in GSUB/GPOS and in CFF)
# TODO(behdad) Text direction considerations.
# TODO(behdad) Text script / language considerations.
-# TODO(behdad) Drop GPOS Device records if not hinting?
# TODO(behdad) Move font name loading hack to Subsetter?