📄 harfbuzz-gsub.c
字号:
for ( m = 0; m < n; m++ ) Free_AlternateSet( &aset[m] ); FREE( aset );Fail2: _HB_OPEN_Free_Coverage( &as->Coverage ); return error;}static void Free_AlternateSubst( HB_GSUB_SubTable* st ){ HB_UShort n, count; HB_AlternateSubst* as = &st->alternate; HB_AlternateSet* aset; if ( as->AlternateSet ) { count = as->AlternateSetCount; aset = as->AlternateSet; for ( n = 0; n < count; n++ ) Free_AlternateSet( &aset[n] ); FREE( aset ); } _HB_OPEN_Free_Coverage( &as->Coverage );}static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub, HB_GSUB_SubTable* st, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_Error error; HB_UShort index, value, alt_index, property; HB_AlternateSubst* as = &st->alternate; HB_GDEFHeader* gdef = gsub->gdef; HB_AlternateSet aset; HB_UNUSED(nesting_level); if ( context_length != 0xFFFF && context_length < 1 ) return HB_Err_Not_Covered; if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; aset = as->AlternateSet[index]; /* we use a user-defined callback function to get the alternate index */ if ( gsub->altfunc ) alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(), aset.GlyphCount, aset.Alternate, gsub->data ); else alt_index = 0; value = aset.Alternate[alt_index]; if ( REPLACE_Glyph( buffer, value, nesting_level ) ) return error; if ( gdef && gdef->NewGlyphClasses ) { /* we inherit the old glyph class to the substituted glyph */ error = _HB_GDEF_Add_Glyph_Property( gdef, value, property ); if ( error && error != HB_Err_Not_Covered ) return error; } return HB_Err_Ok;}/* LookupType 4 *//* Ligature */static HB_Error Load_Ligature( HB_Ligature* l, HB_Stream stream ){ HB_Error error; HB_UShort n, count; HB_UShort* c; if ( ACCESS_Frame( 4L ) ) return error; l->LigGlyph = GET_UShort(); l->ComponentCount = GET_UShort(); FORGET_Frame(); l->Component = NULL; count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */ if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) ) return error; c = l->Component; if ( ACCESS_Frame( count * 2L ) ) { FREE( c ); return error; } for ( n = 0; n < count; n++ ) c[n] = GET_UShort(); FORGET_Frame(); return HB_Err_Ok;}static void Free_Ligature( HB_Ligature* l ){ FREE( l->Component );}/* LigatureSet */static HB_Error Load_LigatureSet( HB_LigatureSet* ls, HB_Stream stream ){ HB_Error error; HB_UShort n = 0, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_Ligature* l; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = ls->LigatureCount = GET_UShort(); FORGET_Frame(); ls->Ligature = NULL; if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) ) return error; l = ls->Ligature; 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_Ligature( &l[n], stream ) ) != HB_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_Ligature( &l[m] ); FREE( l ); return error;}static void Free_LigatureSet( HB_LigatureSet* ls ){ HB_UShort n, count; HB_Ligature* l; if ( ls->Ligature ) { count = ls->LigatureCount; l = ls->Ligature; for ( n = 0; n < count; n++ ) Free_Ligature( &l[n] ); FREE( l ); }}/* LigatureSubstFormat1 */static HB_Error Load_LigatureSubst( HB_GSUB_SubTable* st, HB_Stream stream ){ HB_Error error; HB_LigatureSubst* ls = &st->ligature; HB_UShort n = 0, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_LigatureSet* lset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 4L ) ) return error; ls->SubstFormat = GET_UShort(); /* should be 1 */ new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = ls->LigatureSetCount = GET_UShort(); FORGET_Frame(); ls->LigatureSet = NULL; if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) ) goto Fail2; lset = ls->LigatureSet; 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_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_LigatureSet( &lset[m] ); FREE( lset );Fail2: _HB_OPEN_Free_Coverage( &ls->Coverage ); return error;}static void Free_LigatureSubst( HB_GSUB_SubTable* st ){ HB_UShort n, count; HB_LigatureSubst* ls = &st->ligature; HB_LigatureSet* lset; if ( ls->LigatureSet ) { count = ls->LigatureSetCount; lset = ls->LigatureSet; for ( n = 0; n < count; n++ ) Free_LigatureSet( &lset[n] ); FREE( lset ); } _HB_OPEN_Free_Coverage( &ls->Coverage );}static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub, HB_GSUB_SubTable* st, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_UShort index, property; HB_Error error; HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE; HB_UShort* c; HB_LigatureSubst* ls = &st->ligature; HB_GDEFHeader* gdef = gsub->gdef; HB_Ligature* lig; HB_UNUSED(nesting_level); if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) return error; if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) first_is_mark = TRUE; error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; if ( index >= ls->LigatureSetCount ) return ERR(HB_Err_Invalid_SubTable); lig = ls->LigatureSet[index].Ligature; for ( numlig = ls->LigatureSet[index].LigatureCount; numlig; numlig--, lig++ ) { if ( buffer->in_pos + lig->ComponentCount > buffer->in_length ) goto next_ligature; /* Not enough glyphs in input */ c = lig->Component; is_mark = first_is_mark; if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) break; for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ ) { while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length ) goto next_ligature; j++; } if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) is_mark = FALSE; if ( IN_GLYPH( j ) != c[i - 1] ) goto next_ligature; } if ( gdef && gdef->NewGlyphClasses ) { /* this is just a guess ... */ error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph, is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE ); if ( error && error != HB_Err_Not_Covered ) return error; } if ( j == buffer->in_pos + i ) /* No input glyphs skipped */ { /* We don't use a new ligature ID if there are no skipped glyphs and the ligature already has an ID. */ if ( IN_LIGID( buffer->in_pos ) ) { if ( ADD_String( buffer, i, 1, &lig->LigGlyph, 0xFFFF, 0xFFFF ) ) return error; } else { HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); if ( ADD_String( buffer, i, 1, &lig->LigGlyph, 0xFFFF, ligID ) ) return error; } } else { HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) ) return error; /* Now we must do a second loop to copy the skipped glyphs to `out' and assign component values to it. We start with the glyph after the first component. Glyphs between component i and i+1 belong to component i. Together with the ligID value it is later possible to check whether a specific component value really belongs to a given ligature. */ for ( i = 0; i < lig->ComponentCount - 1; i++ ) { while ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) ) return error; (buffer->in_pos)++; } } return HB_Err_Ok; next_ligature: ; } return HB_Err_Not_Covered;}/* Do the actual substitution for a context substitution (either format 5 or 6). This is only called after we've determined that the input matches the subrule. */static HB_Error Do_ContextSubst( HB_GSUBHeader* gsub, HB_UShort GlyphCount, HB_UShort SubstCount, HB_SubstLookupRecord* subst, HB_Buffer buffer, int nesting_level ){ HB_Error error; HB_UInt i, old_pos; i = 0; while ( i < GlyphCount ) { if ( SubstCount && i == subst->SequenceIndex ) { old_pos = buffer->in_pos; /* Do a substitution */ error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer, GlyphCount, nesting_level ); subst++; SubstCount--; i += buffer->in_pos - old_pos; if ( error == HB_Err_Not_Covered ) { if ( COPY_Glyph( buffer ) ) return error; i++; } else if ( error ) return error; } else { /* No substitution for this index */ if ( COPY_Glyph( buffer ) ) return error; i++; } } return HB_Err_Ok;}/* LookupType 5 *//* SubRule */static HB_Error Load_SubRule( HB_SubRule* sr, HB_Stream stream ){ HB_Error error; HB_UShort n, count; HB_UShort* i; HB_SubstLookupRecord* slr; if ( ACCESS_Frame( 4L ) ) return error; sr->GlyphCount = GET_UShort(); sr->SubstCount = GET_UShort(); FORGET_Frame(); sr->Input = NULL; count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */ if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) ) return error; i = sr->Input; if ( ACCESS_Frame( count * 2L ) ) goto Fail2; for ( n = 0; n < count; n++ ) i[n] = GET_UShort(); FORGET_Frame(); sr->SubstLookupRecord = NULL; count = sr->SubstCount; if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) goto Fail2; slr = sr->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: FREE( i ); return error;}static void Free_SubRule( HB_SubRule* sr ){ FREE( sr->SubstLookupRecord ); FREE( sr->Input );}/* SubRuleSet */static HB_Error Load_SubRuleSet( HB_SubRuleSet* srs, HB_Stream stream ){ HB_Error error; HB_UShort n = 0, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_SubRule* sr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = srs->SubRuleCount = GET_UShort(); FORGET_Frame(); srs->SubRule = NULL; if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) ) return error; sr = srs->SubRule; 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_SubRule( &sr[n], stream ) ) != HB_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_SubRule( &sr[m] ); FREE( sr ); return error;}static void Free_SubRuleSet( HB_SubRuleSet* srs ){ HB_UShort n, count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -