freetype: cherry pick optimization patches from freetype.
authorSubhransu Mohanty <smohantty@gmail.com>
Tue, 30 Jun 2020 03:30:25 +0000 (12:30 +0900)
committerJongmin Lee <jm105.lee@samsung.com>
Mon, 13 Jul 2020 03:33:20 +0000 (12:33 +0900)
src/vector/freetype/v_ft_raster.cpp
src/vector/freetype/v_ft_stroker.cpp

index 51cb1f2..e48ad1b 100644 (file)
@@ -749,100 +749,60 @@ static void gray_split_cubic(SW_FT_Vector* base)
     base[3].y = ( a + c ) >> 3;
 }
 
-static void gray_render_cubic(RAS_ARG_ const SW_FT_Vector* control1,
+
+static void
+gray_render_cubic(RAS_ARG_ const SW_FT_Vector* control1,
                               const SW_FT_Vector*          control2,
                               const SW_FT_Vector*          to)
 {
-    SW_FT_Vector* arc;
-    TPos          min, max, y;
-
-    arc = ras.bez_stack;
-    arc[0].x = UPSCALE(to->x);
-    arc[0].y = UPSCALE(to->y);
-    arc[1].x = UPSCALE(control2->x);
-    arc[1].y = UPSCALE(control2->y);
-    arc[2].x = UPSCALE(control1->x);
-    arc[2].y = UPSCALE(control1->y);
+    SW_FT_Vector* arc = ras.bez_stack;
+
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control2->x );
+    arc[1].y = UPSCALE( control2->y );
+    arc[2].x = UPSCALE( control1->x );
+    arc[2].y = UPSCALE( control1->y );
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    /* Short-cut the arc that crosses the current band. */
-    min = max = arc[0].y;
-
-    y = arc[1].y;
-    if (y < min) min = y;
-    if (y > max) max = y;
-
-    y = arc[2].y;
-    if (y < min) min = y;
-    if (y > max) max = y;
-
-    y = arc[3].y;
-    if (y < min) min = y;
-    if (y > max) max = y;
-
-    if (TRUNC(min) >= ras.max_ey || TRUNC(max) < ras.min_ey) goto Draw;
-
-    for (;;) {
-        /* Decide whether to split or draw. See `Rapid Termination          */
-        /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
-        /* F. Hain, at                                                      */
-        /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf
-         */
-
-        {
-            TPos dx, dy, dx_, dy_;
-            TPos dx1, dy1, dx2, dy2;
-            TPos L, s, s_limit;
-
-            /* dx and dy are x and y components of the P0-P3 chord vector. */
-            dx = dx_ = arc[3].x - arc[0].x;
-            dy = dy_ = arc[3].y - arc[0].y;
-
-            L = SW_FT_HYPOT(dx_, dy_);
-
-            /* Avoid possible arithmetic overflow below by splitting. */
-            if (L > 32767) goto Split;
-
-            /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
-            s_limit = L * (TPos)(ONE_PIXEL / 6);
-
-            /* s is L * the perpendicular distance from P1 to the line P0-P3. */
-            dx1 = arc[1].x - arc[0].x;
-            dy1 = arc[1].y - arc[0].y;
-            s = SW_FT_ABS(dy * dx1 - dx * dy1);
-
-            if (s > s_limit) goto Split;
-
-            /* s is L * the perpendicular distance from P2 to the line P0-P3. */
-            dx2 = arc[2].x - arc[0].x;
-            dy2 = arc[2].y - arc[0].y;
-            s = SW_FT_ABS(dy * dx2 - dx * dy2);
-
-            if (s > s_limit) goto Split;
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+           TRUNC( arc[1].y ) >= ras.max_ey &&
+           TRUNC( arc[2].y ) >= ras.max_ey &&
+           TRUNC( arc[3].y ) >= ras.max_ey ) ||
+         ( TRUNC( arc[0].y ) <  ras.min_ey &&
+           TRUNC( arc[1].y ) <  ras.min_ey &&
+           TRUNC( arc[2].y ) <  ras.min_ey &&
+           TRUNC( arc[3].y ) <  ras.min_ey ) )
+    {
+      ras.x = arc[0].x;
+      ras.y = arc[0].y;
+      return;
+    }
 
-            /* Split super curvy segments where the off points are so far
-               from the chord that the angles P0-P1-P3 or P0-P2-P3 become
-               acute as detected by appropriate dot products. */
-            if (dx1 * (dx1 - dx) + dy1 * (dy1 - dy) > 0 ||
-                dx2 * (dx2 - dx) + dy2 * (dy2 - dy) > 0)
-                goto Split;
+    for (;;)
+    {
+      /* with each split, control points quickly converge towards  */
+      /* chord trisection points and the vanishing distances below */
+      /* indicate when the segment is flat enough to draw          */
+      if ( SW_FT_ABS( 2 * arc[0].x - 3 * arc[1].x + arc[3].x ) > ONE_PIXEL / 2 ||
+           SW_FT_ABS( 2 * arc[0].y - 3 * arc[1].y + arc[3].y ) > ONE_PIXEL / 2 ||
+           SW_FT_ABS( arc[0].x - 3 * arc[2].x + 2 * arc[3].x ) > ONE_PIXEL / 2 ||
+           SW_FT_ABS( arc[0].y - 3 * arc[2].y + 2 * arc[3].y ) > ONE_PIXEL / 2 )
+        goto Split;
+
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+
+      if ( arc == ras.bez_stack )
+        return;
 
-            /* No reason to split. */
-            goto Draw;
-        }
+      arc -= 3;
+      continue;
 
     Split:
-        gray_split_cubic(arc);
-        arc += 3;
-        continue;
-
-    Draw:
-        gray_render_line(RAS_VAR_ arc[0].x, arc[0].y);
-
-        if (arc == ras.bez_stack) return;
-
-        arc -= 3;
+      gray_split_cubic( arc );
+      arc += 3;
     }
 }
 
