diff options
Diffstat (limited to 'src/truetype/ttgxvar.c')
-rw-r--r-- | src/truetype/ttgxvar.c | 198 |
1 files changed, 112 insertions, 86 deletions
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 5d4384e..c0d013c 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -4,7 +4,7 @@ /* */ /* TrueType GX Font Variation loader */ /* */ -/* Copyright 2004-2015 by */ +/* Copyright 2004-2016 by */ /* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -158,48 +158,49 @@ return NULL; } - if ( FT_NEW_ARRAY( points, n ) ) + /* in the nested loops below we increase `i' twice; */ + /* it is faster to simply allocate one more slot */ + /* than to add another test within the loop */ + if ( FT_NEW_ARRAY( points, n + 1 ) ) return NULL; *point_cnt = n; - i = 0; + first = 0; + i = 0; while ( i < n ) { runcnt = FT_GET_BYTE(); if ( runcnt & GX_PT_POINTS_ARE_WORDS ) { runcnt &= GX_PT_POINT_RUN_COUNT_MASK; - first = FT_GET_USHORT(); + first += FT_GET_USHORT(); points[i++] = first; - if ( runcnt < 1 || i + runcnt > n ) - goto Exit; - /* first point not included in run count */ for ( j = 0; j < runcnt; j++ ) { first += FT_GET_USHORT(); points[i++] = first; + if ( i >= n ) + break; } } else { - first = FT_GET_BYTE(); + first += FT_GET_BYTE(); points[i++] = first; - if ( runcnt < 1 || i + runcnt > n ) - goto Exit; - for ( j = 0; j < runcnt; j++ ) { first += FT_GET_BYTE(); points[i++] = first; + if ( i >= n ) + break; } } } - Exit: return points; } @@ -551,7 +552,7 @@ for ( i = 0; i < blend->tuplecount; i++ ) { FT_TRACE5(( " [ " )); - for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ ) + for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ ) { blend->tuplecoords[i * gvar_head.axisCount + j] = FT_GET_SHORT() * 4; /* convert to FT_Fixed */ @@ -613,6 +614,11 @@ { FT_TRACE6(( " axis coordinate %d (%.4f):\n", i, blend->normalizedcoords[i] / 65536.0 )); + if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) + FT_TRACE6(( " intermediate coordinates %d (%.4f, %.4f):\n", + i, + im_start_coords[i] / 65536.0, + im_end_coords[i] / 65536.0 )); /* It's not clear why (for intermediate tuples) we don't need */ /* to check against start/end -- the documentation says we don't. */ @@ -625,62 +631,74 @@ continue; } - else if ( blend->normalizedcoords[i] == 0 ) + if ( blend->normalizedcoords[i] == 0 ) { FT_TRACE6(( " axis coordinate is zero, stop\n" )); apply = 0; break; } - else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) || - ( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) ) + if ( blend->normalizedcoords[i] == tuple_coords[i] ) { - FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n", + FT_TRACE6(( " tuple coordinate value %.4f fits perfectly\n", tuple_coords[i] / 65536.0 )); - apply = 0; - break; + /* `apply' does not change */ + continue; } - else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) + if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) ) { - FT_TRACE6(( " tuple coordinate value %.4f fits\n", - tuple_coords[i] / 65536.0 )); /* not an intermediate tuple */ - apply = FT_MulFix( apply, - blend->normalizedcoords[i] > 0 - ? blend->normalizedcoords[i] - : -blend->normalizedcoords[i] ); - } - else if ( blend->normalizedcoords[i] < im_start_coords[i] || - blend->normalizedcoords[i] > im_end_coords[i] ) - { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded," - " stop\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); - apply = 0; - break; - } + if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) || + blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) ) + { + FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n", + tuple_coords[i] / 65536.0 )); + apply = 0; + break; + } - else if ( blend->normalizedcoords[i] < tuple_coords[i] ) - { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); + FT_TRACE6(( " tuple coordinate value %.4f fits\n", + tuple_coords[i] / 65536.0 )); apply = FT_MulDiv( apply, - blend->normalizedcoords[i] - im_start_coords[i], - tuple_coords[i] - im_start_coords[i] ); + blend->normalizedcoords[i], + tuple_coords[i] ); } - else { - FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", - im_start_coords[i] / 65536.0, - im_end_coords[i] / 65536.0 )); - apply = FT_MulDiv( apply, - im_end_coords[i] - blend->normalizedcoords[i], - im_end_coords[i] - tuple_coords[i] ); + /* intermediate tuple */ + + if ( blend->normalizedcoords[i] < im_start_coords[i] || + blend->normalizedcoords[i] > im_end_coords[i] ) + { + FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded," + " stop\n", + im_start_coords[i] / 65536.0, + im_end_coords[i] / 65536.0 )); + apply = 0; + break; + } + + else if ( blend->normalizedcoords[i] < tuple_coords[i] ) + { + FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", + im_start_coords[i] / 65536.0, + im_end_coords[i] / 65536.0 )); + apply = FT_MulDiv( apply, + blend->normalizedcoords[i] - im_start_coords[i], + tuple_coords[i] - im_start_coords[i] ); + } + + else + { + FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n", + im_start_coords[i] / 65536.0, + im_end_coords[i] / 65536.0 )); + apply = FT_MulDiv( apply, + im_end_coords[i] - blend->normalizedcoords[i], + im_end_coords[i] - tuple_coords[i] ); + } } } @@ -1699,12 +1717,11 @@ /* modeled after `Ins_IUP */ static void - tt_handle_deltas( FT_Outline* outline, - FT_Vector* in_points, - FT_Bool* has_delta ) + tt_interpolate_deltas( FT_Outline* outline, + FT_Vector* out_points, + FT_Vector* in_points, + FT_Bool* has_delta ) { - FT_Vector* out_points; - FT_Int first_point; FT_Int end_point; @@ -1719,8 +1736,6 @@ if ( !outline->n_contours ) return; - out_points = outline->points; - contour = 0; point = 0; @@ -1824,6 +1839,7 @@ GX_Blend blend = face->blend; FT_Vector* points_org = NULL; + FT_Vector* points_out = NULL; FT_Bool* has_delta = NULL; FT_Error error; @@ -1855,6 +1871,7 @@ } if ( FT_NEW_ARRAY( points_org, n_points ) || + FT_NEW_ARRAY( points_out, n_points ) || FT_NEW_ARRAY( has_delta, n_points ) ) goto Fail1; @@ -1877,7 +1894,8 @@ offsetToData = FT_GET_USHORT(); /* rough sanity test */ - if ( offsetToData + tupleCount * 4 > blend->gvar_size ) + if ( offsetToData + ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) * 4 > + blend->gvar_size ) { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" " invalid glyph variation array header\n" )); @@ -1905,6 +1923,9 @@ FT_TRACE5(( "gvar: there are %d tuples:\n", tupleCount & GX_TC_TUPLE_COUNT_MASK )); + for ( j = 0; j < n_points; j++ ) + points_org[j] = outline->points[j]; + for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ ) { FT_UInt tupleDataSize; @@ -1959,10 +1980,10 @@ here = FT_Stream_FTell( stream ); + FT_Stream_SeekSet( stream, offsetToData ); + if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS ) { - FT_Stream_SeekSet( stream, offsetToData ); - localpoints = ft_var_readpackedpoints( stream, blend->gvar_size, &point_count ); @@ -1998,22 +2019,20 @@ /* this means that there are deltas for every point in the glyph */ for ( j = 0; j < n_points; j++ ) { -#ifdef FT_DEBUG_LEVEL_TRACE - FT_Vector point_org = outline->points[j]; -#endif + FT_Pos delta_x = FT_MulFix( deltas_x[j], apply ); + FT_Pos delta_y = FT_MulFix( deltas_y[j], apply ); - outline->points[j].x += FT_MulFix( deltas_x[j], apply ); - outline->points[j].y += FT_MulFix( deltas_y[j], apply ); + outline->points[j].x += delta_x; + outline->points[j].y += delta_y; #ifdef FT_DEBUG_LEVEL_TRACE - if ( ( point_org.x != outline->points[j].x ) || - ( point_org.y != outline->points[j].y ) ) + if ( delta_x || delta_y ) { FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n", j, - point_org.x, - point_org.y, + outline->points[j].x - delta_x, + outline->points[j].y - delta_y, outline->points[j].x, outline->points[j].y )); count++; @@ -2027,9 +2046,6 @@ #endif } - else if ( localpoints == NULL ) - ; /* failure, ignore it */ - else { #ifdef FT_DEBUG_LEVEL_TRACE @@ -2041,13 +2057,13 @@ /* IUP bytecode instruction */ for ( j = 0; j < n_points; j++ ) { - points_org[j] = outline->points[j]; has_delta[j] = FALSE; + points_out[j] = points_org[j]; } for ( j = 0; j < point_count; j++ ) { - FT_UShort idx = localpoints[j]; + FT_UShort idx = points[j]; if ( idx >= n_points ) @@ -2055,34 +2071,43 @@ has_delta[idx] = TRUE; - outline->points[idx].x += FT_MulFix( deltas_x[j], apply ); - outline->points[idx].y += FT_MulFix( deltas_y[j], apply ); + points_out[idx].x += FT_MulFix( deltas_x[j], apply ); + points_out[idx].y += FT_MulFix( deltas_y[j], apply ); } /* no need to handle phantom points here, */ /* since solitary points can't be interpolated */ - tt_handle_deltas( outline, - points_org, - has_delta ); + tt_interpolate_deltas( outline, + points_out, + points_org, + has_delta ); -#ifdef FT_DEBUG_LEVEL_TRACE FT_TRACE7(( " point deltas:\n" )); - for ( j = 0; j < n_points; j++) + for ( j = 0; j < n_points; j++ ) { - if ( ( points_org[j].x != outline->points[j].x ) || - ( points_org[j].y != outline->points[j].y ) ) + FT_Pos delta_x = points_out[j].x - points_org[j].x; + FT_Pos delta_y = points_out[j].y - points_org[j].y; + + + outline->points[j].x += delta_x; + outline->points[j].y += delta_y; + +#ifdef FT_DEBUG_LEVEL_TRACE + if ( delta_x || delta_y ) { FT_TRACE7(( " %d: (%d, %d) -> (%d, %d)\n", j, - points_org[j].x, - points_org[j].y, + outline->points[j].x - delta_x, + outline->points[j].y - delta_y, outline->points[j].x, outline->points[j].y )); count++; } +#endif } +#ifdef FT_DEBUG_LEVEL_TRACE if ( !count ) FT_TRACE7(( " none\n" )); #endif @@ -2111,6 +2136,7 @@ Fail1: FT_FREE( points_org ); + FT_FREE( points_out ); FT_FREE( has_delta ); return error; |