📄 harfbuzz-gsub.c
字号:
}static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr ){ FREE( cscr->SubstLookupRecord ); FREE( cscr->Lookahead ); FREE( cscr->Input ); FREE( cscr->Backtrack );}/* SubClassSet */static HB_Error Load_ChainSubClassSet( HB_ChainContextSubstFormat2* ccsf2, HB_ChainSubClassSet* cscs, HB_Stream stream ){ HB_Error error; HB_UShort n = 0, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_ChainSubClassRule* cscr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = cscs->ChainSubClassRuleCount = GET_UShort(); FORGET_Frame(); cscs->ChainSubClassRule = NULL; if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count, HB_ChainSubClassRule ) ) return error; cscr = cscs->ChainSubClassRule; 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_ChainSubClassRule( ccsf2, &cscr[n], stream ) ) != HB_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_ChainSubClassRule( &cscr[m] ); FREE( cscr ); return error;}static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs ){ HB_UShort n, count; HB_ChainSubClassRule* cscr; if ( cscs->ChainSubClassRule ) { count = cscs->ChainSubClassRuleCount; cscr = cscs->ChainSubClassRule; for ( n = 0; n < count; n++ ) Free_ChainSubClassRule( &cscr[n] ); FREE( cscr ); }}/* ChainContextSubstFormat2 */static HB_Error Load_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2, HB_Stream stream ){ HB_Error error; HB_UShort n = 0, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_UInt backtrack_offset, input_offset, lookahead_offset; HB_ChainSubClassSet* cscs; base_offset = FILE_Pos() - 2; 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( &ccsf2->Coverage, stream ) ) != HB_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 8L ) ) goto Fail5; backtrack_offset = GET_UShort(); input_offset = GET_UShort(); lookahead_offset = GET_UShort(); /* `ChainSubClassSetCount' is the upper limit for input class values, thus we read it now to make an additional safety check. No limit is known or needed for the other two class definitions */ count = ccsf2->ChainSubClassSetCount = GET_UShort(); FORGET_Frame(); if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535, backtrack_offset, base_offset, stream ) ) != HB_Err_Ok ) goto Fail5; if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count, input_offset, base_offset, stream ) ) != HB_Err_Ok ) goto Fail4; if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535, lookahead_offset, base_offset, stream ) ) != HB_Err_Ok ) goto Fail3; ccsf2->ChainSubClassSet = NULL; ccsf2->MaxBacktrackLength = 0; ccsf2->MaxInputLength = 0; ccsf2->MaxLookaheadLength = 0; if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) ) goto Fail2; cscs = ccsf2->ChainSubClassSet; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail1; new_offset = GET_UShort() + base_offset; FORGET_Frame(); if ( new_offset != base_offset ) /* not a NULL offset */ { cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_ChainSubClassSet( ccsf2, &cscs[n], stream ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } else { /* we create a ChainSubClassSet table with no entries */ ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0; ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL; } } return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_ChainSubClassSet( &cscs[m] ); FREE( cscs );Fail2: _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );Fail3: _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );Fail4: _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );Fail5: _HB_OPEN_Free_Coverage( &ccsf2->Coverage ); return error;}static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 ){ HB_UShort n, count; HB_ChainSubClassSet* cscs; if ( ccsf2->ChainSubClassSet ) { count = ccsf2->ChainSubClassSetCount; cscs = ccsf2->ChainSubClassSet; for ( n = 0; n < count; n++ ) Free_ChainSubClassSet( &cscs[n] ); FREE( cscs ); } _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef ); _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef ); _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef ); _HB_OPEN_Free_Coverage( &ccsf2->Coverage );}/* ChainContextSubstFormat3 */static HB_Error Load_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3, HB_Stream stream ){ HB_Error error; HB_UShort n, nb = 0, ni =0, nl = 0, m, count; HB_UShort backtrack_count, input_count, lookahead_count; HB_UInt cur_offset, new_offset, base_offset; HB_Coverage* b; HB_Coverage* i; HB_Coverage* l; HB_SubstLookupRecord* slr; base_offset = FILE_Pos() - 2L; if ( ACCESS_Frame( 2L ) ) return error; ccsf3->BacktrackGlyphCount = GET_UShort(); FORGET_Frame(); ccsf3->BacktrackCoverage = NULL; backtrack_count = ccsf3->BacktrackGlyphCount; if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count, HB_Coverage ) ) return error; b = ccsf3->BacktrackCoverage; for ( nb = 0; nb < backtrack_count; nb++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail4; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) goto Fail4; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail4; ccsf3->InputGlyphCount = GET_UShort(); FORGET_Frame(); ccsf3->InputCoverage = NULL; input_count = ccsf3->InputGlyphCount; if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) ) goto Fail4; i = ccsf3->InputCoverage; for ( ni = 0; ni < input_count; ni++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail3; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok ) goto Fail3; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail3; ccsf3->LookaheadGlyphCount = GET_UShort(); FORGET_Frame(); ccsf3->LookaheadCoverage = NULL; lookahead_count = ccsf3->LookaheadGlyphCount; if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count, HB_Coverage ) ) goto Fail3; l = ccsf3->LookaheadCoverage; for ( nl = 0; nl < lookahead_count; nl++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail2; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail2; ccsf3->SubstCount = GET_UShort(); FORGET_Frame(); ccsf3->SubstLookupRecord = NULL; count = ccsf3->SubstCount; if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count, HB_SubstLookupRecord ) ) goto Fail2; slr = ccsf3->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 HB_Err_Ok;Fail1: FREE( slr );Fail2: for ( m = 0; m < nl; m++ ) _HB_OPEN_Free_Coverage( &l[m] ); FREE( l );Fail3: for ( m = 0; m < ni; m++ ) _HB_OPEN_Free_Coverage( &i[m] ); FREE( i );Fail4: for ( m = 0; m < nb; m++ ) _HB_OPEN_Free_Coverage( &b[m] ); FREE( b ); return error;}static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 ){ HB_UShort n, count; HB_Coverage* c; FREE( ccsf3->SubstLookupRecord ); if ( ccsf3->LookaheadCoverage ) { count = ccsf3->LookaheadGlyphCount; c = ccsf3->LookaheadCoverage; for ( n = 0; n < count; n++ ) _HB_OPEN_Free_Coverage( &c[n] ); FREE( c ); } if ( ccsf3->InputCoverage ) { count = ccsf3->InputGlyphCount; c = ccsf3->InputCoverage; for ( n = 0; n < count; n++ ) _HB_OPEN_Free_Coverage( &c[n] ); FREE( c ); } if ( ccsf3->BacktrackCoverage ) { count = ccsf3->BacktrackGlyphCount; c = ccsf3->BacktrackCoverage; for ( n = 0; n < count; n++ ) _HB_OPEN_Free_Coverage( &c[n] ); FREE( c ); }}/* ChainContextSubst */static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st, HB_Stream stream ){ HB_Error error; HB_ChainContextSubst* ccs = &st->chain; if ( ACCESS_Frame( 2L ) ) return error; ccs->SubstFormat = GET_UShort(); FORGET_Frame(); switch ( ccs->SubstFormat ) { case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream ); case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream ); case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream ); default: return ERR(HB_Err_Invalid_SubTable_Format); } return HB_Err_Ok; /* never reached */}static void Free_ChainContextSubst( HB_GSUB_SubTable* st ){ HB_ChainContextSubst* ccs = &st->chain; switch ( ccs->SubstFormat ) { case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break; case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break; case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break; default: break; }}static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub, HB_ChainContextSubstFormat1* ccsf1, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_UShort index, property; HB_UShort i, j, k, num_csr; HB_UShort bgc, igc, lgc; HB_Error error; HB_ChainSubRule* csr; HB_ChainSubRule curr_csr; HB_GDEFHeader* gdef; gdef = gsub->gdef; if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; csr = ccsf1->ChainSubRuleSet[index].ChainSubRule; num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount; for ( k = 0; k < num_csr; k++ ) { curr_csr = csr[k]; bgc = curr_csr.BacktrackGlyphCount; igc = curr_csr.InputGlyphCount; lgc = curr_csr.LookaheadGlyphCount; if ( context_length != 0xFFFF && context_length < igc ) goto next_chainsubrule; /* check whether context is too long; it is a first guess only */ if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) goto next_chainsubrule; if ( bgc ) { /* since we don't know in advance the number of glyphs to inspect, we search backwards for matches in the backtrack glyph array */ for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) { while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + 1 == bgc - i ) goto next_chainsubrule; j--; } /* In OpenType 1.3, it is undefined whether the offsets of backtrack glyphs is in logical order or not. Version 1.4 will clarify this: Logical order - a b c d e f g h i j i Input offsets - 0 1 Backtrack offsets - 3 2 1 0 Lookahead offsets - 0 1 2 3 */ if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] ) goto next_chainsubrule; } } /* Start at 1 because [0] is implied */ for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) goto next_chainsubrule; j++; } if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] ) goto next_chainsubrule; } /* we are starting to check for lookahead glyphs right after the last context glyph */ for ( i = 0; i < lgc; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + lgc - i == (HB_Int)buffer->in_length ) goto next_chainsubrule; j++; } if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] ) goto next_chainsubrule; } return Do_ContextSubst( gsub, igc, curr_csr.SubstCount, curr_csr.SubstLookupRecord, buffer, nesting_level ); next_chainsubrule: ; } return HB_Err_Not_Covered;}static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub, HB_ChainContextSubstFormat2* ccsf2, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_UShort index, property; HB_Error error; HB_UShort i, j, k;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -