@ -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 )