index c7307eb..3160f84 100644 (file)
@@ -481,65 +481,60 @@ static SW_FT_Error ft_stroke_border_cubicto(SW_FT_StrokeBorder border,
 
 #define SW_FT_ARC_CUBIC_ANGLE (SW_FT_ANGLE_PI / 2)
 
-static SW_FT_Error ft_stroke_border_arcto(SW_FT_StrokeBorder border,
-                                          SW_FT_Vector*      center,
-                                          SW_FT_Fixed        radius,
-                                          SW_FT_Angle        angle_start,
-                                          SW_FT_Angle        angle_diff)
+
+static SW_FT_Error
+ft_stroke_border_arcto( SW_FT_StrokeBorder  border,
+                        SW_FT_Vector*       center,
+                        SW_FT_Fixed         radius,
+                        SW_FT_Angle         angle_start,
+                        SW_FT_Angle         angle_diff )
 {
-    SW_FT_Angle  total, angle, step, rotate, next, theta;
-    SW_FT_Vector a, b, a2, b2;
-    SW_FT_Fixed  length;
-    SW_FT_Error  error = 0;
-
-    /* compute start point */
-    SW_FT_Vector_From_Polar(&a, radius, angle_start);
-    a.x += center->x;
-    a.y += center->y;
-
-    total = angle_diff;
-    angle = angle_start;
-    rotate = (angle_diff >= 0) ? SW_FT_ANGLE_PI2 : -SW_FT_ANGLE_PI2;
-
-    while (total != 0) {
-        step = total;
-        if (step > SW_FT_ARC_CUBIC_ANGLE)
-            step = SW_FT_ARC_CUBIC_ANGLE;
-
-        else if (step < -SW_FT_ARC_CUBIC_ANGLE)
-            step = -SW_FT_ARC_CUBIC_ANGLE;
-
-        next = angle + step;
-        theta = step;
-        if (theta < 0) theta = -theta;
-
-        theta >>= 1;
-
-        /* compute end point */
-        SW_FT_Vector_From_Polar(&b, radius, next);
-        b.x += center->x;
-        b.y += center->y;
-
-        /* compute first and second control points */
-        length = SW_FT_MulDiv(radius, SW_FT_Sin(theta) * 4,
-                              (0x10000L + SW_FT_Cos(theta)) * 3);
-
-        SW_FT_Vector_From_Polar(&a2, length, angle + rotate);
-        a2.x += a.x;
-        a2.y += a.y;
-
-        SW_FT_Vector_From_Polar(&b2, length, next - rotate);
-        b2.x += b.x;
-        b2.y += b.y;
-
-        /* add cubic arc */
-        error = ft_stroke_border_cubicto(border, &a2, &b2, &b);
-        if (error) break;
-
-        /* process the rest of the arc ?? */
-        a = b;
-        total -= step;
-        angle = next;
+    SW_FT_Fixed   coef;
+    SW_FT_Vector  a0, a1, a2, a3;
+    SW_FT_Int     i, arcs = 1;
+    SW_FT_Error   error = 0;
+
+
+    /* number of cubic arcs to draw */
+    while (  angle_diff > SW_FT_ARC_CUBIC_ANGLE * arcs ||
+            -angle_diff > SW_FT_ARC_CUBIC_ANGLE * arcs )
+      arcs++;
+
+    /* control tangents */
+    coef  = SW_FT_Tan( angle_diff / ( 4 * arcs ) );
+    coef += coef / 3;
+
+    /* compute start and first control point */
+    SW_FT_Vector_From_Polar( &a0, radius, angle_start );
+    a1.x = SW_FT_MulFix( -a0.y, coef );
+    a1.y = SW_FT_MulFix(  a0.x, coef );
+
+    a0.x += center->x;
+    a0.y += center->y;
+    a1.x += a0.x;
+    a1.y += a0.y;
+
+    for ( i = 1; i <= arcs; i++ )
+    {
+      /* compute end and second control point */
+      SW_FT_Vector_From_Polar( &a3, radius,
+                            angle_start + i * angle_diff / arcs );
+      a2.x = SW_FT_MulFix(  a3.y, coef );
+      a2.y = SW_FT_MulFix( -a3.x, coef );
+
+      a3.x += center->x;
+      a3.y += center->y;
+      a2.x += a3.x;
+      a2.y += a3.y;
+
+      /* add cubic arc */
+      error = ft_stroke_border_cubicto( border, &a1, &a2, &a3 );
+      if ( error )
+        break;
+
+      /* a0 = a3; */
+      a1.x = a3.x - a2.x + a3.x;
+      a1.y = a3.y - a2.y + a3.y;
     }
 
     return error;
@@ -782,61 +777,56 @@ static SW_FT_Error ft_stroker_arcto(SW_FT_Stroker stroker, SW_FT_Int side)
 }
 
 /* add a cap at the end of an opened path */
-static SW_FT_Error ft_stroker_cap(SW_FT_Stroker stroker, SW_FT_Angle angle,
-                                  SW_FT_Int side)
+static SW_FT_Error
+ft_stroker_cap(SW_FT_Stroker stroker,
+               SW_FT_Angle angle,
+               SW_FT_Int side)
 {
     SW_FT_Error error = 0;
 
-    if (stroker->line_cap == SW_FT_STROKER_LINECAP_ROUND) {
+    if (stroker->line_cap == SW_FT_STROKER_LINECAP_ROUND)
+    {
         /* add a round cap */
         stroker->angle_in = angle;
         stroker->angle_out = angle + SW_FT_ANGLE_PI;
 
         error = ft_stroker_arcto(stroker, side);
-    } else if (stroker->line_cap == SW_FT_STROKER_LINECAP_SQUARE) {
-        /* add a square cap */
-        SW_FT_Vector       delta, delta2;
-        SW_FT_Angle        rotate = SW_FT_SIDE_TO_ROTATE(side);
-        SW_FT_Fixed        radius = stroker->radius;
-        SW_FT_StrokeBorder border = stroker->borders + side;
-
-        SW_FT_Vector_From_Polar(&delta2, radius, angle + rotate);
-        SW_FT_Vector_From_Polar(&delta, radius, angle);
-
-        delta.x += stroker->center.x + delta2.x;
-        delta.y += stroker->center.y + delta2.y;
-
-        error = ft_stroke_border_lineto(border, &delta, FALSE);
-        if (error) goto Exit;
-
-        SW_FT_Vector_From_Polar(&delta2, radius, angle - rotate);
-        SW_FT_Vector_From_Polar(&delta, radius, angle);
-
-        delta.x += delta2.x + stroker->center.x;
-        delta.y += delta2.y + stroker->center.y;
-
-        error = ft_stroke_border_lineto(border, &delta, FALSE);
-    } else if (stroker->line_cap == SW_FT_STROKER_LINECAP_BUTT) {
-        /* add a butt ending */
-        SW_FT_Vector       delta;
-        SW_FT_Angle        rotate = SW_FT_SIDE_TO_ROTATE(side);
-        SW_FT_Fixed        radius = stroker->radius;
-        SW_FT_StrokeBorder border = stroker->borders + side;
+    }
+    else
+    {
+        /* add a square or butt cap */
+        SW_FT_Vector        middle, delta;
+        SW_FT_Fixed         radius = stroker->radius;
+        SW_FT_StrokeBorder  border = stroker->borders + side;
 
-        SW_FT_Vector_From_Polar(&delta, radius, angle + rotate);
+        /* compute middle point and first angle point */
+        SW_FT_Vector_From_Polar( &middle, radius, angle );
+        delta.x = side ?  middle.y : -middle.y;
+        delta.y = side ? -middle.x :  middle.x;
 
-        delta.x += stroker->center.x;
-        delta.y += stroker->center.y;
+        if ( stroker->line_cap == SW_FT_STROKER_LINECAP_SQUARE )
+        {
+            middle.x += stroker->center.x;
+            middle.y += stroker->center.y;
+        }
+        else  /* SW_FT_STROKER_LINECAP_BUTT */
+        {
+            middle.x  = stroker->center.x;
+            middle.y  = stroker->center.y;
+        }
 
-        error = ft_stroke_border_lineto(border, &delta, FALSE);
-        if (error) goto Exit;
+        delta.x  += middle.x;
+        delta.y  += middle.y;
 
-        SW_FT_Vector_From_Polar(&delta, radius, angle - rotate);
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
+        if ( error )
+        goto Exit;
 
-        delta.x += stroker->center.x;
-        delta.y += stroker->center.y;
+        /* compute second angle point */
+        delta.x = middle.x - delta.x + middle.x;
+        delta.y = middle.y - delta.y + middle.y;
 
-        error = ft_stroke_border_lineto(border, &delta, FALSE);
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
     }
 
 Exit:
@@ -849,8 +839,8 @@ static SW_FT_Error ft_stroker_inside(SW_FT_Stroker stroker, SW_FT_Int side,
 {
     SW_FT_StrokeBorder border = stroker->borders + side;
     SW_FT_Angle        phi, theta, rotate;
-    SW_FT_Fixed        length, thcos;
-    SW_FT_Vector       delta;
+    SW_FT_Fixed        length;
+    SW_FT_Vector       sigma, delta;
     SW_FT_Error        error = 0;
     SW_FT_Bool         intersect; /* use intersection of lines? */
 
@@ -860,15 +850,21 @@ static SW_FT_Error ft_stroker_inside(SW_FT_Stroker stroker, SW_FT_Int side,
 
     /* Only intersect borders if between two lineto's and both */
     /* lines are long enough (line_length is zero for curves). */
-    if (!border->movable || line_length == 0)
+    if (!border->movable || line_length == 0  ||
+         theta > 0x59C000 || theta < -0x59C000 )
         intersect = FALSE;
     else {
-        /* compute minimum required length of lines */
-        SW_FT_Fixed min_length =
-            ft_pos_abs(SW_FT_MulFix(stroker->radius, SW_FT_Tan(theta)));
+      /* compute minimum required length of lines */
+      SW_FT_Fixed  min_length;
 
-        intersect = SW_FT_BOOL(stroker->line_length >= min_length &&
-                               line_length >= min_length);
+
+      SW_FT_Vector_Unit( &sigma, theta );
+      min_length =
+        ft_pos_abs( SW_FT_MulDiv( stroker->radius, sigma.y, sigma.x ) );
+
+      intersect = SW_FT_BOOL( min_length                         &&
+                           stroker->line_length >= min_length &&
+                           line_length          >= min_length );
     }
 
     if (!intersect) {
@@ -880,15 +876,13 @@ static SW_FT_Error ft_stroker_inside(SW_FT_Stroker stroker, SW_FT_Int side,
         border->movable = FALSE;
     } else {
         /* compute median angle */
-        phi = stroker->angle_in + theta;
+        phi = stroker->angle_in + theta + rotate;
 
-        thcos = SW_FT_Cos(theta);
+      length = SW_FT_DivFix( stroker->radius, sigma.x );
 
-        length = SW_FT_DivFix(stroker->radius, thcos);
-
-        SW_FT_Vector_From_Polar(&delta, length, phi + rotate);
-        delta.x += stroker->center.x;
-        delta.y += stroker->center.y;
+      SW_FT_Vector_From_Polar( &delta, length, phi );
+      delta.x += stroker->center.x;
+      delta.y += stroker->center.y;
     }
 
     error = ft_stroke_border_lineto(border, &delta, FALSE);
@@ -896,137 +890,156 @@ static SW_FT_Error ft_stroker_inside(SW_FT_Stroker stroker, SW_FT_Int side,
     return error;
 }
 
-/* process an outside corner, i.e. compute bevel/miter/round */
-static SW_FT_Error ft_stroker_outside(SW_FT_Stroker stroker, SW_FT_Int side,
-                                      SW_FT_Fixed line_length)
+  /* process an outside corner, i.e. compute bevel/miter/round */
+static SW_FT_Error
+ft_stroker_outside( SW_FT_Stroker  stroker,
+                    SW_FT_Int      side,
+                    SW_FT_Fixed    line_length )
 {
-    SW_FT_StrokeBorder border = stroker->borders + side;
-    SW_FT_Error        error;
-    SW_FT_Angle        rotate;
+    SW_FT_StrokeBorder  border = stroker->borders + side;
+    SW_FT_Error         error;
+    SW_FT_Angle         rotate;
 
-    if (stroker->line_join == SW_FT_STROKER_LINEJOIN_ROUND)
-        error = ft_stroker_arcto(stroker, side);
-    else {
-        /* this is a mitered (pointed) or beveled (truncated) corner */
-        SW_FT_Fixed sigma = 0, radius = stroker->radius;
-        SW_FT_Angle theta = 0, phi = 0;
-        SW_FT_Fixed thcos = 0;
-        SW_FT_Bool  bevel, fixed_bevel;
 
-        rotate = SW_FT_SIDE_TO_ROTATE(side);
+    if ( stroker->line_join == SW_FT_STROKER_LINEJOIN_ROUND )
+      error = ft_stroker_arcto( stroker, side );
+    else
+    {
+      /* this is a mitered (pointed) or beveled (truncated) corner */
+      SW_FT_Fixed   radius = stroker->radius;
+      SW_FT_Vector  sigma;
+      SW_FT_Angle   theta = 0, phi = 0;
+      SW_FT_Bool    bevel, fixed_bevel;
 
-        bevel = SW_FT_BOOL(stroker->line_join == SW_FT_STROKER_LINEJOIN_BEVEL);
 
-        fixed_bevel = SW_FT_BOOL(stroker->line_join !=
-                                 SW_FT_STROKER_LINEJOIN_MITER_VARIABLE);
+      rotate = SW_FT_SIDE_TO_ROTATE( side );
 
-        if (!bevel) {
-            theta = SW_FT_Angle_Diff(stroker->angle_in, stroker->angle_out);
+      bevel =
+        SW_FT_BOOL( stroker->line_join == SW_FT_STROKER_LINEJOIN_BEVEL );
 
-            if (theta == SW_FT_ANGLE_PI) {
-                theta = rotate;
-                phi = stroker->angle_in;
-            } else {
-                theta /= 2;
-                phi = stroker->angle_in + theta + rotate;
-            }
+      fixed_bevel =
+        SW_FT_BOOL( stroker->line_join != SW_FT_STROKER_LINEJOIN_MITER_VARIABLE );
 
-            thcos = SW_FT_Cos(theta);
-            sigma = SW_FT_MulFix(stroker->miter_limit, thcos);
+      /* check miter limit first */
+      if ( !bevel )
+      {
+        theta = SW_FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
 
-            /* is miter limit exceeded? */
-            if (sigma < 0x10000L) {
-                /* don't create variable bevels for very small deviations; */
-                /* SW_FT_Sin(x) = 0 for x <= 57                               */
-                if (fixed_bevel || ft_pos_abs(theta) > 57) bevel = TRUE;
-            }
+        if ( theta == SW_FT_ANGLE_PI2 )
+          theta = -rotate;
+
+        phi    = stroker->angle_in + theta + rotate;
+
+        SW_FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta );
+
+        /* is miter limit exceeded? */
+        if ( sigma.x < 0x10000L )
+        {
+          /* don't create variable bevels for very small deviations; */
+          /* FT_Sin(x) = 0 for x <= 57                               */
+          if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
+            bevel = TRUE;
         }
+      }
 
-        if (bevel) /* this is a bevel (broken angle) */
+      if ( bevel )  /* this is a bevel (broken angle) */
+      {
+        if ( fixed_bevel )
         {
-            if (fixed_bevel) {
-                /* the outer corners are simply joined together */
-                SW_FT_Vector delta;
-
-                /* add bevel */
-                SW_FT_Vector_From_Polar(&delta, radius,
-                                        stroker->angle_out + rotate);
-                delta.x += stroker->center.x;
-                delta.y += stroker->center.y;
-
-                border->movable = FALSE;
-                error = ft_stroke_border_lineto(border, &delta, FALSE);
-            } else /* variable bevel */
-            {
-                /* the miter is truncated */
-                SW_FT_Vector middle, delta;
-                SW_FT_Fixed  length;
+          /* the outer corners are simply joined together */
+          SW_FT_Vector  delta;
 
-                /* compute middle point */
-                SW_FT_Vector_From_Polar(
-                    &middle, SW_FT_MulFix(radius, stroker->miter_limit), phi);
-                middle.x += stroker->center.x;
-                middle.y += stroker->center.y;
 
-                /* compute first angle point */
-                length = SW_FT_MulDiv(radius, 0x10000L - sigma,
-                                      ft_pos_abs(SW_FT_Sin(theta)));
+          /* add bevel */
+          SW_FT_Vector_From_Polar( &delta,
+                                radius,
+                                stroker->angle_out + rotate );
+          delta.x += stroker->center.x;
+          delta.y += stroker->center.y;
 
-                SW_FT_Vector_From_Polar(&delta, length, phi + rotate);
-                delta.x += middle.x;
-                delta.y += middle.y;
+          border->movable = FALSE;
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+        }
+        else /* variable bevel or clipped miter */
+        {
+          /* the miter is truncated */
+          SW_FT_Vector  middle, delta;
+          SW_FT_Fixed   coef;
 
-                error = ft_stroke_border_lineto(border, &delta, FALSE);
-                if (error) goto Exit;
 
-                /* compute second angle point */
-                SW_FT_Vector_From_Polar(&delta, length, phi - rotate);
-                delta.x += middle.x;
-                delta.y += middle.y;
+          /* compute middle point and first angle point */
+          SW_FT_Vector_From_Polar( &middle,
+                                   SW_FT_MulFix( radius, stroker->miter_limit ),
+                                   phi );
 
-                error = ft_stroke_border_lineto(border, &delta, FALSE);
-                if (error) goto Exit;
+          coef    = SW_FT_DivFix(  0x10000L - sigma.x, sigma.y );
+          delta.x = SW_FT_MulFix(  middle.y, coef );
+          delta.y = SW_FT_MulFix( -middle.x, coef );
 
-                /* finally, add an end point; only needed if not lineto */
-                /* (line_length is zero for curves)                     */
-                if (line_length == 0) {
-                    SW_FT_Vector_From_Polar(&delta, radius,
-                                            stroker->angle_out + rotate);
+          middle.x += stroker->center.x;
+          middle.y += stroker->center.y;
+          delta.x  += middle.x;
+          delta.y  += middle.y;
 
-                    delta.x += stroker->center.x;
-                    delta.y += stroker->center.y;
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+          if ( error )
+            goto Exit;
 
-                    error = ft_stroke_border_lineto(border, &delta, FALSE);
-                }
-            }
-        } else /* this is a miter (intersection) */
-        {
-            SW_FT_Fixed  length;
-            SW_FT_Vector delta;
+          /* compute second angle point */
+          delta.x = middle.x - delta.x + middle.x;
+          delta.y = middle.y - delta.y + middle.y;
 
-            length = SW_FT_DivFix(stroker->radius, thcos);
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
+          if ( error )
+            goto Exit;
+
+          /* finally, add an end point; only needed if not lineto */
+          /* (line_length is zero for curves)                     */
+          if ( line_length == 0 )
+          {
+            SW_FT_Vector_From_Polar( &delta,
+                                  radius,
+                                  stroker->angle_out + rotate );
 
-            SW_FT_Vector_From_Polar(&delta, length, phi);
             delta.x += stroker->center.x;
             delta.y += stroker->center.y;
 
-            error = ft_stroke_border_lineto(border, &delta, FALSE);
-            if (error) goto Exit;
+            error = ft_stroke_border_lineto( border, &delta, FALSE );
+          }
+        }
+      }
+      else /* this is a miter (intersection) */
+      {
+        SW_FT_Fixed   length;
+        SW_FT_Vector  delta;
 
-            /* now add an end point; only needed if not lineto */
-            /* (line_length is zero for curves)                */
-            if (line_length == 0) {
-                SW_FT_Vector_From_Polar(&delta, stroker->radius,
-                                        stroker->angle_out + rotate);
-                delta.x += stroker->center.x;
-                delta.y += stroker->center.y;
 
-                error = ft_stroke_border_lineto(border, &delta, FALSE);
-            }
+        length = SW_FT_MulDiv( stroker->radius, stroker->miter_limit, sigma.x );
+
+        SW_FT_Vector_From_Polar( &delta, length, phi );
+        delta.x += stroker->center.x;
+        delta.y += stroker->center.y;
+
+        error = ft_stroke_border_lineto( border, &delta, FALSE );
+        if ( error )
+          goto Exit;
+
+        /* now add an end point; only needed if not lineto */
+        /* (line_length is zero for curves)                */
+        if ( line_length == 0 )
+        {
+          SW_FT_Vector_From_Polar( &delta,
+                                stroker->radius,
+                                stroker->angle_out + rotate );
+          delta.x += stroker->center.x;
+          delta.y += stroker->center.y;
+
+          error = ft_stroke_border_lineto( border, &delta, FALSE );
         }
+      }
     }
 
-Exit:
+  Exit:
     return error;
 }