📄 harfbuzz-gpos.c
字号:
{ HB_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] ); FREE( lan ); } FREE( cr ); }}/* LigatureArray */static HB_Error Load_LigatureArray( HB_LigatureArray* la, HB_UShort num_classes, HB_Stream stream ){ HB_Error error; HB_UShort n, m, count; HB_UInt 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 ) ) != HB_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_LigatureAttach( &lat[m], num_classes ); FREE( lat ); return error;}static void Free_LigatureArray( HB_LigatureArray* la, HB_UShort num_classes ){ HB_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 ); FREE( lat ); }}/* MarkLigPosFormat1 */static HB_Error Load_MarkLigPos( HB_GPOS_SubTable* st, HB_Stream stream ){ HB_Error error; HB_MarkLigPos* mlp = &st->marklig; HB_UInt 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 ) ) != HB_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 ) ) != HB_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 ) ) != HB_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 ) ) != HB_Err_Ok ) goto Fail1; return HB_Err_Ok;Fail1: Free_MarkArray( &mlp->MarkArray );Fail2: _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );Fail3: _HB_OPEN_Free_Coverage( &mlp->MarkCoverage ); return error;}static void Free_MarkLigPos( HB_GPOS_SubTable* st ){ HB_MarkLigPos* mlp = &st->marklig; Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount ); Free_MarkArray( &mlp->MarkArray ); _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage ); _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );}static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi, HB_GPOS_SubTable* st, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_UShort i, j, mark_index, lig_index, property, class; HB_UShort mark_glyph; HB_Fixed x_mark_value, y_mark_value, x_lig_value, y_lig_value; HB_Error error; HB_GPOSHeader* gpos = gpi->gpos; HB_MarkLigPos* mlp = &st->marklig; HB_MarkArray* ma; HB_LigatureArray* la; HB_LigatureAttach* lat; HB_ComponentRecord* cr; HB_UShort comp_index; HB_Anchor* mark_anchor; HB_Anchor* lig_anchor; HB_Position o; HB_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 ERR(HB_Err_Invalid_SubTable); class = ma->MarkRecord[mark_index].Class; mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor; if ( class >= mlp->ClassCount ) return ERR(HB_Err_Invalid_SubTable); la = &mlp->LigatureArray; if ( lig_index >= la->LigatureCount ) return ERR(HB_Err_Invalid_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 HB_Err_Ok;}/* LookupType 6 *//* Mark2Array */static HB_Error Load_Mark2Array( HB_Mark2Array* m2a, HB_UShort num_classes, HB_Stream stream ){ HB_Error error; HB_UShort k, m, n, count; HB_UInt 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 ) ) != HB_Err_Ok ) goto Fail0; (void)FILE_Seek( cur_offset ); } continue; Fail0: for ( k = 0; k < n; k++ ) Free_Anchor( &m2an[k] ); goto Fail; } return HB_Err_Ok;Fail: for ( k = 0; k < m; k++ ) { m2an = m2r[k].Mark2Anchor; for ( n = 0; n < num_classes; n++ ) Free_Anchor( &m2an[n] ); FREE( m2an ); } FREE( m2r ); return error;}static void Free_Mark2Array( HB_Mark2Array* m2a, HB_UShort num_classes ){ HB_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] ); FREE( m2an ); } FREE( m2r ); }}/* MarkMarkPosFormat1 */static HB_Error Load_MarkMarkPos( HB_GPOS_SubTable* st, HB_Stream stream ){ HB_Error error; HB_MarkMarkPos* mmp = &st->markmark; HB_UInt 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 ) ) != HB_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 ) ) != HB_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 ) ) != HB_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 ) ) != HB_Err_Ok ) goto Fail1; return HB_Err_Ok;Fail1: Free_MarkArray( &mmp->Mark1Array );Fail2: _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );Fail3: _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage ); return error;}static void Free_MarkMarkPos( HB_GPOS_SubTable* st ){ HB_MarkMarkPos* mmp = &st->markmark; Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount ); Free_MarkArray( &mmp->Mark1Array ); _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage ); _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );}static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi, HB_GPOS_SubTable* st, HB_Buffer buffer, HB_UShort flags, HB_UShort context_length, int nesting_level ){ HB_UShort i, j, mark1_index, mark2_index, property, class; HB_Fixed x_mark1_value, y_mark1_value, x_mark2_value, y_mark2_value; HB_Error error; HB_GPOSHeader* gpos = gpi->gpos; HB_MarkMarkPos* mmp = &st->markmark; HB_MarkArray* ma1; HB_Mark2Array* ma2; HB_Mark2Record* m2r; HB_Anchor* mark1_anchor; HB_Anchor* mark2_anchor; HB_Position o; HB_UNUSED(nesting_level); if ( context_length != 0xFFFF && context_length < 1 ) return HB_Err_Not_Covered; if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS ) return HB_Err_Not_Covered; if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(), &mark1_index ); if ( error ) return error; /* now we search backwards for a suitable mark glyph until a non-mark glyph */ if ( buffer->in_pos == 0 ) return HB_Err_Not_Covered; 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 ) ) return HB_Err_Not_Covered; if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) { if ( property == (flags & 0xFF00) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -