Merge pull request #1297 from anthrotype/fix-mark-base-overflow
atttempt to fix offset overflows in MarkBasePos subtables
This commit is contained in:
commit
5a1ccf1640
@ -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)
|
||||||
|
@ -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())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user