Commit b39576f984276ef7b9d6febbea2a509b2c95d0f2

Alexei Podtelezhnikov 2019-09-27T19:18:49

* src/base/ftstroke.c (ft_stroker_cap): Speed up caps.

diff --git a/ChangeLog b/ChangeLog
index fe91986..aacd6ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2019-09-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/base/ftstroke.c (ft_stroker_cap): Speed up caps.
+
 2019-09-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* src/base/ftstroke.c (ft_stroker_outside): Speed up clipped miter.
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index 282f6f6..17250db 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -297,12 +297,13 @@ FT_BEGIN_HEADER
    *     expressed as 16.16 fixed point value.
    *
    * @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
+   *   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`.
+   *   @FT_STROKER_LINEJOIN_MITER_VARIABLE or replaced with a bevel join for
+   *   @FT_STROKER_LINEJOIN_MITER_FIXED.
    *
    *   This function calls @FT_Stroker_Rewind automatically.
    */
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index b02658f..bbbb407 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -923,55 +923,40 @@
 
       error = ft_stroker_arcto( stroker, side );
     }
-    else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
+    else
     {
-      /* add a square cap */
-      FT_Vector        delta, delta2;
-      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
+      /* add a square or butt cap */
+      FT_Vector        middle, delta;
       FT_Fixed         radius = stroker->radius;
       FT_StrokeBorder  border = stroker->borders + side;
 
 
-      FT_Vector_From_Polar( &delta2, radius, angle + rotate );
-      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;
-
-      FT_Vector_From_Polar( &delta2, radius, angle - rotate );
-      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 == FT_STROKER_LINECAP_BUTT )
-    {
-      /* add a butt ending */
-      FT_Vector        delta;
-      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
-      FT_Fixed         radius = stroker->radius;
-      FT_StrokeBorder  border = stroker->borders + side;
-
+      /* compute middle point and first angle point */
+      FT_Vector_From_Polar( &middle, radius, angle );
+      delta.x = side ?  middle.y : -middle.y;
+      delta.y = side ? -middle.x :  middle.x;
 
-      FT_Vector_From_Polar( &delta, radius, angle + rotate );
+      if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
+      {
+        middle.x += stroker->center.x;
+        middle.y += stroker->center.y;
+      }
+      else  /* FT_STROKER_LINECAP_BUTT */
+      {
+        middle.x  = stroker->center.x;
+        middle.y  = stroker->center.y;
+      }
 
-      delta.x += stroker->center.x;
-      delta.y += stroker->center.y;
+      delta.x  += middle.x;
+      delta.y  += middle.y;
 
       error = ft_stroke_border_lineto( border, &delta, FALSE );
       if ( error )
         goto Exit;
 
-      FT_Vector_From_Polar( &delta, radius, angle - rotate );
-
-      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 );
     }