stb_truetype: GPOS handling formatting changes

Was using 4-character spaces and otherwise formatted unlike the
rest of the code, fix this. Also get rid of the outer switch in
GetGlyphGPOSInfoAdvance with just one case; just use an if.
No behavioral changes.
This commit is contained in:
Fabian Giesen 2021-07-07 03:12:33 -07:00
parent 1252a3e641
commit 9fe3b4bb52
1 changed files with 177 additions and 186 deletions

View File

@ -2353,7 +2353,7 @@ STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningent
return length; return length;
} }
static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint8 *data = info->data + info->kern; stbtt_uint8 *data = info->data + info->kern;
stbtt_uint32 needle, straw; stbtt_uint32 needle, straw;
@ -2383,232 +2383,223 @@ static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph
return 0; return 0;
} }
static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
{ {
stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
switch(coverageFormat) { switch (coverageFormat) {
case 1: { case 1: {
stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
// Binary search. // Binary search.
stbtt_int32 l=0, r=glyphCount-1, m; stbtt_int32 l=0, r=glyphCount-1, m;
int straw, needle=glyph; int straw, needle=glyph;
while (l <= r) { while (l <= r) {
stbtt_uint8 *glyphArray = coverageTable + 4; stbtt_uint8 *glyphArray = coverageTable + 4;
stbtt_uint16 glyphID; stbtt_uint16 glyphID;
m = (l + r) >> 1; m = (l + r) >> 1;
glyphID = ttUSHORT(glyphArray + 2 * m); glyphID = ttUSHORT(glyphArray + 2 * m);
straw = glyphID; straw = glyphID;
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 {
return m; return m;
}
} }
} break; }
break;
}
case 2: { case 2: {
stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
stbtt_uint8 *rangeArray = coverageTable + 4; stbtt_uint8 *rangeArray = coverageTable + 4;
// Binary search. // Binary search.
stbtt_int32 l=0, r=rangeCount-1, m; stbtt_int32 l=0, r=rangeCount-1, m;
int strawStart, strawEnd, needle=glyph; int strawStart, strawEnd, needle=glyph;
while (l <= r) { while (l <= r) {
stbtt_uint8 *rangeRecord; stbtt_uint8 *rangeRecord;
m = (l + r) >> 1; m = (l + r) >> 1;
rangeRecord = rangeArray + 6 * m; rangeRecord = rangeArray + 6 * m;
strawStart = ttUSHORT(rangeRecord); strawStart = ttUSHORT(rangeRecord);
strawEnd = ttUSHORT(rangeRecord + 2); strawEnd = ttUSHORT(rangeRecord + 2);
if (needle < strawStart) if (needle < strawStart)
r = m - 1; r = m - 1;
else if (needle > strawEnd) else if (needle > strawEnd)
l = m + 1; l = m + 1;
else { else {
stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
return startCoverageIndex + glyph - strawStart; return startCoverageIndex + glyph - strawStart;
}
} }
} break; }
break;
}
default: { default: return -1; // unsupported
// There are no other cases. }
STBTT_assert(0);
} break;
}
return -1; return -1;
} }
static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
{ {
stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
switch(classDefFormat) switch (classDefFormat)
{ {
case 1: { case 1: {
stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
stbtt_uint8 *classDef1ValueArray = classDefTable + 6; stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
} break; break;
}
case 2: { case 2: {
stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
stbtt_uint8 *classRangeRecords = classDefTable + 4; stbtt_uint8 *classRangeRecords = classDefTable + 4;
// Binary search. // Binary search.
stbtt_int32 l=0, r=classRangeCount-1, m; stbtt_int32 l=0, r=classRangeCount-1, m;
int strawStart, strawEnd, needle=glyph; int strawStart, strawEnd, needle=glyph;
while (l <= r) { while (l <= r) {
stbtt_uint8 *classRangeRecord; stbtt_uint8 *classRangeRecord;
m = (l + r) >> 1; m = (l + r) >> 1;
classRangeRecord = classRangeRecords + 6 * m; classRangeRecord = classRangeRecords + 6 * m;
strawStart = ttUSHORT(classRangeRecord); strawStart = ttUSHORT(classRangeRecord);
strawEnd = ttUSHORT(classRangeRecord + 2); strawEnd = ttUSHORT(classRangeRecord + 2);
if (needle < strawStart) if (needle < strawStart)
r = m - 1; r = m - 1;
else if (needle > strawEnd) else if (needle > strawEnd)
l = m + 1; l = m + 1;
else else
return (stbtt_int32)ttUSHORT(classRangeRecord + 4); return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
} }
} break; break;
}
default: { default:
// Unsupported defition type; return an error. return -1; // Unsupported definition type, return an error.
return -1; }
} break;
}
// "All glyphs not assigned to a class fall into class 0". (OpenType spec) // "All glyphs not assigned to a class fall into class 0". (OpenType spec)
return 0; 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.
#define STBTT_GPOS_TODO_assert(x) #define STBTT_GPOS_TODO_assert(x)
static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
{ {
stbtt_uint16 lookupListOffset; stbtt_uint16 lookupListOffset;
stbtt_uint8 *lookupList; stbtt_uint8 *lookupList;
stbtt_uint16 lookupCount; stbtt_uint16 lookupCount;
stbtt_uint8 *data; stbtt_uint8 *data;
stbtt_int32 i; stbtt_int32 i, sti;
if (!info->gpos) return 0; if (!info->gpos) return 0;
data = info->data + info->gpos; data = info->data + info->gpos;
if (ttUSHORT(data+0) != 1) return 0; // Major version 1 if (ttUSHORT(data+0) != 1) return 0; // Major version 1
if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
lookupListOffset = ttUSHORT(data+8); lookupListOffset = ttUSHORT(data+8);
lookupList = data + lookupListOffset; lookupList = data + lookupListOffset;
lookupCount = ttUSHORT(lookupList); lookupCount = ttUSHORT(lookupList);
for (i=0; i<lookupCount; ++i) { for (i=0; i<lookupCount; ++i) {
stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i); stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
stbtt_uint8 *lookupTable = lookupList + lookupOffset; stbtt_uint8 *lookupTable = lookupList + lookupOffset;
stbtt_uint16 lookupType = ttUSHORT(lookupTable); stbtt_uint16 lookupType = ttUSHORT(lookupTable);
stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
stbtt_uint8 *subTableOffsets = lookupTable + 6; stbtt_uint8 *subTableOffsets = lookupTable + 6;
switch(lookupType) { if (lookupType != 2) // Pair Adjustment Positioning Subtable
case 2: { // Pair Adjustment Positioning Subtable continue;
stbtt_int32 sti;
for (sti=0; sti<subTableCount; sti++) {
stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_uint8 *table = lookupTable + subtableOffset;
stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
if (coverageIndex == -1) continue;
switch (posFormat) { for (sti=0; sti<subTableCount; sti++) {
case 1: { stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
stbtt_int32 l, r, m; stbtt_uint8 *table = lookupTable + subtableOffset;
int straw, needle; stbtt_uint16 posFormat = ttUSHORT(table);
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? if (coverageIndex == -1) continue;
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2;
if (coverageIndex >= pairSetCount) return 0; switch (posFormat) {
case 1: {
stbtt_int32 l, r, m;
int straw, needle;
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats?
stbtt_int32 valueRecordPairSizeInBytes = 2;
stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
stbtt_uint8 *pairValueTable = table + pairPosOffset;
stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
stbtt_uint8 *pairValueArray = pairValueTable + 2;
needle=glyph2; if (coverageIndex >= pairSetCount) return 0;
r=pairValueCount-1;
l=0;
// Binary search. needle=glyph2;
while (l <= r) { r=pairValueCount-1;
stbtt_uint16 secondGlyph; l=0;
stbtt_uint8 *pairValue;
m = (l + r) >> 1;
pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
secondGlyph = ttUSHORT(pairValue);
straw = secondGlyph;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
return xAdvance;
}
}
} else
return 0;
} break;
case 2: { // Binary search.
stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); while (l <= r) {
stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); stbtt_uint16 secondGlyph;
if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? stbtt_uint8 *pairValue;
stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); m = (l + r) >> 1;
stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); secondGlyph = ttUSHORT(pairValue);
int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); straw = secondGlyph;
if (needle < straw)
r = m - 1;
else if (needle > straw)
l = m + 1;
else {
stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
return xAdvance;
}
}
} else
return 0;
break;
}
stbtt_uint16 class1Count = ttUSHORT(table + 12); case 2: {
stbtt_uint16 class2Count = ttUSHORT(table + 14); stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
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);
if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed stbtt_uint16 class1Count = ttUSHORT(table + 12);
if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed stbtt_uint16 class2Count = ttUSHORT(table + 14);
stbtt_uint8 *class1Records = table + 16; if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed
stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed
stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
return xAdvance;
} else
return 0;
} break;
default: { stbtt_uint8 *class1Records = table + 16;
// Unsupported definition type stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
return 0; stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
break; return xAdvance;
}; } else
} return 0;
} break;
break; }
};
default: default:
// TODO: Implement other stuff. return 0; // Unsupported position format
break; }
} }
} }
return 0; return 0;
} }
STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)