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