diff --git a/ChangeLog b/ChangeLog index aacea17ad..f3d12c1e8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2012-12-10 Alexei Podtelezhnikov + + [truetype] Scale F_dot_P down. + + The dot product between freeVector and projVector or cosine of + the angle between these FT_F2Dot14 unit vectors used to be scaled up + by 4 and routinely occupied 32 bits in an FT_Long field F_dot_P. + This patch scales the value down by 2^14 instead, which simplifies + its use throughout the bytecode interpreter. + + This does not lead to the loss of precision because the lower bits + are unreliable anyway. Consider two unit vectors (1,0) and (.6,.8) + for which the true value of F_dot_P is .6 * 0x40000000 = 0x26666666. + These vectors are stored as (0x4000,0) and (0x2666,0x3333) after + rounding and F_dot_P is assigned 0x26660000. The lower bits were + already lost while rounding the unit vector components. + + Besides code simplification, this change can lead to better + performance when FT_MulDiv with the scaled-down F_dot_P is less + likely to use the costly 64-bit path. We are not changing the type + of F_dot_P to FT_F2Dot14 at this point. + + * src/truetype/ttinterp.c (Compute_Funcs): Scale F_dot_P down by 14 + bits and modify its use accordingly. + (Direct_Move, Direct_Move_Orig, Compute_Point_Displacement): Modify + the use of F_dot_P field. + * src/truetype/ttobjs.c (tt_size_run_fpgm): Change arbitrary + assignment of F_dot_P to its theoretical maximum in case we decide + to scale back its type later. + 2012-12-09 Johnson Y. Yan [type1] Another fix for 2012-09-17 commit. diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index e1e09ee8e..736bda32c 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -1861,9 +1861,7 @@ if ( !CUR.ignore_x_mode || ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ - zone->cur[point].x += FT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_X; } @@ -1872,9 +1870,7 @@ if ( v != 0 ) { - zone->cur[point].y += FT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P ); zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y; } @@ -1913,16 +1909,12 @@ v = CUR.GS.freeVector.x; if ( v != 0 ) - zone->org[point].x += FT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P ); v = CUR.GS.freeVector.y; if ( v != 0 ) - zone->org[point].y += FT_MulDiv( distance, - v * 0x10000L, - CUR.F_dot_P ); + zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P ); } @@ -2646,12 +2638,13 @@ #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */ if ( CUR.GS.freeVector.x == 0x4000 ) - CUR.F_dot_P = CUR.GS.projVector.x * 0x10000L; + CUR.F_dot_P = CUR.GS.projVector.x; else if ( CUR.GS.freeVector.y == 0x4000 ) - CUR.F_dot_P = CUR.GS.projVector.y * 0x10000L; + CUR.F_dot_P = CUR.GS.projVector.y; else - CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 + - (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4; + CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x + + (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >> + 14; if ( CUR.GS.projVector.x == 0x4000 ) CUR.func_project = (TT_Project_Func)Project_x; @@ -2670,7 +2663,7 @@ CUR.func_move = (TT_Move_Func)Direct_Move; CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig; - if ( CUR.F_dot_P == 0x40000000L ) + if ( CUR.F_dot_P == 0x4000L ) { if ( CUR.GS.freeVector.x == 0x4000 ) { @@ -2687,8 +2680,8 @@ /* at small sizes, F_dot_P can become too small, resulting */ /* in overflows and `spikes' in a number of glyphs like `w'. */ - if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L ) - CUR.F_dot_P = 0x40000000L; + if ( FT_ABS( CUR.F_dot_P ) < 0x400L ) + CUR.F_dot_P = 0x4000L; /* Disable cached aspect ratio */ CUR.tt_metrics.ratio = 0; @@ -5827,12 +5820,8 @@ else #endif { - *x = FT_MulDiv( d, - (FT_Long)CUR.GS.freeVector.x * 0x10000L, - CUR.F_dot_P ); - *y = FT_MulDiv( d, - (FT_Long)CUR.GS.freeVector.y * 0x10000L, - CUR.F_dot_P ); + *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P ); + *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P ); } return SUCCESS; diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 53c6fa5ab..c61b218c2 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -764,7 +764,7 @@ exec->threshold = 0; exec->instruction_trap = FALSE; - exec->F_dot_P = 0x10000L; + exec->F_dot_P = 0x4000L; exec->pedantic_hinting = pedantic;