📄 harfbuzz-open.c
字号:
{ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; HB_RangeRecord* rr; if ( ACCESS_Frame( 2L ) ) return error; count = cf2->RangeCount = GET_UShort(); FORGET_Frame(); cf2->RangeRecord = NULL; if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) ) return error; rr = cf2->RangeRecord; if ( ACCESS_Frame( count * 6L ) ) goto Fail; for ( n = 0; n < count; n++ ) { rr[n].Start = GET_UShort(); rr[n].End = GET_UShort(); rr[n].StartCoverageIndex = GET_UShort(); /* sanity check; we are limited to 16bit integers */ if ( rr[n].Start > rr[n].End || ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >= 0x10000L ) { error = HB_Err_Invalid_SubTable; goto Fail; } } FORGET_Frame(); return FT_Err_Ok;Fail: FREE( cf2->RangeRecord ); return error;}static void Free_Coverage2( HB_CoverageFormat2* cf2, FT_Memory memory ){ FREE( cf2->RangeRecord );}FT_Error _HB_OPEN_Load_Coverage( HB_Coverage* c, FT_Stream stream ){ FT_Error error; if ( ACCESS_Frame( 2L ) ) return error; c->CoverageFormat = GET_UShort(); FORGET_Frame(); switch ( c->CoverageFormat ) { case 1: return Load_Coverage1( &c->cf.cf1, stream ); case 2: return Load_Coverage2( &c->cf.cf2, stream ); default: return HB_Err_Invalid_SubTable_Format; } return FT_Err_Ok; /* never reached */}void _HB_OPEN_Free_Coverage( HB_Coverage* c, FT_Memory memory ){ switch ( c->CoverageFormat ) { case 1: Free_Coverage1( &c->cf.cf1, memory ); break; case 2: Free_Coverage2( &c->cf.cf2, memory ); break; }}static FT_Error Coverage_Index1( HB_CoverageFormat1* cf1, FT_UShort glyphID, FT_UShort* index ){ FT_UShort min, max, new_min, new_max, middle; FT_UShort* array = cf1->GlyphArray; /* binary search */ if ( cf1->GlyphCount == 0 ) return HB_Err_Not_Covered; new_min = 0; new_max = cf1->GlyphCount - 1; do { min = new_min; max = new_max; /* we use (min + max) / 2 = max - (max - min) / 2 to avoid overflow and rounding errors */ middle = max - ( ( max - min ) >> 1 ); if ( glyphID == array[middle] ) { *index = middle; return FT_Err_Ok; } else if ( glyphID < array[middle] ) { if ( middle == min ) break; new_max = middle - 1; } else { if ( middle == max ) break; new_min = middle + 1; } } while ( min < max ); return HB_Err_Not_Covered;}static FT_Error Coverage_Index2( HB_CoverageFormat2* cf2, FT_UShort glyphID, FT_UShort* index ){ FT_UShort min, max, new_min, new_max, middle; HB_RangeRecord* rr = cf2->RangeRecord; /* binary search */ if ( cf2->RangeCount == 0 ) return HB_Err_Not_Covered; new_min = 0; new_max = cf2->RangeCount - 1; do { min = new_min; max = new_max; /* we use (min + max) / 2 = max - (max - min) / 2 to avoid overflow and rounding errors */ middle = max - ( ( max - min ) >> 1 ); if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End ) { *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start; return FT_Err_Ok; } else if ( glyphID < rr[middle].Start ) { if ( middle == min ) break; new_max = middle - 1; } else { if ( middle == max ) break; new_min = middle + 1; } } while ( min < max ); return HB_Err_Not_Covered;}FT_Error _HB_OPEN_Coverage_Index( HB_Coverage* c, FT_UShort glyphID, FT_UShort* index ){ switch ( c->CoverageFormat ) { case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index ); case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index ); default: return HB_Err_Invalid_SubTable_Format; } return FT_Err_Ok; /* never reached */}/************************************* * Class Definition related functions *************************************//* ClassDefFormat1 */static FT_Error Load_ClassDef1( HB_ClassDefinition* cd, FT_UShort limit, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_UShort* cva; FT_Bool* d; HB_ClassDefFormat1* cdf1; cdf1 = &cd->cd.cd1; if ( ACCESS_Frame( 4L ) ) return error; cdf1->StartGlyph = GET_UShort(); count = cdf1->GlyphCount = GET_UShort(); FORGET_Frame(); /* sanity check; we are limited to 16bit integers */ if ( cdf1->StartGlyph + (long)count >= 0x10000L ) return HB_Err_Invalid_SubTable; cdf1->ClassValueArray = NULL; if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, FT_UShort ) ) return error; d = cd->Defined; cva = cdf1->ClassValueArray; if ( ACCESS_Frame( count * 2L ) ) goto Fail; for ( n = 0; n < count; n++ ) { cva[n] = GET_UShort(); if ( cva[n] >= limit ) { error = HB_Err_Invalid_SubTable; goto Fail; } d[cva[n]] = TRUE; } FORGET_Frame(); return FT_Err_Ok;Fail: FREE( cva ); return error;}static void Free_ClassDef1( HB_ClassDefFormat1* cdf1, FT_Memory memory ){ FREE( cdf1->ClassValueArray );}/* ClassDefFormat2 */static FT_Error Load_ClassDef2( HB_ClassDefinition* cd, FT_UShort limit, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; HB_ClassRangeRecord* crr; FT_Bool* d; HB_ClassDefFormat2* cdf2; cdf2 = &cd->cd.cd2; if ( ACCESS_Frame( 2L ) ) return error; count = cdf2->ClassRangeCount = GET_UShort(); FORGET_Frame(); cdf2->ClassRangeRecord = NULL; if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) ) return error; d = cd->Defined; crr = cdf2->ClassRangeRecord; if ( ACCESS_Frame( count * 6L ) ) goto Fail; for ( n = 0; n < count; n++ ) { crr[n].Start = GET_UShort(); crr[n].End = GET_UShort(); crr[n].Class = GET_UShort(); /* sanity check */ if ( crr[n].Start > crr[n].End || crr[n].Class >= limit ) { error = HB_Err_Invalid_SubTable; goto Fail; } d[crr[n].Class] = TRUE; } FORGET_Frame(); return FT_Err_Ok;Fail: FREE( crr ); return error;}static void Free_ClassDef2( HB_ClassDefFormat2* cdf2, FT_Memory memory ){ FREE( cdf2->ClassRangeRecord );}/* ClassDefinition */FT_Error _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd, FT_UShort limit, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; if ( ALLOC_ARRAY( cd->Defined, limit, FT_Bool ) ) return error; if ( ACCESS_Frame( 2L ) ) goto Fail; cd->ClassFormat = GET_UShort(); FORGET_Frame(); switch ( cd->ClassFormat ) { case 1: error = Load_ClassDef1( cd, limit, stream ); break; case 2: error = Load_ClassDef2( cd, limit, stream ); break; default: error = HB_Err_Invalid_SubTable_Format; break; } if ( error ) goto Fail; cd->loaded = TRUE; return FT_Err_Ok;Fail: FREE( cd->Defined ); return error;}FT_Error _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; if ( ALLOC_ARRAY( cd->Defined, 1, FT_Bool ) ) return error; cd->ClassFormat = 1; /* Meaningless */ cd->Defined[0] = FALSE; if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, FT_UShort ) ) goto Fail; return FT_Err_Ok;Fail: FREE( cd->Defined ); return error;}void _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd, FT_Memory memory ){ if ( !cd->loaded ) return; FREE( cd->Defined ); switch ( cd->ClassFormat ) { case 1: Free_ClassDef1( &cd->cd.cd1, memory ); break; case 2: Free_ClassDef2( &cd->cd.cd2, memory ); break; }}static FT_Error Get_Class1( HB_ClassDefFormat1* cdf1, FT_UShort glyphID, FT_UShort* class, FT_UShort* index ){ FT_UShort* cva = cdf1->ClassValueArray; if ( index ) *index = 0; if ( glyphID >= cdf1->StartGlyph && glyphID <= cdf1->StartGlyph + cdf1->GlyphCount ) { *class = cva[glyphID - cdf1->StartGlyph]; return FT_Err_Ok; } else { *class = 0; return HB_Err_Not_Covered; }}/* we need the index value of the last searched class range record in case of failure for constructed GDEF tables */static FT_Error Get_Class2( HB_ClassDefFormat2* cdf2, FT_UShort glyphID, FT_UShort* class, FT_UShort* index ){ FT_Error error = FT_Err_Ok; FT_UShort min, max, new_min, new_max, middle; HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord; /* binary search */ if ( cdf2->ClassRangeCount == 0 ) { *class = 0; if ( index ) *index = 0; return HB_Err_Not_Covered; } new_min = 0; new_max = cdf2->ClassRangeCount - 1; do { min = new_min; max = new_max; /* we use (min + max) / 2 = max - (max - min) / 2 to avoid overflow and rounding errors */ middle = max - ( ( max - min ) >> 1 ); if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End ) { *class = crr[middle].Class; error = FT_Err_Ok; break; } else if ( glyphID < crr[middle].Start ) { if ( middle == min ) { *class = 0; error = HB_Err_Not_Covered; break; } new_max = middle - 1; } else { if ( middle == max ) { *class = 0; error = HB_Err_Not_Covered; break; } new_min = middle + 1; } } while ( min < max ); if ( index ) *index = middle; return error;}FT_Error _HB_OPEN_Get_Class( HB_ClassDefinition* cd, FT_UShort glyphID, FT_UShort* class, FT_UShort* index ){ switch ( cd->ClassFormat ) { case 1: return Get_Class1( &cd->cd.cd1, glyphID, class, index ); case 2: return Get_Class2( &cd->cd.cd2, glyphID, class, index ); default: return HB_Err_Invalid_SubTable_Format; } return FT_Err_Ok; /* never reached */}/*************************** * Device related functions ***************************/FT_Error _HB_OPEN_Load_Device( HB_Device* d, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_UShort* dv; if ( ACCESS_Frame( 6L ) ) return error; d->StartSize = GET_UShort(); d->EndSize = GET_UShort(); d->DeltaFormat = GET_UShort(); FORGET_Frame(); if ( d->StartSize > d->EndSize || d->DeltaFormat == 0 || d->DeltaFormat > 3 ) return HB_Err_Invalid_SubTable; d->DeltaValue = NULL; count = ( ( d->EndSize - d->StartSize + 1 ) >> ( 4 - d->DeltaFormat ) ) + 1; if ( ALLOC_ARRAY( d->DeltaValue, count, FT_UShort ) ) return error; if ( ACCESS_Frame( count * 2L ) ) { FREE( d->DeltaValue ); return error; } dv = d->DeltaValue; for ( n = 0; n < count; n++ ) dv[n] = GET_UShort(); FORGET_Frame(); return FT_Err_Ok;}void _HB_OPEN_Free_Device( HB_Device* d, FT_Memory memory ){ FREE( d->DeltaValue );}/* Since we have the delta values stored in compressed form, we must uncompress it now. To simplify the interface, the function always returns a meaningful value in `value'; the error is just for information. | | format = 1: 0011223344556677|8899101112131415|... | | byte 1 byte 2 00: (byte >> 14) & mask 11: (byte >> 12) & mask ... mask = 0x0003 | | format = 2: 0000111122223333|4444555566667777|... | | byte 1 byte 2 0000: (byte >> 12) & mask 1111: (byte >> 8) & mask ... mask = 0x000F | | format = 3: 0000000011111111|2222222233333333|... | | byte 1 byte 2 00000000: (byte >> 8) & mask 11111111: (byte >> 0) & mask .... mask = 0x00FF */FT_Error _HB_OPEN_Get_Device( HB_Device* d, FT_UShort size, FT_Short* value ){ FT_UShort byte, bits, mask, f, s; f = d->DeltaFormat; if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize ) { s = size - d->StartSize; byte = d->DeltaValue[s >> ( 4 - f )]; bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) ); mask = 0xFFFF >> ( 16 - ( 1 << f ) ); *value = (FT_Short)( bits & mask ); /* conversion to a signed value */ if ( *value >= ( ( mask + 1 ) >> 1 ) ) *value -= mask + 1; return FT_Err_Ok; } else { *value = 0; return HB_Err_Not_Covered; }}/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -