Improve subsetting of Context formats
When recursing for closure, just pass down glyphs that could have actually matched the rule. This can result in wrong results if the recursed lookup is NOT one-to-one. Fix coming. In the mean time, test with NotoSansDevanagari-Bold.ttf and chars uni91f,uni94d,uni930 to see the difference.
This commit is contained in:
parent
6c11b894f3
commit
849d25c95d
100
pyotlss.py
100
pyotlss.py
@ -49,6 +49,11 @@ def intersect (self, glyphs):
|
|||||||
"Returns ascending list of matching coverage values."
|
"Returns ascending list of matching coverage values."
|
||||||
return [i for (i,g) in enumerate (self.glyphs) if g in glyphs]
|
return [i for (i,g) in enumerate (self.glyphs) if g in glyphs]
|
||||||
|
|
||||||
|
@add_method(fontTools.ttLib.tables.otTables.Coverage)
|
||||||
|
def intersect_glyphs (self, glyphs):
|
||||||
|
"Returns set of intersecting glyphs."
|
||||||
|
return set (g for g in self.glyphs if g in glyphs)
|
||||||
|
|
||||||
@add_method(fontTools.ttLib.tables.otTables.Coverage)
|
@add_method(fontTools.ttLib.tables.otTables.Coverage)
|
||||||
def subset (self, glyphs):
|
def subset (self, glyphs):
|
||||||
"Returns ascending list of remaining coverage values."
|
"Returns ascending list of remaining coverage values."
|
||||||
@ -68,14 +73,11 @@ def intersect (self, glyphs):
|
|||||||
[v for g,v in self.classDefs.items() if g in glyphs])
|
[v for g,v in self.classDefs.items() if g in glyphs])
|
||||||
|
|
||||||
@add_method(fontTools.ttLib.tables.otTables.ClassDef)
|
@add_method(fontTools.ttLib.tables.otTables.ClassDef)
|
||||||
def intersects_class (self, glyphs, klass):
|
def intersect_class (self, glyphs, klass):
|
||||||
"Returns true if any of glyphs has requested class."
|
"Returns set of glyphs matching class."
|
||||||
assert isinstance (klass, int)
|
|
||||||
if klass == 0:
|
if klass == 0:
|
||||||
if any (g not in self.classDefs for g in glyphs):
|
return set (g for g in glyphs if g not in self.classDefs)
|
||||||
return True
|
return set (g for g,v in self.classDefs.items() if v == klass and g in glyphs)
|
||||||
# Fall through
|
|
||||||
return any (g in glyphs for g,v in self.classDefs.items() if v == klass)
|
|
||||||
|
|
||||||
@add_method(fontTools.ttLib.tables.otTables.ClassDef)
|
@add_method(fontTools.ttLib.tables.otTables.ClassDef)
|
||||||
def subset (self, glyphs, remap=False):
|
def subset (self, glyphs, remap=False):
|
||||||
@ -362,10 +364,10 @@ def __classify_context (self):
|
|||||||
if Format == 1:
|
if Format == 1:
|
||||||
Coverage = lambda r: r.Coverage
|
Coverage = lambda r: r.Coverage
|
||||||
ChainCoverage = lambda r: r.Coverage
|
ChainCoverage = lambda r: r.Coverage
|
||||||
ContextData = None
|
ContextData = lambda r: (None,)
|
||||||
ChainContextData = None
|
ChainContextData = lambda r: (None, None, None)
|
||||||
RuleData = lambda r: r.Input
|
RuleData = lambda r: (r.Input,)
|
||||||
ChainRuleData = lambda r: r.Backtrack + r.Input + r.LookAhead
|
ChainRuleData = lambda r: (r.Backtrack, r.Input, r.LookAhead)
|
||||||
SetRuleData = None
|
SetRuleData = None
|
||||||
ChainSetRuleData = None
|
ChainSetRuleData = None
|
||||||
elif Format == 2:
|
elif Format == 2:
|
||||||
@ -405,11 +407,13 @@ def __classify_context (self):
|
|||||||
self.RuleCount = ChainTyp+'RuleCount'
|
self.RuleCount = ChainTyp+'RuleCount'
|
||||||
self.RuleSet = ChainTyp+'RuleSet'
|
self.RuleSet = ChainTyp+'RuleSet'
|
||||||
self.RuleSetCount = ChainTyp+'RuleSetCount'
|
self.RuleSetCount = ChainTyp+'RuleSetCount'
|
||||||
|
self.Intersect = lambda glyphs, ContextData, RuleData: [RuleData] if RuleData in glyphs else []
|
||||||
elif Format == 2:
|
elif Format == 2:
|
||||||
self.Rule = ChainTyp+'ClassRule'
|
self.Rule = ChainTyp+'ClassRule'
|
||||||
self.RuleCount = ChainTyp+'ClassRuleCount'
|
self.RuleCount = ChainTyp+'ClassRuleCount'
|
||||||
self.RuleSet = ChainTyp+'ClassSet'
|
self.RuleSet = ChainTyp+'ClassSet'
|
||||||
self.RuleSetCount = ChainTyp+'ClassSetCount'
|
self.RuleSetCount = ChainTyp+'ClassSetCount'
|
||||||
|
self.Intersect = lambda glyphs, ContextData, RuleData: ContextData.intersect_class (glyphs, RuleData)
|
||||||
|
|
||||||
self.ClassDef = 'InputClassDef' if Chain else 'ClassDef'
|
self.ClassDef = 'InputClassDef' if Chain else 'ClassDef'
|
||||||
|
|
||||||
@ -429,34 +433,65 @@ def closure_glyphs (self, s, cur_glyphs=None):
|
|||||||
indices = c.Coverage (self).intersect (s.glyphs)
|
indices = c.Coverage (self).intersect (s.glyphs)
|
||||||
if not indices:
|
if not indices:
|
||||||
return []
|
return []
|
||||||
cur_glyphs = set (g for g in c.Coverage (self).glyphs if g in s.glyphs)
|
cur_glyphs = c.Coverage (self).intersect_glyphs (s.glyphs);
|
||||||
|
|
||||||
if self.Format == 1:
|
if self.Format == 1:
|
||||||
|
ContextData = c.ContextData (self)
|
||||||
rss = getattr (self, c.RuleSet)
|
rss = getattr (self, c.RuleSet)
|
||||||
return sum ((s.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs \
|
add = []
|
||||||
(s, cur_glyphs=(cur_glyphs if ll.SequenceIndex == 0 else s.glyphs)) \
|
for i in indices:
|
||||||
for i in indices if rss[i] \
|
if not rss[i]: continue
|
||||||
for r in getattr (rss[i], c.Rule) \
|
for r in getattr (rss[i], c.Rule):
|
||||||
if r and all (g in s.glyphs for g in c.RuleData (r)) \
|
if not r: continue
|
||||||
for ll in getattr (r, c.LookupRecord) if ll \
|
if all (all (c.Intersect (s.glyphs, cd, k) for k in klist)
|
||||||
), [])
|
for cd,klist in zip (ContextData, c.RuleData (r))):
|
||||||
|
for ll in getattr (r, c.LookupRecord):
|
||||||
|
if not ll: continue
|
||||||
|
seqi = ll.SequenceIndex
|
||||||
|
if seqi == 0:
|
||||||
|
pos_glyphs = set (c.Coverage (self).glyphs[i])
|
||||||
|
else:
|
||||||
|
pos_glyphs = set (r.Input[seqi - 1])
|
||||||
|
lookup = s.table.LookupList.Lookup[ll.LookupListIndex]
|
||||||
|
add.extend (lookup.closure_glyphs (s, cur_glyphs=pos_glyphs))
|
||||||
|
return add
|
||||||
elif self.Format == 2:
|
elif self.Format == 2:
|
||||||
indices = getattr (self, c.ClassDef).intersect (cur_glyphs)
|
ClassDef = getattr (self, c.ClassDef)
|
||||||
|
indices = ClassDef.intersect (cur_glyphs)
|
||||||
|
ContextData = c.ContextData (self)
|
||||||
rss = getattr (self, c.RuleSet)
|
rss = getattr (self, c.RuleSet)
|
||||||
return sum ((s.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs \
|
add = []
|
||||||
(s, cur_glyphs=(cur_glyphs if ll.SequenceIndex == 0 else s.glyphs)) \
|
for i in indices:
|
||||||
for i in indices if rss[i] \
|
if not rss[i]: continue
|
||||||
for r in getattr (rss[i], c.Rule) \
|
for r in getattr (rss[i], c.Rule):
|
||||||
if r and all (all (cd.intersects_class (s.glyphs, k) for k in klist) \
|
if not r: continue
|
||||||
for cd,klist in zip (c.ContextData (self), c.RuleData (r))) \
|
if all (all (c.Intersect (s.glyphs, cd, k) for k in klist)
|
||||||
for ll in getattr (r, c.LookupRecord) if ll \
|
for cd,klist in zip (ContextData, c.RuleData (r))):
|
||||||
), [])
|
for ll in getattr (r, c.LookupRecord):
|
||||||
|
if not ll: continue
|
||||||
|
seqi = ll.SequenceIndex
|
||||||
|
if seqi == 0:
|
||||||
|
pos_glyphs = ClassDef.intersect_class (cur_glyphs, i)
|
||||||
|
else:
|
||||||
|
pos_glyphs = ClassDef.intersect_class (s.glyphs, r.Input[seqi - 1])
|
||||||
|
lookup = s.table.LookupList.Lookup[ll.LookupListIndex]
|
||||||
|
add.extend (lookup.closure_glyphs (s, cur_glyphs=pos_glyphs))
|
||||||
|
return add
|
||||||
elif self.Format == 3:
|
elif self.Format == 3:
|
||||||
if not all (x.intersect (s.glyphs) for x in c.RuleData (self)):
|
if not all (x.intersect (s.glyphs) for x in c.RuleData (self)):
|
||||||
return []
|
return []
|
||||||
return sum ((s.table.LookupList.Lookup[ll.LookupListIndex].closure_glyphs \
|
r = self
|
||||||
(s, cur_glyphs=(cur_glyphs if ll.SequenceIndex == 0 else s.glyphs)) \
|
add = []
|
||||||
for ll in getattr (self, c.LookupRecord) if ll), [])
|
for ll in getattr (r, c.LookupRecord):
|
||||||
|
if not ll: continue
|
||||||
|
seqi = ll.SequenceIndex
|
||||||
|
if seqi == 0:
|
||||||
|
pos_glyphs = cur_glyphs
|
||||||
|
else:
|
||||||
|
pos_glyphs = r.InputCoverage[seqi].intersect_glyphs (s.glyphs)
|
||||||
|
lookup = s.table.LookupList.Lookup[ll.LookupListIndex]
|
||||||
|
add.extend (lookup.closure_glyphs (s, cur_glyphs=pos_glyphs))
|
||||||
|
return add
|
||||||
else:
|
else:
|
||||||
assert 0, "unknown format: %s" % self.Format
|
assert 0, "unknown format: %s" % self.Format
|
||||||
|
|
||||||
@ -473,7 +508,8 @@ def subset_glyphs (self, s):
|
|||||||
if not rs: continue
|
if not rs: continue
|
||||||
ss = getattr (rs, c.Rule)
|
ss = getattr (rs, c.Rule)
|
||||||
ss = [r for r in ss \
|
ss = [r for r in ss \
|
||||||
if r and all (g in s.glyphs for g in c.RuleData (r))]
|
if r and all (all (g in s.glyphs for g in glist) \
|
||||||
|
for glist in c.RuleData (r))]
|
||||||
setattr (rs, c.Rule, ss)
|
setattr (rs, c.Rule, ss)
|
||||||
setattr (rs, c.RuleCount, len (ss))
|
setattr (rs, c.RuleCount, len (ss))
|
||||||
# Prune empty subrulesets
|
# Prune empty subrulesets
|
||||||
|
Loading…
x
Reference in New Issue
Block a user