📄 harfbuzz-gpos.c
字号:
if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) ) goto Fail; lan = cr[m].LigatureAnchor; for ( n = 0; n < num_classes; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail0; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Anchor( &lan[n], stream ) ) != FT_Err_Ok ) goto Fail0; (void)FILE_Seek( cur_offset ); } else lan[n].PosFormat = 0; } continue; Fail0: for ( k = 0; k < n; k++ ) Free_Anchor( &lan[k], memory ); goto Fail; } return FT_Err_Ok;Fail: for ( k = 0; k < m; k++ ) { lan = cr[k].LigatureAnchor; for ( n = 0; n < num_classes; n++ ) Free_Anchor( &lan[n], memory ); FREE( lan ); } FREE( cr ); return error;}static void Free_LigatureAttach( HB_LigatureAttach* lat, FT_UShort num_classes, FT_Memory memory ){ FT_UShort m, n, count; HB_ComponentRecord* cr; HB_Anchor* lan; if ( lat->ComponentRecord ) { count = lat->ComponentCount; cr = lat->ComponentRecord; for ( m = 0; m < count; m++ ) { lan = cr[m].LigatureAnchor; for ( n = 0; n < num_classes; n++ ) Free_Anchor( &lan[n], memory ); FREE( lan ); } FREE( cr ); }}/* LigatureArray */static FT_Error Load_LigatureArray( HB_LigatureArray* la, FT_UShort num_classes, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_LigatureAttach* lat; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = la->LigatureCount = GET_UShort(); FORGET_Frame(); la->LigatureAttach = NULL; if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) ) return error; lat = la->LigatureAttach; 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_LigatureAttach( &lat[n], num_classes, stream ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_LigatureAttach( &lat[m], num_classes, memory ); FREE( lat ); return error;}static void Free_LigatureArray( HB_LigatureArray* la, FT_UShort num_classes, FT_Memory memory ){ FT_UShort n, count; HB_LigatureAttach* lat; if ( la->LigatureAttach ) { count = la->LigatureCount; lat = la->LigatureAttach; for ( n = 0; n < count; n++ ) Free_LigatureAttach( &lat[n], num_classes, memory ); FREE( lat ); }}/* MarkLigPosFormat1 */static FT_Error Load_MarkLigPos( HB_GPOS_SubTable* st, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; HB_MarkLigPos* mlp = &st->marklig; FT_ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 4L ) ) return error; mlp->PosFormat = GET_UShort(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); 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( &mlp->LigatureCoverage, stream ) ) != FT_Err_Ok ) goto Fail3; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 4L ) ) goto Fail2; mlp->ClassCount = GET_UShort(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != FT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); 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_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, stream ) ) != FT_Err_Ok ) goto Fail1; return FT_Err_Ok;Fail1: Free_MarkArray( &mlp->MarkArray, memory );Fail2: _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );Fail3: _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory ); return error;}static void Free_MarkLigPos( HB_GPOS_SubTable* st, FT_Memory memory){ HB_MarkLigPos* mlp = &st->marklig; Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, memory ); Free_MarkArray( &mlp->MarkArray, memory ); _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory ); _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );}static FT_Error Lookup_MarkLigPos( GPOS_Instance* gpi, HB_GPOS_SubTable* st, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_UShort i, j, mark_index, lig_index, property, class; FT_UShort mark_glyph; FT_Pos x_mark_value, y_mark_value, x_lig_value, y_lig_value; FT_Error error; HB_GPOSHeader* gpos = gpi->gpos; HB_MarkLigPos* mlp = &st->marklig; HB_MarkArray* ma; HB_LigatureArray* la; HB_LigatureAttach* lat; HB_ComponentRecord* cr; FT_UShort comp_index; HB_Anchor* mark_anchor; HB_Anchor* lig_anchor; HB_Position o; FT_UNUSED(nesting_level); if ( context_length != 0xFFFF && context_length < 1 ) return HB_Err_Not_Covered; if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES ) return HB_Err_Not_Covered; mark_glyph = IN_CURGLYPH(); if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index ); if ( error ) return error; /* now we search backwards for a non-mark glyph */ i = 1; j = buffer->in_pos - 1; while ( i <= buffer->in_pos ) { error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ), &property ); if ( error ) return error; if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) break; i++; j--; } /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is too strong, thus it is commented out. */#if 0 if ( property != HB_GDEF_LIGATURE ) return HB_Err_Not_Covered;#endif if ( i > buffer->in_pos ) return HB_Err_Not_Covered; error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ), &lig_index ); if ( error ) return error; ma = &mlp->MarkArray; if ( mark_index >= ma->MarkCount ) return HB_Err_Invalid_GPOS_SubTable; class = ma->MarkRecord[mark_index].Class; mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; if ( class >= mlp->ClassCount ) return HB_Err_Invalid_GPOS_SubTable; la = &mlp->LigatureArray; if ( lig_index >= la->LigatureCount ) return HB_Err_Invalid_GPOS_SubTable; lat = &la->LigatureAttach[lig_index]; /* We must now check whether the ligature ID of the current mark glyph is identical to the ligature ID of the found ligature. If yes, we can directly use the component index. If not, we attach the mark glyph to the last component of the ligature. */ if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) ) { comp_index = IN_COMPONENT( buffer->in_pos ); if ( comp_index >= lat->ComponentCount ) return HB_Err_Not_Covered; } else comp_index = lat->ComponentCount - 1; cr = &lat->ComponentRecord[comp_index]; lig_anchor = &cr->LigatureAnchor[class]; error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(), &x_mark_value, &y_mark_value ); if ( error ) return error; error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ), &x_lig_value, &y_lig_value ); if ( error ) return error; /* anchor points are not cumulative */ o = POSITION( buffer->in_pos ); o->x_pos = x_lig_value - x_mark_value; o->y_pos = y_lig_value - y_mark_value; o->x_advance = 0; o->y_advance = 0; o->back = i; (buffer->in_pos)++; return FT_Err_Ok;}/* LookupType 6 *//* Mark2Array */static FT_Error Load_Mark2Array( HB_Mark2Array* m2a, FT_UShort num_classes, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort k, m, n, count; FT_ULong cur_offset, new_offset, base_offset; HB_Mark2Record* m2r; HB_Anchor* m2an; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = m2a->Mark2Count = GET_UShort(); FORGET_Frame(); m2a->Mark2Record = NULL; if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) ) return error; m2r = m2a->Mark2Record; for ( m = 0; m < count; m++ ) { m2r[m].Mark2Anchor = NULL; if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, HB_Anchor ) ) goto Fail; m2an = m2r[m].Mark2Anchor; for ( n = 0; n < num_classes; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail0; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Anchor( &m2an[n], stream ) ) != FT_Err_Ok ) goto Fail0; (void)FILE_Seek( cur_offset ); } continue; Fail0: for ( k = 0; k < n; k++ ) Free_Anchor( &m2an[k], memory ); goto Fail; } return FT_Err_Ok;Fail: for ( k = 0; k < m; k++ ) { m2an = m2r[k].Mark2Anchor; for ( n = 0; n < num_classes; n++ ) Free_Anchor( &m2an[n], memory ); FREE( m2an ); } FREE( m2r ); return error;}static void Free_Mark2Array( HB_Mark2Array* m2a, FT_UShort num_classes, FT_Memory memory ){ FT_UShort m, n, count; HB_Mark2Record* m2r; HB_Anchor* m2an; if ( m2a->Mark2Record ) { count = m2a->Mark2Count; m2r = m2a->Mark2Record; for ( m = 0; m < count; m++ ) { m2an = m2r[m].Mark2Anchor; for ( n = 0; n < num_classes; n++ ) Free_Anchor( &m2an[n], memory ); FREE( m2an ); } FREE( m2r ); }}/* MarkMarkPosFormat1 */static FT_Error Load_MarkMarkPos( HB_GPOS_SubTable* st, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; HB_MarkMarkPos* mmp = &st->markmark; FT_ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 4L ) ) return error; mmp->PosFormat = GET_UShort(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); 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( &mmp->Mark2Coverage, stream ) ) != FT_Err_Ok ) goto Fail3; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 4L ) ) goto Fail2; mmp->ClassCount = GET_UShort(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != FT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); 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_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, stream ) ) != FT_Err_Ok ) goto Fail1; return FT_Err_Ok;Fail1: Free_MarkArray( &mmp->Mark1Array, memory );Fail2: _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );Fail3: _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory ); return error;}static void Free_MarkMarkPos( HB_GPOS_SubTable* st,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -