From 24e897db28da40dc522886953cf301e3ff92c122 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Sat, 20 Oct 2012 22:23:01 -0400 Subject: [PATCH] [truetype] Cheaper way to threshold angles between vectors. * src/truetype/ttinterp.c (Ins_ISECT): Thresholding tangent is a lot cheaper than thresholding sine. --- ChangeLog | 7 +++++++ src/truetype/ttinterp.c | 43 ++++++++++++----------------------------- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index c7d401e23..3e92e6fdc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2012-10-20 Alexei Podtelezhnikov + + [truetype] Cheaper way to threshold angles between vectors. + + * src/truetype/ttinterp.c (Ins_ISECT): Thresholding tangent is a lot + cheaper than thresholding sine. + 2012-10-20 Werner Lemberg [cff] Improve parsing of invalid real numbers. diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 41f77cd06..765d323db 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -6835,15 +6835,12 @@ a0, a1, b0, b1; - FT_F26Dot6 discriminant; + FT_F26Dot6 discriminant, dotproduct; FT_F26Dot6 dx, dy, dax, day, dbx, dby; - FT_F26Dot6 len_a, len_b; - FT_Long sine; - FT_F26Dot6 val; FT_Vector R; @@ -6882,34 +6879,18 @@ discriminant = TT_MULDIV( dax, -dby, 0x40 ) + TT_MULDIV( day, dbx, 0x40 ); + dotproduct = TT_MULDIV( dax, dbx, 0x40 ) + + TT_MULDIV( day, dby, 0x40 ); - /* Let */ - /* */ - /* a = vector(a0, a1) */ - /* b = vector(b0, b1) . */ - /* */ - /* Then */ - /* */ - /* dot_product(normal_vector(a), b) */ - /* = discriminant */ - /* = |a| * |b| * sin(alpha) . */ - - len_a = TT_VecLen( dax, day ); - len_b = TT_VecLen( dbx, dby ); - - if ( len_a && len_b ) - { - /* precision: (F.6 * F.16) / F.6 = F.16 */ - sine = FT_DivFix( discriminant, len_a ); - /* precision: (F.16 * F.16) / F.6 = F.26 */ - sine = FT_DivFix( sine, len_b ); - } - else - sine = 0; - - /* We reject grazing intersections; heuristic value 2342066 */ - /* corresponds to arcsin(2342066/2^26), this is approx 2 degrees. */ - if ( FT_ABS( sine ) >= 2342066 ) + /* The discriminant above is actually a cross product of vectors */ + /* da and db. Together with the dot product, they can be used as */ + /* surrogates for sine and cosine of the angle between the vectors. */ + /* Indeed, */ + /* dotproduct = |da||db|cos(angle) */ + /* discriminant = |da||db|sin(angle) . */ + /* We use these equations to reject grazing intersections by */ + /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */ + if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) ) { val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );