Merge pull request #364 from brawer/MultipleSubst

[otTables] Simplify API for MultipleSubst
This commit is contained in:
Sascha Brawer 2015-09-10 15:24:58 +02:00
commit 088918ed76
3 changed files with 109 additions and 11 deletions

View File

@ -401,20 +401,15 @@ def subset_glyphs(self, s):
@_add_method(otTables.MultipleSubst)
def closure_glyphs(self, s, cur_glyphs):
indices = self.Coverage.intersect(cur_glyphs)
_set_update(s.glyphs, *(self.Sequence[i].Substitute for i in indices))
for glyph, subst in self.mapping.items():
if glyph in cur_glyphs:
_set_update(s.glyphs, subst)
@_add_method(otTables.MultipleSubst)
def subset_glyphs(self, s):
indices = self.Coverage.subset(s.glyphs)
self.Sequence = [self.Sequence[i] for i in indices]
# Now drop rules generating glyphs we don't want
indices = [i for i,seq in enumerate(self.Sequence)
if all(sub in s.glyphs for sub in seq.Substitute)]
self.Sequence = [self.Sequence[i] for i in indices]
self.Coverage.remap(indices)
self.SequenceCount = len(self.Sequence)
return bool(self.SequenceCount)
self.mapping = {g:v for g,v in self.mapping.items()
if g in s.glyphs and all(sub in s.glyphs for sub in v)}
return bool(self.mapping)
@_add_method(otTables.AlternateSubst)
def closure_glyphs(self, s, cur_glyphs):

View File

@ -203,6 +203,55 @@ class SingleSubst(FormatSwitchingBaseTable):
mapping[attrs["in"]] = attrs["out"]
class MultipleSubst(FormatSwitchingBaseTable):
def postRead(self, rawTable, font):
mapping = {}
if self.Format == 1:
glyphs = _getGlyphsFromCoverageTable(rawTable["Coverage"])
subst = [s.Substitute for s in rawTable["Sequence"]]
mapping = dict(zip(glyphs, subst))
else:
assert 0, "unknown format: %s" % self.Format
self.mapping = mapping
del self.Format # Don't need this anymore
def preWrite(self, font):
mapping = getattr(self, "mapping", None)
if mapping is None:
mapping = self.mapping = {}
cov = Coverage()
cov.glyphs = sorted(list(mapping.keys()), key=font.getGlyphID)
self.Format = 1
rawTable = {
"Coverage": cov,
"Sequence": [self.makeSequence_(mapping[glyph])
for glyph in cov.glyphs],
}
return rawTable
def toXML2(self, xmlWriter, font):
items = sorted(self.mapping.items())
for inGlyph, outGlyphs in items:
out = ",".join(outGlyphs)
xmlWriter.simpletag("Substitution",
[("in", inGlyph), ("out", out)])
xmlWriter.newline()
def fromXML(self, name, attrs, content, font):
mapping = getattr(self, "mapping", None)
if mapping is None:
mapping = {}
self.mapping = mapping
outGlyphs = attrs["out"].split(",")
mapping[attrs["in"]] = [g.strip() for g in outGlyphs]
@staticmethod
def makeSequence_(g):
seq = Sequence()
seq.Substitute = g
return seq
class ClassDef(FormatSwitchingBaseTable):
def postRead(self, rawTable, font):

View File

@ -89,6 +89,60 @@ class SingleSubstTest(unittest.TestCase):
self.assertEqual(table.mapping, {"A": "a", "B": "b", "C": "c"})
class MultipleSubstTest(unittest.TestCase):
def setUp(self):
self.glyphs = ".notdef c f i t c_t f_f_i".split()
self.font = FakeFont(self.glyphs)
def test_postRead_format1(self):
makeSequence = otTables.MultipleSubst.makeSequence_
table = otTables.MultipleSubst()
table.Format = 1
rawTable = {
"Coverage": makeCoverage(["c_t", "f_f_i"]),
"Sequence": [
makeSequence(["c", "t"]),
makeSequence(["f", "f", "i"])
]
}
table.postRead(rawTable, self.font)
self.assertEqual(table.mapping, {
"c_t": ["c", "t"],
"f_f_i": ["f", "f", "i"]
})
def test_postRead_formatUnknown(self):
table = otTables.MultipleSubst()
table.Format = 987
self.assertRaises(AssertionError, table.postRead, {}, self.font)
def test_preWrite_format1(self):
table = otTables.MultipleSubst()
table.mapping = {"c_t": ["c", "t"], "f_f_i": ["f", "f", "i"]}
rawTable = table.preWrite(self.font)
self.assertEqual(table.Format, 1)
self.assertEqual(rawTable["Coverage"].glyphs, ["c_t", "f_f_i"])
def test_toXML2(self):
writer = XMLWriter(StringIO())
table = otTables.MultipleSubst()
table.mapping = {"c_t": ["c", "t"], "f_f_i": ["f", "f", "i"]}
table.toXML2(writer, self.font)
self.assertEqual(writer.file.getvalue().splitlines()[1:], [
'<Substitution in="c_t" out="c,t"/>',
'<Substitution in="f_f_i" out="f,f,i"/>',
])
def test_fromXML(self):
table = otTables.MultipleSubst()
table.fromXML("Substitution",
{"in": "c_t", "out": "c,t"}, [], self.font)
table.fromXML("Substitution",
{"in": "f_f_i", "out": "f,f,i"}, [], self.font)
self.assertEqual(table.mapping,
{'c_t': ['c', 't'], 'f_f_i': ['f', 'f', 'i']})
class LigatureSubstTest(unittest.TestCase):
def setUp(self):
self.glyphs = ".notdef c f i t c_t f_f f_i f_f_i".split()