Merge pull request #1706 from dscorbett/splitMultipleSubst

Fix MultipleSubst subtable overflows
This commit is contained in:
Cosimo Lupo 2019-09-11 09:53:13 +02:00 committed by GitHub
commit f2915e7480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 1 deletions

View File

@ -1226,6 +1226,32 @@ def fixLookupOverFlows(ttf, overflowRecord):
ok = 1
return ok
def splitMultipleSubst(oldSubTable, newSubTable, overflowRecord):
ok = 1
newSubTable.Format = oldSubTable.Format
oldMapping = sorted(oldSubTable.mapping.items())
oldLen = len(oldMapping)
if overflowRecord.itemName in ['Coverage', 'RangeRecord']:
# Coverage table is written last. Overflow is to or within the
# the coverage table. We will just cut the subtable in half.
newLen = oldLen // 2
elif overflowRecord.itemName == 'Sequence':
# We just need to back up by two items from the overflowed
# Sequence index to make sure the offset to the Coverage table
# doesn't overflow.
newLen = overflowRecord.itemIndex - 1
newSubTable.mapping = {}
for i in range(newLen, oldLen):
item = oldMapping[i]
key = item[0]
newSubTable.mapping[key] = item[1]
del oldSubTable.mapping[key]
return ok
def splitAlternateSubst(oldSubTable, newSubTable, overflowRecord):
ok = 1
newSubTable.Format = oldSubTable.Format
@ -1413,7 +1439,7 @@ def splitMarkBasePos(oldSubTable, newSubTable, overflowRecord):
splitTable = { 'GSUB': {
# 1: splitSingleSubst,
# 2: splitMultipleSubst,
2: splitMultipleSubst,
3: splitAlternateSubst,
4: splitLigatureSubst,
# 5: splitContextSubst,

View File

@ -546,6 +546,37 @@ class InsertionMorphActionTest(unittest.TestCase):
})
class SplitMultipleSubstTest:
def overflow(self, itemName, itemRecord):
from fontTools.otlLib.builder import buildMultipleSubstSubtable
from fontTools.ttLib.tables.otBase import OverflowErrorRecord
oldSubTable = buildMultipleSubstSubtable({'e': 1, 'a': 2, 'b': 3, 'c': 4, 'd': 5})
oldSubTable.Format = 1
newSubTable = otTables.MultipleSubst()
ok = otTables.splitMultipleSubst(oldSubTable, newSubTable, OverflowErrorRecord((None, None, None, itemName, itemRecord)))
assert ok
assert oldSubTable.Format == newSubTable.Format
return oldSubTable.mapping, newSubTable.mapping
def test_Coverage(self):
oldMapping, newMapping = self.overflow('Coverage', None)
assert oldMapping == {'a': 2, 'b': 3}
assert newMapping == {'c': 4, 'd': 5, 'e': 1}
def test_RangeRecord(self):
oldMapping, newMapping = self.overflow('RangeRecord', None)
assert oldMapping == {'a': 2, 'b': 3}
assert newMapping == {'c': 4, 'd': 5, 'e': 1}
def test_Sequence(self):
oldMapping, newMapping = self.overflow('Sequence', 4)
assert oldMapping == {'a': 2, 'b': 3,'c': 4}
assert newMapping == {'d': 5, 'e': 1}
def test_splitMarkBasePos():
from fontTools.otlLib.builder import buildAnchor, buildMarkBasePosSubtable