📄 ftxgpos.c
字号:
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->face, vr->XIdPlacement, &value, gpos->data ); if ( error ) return error; gd->x_pos += value; } if ( format & HAVE_Y_ID_PLACEMENT ) { error = (gpos->mmfunc)( gpi->face, vr->YIdPlacement, &value, gpos->data ); if ( error ) return error; gd->y_pos += value; } if ( format & HAVE_X_ID_ADVANCE ) { error = (gpos->mmfunc)( gpi->face, vr->XIdAdvance, &value, gpos->data ); if ( error ) return error; gd->x_advance += value; } if ( format & HAVE_Y_ID_ADVANCE ) { error = (gpos->mmfunc)( gpi->face, vr->YIdAdvance, &value, gpos->data ); if ( error ) return error; gd->y_advance += value; } return error; } /* AnchorFormat1 */ /* AnchorFormat2 */ /* AnchorFormat3 */ /* AnchorFormat4 */ static FT_Error Load_Anchor( TTO_Anchor* an, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; FT_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, stream ) ) != 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 = NULL; } 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, stream ) ) != 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 = NULL; } 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, memory ); return error; } static void Free_Anchor( TTO_Anchor* an, FT_Memory memory) { if ( an->PosFormat == 3 ) { Free_Device( &an->af.af3.YDeviceTable, memory ); Free_Device( &an->af.af3.XDeviceTable, memory ); } } static FT_Error Get_Anchor( GPOS_Instance* gpi, TTO_Anchor* an, FT_UShort glyph_index, FT_Pos* x_value, FT_Pos* y_value ) { FT_Error error = TT_Err_Ok; FT_Outline outline; TTO_GPOSHeader* gpos = gpi->gpos; FT_UShort ap; FT_Short pixel_value; FT_UShort load_flags; FT_UShort x_ppem, y_ppem; FT_Fixed x_scale, y_scale; x_ppem = gpi->face->size->metrics.x_ppem; y_ppem = gpi->face->size->metrics.y_ppem; x_scale = gpi->face->size->metrics.x_scale; y_scale = gpi->face->size->metrics.y_scale; 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 & ~FT_LOAD_NO_SCALE; if ( !gpi->dvi ) { error = (gpos->gfunc)( gpi->face, glyph_index, load_flags ); if ( error ) return error; if ( gpi->face->glyph->format != ft_glyph_format_outline ) return TTO_Err_Invalid_GPOS_SubTable; ap = an->af.af2.AnchorPoint; outline = gpi->face->glyph->outline; /* 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 ( !outline.n_points ) goto no_contour_point; if ( ap >= outline.n_points ) return TTO_Err_Invalid_GPOS_SubTable; *x_value = outline.points[ap].x; *y_value = 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: if ( !gpi->dvi ) { 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->face, an->af.af4.XIdAnchor, x_value, gpos->data ); if ( error ) return error; error = (gpos->mmfunc)( gpi->face, an->af.af4.YIdAnchor, y_value, gpos->data ); if ( error ) return error; break; } return error; } /* MarkArray */ static FT_Error Load_MarkArray ( TTO_MarkArray* ma, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, m, count; FT_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, stream ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( m = 0; m < n; m++ ) Free_Anchor( &mr[m].MarkAnchor, memory ); FREE( mr ); return error; } static void Free_MarkArray( TTO_MarkArray* ma, FT_Memory memory ) { FT_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, memory ); FREE( mr ); } } /* LookupType 1 */ /* SinglePosFormat1 */ /* SinglePosFormat2 */ FT_Error Load_SinglePos( TTO_SinglePos* sp, FT_Stream stream ) { FT_Error error; FT_Memory memory = stream->memory; FT_UShort n, m, count, format; FT_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, stream ) ) != 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, stream ); 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; vr = sp->spf.spf2.Value; for ( n = 0; n < count; n++ ) { error = Load_ValueRecord( &vr[n], format, base_offset, stream ); if ( error ) goto Fail1; } break; default: return TTO_Err_Invalid_GPOS_SubTable_Format; } return TT_Err_Ok; Fail1: for ( m = 0; m < n; m++ ) Free_ValueRecord( &vr[m], format, memory ); FREE( vr ); Fail2: Free_Coverage( &sp->Coverage, memory ); return error; } void Free_SinglePos( TTO_SinglePos* sp, FT_Memory memory ) { FT_UShort n, count, format; TTO_ValueRecord* v; format = sp->ValueFormat; switch ( sp->PosFormat ) { case 1: Free_ValueRecord( &sp->spf.spf1.Value, format, memory ); 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, memory ); FREE( v ); } break; } Free_Coverage( &sp->Coverage, memory ); } static FT_Error Lookup_SinglePos( GPOS_Instance* gpi, TTO_SinglePos* sp, OTL_Buffer buffer, FT_UShort flags, FT_UShort context_length ) { FT_UShort index, property; FT_Error error; TTO_GPOSHeader* gpos = gpi->gpos; if ( context_length != 0xFFFF && context_length < 1 ) return TTO_Err_Not_Covered; if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) ) return error; error = Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index ); if ( error ) return error; switch ( sp->PosFormat ) { case 1: error = Get_ValueRecord( gpi, &sp->spf.spf1.Value, sp->ValueFormat, POSITION( buffer->in_pos ) ); if ( error ) return error; break; case 2: if ( index >= sp->spf.spf2.ValueCount ) return TTO_Err_Invalid_GPOS_SubTable;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -