* src/base/ftstroke.c (ft_stroker_outside): Speed up clipped miter.

* include/freetype/ftstroke.h: Wordsmith miter docs.
This commit is contained in:
Alexei Podtelezhnikov 2019-09-25 21:50:16 -04:00
parent db4083fd7f
commit 432efa25b3
3 changed files with 46 additions and 48 deletions

View File

@ -1,3 +1,8 @@
2019-09-25 Alexei Podtelezhnikov <apodtele@gmail.com>
* src/base/ftstroke.c (ft_stroker_outside): Speed up clipped miter.
* include/freetype/ftstroke.h: Wordsmith miter docs.
2019-09-25 Werner Lemberg <wl@gnu.org>
* src/sfnt/sfwoff2.c (woff2_open_font): Check (sum of) table sizes.

View File

@ -114,22 +114,19 @@ FT_BEGIN_HEADER
* FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the miter
* limit is exceeded. The outer edges of the strokes for the two
* segments are extended until they meet at an angle. If the segments
* meet at too sharp an angle (such that the miter would extend from
* the intersection of the segments a distance greater than the product
* of the miter limit value and the border radius), then a bevel join
* (see above) is used instead. This prevents long spikes being
* created. `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line
* join as used in PostScript and PDF.
* segments are extended until they meet at an angle. A bevel join
* (see above) is used if the segments meet at too sharp an angle and
* the outer edges meet beyond a distance corresponding to the meter
* limit. This prevents long spikes being created.
* `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line join as
* used in PostScript and PDF.
*
* FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if the miter
* limit is exceeded. The intersection of the strokes is clipped at a
* line perpendicular to the bisector of the angle between the strokes,
* at the distance from the intersection of the segments equal to the
* product of the miter limit value and the border radius. This
* prevents long spikes being created.
* limit is exceeded. The intersection of the strokes is clipped
* perpendicularly to the bisector, at a distance corresponding to
* the miter limit. This prevents long spikes being created.
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join
* as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for
* `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward
@ -296,13 +293,17 @@ FT_BEGIN_HEADER
* The line join style.
*
* miter_limit ::
* The miter limit for the `FT_STROKER_LINEJOIN_MITER_FIXED` and
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` line join styles, expressed as
* 16.16 fixed-point value.
* The maximum reciprocal sine of half-angle at the miter join,
* expressed as 16.16 fixed point value.
*
* @note:
* The radius is expressed in the same units as the outline coordinates.
*
* The miter limit multiplied by the radius gives the maximum size
* of a miter spike, at which it is clipped for
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` or replaced with a bevel join for
* `FT_STROKER_LINEJOIN_MITER_FIXED`.
*
* This function calls @FT_Stroker_Rewind automatically.
*/
FT_EXPORT( void )

View File

@ -1062,10 +1062,10 @@
else
{
/* this is a mitered (pointed) or beveled (truncated) corner */
FT_Fixed sigma = 0, radius = stroker->radius;
FT_Angle theta = 0, phi = 0;
FT_Fixed thcos = 0;
FT_Bool bevel, fixed_bevel;
FT_Fixed radius = stroker->radius;
FT_Vector sigma;
FT_Angle theta = 0, phi = 0;
FT_Bool bevel, fixed_bevel;
rotate = FT_SIDE_TO_ROTATE( side );
@ -1076,26 +1076,20 @@
fixed_bevel =
FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
/* check miter limit first */
if ( !bevel )
{
theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
if ( theta == FT_ANGLE_PI )
{
theta = rotate;
phi = stroker->angle_in;
}
else
{
theta /= 2;
phi = stroker->angle_in + theta + rotate;
}
if ( theta == FT_ANGLE_PI2 )
theta = -rotate;
thcos = FT_Cos( theta );
sigma = FT_MulFix( stroker->miter_limit, thcos );
phi = stroker->angle_in + theta + rotate;
FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta );
/* is miter limit exceeded? */
if ( sigma < 0x10000L )
if ( sigma.x < 0x10000L )
{
/* don't create variable bevels for very small deviations; */
/* FT_Sin(x) = 0 for x <= 57 */
@ -1122,36 +1116,34 @@
border->movable = FALSE;
error = ft_stroke_border_lineto( border, &delta, FALSE );
}
else /* variable bevel */
else /* variable bevel or clipped miter */
{
/* the miter is truncated */
FT_Vector middle, delta;
FT_Fixed length;
FT_Fixed coef;
/* compute middle point */
/* compute middle point and first angle point */
FT_Vector_From_Polar( &middle,
FT_MulFix( radius, stroker->miter_limit ),
phi );
coef = FT_DivFix( 0x10000L - sigma.x, sigma.y );
delta.x = FT_MulFix( middle.y, coef );
delta.y = FT_MulFix( -middle.x, coef );
middle.x += stroker->center.x;
middle.y += stroker->center.y;
/* compute first angle point */
length = FT_MulDiv( radius, 0x10000L - sigma,
ft_pos_abs( FT_Sin( theta ) ) );
FT_Vector_From_Polar( &delta, length, phi + rotate );
delta.x += middle.x;
delta.y += middle.y;
delta.x += middle.x;
delta.y += middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
goto Exit;
/* compute second angle point */
FT_Vector_From_Polar( &delta, length, phi - rotate );
delta.x += middle.x;
delta.y += middle.y;
delta.x = middle.x - delta.x + middle.x;
delta.y = middle.y - delta.y + middle.y;
error = ft_stroke_border_lineto( border, &delta, FALSE );
if ( error )
@ -1178,7 +1170,7 @@
FT_Vector delta;
length = FT_DivFix( stroker->radius, thcos );
length = FT_MulDiv( stroker->radius, stroker->miter_limit, sigma.x );
FT_Vector_From_Polar( &delta, length, phi );
delta.x += stroker->center.x;