stb_truetype: GPOS parsing fixes
Glyphs not assigned a glyph class should default to class 0 as per the OpenType spec. Also, change the code to treat malformed data as an error to be handled, not an assert, and change the way the version checking works. Fixes the issue mentioned in PR #1035. Also, this part of the code is indented incorrectly; will fix that in a subsequent commit.
This commit is contained in:
parent
e590505492
commit
1252a3e641
@ -2479,12 +2479,13 @@ static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
// There are no other cases.
|
// Unsupported defition type; return an error.
|
||||||
STBTT_assert(0);
|
return -1;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
// "All glyphs not assigned to a class fall into class 0". (OpenType spec)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
|
// Define to STBTT_assert(x) if you want to break on unimplemented formats.
|
||||||
@ -2533,75 +2534,67 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
|||||||
int straw, needle;
|
int straw, needle;
|
||||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||||
stbtt_int32 valueRecordPairSizeInBytes = 2;
|
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
||||||
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
|
stbtt_int32 valueRecordPairSizeInBytes = 2;
|
||||||
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
|
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
|
||||||
stbtt_uint8 *pairValueTable = table + pairPosOffset;
|
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
|
||||||
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
|
stbtt_uint8 *pairValueTable = table + pairPosOffset;
|
||||||
stbtt_uint8 *pairValueArray = pairValueTable + 2;
|
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
|
||||||
// TODO: Support more formats.
|
stbtt_uint8 *pairValueArray = pairValueTable + 2;
|
||||||
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
|
||||||
if (valueFormat1 != 4) return 0;
|
|
||||||
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
|
||||||
if (valueFormat2 != 0) return 0;
|
|
||||||
|
|
||||||
STBTT_assert(coverageIndex < pairSetCount);
|
if (coverageIndex >= pairSetCount) return 0;
|
||||||
STBTT__NOTUSED(pairSetCount);
|
|
||||||
|
|
||||||
needle=glyph2;
|
needle=glyph2;
|
||||||
r=pairValueCount-1;
|
r=pairValueCount-1;
|
||||||
l=0;
|
l=0;
|
||||||
|
|
||||||
// Binary search.
|
// Binary search.
|
||||||
while (l <= r) {
|
while (l <= r) {
|
||||||
stbtt_uint16 secondGlyph;
|
stbtt_uint16 secondGlyph;
|
||||||
stbtt_uint8 *pairValue;
|
stbtt_uint8 *pairValue;
|
||||||
m = (l + r) >> 1;
|
m = (l + r) >> 1;
|
||||||
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
|
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
|
||||||
secondGlyph = ttUSHORT(pairValue);
|
secondGlyph = ttUSHORT(pairValue);
|
||||||
straw = secondGlyph;
|
straw = secondGlyph;
|
||||||
if (needle < straw)
|
if (needle < straw)
|
||||||
r = m - 1;
|
r = m - 1;
|
||||||
else if (needle > straw)
|
else if (needle > straw)
|
||||||
l = m + 1;
|
l = m + 1;
|
||||||
else {
|
else {
|
||||||
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
|
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
|
||||||
return xAdvance;
|
return xAdvance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
return 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
|
||||||
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
|
||||||
|
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
|
||||||
|
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
|
||||||
|
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
|
||||||
|
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
|
||||||
|
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
|
||||||
|
|
||||||
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
|
stbtt_uint16 class1Count = ttUSHORT(table + 12);
|
||||||
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
|
stbtt_uint16 class2Count = ttUSHORT(table + 14);
|
||||||
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
|
|
||||||
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
|
|
||||||
|
|
||||||
stbtt_uint16 class1Count = ttUSHORT(table + 12);
|
if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
|
||||||
stbtt_uint16 class2Count = ttUSHORT(table + 14);
|
if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
|
||||||
STBTT_assert(glyph1class < class1Count);
|
|
||||||
STBTT_assert(glyph2class < class2Count);
|
|
||||||
|
|
||||||
// TODO: Support more formats.
|
|
||||||
STBTT_GPOS_TODO_assert(valueFormat1 == 4);
|
|
||||||
if (valueFormat1 != 4) return 0;
|
|
||||||
STBTT_GPOS_TODO_assert(valueFormat2 == 0);
|
|
||||||
if (valueFormat2 != 0) return 0;
|
|
||||||
|
|
||||||
if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
|
|
||||||
stbtt_uint8 *class1Records = table + 16;
|
stbtt_uint8 *class1Records = table + 16;
|
||||||
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
|
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
|
||||||
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
|
||||||
return xAdvance;
|
return xAdvance;
|
||||||
}
|
} else
|
||||||
|
return 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
// There are no other cases.
|
// Unsupported definition type
|
||||||
STBTT_assert(0);
|
return 0;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user