📄 ftxopen.c
字号:
default: return TTO_Err_Invalid_GPOS_SubTable_Format; } return TT_Err_Ok; /* never reached */ } static void Free_SubTable( TTO_SubTable* st, TTO_Type table_type, FT_UShort lookup_type, FT_Memory memory ) { if ( table_type == GSUB ) switch ( lookup_type ) { case GSUB_LOOKUP_SINGLE: Free_SingleSubst( &st->st.gsub.single, memory ); break; case GSUB_LOOKUP_MULTIPLE: Free_MultipleSubst( &st->st.gsub.multiple, memory ); break; case GSUB_LOOKUP_ALTERNATE: Free_AlternateSubst( &st->st.gsub.alternate, memory ); break; case GSUB_LOOKUP_LIGATURE: Free_LigatureSubst( &st->st.gsub.ligature, memory ); break; case GSUB_LOOKUP_CONTEXT: Free_ContextSubst( &st->st.gsub.context, memory ); break; case GSUB_LOOKUP_CHAIN: Free_ChainContextSubst( &st->st.gsub.chain, memory ); break; } else switch ( lookup_type ) { case GPOS_LOOKUP_SINGLE: Free_SinglePos( &st->st.gpos.single, memory ); break; case GPOS_LOOKUP_PAIR: Free_PairPos( &st->st.gpos.pair, memory ); break; case GPOS_LOOKUP_CURSIVE: Free_CursivePos( &st->st.gpos.cursive, memory ); break; case GPOS_LOOKUP_MARKBASE: Free_MarkBasePos( &st->st.gpos.markbase, memory ); break; case GPOS_LOOKUP_MARKLIG: Free_MarkLigPos( &st->st.gpos.marklig, memory ); break; case GPOS_LOOKUP_MARKMARK: Free_MarkMarkPos( &st->st.gpos.markmark, memory ); break; case GPOS_LOOKUP_CONTEXT: Free_ContextPos( &st->st.gpos.context, memory ); break; case GPOS_LOOKUP_CHAIN: Free_ChainContextPos ( &st->st.gpos.chain, memory ); break; } } /* Lookup */ static FT_Error Load_Lookup( TTO_Lookup* l, FT_Stream stream, TTO_Type type ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; TTO_SubTable* st; FT_Bool is_extension = FALSE; base_offset = FILE_Pos(); if ( ACCESS_Frame( 6L ) ) return error; l->LookupType = GET_UShort(); l->LookupFlag = GET_UShort(); count = l->SubTableCount = GET_UShort(); FORGET_Frame(); l->SubTable = NULL; if ( ALLOC_ARRAY( l->SubTable, count, TTO_SubTable ) ) return error; st = l->SubTable; if ( ( type == GSUB && l->LookupType == GSUB_LOOKUP_EXTENSION ) || ( type == GPOS && l->LookupType == GPOS_LOOKUP_EXTENSION ) ) is_extension = TRUE; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( is_extension ) { if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) ) goto Fail; (void)GET_UShort(); /* format should be 1 */ l->LookupType = GET_UShort(); new_offset = GET_ULong() + base_offset; FORGET_Frame(); } if ( FILE_Seek( new_offset ) || ( error = Load_SubTable( &st[n], stream, type, l->LookupType ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( m = 0; m < n; m++ ) Free_SubTable( &st[m], type, l->LookupType, memory ); FREE( l->SubTable ); return error; } static void Free_Lookup( TTO_Lookup* l, TTO_Type type, FT_Memory memory) { FT_UShort n, count; TTO_SubTable* st; if ( l->SubTable ) { count = l->SubTableCount; st = l->SubTable; for ( n = 0; n < count; n++ ) Free_SubTable( &st[n], type, l->LookupType, memory ); FREE( st ); } } /* LookupList */ FT_Error Load_LookupList( TTO_LookupList* ll, FT_Stream stream, TTO_Type type ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; TTO_Lookup* l; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = ll->LookupCount = GET_UShort(); FORGET_Frame(); ll->Lookup = NULL; if ( ALLOC_ARRAY( ll->Lookup, count, TTO_Lookup ) ) return error; l = ll->Lookup; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Lookup( &l[n], stream, type ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( m = 0; m < n; m++ ) Free_Lookup( &l[m], type, memory ); FREE( ll->Lookup ); return error; } void Free_LookupList( TTO_LookupList* ll, TTO_Type type, FT_Memory memory ) { FT_UShort n, count; TTO_Lookup* l; if ( ll->Lookup ) { count = ll->LookupCount; l = ll->Lookup; for ( n = 0; n < count; n++ ) Free_Lookup( &l[n], type, memory ); FREE( l ); } } /***************************** * Coverage related functions *****************************/ /* CoverageFormat1 */ static FT_Error Load_Coverage1( TTO_CoverageFormat1* cf1, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_UShort* ga; if ( ACCESS_Frame( 2L ) ) return error; count = cf1->GlyphCount = GET_UShort(); FORGET_Frame(); cf1->GlyphArray = NULL; if ( ALLOC_ARRAY( cf1->GlyphArray, count, FT_UShort ) ) return error; ga = cf1->GlyphArray; if ( ACCESS_Frame( count * 2L ) ) { FREE( cf1->GlyphArray ); return error; } for ( n = 0; n < count; n++ ) ga[n] = GET_UShort(); FORGET_Frame(); return TT_Err_Ok; } static void Free_Coverage1( TTO_CoverageFormat1* cf1, FT_Memory memory) { FREE( cf1->GlyphArray ); } /* CoverageFormat2 */ static FT_Error Load_Coverage2( TTO_CoverageFormat2* cf2, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; TTO_RangeRecord* rr; if ( ACCESS_Frame( 2L ) ) return error; count = cf2->RangeCount = GET_UShort(); FORGET_Frame(); cf2->RangeRecord = NULL; if ( ALLOC_ARRAY( cf2->RangeRecord, count, TTO_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 = TTO_Err_Invalid_SubTable; goto Fail; } } FORGET_Frame(); return TT_Err_Ok; Fail: FREE( cf2->RangeRecord ); return error; } static void Free_Coverage2( TTO_CoverageFormat2* cf2, FT_Memory memory ) { FREE( cf2->RangeRecord ); } FT_Error Load_Coverage( TTO_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 TTO_Err_Invalid_SubTable_Format; } return TT_Err_Ok; /* never reached */ } void Free_Coverage( TTO_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 inline FT_Error Coverage_Index1( TTO_CoverageFormat1* cf1, FT_UShort glyphID, FT_UShort* index ) { FT_UShort *min, *max, *middle; /* binary search */ min = cf1->GlyphArray; max = min + cf1->GlyphCount - 1; do { /* we use (min + max) / 2 = max - (max - min) / 2 to avoid overflow and rounding errors */ middle = max - ( ( max - min ) >> 1 ); if ( glyphID == *middle ) { *index = middle - cf1->GlyphArray; return TT_Err_Ok; } else if ( glyphID < *middle ) { max = middle - 1; } else { min = middle + 1; } } while ( min <= max ); return TTO_Err_Not_Covered; } static inline FT_Error Coverage_Index2( TTO_CoverageFormat2* cf2, FT_UShort glyphID, FT_UShort* index ) { TTO_RangeRecord* min, *max, *middle; /* binary search */ min = cf2->RangeRecord; max = min + cf2->RangeCount - 1; do { /* we use (min + max) / 2 = max - (max - min) / 2 to avoid overflow and rounding errors */ middle = max - ( ( max - min ) >> 1 ); if ( glyphID >= middle->Start && glyphID <= middle->End ) { *index = middle->StartCoverageIndex + glyphID - middle->Start; return TT_Err_Ok;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -