📄 harfbuzz-gsub.c
字号:
(void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = as->AlternateSetCount = GET_UShort(); FORGET_Frame(); as->AlternateSet = NULL; if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) ) goto Fail2; aset = as->AlternateSet; 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_AlternateSet( &aset[n], stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_AlternateSet( &aset[m], memory ); FREE( aset );Fail2: _HB_OPEN_Free_Coverage( &as->Coverage, memory ); return error;}static void Free_AlternateSubst( HB_GSUB_SubTable* st, FT_Memory memory ){ FT_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], memory ); FREE( aset ); } _HB_OPEN_Free_Coverage( &as->Coverage, memory );}static FT_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub, HB_GSUB_SubTable* st, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_Error error; FT_UShort index, alt_index, property; HB_AlternateSubst* as = &st->alternate; HB_GDEFHeader* gdef = gsub->gdef; HB_AlternateSet aset; FT_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; if ( ADD_Glyph( buffer, aset.Alternate[alt_index], 0xFFFF, 0xFFFF ) ) return error; if ( gdef && gdef->NewGlyphClasses ) { /* we inherit the old glyph class to the substituted glyph */ error = _HB_GDEF_Add_Glyph_Property( gdef, aset.Alternate[alt_index], property ); if ( error && error != HB_Err_Not_Covered ) return error; } return FT_Err_Ok;}/* LookupType 4 *//* Ligature */static FT_Error Load_Ligature( HB_Ligature* l, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_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, FT_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 FT_Err_Ok;}static void Free_Ligature( HB_Ligature* l, FT_Memory memory ){ FREE( l->Component );}/* LigatureSet */static FT_Error Load_LigatureSet( HB_LigatureSet* ls, 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_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 ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_Ligature( &l[m], memory ); FREE( l ); return error;}static void Free_LigatureSet( HB_LigatureSet* ls, FT_Memory memory ){ FT_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], memory ); FREE( l ); }}/* LigatureSubstFormat1 */static FT_Error Load_LigatureSubst( HB_GSUB_SubTable* st, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; HB_LigatureSubst* ls = &st->ligature; FT_UShort n = 0, m, count; FT_ULong 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 ) ) != FT_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 ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_LigatureSet( &lset[m], memory ); FREE( lset );Fail2: _HB_OPEN_Free_Coverage( &ls->Coverage, memory ); return error;}static void Free_LigatureSubst( HB_GSUB_SubTable* st, FT_Memory memory ){ FT_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], memory ); FREE( lset ); } _HB_OPEN_Free_Coverage( &ls->Coverage, memory );}static FT_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub, HB_GSUB_SubTable* st, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_UShort index, property; FT_Error error; FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE; FT_UShort* c; HB_LigatureSubst* ls = &st->ligature; HB_GDEFHeader* gdef = gsub->gdef; HB_Ligature* lig; FT_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 HB_Err_Invalid_GSUB_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 == (FT_Long)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 { FT_UShort ligID = hb_buffer_allocate_ligid( buffer ); if ( ADD_String( buffer, i, 1, &lig->LigGlyph, 0xFFFF, ligID ) ) return error; } } else { FT_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 FT_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 FT_Error Do_ContextSubst( HB_GSUBHeader* gsub, FT_UShort GlyphCount, FT_UShort SubstCount, HB_SubstLookupRecord* subst, HB_Buffer buffer, int nesting_level ){ FT_Error error; FT_UShort 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 ) { /* XXX "can't happen" -- but don't count on it */ if ( ADD_Glyph( buffer, IN_CURGLYPH(), 0xFFFF, 0xFFFF ) ) return error; i++; } else if ( error ) return error; } else { /* No substitution for this index */ if ( ADD_Glyph( buffer, IN_CURGLYPH(), 0xFFFF, 0xFFFF ) ) return error; i++; } } return FT_Err_Ok;}/* LookupType 5 *//* SubRule */static FT_Error Load_SubRule( HB_SubRule* sr, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, count; FT_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, FT_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 FT_Err_Ok;Fail1: FREE( slr );Fail2: FREE( i ); return error;}static void Free_SubRule( HB_SubRule* sr, FT_Memory memory ){ FREE( sr->SubstLookupRecord ); FREE( sr->Input );}/* SubRuleSet */static FT_Error Load_SubRuleSet( HB_SubRuleSet* srs, 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -