📄 ttgxvar.c
字号:
goto Exit;
}
table_start = FT_Stream_FTell( stream );
if ( FT_GET_LONG() != 0x00010000L )
{
FT_TRACE2(( "bad table version!\n" ));
error = TT_Err_Ok;
goto FExit;
}
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
goto FExit;
tupleCount = FT_GET_USHORT();
offsetToData = table_start + FT_GET_USHORT();
/* The documentation implies there are flags packed into the */
/* tuplecount, but John Jenkins says that shared points don't apply */
/* to `cvar', and no other flags are defined. */
for ( i = 0; i < ( tupleCount & 0xFFF ); ++i )
{
FT_UInt tupleDataSize;
FT_UInt tupleIndex;
FT_Fixed apply;
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
/* There is no provision here for a global tuple coordinate section, */
/* so John says. There are no tuple indices, just embedded tuples. */
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; ++j )
tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
/* short frac to fixed */
}
else
{
/* skip this tuple; it makes no sense */
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
for ( j = 0; j < 2 * blend->num_axis; ++j )
(void)FT_GET_SHORT();
offsetToData += tupleDataSize;
continue;
}
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
for ( j = 0; j < blend->num_axis; ++j )
im_start_coords[j] = FT_GET_SHORT() << 2;
for ( j = 0; j < blend->num_axis; ++j )
im_end_coords[j] = FT_GET_SHORT() << 2;
}
apply = ft_var_apply_tuple( blend,
(FT_UShort)tupleIndex,
tuple_coords,
im_start_coords,
im_end_coords );
if ( /* tuple isn't active for our blend */
apply == 0 ||
/* global points not allowed, */
/* if they aren't local, makes no sense */
!( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) )
{
offsetToData += tupleDataSize;
continue;
}
here = FT_Stream_FTell( stream );
FT_Stream_SeekSet( stream, offsetToData );
localpoints = ft_var_readpackedpoints( stream, &point_count );
deltas = ft_var_readpackeddeltas( stream,
point_count == 0 ? face->cvt_size
: point_count );
if ( localpoints == NULL || deltas == NULL )
/* failure, ignore it */;
else if ( localpoints == ALL_POINTS )
{
/* this means that there are deltas for every entry in cvt */
for ( j = 0; j < face->cvt_size; ++j )
face->cvt[j] = (FT_Short)( face->cvt[j] +
FT_MulFix( deltas[j], apply ) );
}
else
{
for ( j = 0; j < point_count; ++j )
{
int pindex = localpoints[j];
face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
FT_MulFix( deltas[j], apply ) );
}
}
if ( localpoints != ALL_POINTS )
FT_FREE( localpoints );
FT_FREE( deltas );
offsetToData += tupleDataSize;
FT_Stream_SeekSet( stream, here );
}
FExit:
FT_FRAME_EXIT();
Exit:
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Vary_Get_Glyph_Deltas */
/* */
/* <Description> */
/* Load the appropriate deltas for the current glyph. */
/* */
/* <Input> */
/* face :: A handle to the target face object. */
/* */
/* glyph_index :: The index of the glyph being modified. */
/* */
/* n_points :: The number of the points in the glyph, including */
/* phantom points. */
/* */
/* <Output> */
/* deltas :: The array of points to change. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
TT_Vary_Get_Glyph_Deltas( TT_Face face,
FT_UInt glyph_index,
FT_Vector* *deltas,
FT_UInt n_points )
{
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
FT_Vector* delta_xy;
FT_Error error;
FT_ULong glyph_start;
FT_UInt tupleCount;
FT_ULong offsetToData;
FT_ULong here;
FT_UInt i, j;
FT_Fixed* tuple_coords = NULL;
FT_Fixed* im_start_coords = NULL;
FT_Fixed* im_end_coords = NULL;
FT_UInt point_count, spoint_count = 0;
FT_UShort* sharedpoints = NULL;
FT_UShort* localpoints = NULL;
FT_UShort* points;
FT_Short *deltas_x, *deltas_y;
if ( !face->doblend || blend == NULL )
return TT_Err_Invalid_Argument;
/* to be freed by the caller */
if ( FT_NEW_ARRAY( delta_xy, n_points ) )
goto Exit;
*deltas = delta_xy;
if ( glyph_index >= blend->gv_glyphcnt ||
blend->glyphoffsets[glyph_index] ==
blend->glyphoffsets[glyph_index + 1] )
return TT_Err_Ok; /* no variation data for this glyph */
if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
blend->glyphoffsets[glyph_index] ) )
goto Fail1;
glyph_start = FT_Stream_FTell( stream );
/* each set of glyph variation data is formatted similarly to `cvar' */
/* (except we get shared points and global tuples) */
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
goto Fail2;
tupleCount = FT_GET_USHORT();
offsetToData = glyph_start + FT_GET_USHORT();
if ( tupleCount & GX_TC_TUPLES_SHARE_POINT_NUMBERS )
{
here = FT_Stream_FTell( stream );
FT_Stream_SeekSet( stream, offsetToData );
sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
offsetToData = FT_Stream_FTell( stream );
FT_Stream_SeekSet( stream, here );
}
for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); ++i )
{
FT_UInt tupleDataSize;
FT_UInt tupleIndex;
FT_Fixed apply;
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; ++j )
tuple_coords[j] = FT_GET_SHORT() << 2; /* convert from */
/* short frac to fixed */
}
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
{
error = TT_Err_Invalid_Table;
goto Fail3;
}
else
{
FT_MEM_COPY(
tuple_coords,
&blend->tuplecoords[(tupleIndex & 0xFFF) * blend->num_axis],
blend->num_axis * sizeof ( FT_Fixed ) );
}
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
for ( j = 0; j < blend->num_axis; ++j )
im_start_coords[j] = FT_GET_SHORT() << 2;
for ( j = 0; j < blend->num_axis; ++j )
im_end_coords[j] = FT_GET_SHORT() << 2;
}
apply = ft_var_apply_tuple( blend,
(FT_UShort)tupleIndex,
tuple_coords,
im_start_coords,
im_end_coords );
if ( apply == 0 ) /* tuple isn't active for our blend */
{
offsetToData += tupleDataSize;
continue;
}
here = FT_Stream_FTell( stream );
if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
{
FT_Stream_SeekSet( stream, offsetToData );
localpoints = ft_var_readpackedpoints( stream, &point_count );
points = localpoints;
}
else
{
points = sharedpoints;
point_count = spoint_count;
}
deltas_x = ft_var_readpackeddeltas( stream,
point_count == 0 ? n_points
: point_count );
deltas_y = ft_var_readpackeddeltas( stream,
point_count == 0 ? n_points
: point_count );
if ( points == NULL || deltas_y == NULL || deltas_x == NULL )
; /* failure, ignore it */
else if ( points == ALL_POINTS )
{
/* this means that there are deltas for every point in the glyph */
for ( j = 0; j < n_points; ++j )
{
delta_xy[j].x += FT_MulFix( deltas_x[j], apply );
delta_xy[j].y += FT_MulFix( deltas_y[j], apply );
}
}
else
{
for ( j = 0; j < point_count; ++j )
{
delta_xy[localpoints[j]].x += FT_MulFix( deltas_x[j], apply );
delta_xy[localpoints[j]].y += FT_MulFix( deltas_y[j], apply );
}
}
if ( localpoints != ALL_POINTS )
FT_FREE( localpoints );
FT_FREE( deltas_x );
FT_FREE( deltas_y );
offsetToData += tupleDataSize;
FT_Stream_SeekSet( stream, here );
}
Fail3:
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
Fail2:
FT_FRAME_EXIT();
Fail1:
if ( error )
{
FT_FREE( delta_xy );
*deltas = NULL;
}
Exit:
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* tt_done_blend */
/* */
/* <Description> */
/* Frees the blend internal data structure. */
/* */
FT_LOCAL_DEF( void )
tt_done_blend( FT_Memory memory,
GX_Blend blend )
{
if ( blend != NULL )
{
FT_UInt i;
FT_FREE( blend->normalizedcoords );
FT_FREE( blend->mmvar );
if ( blend->avar_segment != NULL )
{
for ( i = 0; i < blend->num_axis; ++i )
FT_FREE( blend->avar_segment[i].correspondence );
FT_FREE( blend->avar_segment );
}
FT_FREE( blend->tuplecoords );
FT_FREE( blend->glyphoffsets );
FT_FREE( blend );
}
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -