Implement last remaining Context format
Used by OldStandard.ttf.
diff --git a/pyotlss.py b/pyotlss.py
index 11c3f1e..d5499a1 100755
--- a/pyotlss.py
+++ b/pyotlss.py
@@ -45,6 +45,16 @@
return indices
@add_method(fontTools.ttLib.tables.otTables.ClassDef)
+def intersect_glyphs (self, glyphs):
+ "Returns ascending list of matching class values."
+ return unique_sorted (v for g,v in self.classDefs.items() if g in glyphs)
+
+@add_method(fontTools.ttLib.tables.otTables.ClassDef)
+def intersects_glyphs_class (self, glyphs, klass):
+ "Returns true if any of glyphs has requested class."
+ return any (g in glyphs for g,v in self.classDefs.items() if v == klass)
+
+@add_method(fontTools.ttLib.tables.otTables.ClassDef)
def subset_glyphs (self, glyphs):
"Returns ascending list of remaining classes."
self.classDefs = {g:v for g,v in self.classDefs.items() if g in glyphs}
@@ -309,34 +319,59 @@
self.RuleCount = ChainTyp+'RuleCount'
self.RuleSet = ChainTyp+'RuleSet'
self.RuleSetCount = ChainTyp+'RuleSetCount'
- def ContextData (r, Format):
+ def ContextData (r):
+ if r.Format == 1:
+ assert 0
+ return r.Input
+ elif r.Format == 2:
+ return [r.ClassDef]
+ elif r.Format == 3:
+ assert 0
+ return r.Coverage
+ else:
+ assert 0, "unknown format: %s" % r.Format
+ def ChainContextData (r):
+ if r.Format == 1:
+ assert 0
+ return r.Backtrack + r.Input + r.LookAhead
+ elif r.Format == 2:
+ return [r.LookAheadClassDef, r.InputClassDef, r.BacktrackClassDef]
+ elif r.Format == 3:
+ assert 0
+ return r.LookAheadCoverage + r.InputCoverage + r.BacktrackCoverage
+ else:
+ assert 0, "unknown format: %s" % Format
+ def RuleData (r, Format):
if Format == 1:
return r.Input
elif Format == 2:
- return [r.ClassDef]
+ return [r.Class]
elif Format == 3:
return r.Coverage
else:
assert 0, "unknown format: %s" % Format
- def ChainContextData (r, Format):
+ def ChainRuleData (r, Format):
if Format == 1:
return r.Backtrack + r.Input + r.LookAhead
elif Format == 2:
- return [r.LookAheadClassDef, r.BacktrackClassDef, r.InputClassDef]
+ return [r.LookAhead, r.Input, r.Backtrack]
elif Format == 3:
- return r.InputCoverage + r.LookAheadCoverage + r.BacktrackCoverage
+ return r.LookAheadCoverage + r.InputCoverage + r.BacktrackCoverage
else:
assert 0, "unknown format: %s" % Format
if Chain:
self.ContextData = ChainContextData
+ self.RuleData = ChainRuleData
else:
self.ContextData = ContextData
+ self.RuleData = RuleData
# Format 2
self.ClassRule = ChainTyp+'ClassRule'
self.ClassRuleCount = ChainTyp+'ClassRuleCount'
self.ClassRuleSet = ChainTyp+'ClassSet'
self.ClassRuleSetCount = ChainTyp+'ClassSetCount'
+ self.ClassDef = 'InputClassDef' if Chain else 'ClassDef'
if not hasattr (self.__class__, "__ContextContext"):
self.__class__.__ContextContext = ContextContext (self)
@@ -352,13 +387,21 @@
return sum ((table.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs (glyphs, table) \
for i in indices \
for r in getattr (rss[i], c.Rule) \
- if r and all (g in glyphs for g in c.ContextData (r, self.Format)) \
+ if r and all (g in glyphs for g in c.RuleData (r, self.Format)) \
for ll in getattr (r, c.LookupRecord) if ll \
), [])
elif self.Format == 2:
- assert 0 # XXX
+ indices = getattr (self, c.ClassDef).intersect_glyphs (glyphs)
+ rss = getattr (self, c.ClassRuleSet)
+ return sum ((table.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs (glyphs, table) \
+ for i in indices \
+ for r in getattr (rss[i], c.ClassRule) \
+ if r and all (cd.intersects_glyphs_class (glyphs, k) \
+ for cd,k in zip (c.ContextData (self), c.RuleData (r, self.Format))) \
+ for ll in getattr (r, c.LookupRecord) if ll \
+ ), [])
elif self.Format == 3:
- if not all (x.intersect_glyphs (glyphs) for x in c.ContextData (self, self.Format)):
+ if not all (x.intersect_glyphs (glyphs) for x in c.RuleData (self, self.Format)):
return []
return sum ((table.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs (glyphs, table) \
for ll in getattr (self, c.LookupRecord) if ll), [])
@@ -378,7 +421,7 @@
if rs:
ss = getattr (rs, c.Rule)
ss = [r for r in ss \
- if r and all (g in glyphs for g in c.ContextData (r, self.Format))]
+ if r and all (g in glyphs for g in c.RuleData (r, self.Format))]
setattr (rs, c.Rule, ss)
setattr (rs, c.RuleCount, len (ss))
# Prune empty subrulesets
@@ -390,9 +433,9 @@
# TODO Renumber classes then prune rules that can't apply
# But then I first need to find fonts that use this type. D'oh!
return self.Coverage.subset_glyphs (glyphs) and \
- all (x.subset_glyphs (glyphs) for x in c.ContextData (self, self.Format))
+ all (x.subset_glyphs (glyphs) for x in c.ContextData (self))
elif self.Format == 3:
- return all (x.subset_glyphs (glyphs) for x in c.ContextData (self, self.Format))
+ return all (x.subset_glyphs (glyphs) for x in c.RuleData (self, self.Format))
else:
assert 0, "unknown format: %s" % self.Format
@@ -824,7 +867,6 @@
# TODO OS/2 ulUnicodeRange / ulCodePageRange?
# TODO Drop unneeded GSUB/GPOS Script/LangSys entries
-# TODO Finish GSUB glyph closure
# TODO Avoid recursing too much
# TODO Text direction considerations
# TODO Text script / language considerations