📄 ftxgpos.c
字号:
Free_Device( &an->af.af3.XDeviceTable ); return error; } static void Free_Anchor( TTO_Anchor* an ) { if ( an->PosFormat == 3 ) { Free_Device( &an->af.af3.YDeviceTable ); Free_Device( &an->af.af3.XDeviceTable ); } } /* MarkArray */ static TT_Error Load_MarkArray ( TTO_MarkArray* ma, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; ULong cur_offset, new_offset, base_offset; TTO_MarkRecord* mr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = ma->MarkCount = GET_UShort(); FORGET_Frame(); ma->MarkRecord = NULL; if ( ALLOC_ARRAY( ma->MarkRecord, count, TTO_MarkRecord ) ) return error; mr = ma->MarkRecord; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 4L ) ) goto Fail; mr[n].Class = GET_UShort(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Anchor( &mr[n].MarkAnchor, input ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( n = 0; n < count; n++ ) Free_Anchor( &mr[n].MarkAnchor ); FREE( mr ); return error; } static void Free_MarkArray( TTO_MarkArray* ma ) { UShort n, count; TTO_MarkRecord* mr; if ( ma->MarkRecord ) { count = ma->MarkCount; mr = ma->MarkRecord; for ( n = 0; n < count; n++ ) Free_Anchor( &mr[n].MarkAnchor ); FREE( mr ); } } /* LookupType 1 */ /* SinglePosFormat1 */ /* SinglePosFormat2 */ TT_Error Load_SinglePos( TTO_SinglePos* sp, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count, format; ULong cur_offset, new_offset, base_offset; TTO_ValueRecord* v; base_offset = FILE_Pos(); if ( ACCESS_Frame( 6L ) ) return error; sp->PosFormat = GET_UShort(); new_offset = GET_UShort() + base_offset; format = sp->ValueFormat = GET_UShort(); FORGET_Frame(); if ( !format ) return TTO_Err_Invalid_GPOS_SubTable; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Coverage( &sp->Coverage, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); switch ( sp->PosFormat ) { case 1: error = Load_ValueRecord( &sp->spf.spf1.Value, format, input ); if ( error ) goto Fail2; break; case 2: if ( ACCESS_Frame( 2L ) ) goto Fail2; count = sp->spf.spf2.ValueCount = GET_UShort(); FORGET_Frame(); sp->spf.spf2.Value = NULL; if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, TTO_ValueRecord ) ) goto Fail2; v = sp->spf.spf2.Value; for ( n = 0; n < count; n++ ) { error = Load_ValueRecord( &v[n], format, input ); if ( error ) goto Fail1; } break; default: return TTO_Err_Invalid_GPOS_SubTable_Format; } return TT_Err_Ok; Fail1: for ( n = 0; n < count; n++ ) Free_ValueRecord( &v[n], format ); FREE( v ); Fail2: Free_Coverage( &sp->Coverage ); return error; } void Free_SinglePos( TTO_SinglePos* sp ) { UShort n, count, format; TTO_ValueRecord* v; format = sp->ValueFormat; switch ( sp->PosFormat ) { case 1: Free_ValueRecord( &sp->spf.spf1.Value, format ); break; case 2: if ( sp->spf.spf2.Value ) { count = sp->spf.spf2.ValueCount; v = sp->spf.spf2.Value; for ( n = 0; n < count; n++ ) Free_ValueRecord( &v[n], format ); FREE( v ); } break; } Free_Coverage( &sp->Coverage ); } /* LookupType 2 */ /* PairSet */ static TT_Error Load_PairSet ( TTO_PairSet* ps, UShort format1, UShort format2, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; TTO_PairValueRecord* pvr; if ( ACCESS_Frame( 2L ) ) return error; count = ps->PairValueCount = GET_UShort(); FORGET_Frame(); ps->PairValueRecord = NULL; if ( ALLOC_ARRAY( ps->PairValueRecord, count, TTO_PairValueRecord ) ) return error; pvr = ps->PairValueRecord; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail; pvr[n].SecondGlyph = GET_UShort(); FORGET_Frame(); if ( format1 ) { error = Load_ValueRecord( &pvr[n].Value1, format1, input ); if ( error ) goto Fail; } if ( format2 ) { error = Load_ValueRecord( &pvr[n].Value2, format2, input ); if ( error ) goto Fail; } } return TT_Err_Ok; Fail: for ( n = 0; n < count; n++ ) { if ( format1 ) Free_ValueRecord( &pvr[n].Value1, format1 ); if ( format2 ) Free_ValueRecord( &pvr[n].Value2, format2 ); } FREE( pvr ); return error; } static void Free_PairSet( TTO_PairSet* ps, UShort format1, UShort format2 ) { UShort n, count; TTO_PairValueRecord* pvr; if ( ps->PairValueRecord ) { count = ps->PairValueCount; pvr = ps->PairValueRecord; for ( n = 0; n < count; n++ ) { if ( format1 ) Free_ValueRecord( &pvr[n].Value1, format1 ); if ( format2 ) Free_ValueRecord( &pvr[n].Value2, format2 ); } FREE( pvr ); } } /* PairPosFormat1 */ static TT_Error Load_PairPosFormat1( TTO_PairPosFormat1* ppf1, UShort format1, UShort format2, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; ULong cur_offset, new_offset, base_offset; TTO_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, TTO_PairSet ) ) goto Fail; 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, input ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( n = 0; n < count; n++ ) Free_PairSet( &ps[n], format1, format2 ); FREE( ps ); return error; } static void Free_PairPosFormat1( TTO_PairPosFormat1* ppf1, UShort format1, UShort format2 ) { UShort n, count; TTO_PairSet* ps; if ( ppf1->PairSet ) { count = ppf1->PairSetCount; ps = ppf1->PairSet; for ( n = 0; n < count; n++ ) Free_PairSet( &ps[n], format1, format2 ); FREE( ps ); } } /* PairPosFormat2 */ static TT_Error Load_PairPosFormat2( TTO_PairPosFormat2* ppf2, UShort format1, UShort format2, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort m, n, count1, count2; ULong cur_offset, new_offset1, new_offset2, base_offset; TTO_Class1Record* c1r; TTO_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 = Load_ClassDefinition( &ppf2->ClassDef1, count1, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset2 ) || ( error = Load_ClassDefinition( &ppf2->ClassDef2, count2, input ) ) != TT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); ppf2->Class1Record = NULL; if ( ALLOC_ARRAY( ppf2->Class1Record, count1, TTO_Class1Record ) ) goto Fail1; c1r = ppf2->Class1Record; for ( m = 0; m < count1; m++ ) { c1r[m].Class2Record = NULL; if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, TTO_Class2Record ) ) goto Fail1; c2r = c1r[m].Class2Record; for ( n = 0; n < count2; n++ ) { if ( format1 ) { Load_ValueRecord( &c2r[n].Value1, format1, input ); if ( error ) goto Fail1; } if ( format2 ) { Load_ValueRecord( &c2r[n].Value2, format2, input ); if ( error ) goto Fail1; } } } return TT_Err_Ok; Fail1: for ( m = 0; m < count1; m++ ) { c2r = c1r[m].Class2Record; for ( n = 0; n < count2; n++ ) { if ( format1 ) Free_ValueRecord( &c2r[n].Value1, format1 ); if ( format2 ) Free_ValueRecord( &c2r[n].Value2, format2 ); } FREE( c2r ); } FREE( c1r ); Free_ClassDefinition( &ppf2->ClassDef2 ); Fail2: Free_ClassDefinition( &ppf2->ClassDef1 ); return error; } static void Free_PairPosFormat2( TTO_PairPosFormat2* ppf2, UShort format1, UShort format2 ) { UShort m, n, count1, count2; TTO_Class1Record* c1r; TTO_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 ); if ( format2 ) Free_ValueRecord( &c2r[n].Value2, format2 ); } FREE( c2r ); } FREE( c1r ); Free_ClassDefinition( &ppf2->ClassDef2 ); Free_ClassDefinition( &ppf2->ClassDef1 ); } } TT_Error Load_PairPos( TTO_PairPos* pp, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort format1, format2; 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 = Load_Coverage( &pp->Coverage, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); switch ( pp->PosFormat ) { case 1: error = Load_PairPosFormat1( &pp->ppf.ppf1, format1, format2, input ); if ( error ) goto Fail; break; case 2: error = Load_PairPosFormat2( &pp->ppf.ppf2, format1, format2, input ); if ( error ) goto Fail; break; default: return TTO_Err_Invalid_GPOS_SubTable_Format; } return TT_Err_Ok; Fail: Free_Coverage( &pp->Coverage ); return error; } void Free_PairPos( TTO_PairPos* pp ) { UShort format1, format2; format1 = pp->ValueFormat1; format2 = pp->ValueFormat2; switch ( pp->PosFormat ) { case 1: Free_PairPosFormat1( &pp->ppf.ppf1, format1, format2 ); break; case 2: Free_PairPosFormat2( &pp->ppf.ppf2, format1, format2 ); break; } Free_Coverage( &pp->Coverage ); } /* LookupType 3 */ /* CursivePosFormat1 */ TT_Error Load_CursivePos( TTO_CursivePos* cp, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -