Merge pull request #1297 from anthrotype/fix-mark-base-overflow

atttempt to fix offset overflows in MarkBasePos subtables
This commit is contained in:
Cosimo Lupo 2018-07-23 12:58:39 +01:00 committed by GitHub
commit 5a1ccf1640
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 111 additions and 1 deletions

View File

@ -1281,6 +1281,67 @@ def splitPairPos(oldSubTable, newSubTable, overflowRecord):
return ok return ok
def splitMarkBasePos(oldSubTable, newSubTable, overflowRecord):
# split half of the mark classes to the new subtable
classCount = oldSubTable.ClassCount
if classCount < 2:
# oh well, not much left to split...
return False
oldClassCount = classCount // 2
newClassCount = classCount - oldClassCount
oldMarkCoverage, oldMarkRecords = [], []
newMarkCoverage, newMarkRecords = [], []
for glyphName, markRecord in zip(
oldSubTable.MarkCoverage.glyphs,
oldSubTable.MarkArray.MarkRecord
):
if markRecord.Class < oldClassCount:
oldMarkCoverage.append(glyphName)
oldMarkRecords.append(markRecord)
else:
newMarkCoverage.append(glyphName)
newMarkRecords.append(markRecord)
oldBaseRecords, newBaseRecords = [], []
for rec in oldSubTable.BaseArray.BaseRecord:
oldBaseRecord, newBaseRecord = rec.__class__(), rec.__class__()
oldBaseRecord.BaseAnchor = rec.BaseAnchor[:oldClassCount]
newBaseRecord.BaseAnchor = rec.BaseAnchor[oldClassCount:]
oldBaseRecords.append(oldBaseRecord)
newBaseRecords.append(newBaseRecord)
newSubTable.Format = oldSubTable.Format
oldSubTable.MarkCoverage.glyphs = oldMarkCoverage
newSubTable.MarkCoverage = oldSubTable.MarkCoverage.__class__()
newSubTable.MarkCoverage.Format = oldSubTable.MarkCoverage.Format
newSubTable.MarkCoverage.glyphs = newMarkCoverage
# share the same BaseCoverage in both halves
newSubTable.BaseCoverage = oldSubTable.BaseCoverage
oldSubTable.ClassCount = oldClassCount
newSubTable.ClassCount = newClassCount
oldSubTable.MarkArray.MarkRecord = oldMarkRecords
newSubTable.MarkArray = oldSubTable.MarkArray.__class__()
newSubTable.MarkArray.MarkRecord = newMarkRecords
oldSubTable.MarkArray.MarkCount = len(oldMarkRecords)
newSubTable.MarkArray.MarkCount = len(newMarkRecords)
oldSubTable.BaseArray.BaseRecord = oldBaseRecords
newSubTable.BaseArray = oldSubTable.BaseArray.__class__()
newSubTable.BaseArray.BaseRecord = newBaseRecords
oldSubTable.BaseArray.BaseCount = len(oldBaseRecords)
newSubTable.BaseArray.BaseCount = len(newBaseRecords)
return True
splitTable = { 'GSUB': { splitTable = { 'GSUB': {
# 1: splitSingleSubst, # 1: splitSingleSubst,
# 2: splitMultipleSubst, # 2: splitMultipleSubst,
@ -1295,7 +1356,7 @@ splitTable = { 'GSUB': {
# 1: splitSinglePos, # 1: splitSinglePos,
2: splitPairPos, 2: splitPairPos,
# 3: splitCursivePos, # 3: splitCursivePos,
# 4: splitMarkBasePos, 4: splitMarkBasePos,
# 5: splitMarkLigPos, # 5: splitMarkLigPos,
# 6: splitMarkMarkPos, # 6: splitMarkMarkPos,
# 7: splitContextPos, # 7: splitContextPos,
@ -1347,6 +1408,11 @@ def fixSubTableOverFlows(ttf, overflowRecord):
try: try:
splitFunc = splitTable[overflowRecord.tableType][subTableType] splitFunc = splitTable[overflowRecord.tableType][subTableType]
except KeyError: except KeyError:
log.error(
"Don't know how to split %s lookup type %s",
overflowRecord.tableType,
subTableType,
)
return ok return ok
ok = splitFunc(subtable, newSubTable, overflowRecord) ok = splitFunc(subtable, newSubTable, overflowRecord)

View File

@ -485,6 +485,50 @@ class InsertionMorphActionTest(unittest.TestCase):
self.assertEqual(hexStr(writer.getAllData()), "1234fc4300090007") self.assertEqual(hexStr(writer.getAllData()), "1234fc4300090007")
def test_splitMarkBasePos():
from fontTools.otlLib.builder import buildAnchor, buildMarkBasePosSubtable
marks = {
"acutecomb": (0, buildAnchor(0, 600)),
"gravecomb": (0, buildAnchor(0, 590)),
"cedillacomb": (1, buildAnchor(0, 0)),
}
bases = {
"a": {
0: buildAnchor(350, 500),
1: None,
},
"c": {
0: buildAnchor(300, 700),
1: buildAnchor(300, 0),
},
}
glyphOrder = ["a", "c", "acutecomb", "gravecomb", "cedillacomb"]
glyphMap = {g: i for i, g in enumerate(glyphOrder)}
oldSubTable = buildMarkBasePosSubtable(marks, bases, glyphMap)
oldSubTable.MarkCoverage.Format = oldSubTable.BaseCoverage.Format = 1
newSubTable = otTables.MarkBasePos()
ok = otTables.splitMarkBasePos(oldSubTable, newSubTable, overflowRecord=None)
assert ok
assert oldSubTable.Format == newSubTable.Format
assert oldSubTable.MarkCoverage.glyphs == [
"acutecomb", "gravecomb"
]
assert newSubTable.MarkCoverage.glyphs == ["cedillacomb"]
assert newSubTable.MarkCoverage.Format == 1
assert oldSubTable.BaseCoverage.glyphs == newSubTable.BaseCoverage.glyphs
assert newSubTable.BaseCoverage.Format == 1
assert oldSubTable.ClassCount == newSubTable.ClassCount == 1
assert oldSubTable.MarkArray.MarkCount == 2
assert newSubTable.MarkArray.MarkCount == 1
assert oldSubTable.BaseArray.BaseCount == newSubTable.BaseArray.BaseCount
assert newSubTable.BaseArray.BaseRecord[0].BaseAnchor[0] is None
assert newSubTable.BaseArray.BaseRecord[1].BaseAnchor[0] == buildAnchor(300, 0)
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
sys.exit(unittest.main()) sys.exit(unittest.main())