📄 harfbuzz-gsub.c
字号:
HB_GDEFHeader* gdef; gdef = gsub->gdef; if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; sr = csf1->SubRuleSet[index].SubRule; numsr = csf1->SubRuleSet[index].SubRuleCount; for ( k = 0; k < numsr; k++ ) { if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) goto next_subrule; if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length ) goto next_subrule; /* context is too long */ for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + sr[k].GlyphCount - i == (FT_Long)buffer->in_length ) goto next_subrule; j++; } if ( IN_GLYPH( j ) != sr[k].Input[i - 1] ) goto next_subrule; } return Do_ContextSubst( gsub, sr[k].GlyphCount, sr[k].SubstCount, sr[k].SubstLookupRecord, buffer, nesting_level ); next_subrule: ; } return HB_Err_Not_Covered;}static FT_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub, HB_ContextSubstFormat2* csf2, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_UShort index, property; FT_Error error; FT_Memory memory = gsub->memory; FT_UShort i, j, k, known_classes; FT_UShort* classes; FT_UShort* cl; HB_SubClassSet* scs; HB_SubClassRule* sr; HB_GDEFHeader* gdef; gdef = gsub->gdef; if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; /* Note: The coverage table in format 2 doesn't give an index into anything. It just lets us know whether or not we need to do any lookup at all. */ error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) ) return error; error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(), &classes[0], NULL ); if ( error && error != HB_Err_Not_Covered ) goto End; known_classes = 0; scs = &csf2->SubClassSet[classes[0]]; if ( !scs ) { error = HB_Err_Invalid_GSUB_SubTable; goto End; } for ( k = 0; k < scs->SubClassRuleCount; k++ ) { sr = &scs->SubClassRule[k]; if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) goto next_subclassrule; if ( buffer->in_pos + sr->GlyphCount > buffer->in_length ) goto next_subclassrule; /* context is too long */ cl = sr->Class; /* Start at 1 because [0] is implied */ for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) goto End; if ( j + sr->GlyphCount - i < (FT_Long)buffer->in_length ) goto next_subclassrule; j++; } if ( i > known_classes ) { /* Keeps us from having to do this for each rule */ error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); if ( error && error != HB_Err_Not_Covered ) goto End; known_classes = i; } if ( cl[i - 1] != classes[i] ) goto next_subclassrule; } error = Do_ContextSubst( gsub, sr->GlyphCount, sr->SubstCount, sr->SubstLookupRecord, buffer, nesting_level ); goto End; next_subclassrule: ; } error = HB_Err_Not_Covered;End: FREE( classes ); return error;}static FT_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub, HB_ContextSubstFormat3* csf3, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_Error error; FT_UShort index, i, j, property; HB_Coverage* c; HB_GDEFHeader* gdef; gdef = gsub->gdef; if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) return HB_Err_Not_Covered; if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length ) return HB_Err_Not_Covered; /* context is too long */ c = csf3->Coverage; for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + csf3->GlyphCount - i == (FT_Long)buffer->in_length ) return HB_Err_Not_Covered; j++; } error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index ); if ( error ) return error; } return Do_ContextSubst( gsub, csf3->GlyphCount, csf3->SubstCount, csf3->SubstLookupRecord, buffer, nesting_level );}static FT_Error Lookup_ContextSubst( HB_GSUBHeader* gsub, HB_GSUB_SubTable* st, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ HB_ContextSubst* cs = &st->context; switch ( cs->SubstFormat ) { case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level ); case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level ); case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level ); default: return HB_Err_Invalid_GSUB_SubTable_Format; } return FT_Err_Ok; /* never reached */}/* LookupType 6 *//* ChainSubRule */static FT_Error Load_ChainSubRule( HB_ChainSubRule* csr, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_UShort* b; FT_UShort* i; FT_UShort* l; HB_SubstLookupRecord* slr; if ( ACCESS_Frame( 2L ) ) return error; csr->BacktrackGlyphCount = GET_UShort(); FORGET_Frame(); csr->Backtrack = NULL; count = csr->BacktrackGlyphCount; if ( ALLOC_ARRAY( csr->Backtrack, count, FT_UShort ) ) return error; b = csr->Backtrack; if ( ACCESS_Frame( count * 2L ) ) goto Fail4; for ( n = 0; n < count; n++ ) b[n] = GET_UShort(); FORGET_Frame(); if ( ACCESS_Frame( 2L ) ) goto Fail4; csr->InputGlyphCount = GET_UShort(); FORGET_Frame(); csr->Input = NULL; count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ if ( ALLOC_ARRAY( csr->Input, count, FT_UShort ) ) goto Fail4; i = csr->Input; if ( ACCESS_Frame( count * 2L ) ) goto Fail3; for ( n = 0; n < count; n++ ) i[n] = GET_UShort(); FORGET_Frame(); if ( ACCESS_Frame( 2L ) ) goto Fail3; csr->LookaheadGlyphCount = GET_UShort(); FORGET_Frame(); csr->Lookahead = NULL; count = csr->LookaheadGlyphCount; if ( ALLOC_ARRAY( csr->Lookahead, count, FT_UShort ) ) goto Fail3; l = csr->Lookahead; if ( ACCESS_Frame( count * 2L ) ) goto Fail2; for ( n = 0; n < count; n++ ) l[n] = GET_UShort(); FORGET_Frame(); if ( ACCESS_Frame( 2L ) ) goto Fail2; csr->SubstCount = GET_UShort(); FORGET_Frame(); csr->SubstLookupRecord = NULL; count = csr->SubstCount; if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) goto Fail2; slr = csr->SubstLookupRecord; if ( ACCESS_Frame( count * 4L ) ) goto Fail1; for ( n = 0; n < count; n++ ) { slr[n].SequenceIndex = GET_UShort(); slr[n].LookupListIndex = GET_UShort(); } FORGET_Frame(); return FT_Err_Ok;Fail1: FREE( slr );Fail2: FREE( l );Fail3: FREE( i );Fail4: FREE( b ); return error;}static void Free_ChainSubRule( HB_ChainSubRule* csr, FT_Memory memory ){ FREE( csr->SubstLookupRecord ); FREE( csr->Lookahead ); FREE( csr->Input ); FREE( csr->Backtrack );}/* ChainSubRuleSet */static FT_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n = 0, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_ChainSubRule* csr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = csrs->ChainSubRuleCount = GET_UShort(); FORGET_Frame(); csrs->ChainSubRule = NULL; if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) ) return error; csr = csrs->ChainSubRule; 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_ChainSubRule( &csr[n], stream ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_ChainSubRule( &csr[m], memory ); FREE( csr ); return error;}static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs, FT_Memory memory ){ FT_UShort n, count; HB_ChainSubRule* csr; if ( csrs->ChainSubRule ) { count = csrs->ChainSubRuleCount; csr = csrs->ChainSubRule; for ( n = 0; n < count; n++ ) Free_ChainSubRule( &csr[n], memory ); FREE( csr ); }}/* ChainContextSubstFormat1 */static FT_Error Load_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n = 0, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_ChainSubRuleSet* csrs; base_offset = FILE_Pos() - 2L; if ( ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = ccsf1->ChainSubRuleSetCount = GET_UShort(); FORGET_Frame(); ccsf1->ChainSubRuleSet = NULL; if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) ) goto Fail2; csrs = ccsf1->ChainSubRuleSet; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail1; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_ChainSubRuleSet( &csrs[m], memory ); FREE( csrs );Fail2: _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory ); return error;}static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1, FT_Memory memory ){ FT_UShort n, count; HB_ChainSubRuleSet* csrs; if ( ccsf1->ChainSubRuleSet ) { count = ccsf1->ChainSubRuleSetCount; csrs = ccsf1->ChainSubRuleSet; for ( n = 0; n < count; n++ ) Free_ChainSubRuleSet( &csrs[n], memory ); FREE( csrs ); } _HB_OPEN_Free_Coverage( &ccsf1->Coverage, memory );}/* ChainSubClassRule */static FT_Error Load_ChainSubClassRule( HB_ChainContextSubstFormat2* ccsf2, HB_ChainSubClassRule* cscr, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_UShort* b; FT_UShort* i; FT_UShort* l; HB_SubstLookupRecord* slr; FT_Bool* d; if ( ACCESS_Frame( 2L ) ) return error; cscr->BacktrackGlyphCount = GET_UShort(); FORGET_Frame(); if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength ) ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount; cscr->Backtrack = NULL; count = cscr->BacktrackGlyphCount; if ( ALLOC_ARRAY( cscr->Backtrack, count, FT_UShort ) ) return error; b = cscr->Backtrack; d = ccsf2->BacktrackClassDef.Defined; if ( ACCESS_Frame( count * 2L ) ) goto Fail4; for ( n = 0; n < count; n++ ) { b[n] = GET_UShort(); /* We check whether the specific class is used at all. If not, class 0 is used instead. */ if ( !d[b[n]] ) b[n] = 0; } FORGET_Frame(); if ( ACCESS_Frame( 2L ) ) goto Fail4; cscr->InputGlyphCount = GET_UShort(); FORGET_Frame(); if ( cscr->InputGlyphCount > ccsf2->MaxInputLength ) ccsf2->MaxInputLength = cscr->InputGlyphCount; cscr->Input = NULL; count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ if ( ALLOC_ARRAY( cscr->Input, count, FT_UShort ) ) goto Fail4; i = cscr->Input; d = ccsf2->InputClassDef.Defined; if ( ACCESS_Frame( count * 2L ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -