From a0172d10e816fdd7b8d7b748f570ba16d9e753bd Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Mon, 17 Aug 2015 22:58:59 -0400 Subject: [PATCH] [base] Improve emboldener (#45596). * src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement of zero-lenght segments. --- ChangeLog | 7 +++ src/base/ftoutln.c | 143 +++++++++++++++++++++++++-------------------- 2 files changed, 87 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf9ad5d64..b3c0fd16d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-08-17 Alexei Podtelezhnikov + + [base] Improve emboldener (#45596). + + * src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement + of zero-lenght segments. + 2015-08-16 Alexei Podtelezhnikov [base] Reoptimize arithmetic. diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 8804cc70b..297db2ee3 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -908,8 +908,7 @@ FT_Pos ystrength ) { FT_Vector* points; - FT_Vector v_prev, v_first, v_next, v_cur; - FT_Int c, n, first; + FT_Int c, first, last; FT_Int orientation; @@ -935,76 +934,94 @@ first = 0; for ( c = 0; c < outline->n_contours; c++ ) { - FT_Vector in, out, shift; - FT_Fixed l_in, l_out, l, q, d; - FT_Int last = outline->contours[c]; + FT_Vector in, out, anchor, shift; + FT_Fixed l_in = 0, l_out, l_anchor, l, q, d; + FT_Int i, j, k; - v_first = points[first]; - v_prev = points[last]; - v_cur = v_first; + last = outline->contours[c]; - /* compute incoming normalized vector */ - in.x = v_cur.x - v_prev.x; - in.y = v_cur.y - v_prev.y; - l_in = (FT_Fixed)FT_Vector_NormLen( &in ); - - for ( n = first; n <= last; n++ ) + /* Counter i cycles though the points; counter j advances only */ + /* when points are moved; anchor k markes the first moved point. */ + for ( i = last, j = first, k = -1; + j != i && i != k; + j = j < last ? j + 1 : first ) { - if ( n < last ) - v_next = points[n + 1]; - else - v_next = v_first; - - /* compute outgoing normalized vector */ - out.x = v_next.x - v_cur.x; - out.y = v_next.y - v_cur.y; - l_out = (FT_Fixed)FT_Vector_NormLen( &out ); - - d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); - - /* shift only if turn is less than ~160 degrees */ - if ( d > -0xF000L ) + if ( j != k ) { - d = d + 0x10000L; - - /* shift along lateral bisector in appropriate orientation */ - shift.x = in.y + out.y; - shift.y = in.x + out.x; - - if ( orientation == FT_ORIENTATION_TRUETYPE ) - shift.x = -shift.x; - else - shift.y = -shift.y; - - /* restrict shift magnitude to better handle collapsing segments */ - q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); - if ( orientation == FT_ORIENTATION_TRUETYPE ) - q = -q; - - l = FT_MIN( l_in, l_out ); - - /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ - if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) ) - shift.x = FT_MulDiv( shift.x, xstrength, d ); - else - shift.x = FT_MulDiv( shift.x, l, q ); - - - if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) ) - shift.y = FT_MulDiv( shift.y, ystrength, d ); - else - shift.y = FT_MulDiv( shift.y, l, q ); + out.x = points[j].x - points[i].x; + out.y = points[j].y - points[i].y; + l_out = FT_Vector_NormLen( &out ); } else - shift.x = shift.y = 0; + { + out = anchor; + l_out = l_anchor; + } - points[n].x = v_cur.x + xstrength + shift.x; - points[n].y = v_cur.y + ystrength + shift.y; + if ( l_out == 0 ) + continue; - in = out; - l_in = l_out; - v_cur = v_next; + if ( l_in != 0 ) + { + if ( k < 0 ) + { + k = i; + anchor = in; + l_anchor = l_in; + } + + d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); + + /* shift only if turn is less than ~160 degrees */ + if ( d > -0xF000L ) + { + d = d + 0x10000L; + + /* shift components along lateral bisector in proper orientation */ + shift.x = in.y + out.y; + shift.y = in.x + out.x; + + if ( orientation == FT_ORIENTATION_TRUETYPE ) + shift.x = -shift.x; + else + shift.y = -shift.y; + + /* restrict shift magnitude to better handle collapsing segments */ + q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); + if ( orientation == FT_ORIENTATION_TRUETYPE ) + q = -q; + + l = FT_MIN( l_in, l_out ); + + /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ + if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) ) + shift.x = FT_MulDiv( shift.x, xstrength, d ); + else + shift.x = FT_MulDiv( shift.x, l, q ); + + + if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) ) + shift.y = FT_MulDiv( shift.y, ystrength, d ); + else + shift.y = FT_MulDiv( shift.y, l, q ); + } + else + shift.x = shift.y = 0; + + for ( ; + i != j; + i = i < last ? i + 1 : first ) + { + points[i].x += xstrength + shift.x; + points[i].y += ystrength + shift.y; + } + } + else + i = j; + + in = out; + l_in = l_out; } first = last + 1;