📄 ftxgpos.c
字号:
if ( format & HAVE_X_ID_ADVANCE ) { if ( ACCESS_Frame( 2L ) ) goto Fail1; vr->XIdAdvance = GET_UShort(); FORGET_Frame(); } else vr->XIdAdvance = 0; if ( format & HAVE_Y_ID_ADVANCE ) { if ( ACCESS_Frame( 2L ) ) goto Fail1; vr->YIdAdvance = GET_UShort(); FORGET_Frame(); } else vr->YIdAdvance = 0; return TT_Err_Ok; Fail1: Free_Device( &vr->YAdvanceDevice ); Fail2: Free_Device( &vr->XAdvanceDevice ); Fail3: Free_Device( &vr->YPlacementDevice ); return error; } static void Free_ValueRecord( TTO_ValueRecord* vr, UShort format ) { if ( format & HAVE_Y_ADVANCE_DEVICE ) Free_Device( &vr->YAdvanceDevice ); if ( format & HAVE_X_ADVANCE_DEVICE ) Free_Device( &vr->XAdvanceDevice ); if ( format & HAVE_Y_PLACEMENT_DEVICE ) Free_Device( &vr->YPlacementDevice ); if ( format & HAVE_X_PLACEMENT_DEVICE ) Free_Device( &vr->XPlacementDevice ); } static TT_Error Get_ValueRecord( GPOS_Instance* gpi, TTO_ValueRecord* vr, UShort format, TTO_GPOS_Data* gd ) { TT_Pos value; Short pixel_value; TT_Error error = TT_Err_Ok; TTO_GPOSHeader* gpos = gpi->gpos; PInstance ins; UShort x_ppem, y_ppem; Fixed x_scale, y_scale; if ( !format ) return TT_Err_Ok; ins = HANDLE_Instance( gpi->instance ); x_ppem = ins->metrics.x_ppem; y_ppem = ins->metrics.y_ppem; x_scale = TT_MulDiv( 0x10000, ins->metrics.x_scale1, ins->metrics.x_scale2 ); y_scale = TT_MulDiv( 0x10000, ins->metrics.y_scale1, ins->metrics.y_scale2 ); /* design units -> fractional pixel */ if ( format & HAVE_X_PLACEMENT ) gd->x_pos += x_scale * vr->XPlacement / 0x10000; if ( format & HAVE_Y_PLACEMENT ) gd->y_pos += y_scale * vr->YPlacement / 0x10000; if ( format & HAVE_X_ADVANCE ) gd->x_advance += x_scale * vr->XAdvance / 0x10000; if ( format & HAVE_Y_ADVANCE ) gd->y_advance += y_scale * vr->YAdvance / 0x10000; /* we use the device tables only if gpi->glyph.z is not NULL */ if ( gpi->glyph.z ) { /* pixel -> fractional pixel */ if ( format & HAVE_X_PLACEMENT_DEVICE ) { Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value ); gd->x_pos += pixel_value << 6; } if ( format & HAVE_Y_PLACEMENT_DEVICE ) { Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value ); gd->y_pos += pixel_value << 6; } if ( format & HAVE_X_ADVANCE_DEVICE ) { Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value ); gd->x_advance += pixel_value << 6; } if ( format & HAVE_Y_ADVANCE_DEVICE ) { Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value ); gd->y_advance += pixel_value << 6; } } /* values returned from mmfunc() are already in fractional pixels */ if ( format & HAVE_X_ID_PLACEMENT ) { error = (gpos->mmfunc)( gpi->instance, vr->XIdPlacement, &value, gpos->data ); if ( error ) return error; gd->x_pos += value; } if ( format & HAVE_Y_ID_PLACEMENT ) { error = (gpos->mmfunc)( gpi->instance, vr->YIdPlacement, &value, gpos->data ); if ( error ) return error; gd->y_pos += value; } if ( format & HAVE_X_ID_ADVANCE ) { error = (gpos->mmfunc)( gpi->instance, vr->XIdAdvance, &value, gpos->data ); if ( error ) return error; gd->x_advance += value; } if ( format & HAVE_Y_ID_ADVANCE ) { error = (gpos->mmfunc)( gpi->instance, vr->YIdAdvance, &value, gpos->data ); if ( error ) return error; gd->y_advance += value; } return error; } /* AnchorFormat1 */ /* AnchorFormat2 */ /* AnchorFormat3 */ /* AnchorFormat4 */ static TT_Error Load_Anchor( TTO_Anchor* an, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; an->PosFormat = GET_UShort(); FORGET_Frame(); switch ( an->PosFormat ) { case 1: if ( ACCESS_Frame( 4L ) ) return error; an->af.af1.XCoordinate = GET_Short(); an->af.af1.YCoordinate = GET_Short(); FORGET_Frame(); break; case 2: if ( ACCESS_Frame( 6L ) ) return error; an->af.af2.XCoordinate = GET_Short(); an->af.af2.YCoordinate = GET_Short(); an->af.af2.AnchorPoint = GET_UShort(); FORGET_Frame(); break; case 3: if ( ACCESS_Frame( 6L ) ) return error; an->af.af3.XCoordinate = GET_Short(); an->af.af3.YCoordinate = GET_Short(); new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Device( &an->af.af3.XDeviceTable, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); } else { an->af.af3.XDeviceTable.StartSize = 0; an->af.af3.XDeviceTable.EndSize = 0; an->af.af3.XDeviceTable.DeltaValue = 0; } if ( ACCESS_Frame( 2L ) ) goto Fail; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Device( &an->af.af3.YDeviceTable, input ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } else { an->af.af3.YDeviceTable.StartSize = 0; an->af.af3.YDeviceTable.EndSize = 0; an->af.af3.YDeviceTable.DeltaValue = 0; } break; case 4: if ( ACCESS_Frame( 4L ) ) return error; an->af.af4.XIdAnchor = GET_UShort(); an->af.af4.YIdAnchor = GET_UShort(); FORGET_Frame(); break; default: return TTO_Err_Invalid_GPOS_SubTable_Format; } return TT_Err_Ok; Fail: 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 ); } } static TT_Error Get_Anchor( GPOS_Instance* gpi, TTO_Anchor* an, TT_UShort glyph_index, TT_Pos* x_value, TT_Pos* y_value ) { TT_Error error = TT_Err_Ok; PInstance ins; PGlyph glyph; TTO_GPOSHeader* gpos = gpi->gpos; UShort ap; Short pixel_value; UShort load_flags; UShort x_ppem, y_ppem; Fixed x_scale, y_scale; ins = HANDLE_Instance( gpi->instance ); x_ppem = ins->metrics.x_ppem; y_ppem = ins->metrics.y_ppem; x_scale = TT_MulDiv( 0x10000, ins->metrics.x_scale1, ins->metrics.x_scale2 ); y_scale = TT_MulDiv( 0x10000, ins->metrics.y_scale1, ins->metrics.y_scale2 ); switch ( an->PosFormat ) { case 0: /* The special case of an empty AnchorTable */ return TTO_Err_Not_Covered; case 1: *x_value = x_scale * an->af.af1.XCoordinate / 0x10000; *y_value = y_scale * an->af.af1.YCoordinate / 0x10000; break; case 2: /* glyphs must be scaled */ load_flags = gpi->load_flags | TTLOAD_SCALE_GLYPH; /* we use the glyph contour point only if gpi->glyph.z is not NULL */ if ( gpi->glyph.z ) { error = (gpos->gfunc)( gpi->instance, gpi->glyph, glyph_index, load_flags ); if ( error ) return error; glyph = HANDLE_Glyph( gpi->glyph ); ap = an->af.af2.AnchorPoint; /* if outline.n_points is set to zero by gfunc(), we use the design coordinate value pair. This can happen e.g. for sbit glyphs */ if ( !glyph->outline.n_points ) goto no_contour_point; if ( ap >= glyph->outline.n_points ) return TTO_Err_Invalid_GPOS_SubTable; *x_value = glyph->outline.points[ap].x; *y_value = glyph->outline.points[ap].y; } else { no_contour_point: *x_value = x_scale * an->af.af3.XCoordinate / 0x10000; *y_value = y_scale * an->af.af3.YCoordinate / 0x10000; } break; case 3: /* we use the device tables only if gpi->glyph.z is not NULL */ if ( gpi->glyph.z ) { Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value ); *x_value = pixel_value << 6; Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value ); *y_value = pixel_value << 6; } else *x_value = *y_value = 0; *x_value += x_scale * an->af.af3.XCoordinate / 0x10000; *y_value += y_scale * an->af.af3.YCoordinate / 0x10000; break; case 4: error = (gpos->mmfunc)( gpi->instance, an->af.af4.XIdAnchor, x_value, gpos->data ); if ( error ) return error; error = (gpos->mmfunc)( gpi->instance, an->af.af4.YIdAnchor, y_value, gpos->data ); if ( error ) return error; break; } return error; } /* 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* vr; 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, base_offset, 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -