* 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> 2019-09-25 Werner Lemberg <wl@gnu.org>
* src/sfnt/sfwoff2.c (woff2_open_font): Check (sum of) table sizes. * 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 :: * FT_STROKER_LINEJOIN_MITER_FIXED ::
* Used to render mitered line joins, with fixed bevels if the miter * Used to render mitered line joins, with fixed bevels if the miter
* limit is exceeded. The outer edges of the strokes for the two * limit is exceeded. The outer edges of the strokes for the two
* segments are extended until they meet at an angle. If the segments * segments are extended until they meet at an angle. A bevel join
* meet at too sharp an angle (such that the miter would extend from * (see above) is used if the segments meet at too sharp an angle and
* the intersection of the segments a distance greater than the product * the outer edges meet beyond a distance corresponding to the meter
* of the miter limit value and the border radius), then a bevel join * limit. This prevents long spikes being created.
* (see above) is used instead. This prevents long spikes being * `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line join as
* created. `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line * used in PostScript and PDF.
* join as used in PostScript and PDF.
* *
* FT_STROKER_LINEJOIN_MITER_VARIABLE :: * FT_STROKER_LINEJOIN_MITER_VARIABLE ::
* FT_STROKER_LINEJOIN_MITER :: * FT_STROKER_LINEJOIN_MITER ::
* Used to render mitered line joins, with variable bevels if the 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 * limit is exceeded. The intersection of the strokes is clipped
* line perpendicular to the bisector of the angle between the strokes, * perpendicularly to the bisector, at a distance corresponding to
* at the distance from the intersection of the segments equal to the * the miter limit. This prevents long spikes being created.
* product of the miter limit value and the border radius. This
* prevents long spikes being created.
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join * `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join
* as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for * as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for
* `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward * `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward
@ -296,13 +293,17 @@ FT_BEGIN_HEADER
* The line join style. * The line join style.
* *
* miter_limit :: * miter_limit ::
* The miter limit for the `FT_STROKER_LINEJOIN_MITER_FIXED` and * The maximum reciprocal sine of half-angle at the miter join,
* `FT_STROKER_LINEJOIN_MITER_VARIABLE` line join styles, expressed as * expressed as 16.16 fixed point value.
* 16.16 fixed-point value.
* *
* @note: * @note:
* The radius is expressed in the same units as the outline coordinates. * 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. * This function calls @FT_Stroker_Rewind automatically.
*/ */
FT_EXPORT( void ) FT_EXPORT( void )

View File

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