>From 5546a5f216f91c61161c6e05bf17b1ad7afca56a Mon Sep 17 00:00:00 2001 From: Byeongsik Jeon Date: Tue, 9 Oct 2018 07:33:10 +0900 Subject: [PATCH v2] Improve FT_Outline_Embolden for the unintended artifacts (#45596). To: freetype-devel FreeType-Bugs: https://savannah.nongnu.org/bugs/?45596 --- src/base/ftoutln.c | 121 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c index 85a469737..046b9c4d6 100644 --- a/src/base/ftoutln.c +++ b/src/base/ftoutln.c @@ -892,6 +892,7 @@ /* documentation is in ftoutln.h */ +#if 0 FT_EXPORT_DEF( FT_Error ) FT_Outline_EmboldenXY( FT_Outline* outline, FT_Pos xstrength, @@ -1023,7 +1024,127 @@ return FT_Err_Ok; } +#else + + FT_EXPORT_DEF( FT_Error ) + FT_Outline_EmboldenXY( FT_Outline* outline, + FT_Pos xstrength, + FT_Pos ystrength ) + { + FT_Vector* points; + FT_Orientation orientation; + FT_Vector strength; + FT_Int n_cont, n_first, n_last; + + if ( !outline ) return FT_THROW( Invalid_Outline ); + + strength.x = xstrength / 2; + strength.y = ystrength / 2; + if ( strength.x == 0 && strength.y == 0 ) return FT_Err_Ok; + + orientation = FT_Outline_Get_Orientation( outline ); + if ( orientation == FT_ORIENTATION_NONE ) + { + if ( outline->n_contours ) return FT_THROW( Invalid_Argument ); + else return FT_Err_Ok; + } + + points = outline->points; + + for ( n_cont = n_first = 0; n_cont < outline->n_contours; + n_cont++, n_first = n_last + 1 ) + { + FT_Vector in, out, anchor, shift; + FT_Fixed det, deg, l_out, l_anchor; + FT_Int n_tail, n_head, n_prev, n_anchor; + FT_Fixed a, b, c, k; + + n_last = outline->contours[n_cont]; + n_anchor = -1; + in.x = in.y = anchor.x = anchor.y = 0; + + for ( n_prev = n_last, n_head = n_first; n_head <= n_last; + n_prev = n_head, n_head++ ) + { + out.x = points[n_head].x - points[n_prev].x; + out.y = points[n_head].y - points[n_prev].y; + l_out = FT_Vector_NormLen( &out ); + + if ( l_out == 0 ) continue; + + det = FT_MulFix( in.x, out.y ) - FT_MulFix( in.y, out.x ); + if ( det != 0 ) + { + anchor = in = out; + l_anchor = l_out; + n_anchor = n_tail = n_head; + break; + } + + in = out; + } + + while ( n_anchor != -1 ) + { + n_prev = n_head; + n_head = ( n_head < n_last )? n_head + 1 : n_first; + if ( n_head != n_anchor ) + { + out.x = points[n_head].x - points[n_prev].x; + out.y = points[n_head].y - points[n_prev].y; + l_out = FT_Vector_NormLen( &out ); + } + else + { + out = anchor; + l_out = l_anchor; + n_anchor = -1; + } + if ( l_out == 0 ) continue; + + deg = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); + if ( deg == -0x10000L ) continue; /* overlapped segment */ + + /* deg = in.x * out.x + in.y * out.y = -cos(theta) + * f(deg) = a * deg^2 + b * deg + d + * f(1) = 1 , theta = 180 + * f(0) = sqrt(2) , theta = 90, 270 + * f(-1) = k , theta = 0, 360 + */ + k = (FT_Fixed)( 1.5 * 65536. ); + c = 92682L; /* sqrt(2) */ + b = FT_MulDiv( 65536L, 65536L - k, 2 * 65536L ); + a = FT_MulDiv( 65536L, k + 65536L, 2 * 65536L ) - 92682L; + deg = FT_MulFix( a, FT_MulFix( deg, deg )) + FT_MulFix( b, deg ) + c; + /* f(deg) = a * deg + b , not controllable */ + /* deg = FT_MulFix( -27146L, deg ) + 92682L; */ + + 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; + FT_Vector_NormLen( &shift ); + + shift.x = FT_MulFix( strength.x, FT_MulFix( shift.x, deg ) ); + shift.y = FT_MulFix( strength.y, FT_MulFix( shift.y, deg ) ); + + for ( ; n_tail != n_head; + n_tail = ( n_tail < n_last )? n_tail + 1 : n_first ) + { + points[n_tail].x += strength.x + shift.x; + points[n_tail].y += strength.y + shift.y; + } + + in = out; + } + } + + return FT_Err_Ok; + } +#endif /* documentation is in ftoutln.h */ -- 2.19.1