📄 harfbuzz-gpos.c
字号:
FT_ULong cur_offset, new_offset, base_offset; HB_PairSet* ps; base_offset = FILE_Pos() - 8L; if ( ACCESS_Frame( 2L ) ) return error; count = ppf1->PairSetCount = GET_UShort(); FORGET_Frame(); ppf1->PairSet = NULL; if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) ) return error; ps = ppf1->PairSet; 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_PairSet( &ps[n], format1, format2, stream ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_PairSet( &ps[m], format1, format2, memory ); FREE( ps ); return error;}static void Free_PairPos1( HB_PairPosFormat1* ppf1, FT_UShort format1, FT_UShort format2, FT_Memory memory ){ FT_UShort n, count; HB_PairSet* ps; if ( ppf1->PairSet ) { count = ppf1->PairSetCount; ps = ppf1->PairSet; for ( n = 0; n < count; n++ ) Free_PairSet( &ps[n], format1, format2, memory ); FREE( ps ); }}/* PairPosFormat2 */static FT_Error Load_PairPos2( HB_PairPosFormat2* ppf2, FT_UShort format1, FT_UShort format2, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; FT_UShort m, n, k, count1, count2; FT_ULong cur_offset, new_offset1, new_offset2, base_offset; HB_Class1Record* c1r; HB_Class2Record* c2r; base_offset = FILE_Pos() - 8L; if ( ACCESS_Frame( 8L ) ) return error; new_offset1 = GET_UShort() + base_offset; new_offset2 = GET_UShort() + base_offset; /* `Class1Count' and `Class2Count' are the upper limits for class values, thus we read it now to make additional safety checks. */ count1 = ppf2->Class1Count = GET_UShort(); count2 = ppf2->Class2Count = GET_UShort(); FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset1 ) || ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1, stream ) ) != FT_Err_Ok ) return error; if ( FILE_Seek( new_offset2 ) || ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2, stream ) ) != FT_Err_Ok ) goto Fail3; (void)FILE_Seek( cur_offset ); ppf2->Class1Record = NULL; if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) ) goto Fail2; c1r = ppf2->Class1Record; for ( m = 0; m < count1; m++ ) { c1r[m].Class2Record = NULL; if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) ) goto Fail1; c2r = c1r[m].Class2Record; for ( n = 0; n < count2; n++ ) { if ( format1 ) { error = Load_ValueRecord( &c2r[n].Value1, format1, base_offset, stream ); if ( error ) goto Fail0; } if ( format2 ) { error = Load_ValueRecord( &c2r[n].Value2, format2, base_offset, stream ); if ( error ) { if ( format1 ) Free_ValueRecord( &c2r[n].Value1, format1, memory ); goto Fail0; } } } continue; Fail0: for ( k = 0; k < n; k++ ) { if ( format1 ) Free_ValueRecord( &c2r[k].Value1, format1, memory ); if ( format2 ) Free_ValueRecord( &c2r[k].Value2, format2, memory ); } goto Fail1; } return FT_Err_Ok;Fail1: for ( k = 0; k < m; k++ ) { c2r = c1r[k].Class2Record; for ( n = 0; n < count2; n++ ) { if ( format1 ) Free_ValueRecord( &c2r[n].Value1, format1, memory ); if ( format2 ) Free_ValueRecord( &c2r[n].Value2, format2, memory ); } FREE( c2r ); } FREE( c1r );Fail2: _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );Fail3: _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory ); return error;}static void Free_PairPos2( HB_PairPosFormat2* ppf2, FT_UShort format1, FT_UShort format2, FT_Memory memory ){ FT_UShort m, n, count1, count2; HB_Class1Record* c1r; HB_Class2Record* c2r; if ( ppf2->Class1Record ) { c1r = ppf2->Class1Record; count1 = ppf2->Class1Count; count2 = ppf2->Class2Count; for ( m = 0; m < count1; m++ ) { c2r = c1r[m].Class2Record; for ( n = 0; n < count2; n++ ) { if ( format1 ) Free_ValueRecord( &c2r[n].Value1, format1, memory ); if ( format2 ) Free_ValueRecord( &c2r[n].Value2, format2, memory ); } FREE( c2r ); } FREE( c1r ); _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory ); _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory ); }}static FT_Error Load_PairPos( HB_GPOS_SubTable* st, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; HB_PairPos* pp = &st->pair; FT_UShort format1, format2; FT_ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 8L ) ) return error; pp->PosFormat = GET_UShort(); new_offset = GET_UShort() + base_offset; format1 = pp->ValueFormat1 = GET_UShort(); format2 = pp->ValueFormat2 = GET_UShort(); FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); switch ( pp->PosFormat ) { case 1: error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream ); if ( error ) goto Fail; break; case 2: error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream ); if ( error ) goto Fail; break; default: return HB_Err_Invalid_GPOS_SubTable_Format; } return FT_Err_Ok;Fail: _HB_OPEN_Free_Coverage( &pp->Coverage, memory ); return error;}static void Free_PairPos( HB_GPOS_SubTable* st, FT_Memory memory ){ FT_UShort format1, format2; HB_PairPos* pp = &st->pair; format1 = pp->ValueFormat1; format2 = pp->ValueFormat2; switch ( pp->PosFormat ) { case 1: Free_PairPos1( &pp->ppf.ppf1, format1, format2, memory ); break; case 2: Free_PairPos2( &pp->ppf.ppf2, format1, format2, memory ); break; } _HB_OPEN_Free_Coverage( &pp->Coverage, memory );}static FT_Error Lookup_PairPos1( GPOS_Instance* gpi, HB_PairPosFormat1* ppf1, HB_Buffer buffer, FT_UShort first_pos, FT_UShort index, FT_UShort format1, FT_UShort format2 ){ FT_Error error; FT_UShort numpvr, glyph2; HB_PairValueRecord* pvr; if ( index >= ppf1->PairSetCount ) return HB_Err_Invalid_GPOS_SubTable; pvr = ppf1->PairSet[index].PairValueRecord; if ( !pvr ) return HB_Err_Invalid_GPOS_SubTable; glyph2 = IN_CURGLYPH(); for ( numpvr = ppf1->PairSet[index].PairValueCount; numpvr; numpvr--, pvr++ ) { if ( glyph2 == pvr->SecondGlyph ) { error = Get_ValueRecord( gpi, &pvr->Value1, format1, POSITION( first_pos ) ); if ( error ) return error; return Get_ValueRecord( gpi, &pvr->Value2, format2, POSITION( buffer->in_pos ) ); } } return HB_Err_Not_Covered;}static FT_Error Lookup_PairPos2( GPOS_Instance* gpi, HB_PairPosFormat2* ppf2, HB_Buffer buffer, FT_UShort first_pos, FT_UShort format1, FT_UShort format2 ){ FT_Error error; FT_UShort cl1, cl2; HB_Class1Record* c1r; HB_Class2Record* c2r; error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ), &cl1, NULL ); if ( error && error != HB_Err_Not_Covered ) return error; error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(), &cl2, NULL ); if ( error && error != HB_Err_Not_Covered ) return error; c1r = &ppf2->Class1Record[cl1]; if ( !c1r ) return HB_Err_Invalid_GPOS_SubTable; c2r = &c1r->Class2Record[cl2]; error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) ); if ( error ) return error; return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );}static FT_Error Lookup_PairPos( GPOS_Instance* gpi, HB_GPOS_SubTable* st, HB_Buffer buffer, FT_UShort flags, FT_UShort context_length, int nesting_level ){ FT_Error error; FT_UShort index, property, first_pos; HB_GPOSHeader* gpos = gpi->gpos; HB_PairPos* pp = &st->pair; FT_UNUSED(nesting_level); if ( buffer->in_pos >= buffer->in_length - 1 ) return HB_Err_Not_Covered; /* Not enough glyphs in stream */ if ( context_length != 0xFFFF && context_length < 2 ) return HB_Err_Not_Covered; if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) ) return error; error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; /* second glyph */ first_pos = buffer->in_pos; (buffer->in_pos)++; while ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) ) { if ( error && error != HB_Err_Not_Covered ) return error; if ( buffer->in_pos == buffer->in_length ) return HB_Err_Not_Covered; (buffer->in_pos)++; } switch ( pp->PosFormat ) { case 1: error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer, first_pos, index, pp->ValueFormat1, pp->ValueFormat2 ); break; case 2: error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos, pp->ValueFormat1, pp->ValueFormat2 ); break; default: return HB_Err_Invalid_GPOS_SubTable_Format; } /* adjusting the `next' glyph */ if ( pp->ValueFormat2 ) (buffer->in_pos)++; return error;}/* LookupType 3 *//* CursivePosFormat1 */static FT_Error Load_CursivePos( HB_GPOS_SubTable* st, FT_Stream stream ){ FT_Error error; FT_Memory memory = stream->memory; HB_CursivePos* cp = &st->cursive; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_EntryExitRecord* eer; base_offset = FILE_Pos(); if ( ACCESS_Frame( 4L ) ) return error; cp->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( &cp->Coverage, stream ) ) != FT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = cp->EntryExitCount = GET_UShort(); FORGET_Frame(); cp->EntryExitRecord = NULL; if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) ) goto Fail2; eer = cp->EntryExitRecord; for ( n = 0; n < count; n++ ) { FT_ULong entry_offset; if ( ACCESS_Frame( 2L ) ) return error; entry_offset = 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( &eer[n].EntryAnchor, stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } else eer[n].EntryAnchor.PosFormat = 0; if ( ACCESS_Frame( 2L ) ) return error; 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( &eer[n].ExitAnchor, stream ) ) != FT_Err_Ok ) { if ( entry_offset ) Free_Anchor( &eer[n].EntryAnchor, memory ); goto Fail1; } (void)FILE_Seek( cur_offset ); } else eer[n].ExitAnchor.PosFormat = 0; } return FT_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) { Free_Anchor( &eer[m].EntryAnchor, memory ); Free_Anchor( &eer[m].ExitAnchor, memory ); } FREE( eer );Fail2: _HB_OPEN_Free_Coverage( &cp->Coverage, memory ); return error;}static void Free_CursivePos( HB_GPOS_SubTable* st, FT_Memory memory ){ FT_UShort n, count; HB_CursivePos* cp = &st->cursive; HB_EntryExitRecord* eer; if ( cp->EntryExitRecord ) { count = cp->EntryExitCount; eer = cp->EntryExitRecord; for ( n = 0; n < count; n++ ) { Free_Anchor( &eer[n].EntryAnchor, memory ); Free_Anchor( &eer[n].ExitAnchor, memory ); } FREE( eer );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -