[base] Improve emboldener (#45596).
* src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement of zero-lenght segments.
This commit is contained in:
parent
815c32469b
commit
a0172d10e8
|
@ -1,3 +1,10 @@
|
|||
2015-08-17 Alexei Podtelezhnikov <apodtele@gmail.com>
|
||||
|
||||
[base] Improve emboldener (#45596).
|
||||
|
||||
* src/base/ftoutln.c (FT_Outline_EmboldenXY): Correct displacement
|
||||
of zero-lenght segments.
|
||||
|
||||
2015-08-16 Alexei Podtelezhnikov <apodtele@gmail.com>
|
||||
|
||||
[base] Reoptimize arithmetic.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue