diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index ccbb1d7..7575fe1 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -79,12 +79,31 @@ #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) +typedef int (*diagnostics_Function)(char *message, char *opcode, int is_composite, int IP, int callTop, int opc, int start); + +static diagnostics_Function diagnostics = NULL; + #undef SUCCESS #define SUCCESS 0 #undef FAILURE #define FAILURE 1 + FT_EXPORT_DEF( void ) + TT_diagnostics_unset( void ) + { + diagnostics = NULL; + } + + FT_EXPORT_DEF( void ) + TT_diagnostics_set( diagnostics_Function funcptr ) + { + diagnostics = funcptr; + } + +#define DIAGNOSTICS(message, context) if (diagnostics) (*diagnostics)(message, opcode_name[(context)->opcode] + 2, (context)->is_composite , (context)->IP, (context)->callTop, ((context)->callTop ? ((context)->callStack + (context)->callTop - 1)->Def->opc : 0), ((context)->callTop ? ((context)->callStack + (context)->callTop - 1)->Def->start : 0)) + + /*************************************************************************/ /* */ @@ -1649,6 +1668,7 @@ FT_F26Dot6 distance ) { FT_F26Dot6 v; + FT_Long F_dot_P = 0, moved_x = 0, moved_y = 0; v = exc->GS.freeVector.x; @@ -1660,7 +1680,8 @@ ( !exc->ignore_x_mode || ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + moved_x = FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x += moved_x; zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1669,10 +1690,21 @@ if ( v != 0 ) { - zone->cur[point].y += FT_MulDiv( distance, v, exc->F_dot_P ); + moved_y = FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].y += moved_y; zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } + + F_dot_P = + ( (FT_Long)exc->GS.projVector.x * exc->GS.freeVector.x + + (FT_Long)exc->GS.projVector.y * exc->GS.freeVector.y ) >> 14; + + if ( FT_ABS( F_dot_P ) < 0x400L ) + { + if ( (moved_x == 0 || moved_y == 0) && distance != 0 ) + DIAGNOSTICS("_rast_W_PF_VECTORS_AT_OR_NEAR_PERP", exc); + } } @@ -3951,6 +3983,10 @@ } exc->numIDefs++; } + else + { + DIAGNOSTICS("_rast_E_INSTR_DEFD_BY_FS", exc); + } /* opcode must be unsigned 8-bit integer */ if ( 0 > args[0] || args[0] > 0x00FF ) @@ -4130,6 +4166,7 @@ if ( BOUNDS( aIdx1, exc->zp2.n_points ) || BOUNDS( aIdx2, exc->zp1.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return FAILURE; @@ -4276,7 +4313,7 @@ { FT_Short S; FT_Long X, Y; - + FT_Long P_dot_P; /* Only use low 16bits, then sign extend */ S = (FT_Short)args[1]; @@ -4284,6 +4321,11 @@ S = (FT_Short)args[0]; X = (FT_Long)S; + P_dot_P = ( X * X + Y * Y ) >> 14; + + if ( P_dot_P < 0x3C00 ) /* arbitrary - expect 0x4000 */ + DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc ); + Normalize( X, Y, &exc->GS.projVector ); exc->GS.dualVector = exc->GS.projVector; @@ -4303,7 +4345,7 @@ { FT_Short S; FT_Long X, Y; - + FT_Long F_dot_F; /* Only use low 16bits, then sign extend */ S = (FT_Short)args[1]; @@ -4311,6 +4353,11 @@ S = (FT_Short)args[0]; X = S; + F_dot_F = ( X * X + Y * Y ) >> 14; + + if ( F_dot_F < 0x3C00 ) /* arbitrary - expect 0x4000 */ + DIAGNOSTICS("_rast_E_VECTOR_XY_INVALID", exc ); + Normalize( X, Y, &exc->GS.freeVector ); Compute_Funcs( exc ); } @@ -4652,6 +4699,7 @@ if ( BOUNDSL( L, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); R = 0; @@ -4690,6 +4738,7 @@ if ( BOUNDS( L, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -4735,6 +4784,7 @@ if ( BOUNDS( L, exc->zp0.n_points ) || BOUNDS( K, exc->zp1.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); D = 0; @@ -4815,6 +4865,7 @@ if ( BOUNDS( p2, exc->zp1.n_points ) || BOUNDS( p1, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -5043,6 +5094,9 @@ exc->GS.instruct_control &= ~(FT_Byte)Kf; exc->GS.instruct_control |= (FT_Byte)L; + if ( exc->curRange != tt_coderange_font ) + DIAGNOSTICS("_rast_E_NOT_CALLED_FROM_PREPROGRAM", exc); + #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING /* INSTCTRL modifying flag 3 also has an effect */ /* outside of the CVT program */ @@ -5148,6 +5202,7 @@ if ( BOUNDS( point, exc->pts.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Invalid_Reference ); @@ -5185,6 +5240,7 @@ if ( BOUNDS( K, exc->pts.n_points ) || BOUNDS( L, exc->pts.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -5214,6 +5270,7 @@ if ( BOUNDS( K, exc->pts.n_points ) || BOUNDS( L, exc->pts.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -5249,6 +5306,7 @@ if ( BOUNDS( p, zp.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); *refp = 0; @@ -5323,6 +5381,7 @@ if ( BOUNDS( point, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Invalid_Reference ); @@ -5487,6 +5546,7 @@ if ( BOUNDS( point, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Invalid_Reference ); @@ -5621,6 +5681,7 @@ if ( BOUNDS( point, exc->zp1.n_points ) || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -5675,6 +5736,7 @@ if ( BOUNDS( point, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -5741,6 +5803,8 @@ if ( BOUNDS( point, exc->zp0.n_points ) || BOUNDSL( cvtEntry, exc->cvtSize ) ) { + if ( BOUNDS( point, exc->zp0.n_points ) ) + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; @@ -5850,6 +5914,7 @@ if ( BOUNDS( point, exc->zp1.n_points ) || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; @@ -6004,6 +6069,9 @@ BOUNDSL( cvtEntry, exc->cvtSize + 1 ) || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { + if ( BOUNDS( point, exc->zp1.n_points ) || + BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; @@ -6214,6 +6282,8 @@ if ( exc->top < exc->GS.loop || BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) { + if ( BOUNDS( exc->GS.rp0, exc->zp0.n_points ) ) + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; @@ -6227,6 +6297,7 @@ if ( BOUNDS( point, exc->zp1.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Invalid_Reference ); @@ -6288,6 +6359,7 @@ BOUNDS( a1, exc->zp1.n_points ) || BOUNDS( point, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -6365,6 +6437,7 @@ if ( BOUNDS( p1, exc->zp1.n_points ) || BOUNDS( p2, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -6411,6 +6484,7 @@ if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); goto Fail; @@ -6430,6 +6504,7 @@ if ( BOUNDS( exc->GS.rp1, exc->zp0.n_points ) || BOUNDS( exc->GS.rp2, exc->zp1.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); old_range = 0; cur_range = 0; } @@ -6464,6 +6539,7 @@ /* check point bounds */ if ( BOUNDS( point, exc->zp2.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) { exc->error = FT_THROW( Invalid_Reference ); @@ -6512,13 +6588,18 @@ /* new_dist - cur_dist = delta , */ /* new_dist - cur_dist = org_dist - cur_dist , */ /* new_dist = org_dist . */ - new_dist = org_dist; + DIAGNOSTICS("_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc); } } else new_dist = 0; + /* + if ( (new_dist - cur_dist) != 0 && (new_dist - org_dist) == 0) + DIAGNOSTICS("_rast_E_RP1_RP2_SAME_POS_ON_PROJ", exc); + */ + exc->func_move( exc, &exc->zp2, (FT_UShort)point, @@ -6549,6 +6630,7 @@ if ( BOUNDS( point, exc->zp0.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); return; @@ -6757,8 +6839,10 @@ end_point = exc->pts.contours[contour] - exc->pts.first_point; first_point = point; - if ( BOUNDS( end_point, exc->pts.n_points ) ) + if ( BOUNDS( end_point, exc->pts.n_points ) ) { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); end_point = exc->pts.n_points - 1; + } while ( point <= end_point && ( exc->pts.tags[point] & mask ) == 0 ) point++; @@ -6950,8 +7034,11 @@ } } else + { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); + } } Fail: