diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 2e3f9ef..534e30f 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -90,12 +90,29 @@ #define BOUNDSL( x, n ) ( (FT_ULong)(x) >= (FT_ULong)(n) ) +typedef int (*diagnostics_Function)(const char* message, const char* const opcode, int range_base, 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)->callTop ? (context)->callStack->Caller_Range : (context)->curRange ), (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)) /*************************************************************************/ /* */ @@ -910,7 +927,7 @@ }; -#ifdef FT_DEBUG_LEVEL_TRACE +#if defined(FT_DEBUG_LEVEL_TRACE) || defined(DIAGNOSTICS) /* the first hex digit gives the length of the opcode name; the space */ /* after the digit is here just to increase readability of the source */ @@ -1664,17 +1681,19 @@ FT_F26Dot6 distance ) { FT_F26Dot6 v; + FT_Long F_dot_P = 0, moved_x = 0, moved_y = 0; v = exc->GS.freeVector.x; if ( v != 0 ) { + moved_x = FT_MulDiv( distance, v, exc->F_dot_P ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY if ( SUBPIXEL_HINTING_INFINALITY && ( !exc->ignore_x_mode || ( exc->sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x += moved_x; else #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ @@ -1683,12 +1702,12 @@ /* diagonal moves, but only post-IUP. DejaVu tries to adjust */ /* diagonal stems like on `Z' and `z' post-IUP. */ if ( SUBPIXEL_HINTING_MINIMAL && !exc->backwards_compatibility ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x += moved_x; else #endif if ( NO_SUBPIXEL_HINTING ) - zone->cur[point].x += FT_MulDiv( distance, v, exc->F_dot_P ); + zone->cur[point].x += moved_x; zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1697,16 +1716,27 @@ if ( v != 0 ) { + moved_y = FT_MulDiv( distance, v, exc->F_dot_P ); #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL if ( !( SUBPIXEL_HINTING_MINIMAL && exc->backwards_compatibility && exc->iupx_called && exc->iupy_called ) ) #endif - zone->cur[point].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 ); + } } @@ -3982,6 +4012,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 ) @@ -4161,6 +4195,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; @@ -4307,6 +4342,7 @@ { FT_Short S; FT_Long X, Y; + FT_Long P_dot_P; /* Only use low 16bits, then sign extend */ @@ -4315,6 +4351,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; @@ -4334,6 +4375,7 @@ { FT_Short S; FT_Long X, Y; + FT_Long F_dot_F; /* Only use low 16bits, then sign extend */ @@ -4342,6 +4384,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 ); } @@ -4683,6 +4730,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; @@ -4721,6 +4769,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; @@ -4766,6 +4815,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; @@ -4846,6 +4896,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; @@ -5074,6 +5125,9 @@ exc->GS.instruct_control &= ~(FT_Byte)Kf; exc->GS.instruct_control |= (FT_Byte)L; + if ( exc->callTop && ( exc->callStack->Caller_Range == tt_coderange_glyph ) ) + DIAGNOSTICS("_rast_E_NOT_CALLED_FROM_PREPROGRAM", exc ); + if ( K == 3 ) { #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY @@ -5199,6 +5253,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 ); @@ -5245,6 +5300,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; @@ -5283,6 +5339,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; @@ -5318,6 +5375,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; @@ -5405,6 +5463,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 ); @@ -5574,6 +5633,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 ); @@ -5721,6 +5781,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; @@ -5775,6 +5836,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; @@ -5841,6 +5903,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; @@ -5950,6 +6014,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; @@ -6105,6 +6170,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; @@ -6315,6 +6383,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; @@ -6328,6 +6398,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 ); @@ -6389,6 +6460,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; @@ -6468,6 +6540,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; @@ -6514,6 +6587,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; @@ -6533,6 +6607,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; } @@ -6567,6 +6642,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 ); @@ -6615,13 +6691,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, @@ -6652,6 +6733,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; @@ -6877,8 +6959,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++; @@ -7086,8 +7170,11 @@ } } else + { + DIAGNOSTICS("_rast_E_POINT_OUT_OF_RANGE", exc ); if ( exc->pedantic_hinting ) exc->error = FT_THROW( Invalid_Reference ); + } } Fail: