Commit e9e93d1b19201a5e258f6cd91ada496b6c636a83

Werner Lemberg 2011-09-17T09:21:25

[smooth] Slightly optimize conic and cubic flatterners. * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move out some code from the main loop to speed it up.

diff --git a/ChangeLog b/ChangeLog
index 5b37e68..6187645 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-09-17  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth] Slightly optimize conic and cubic flatterners.
+
+	* src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move
+	out some code from the main loop to speed it up.
+
 2011-09-11  Tomas Hoger  <thoger@redhat.com>
 
 	Slightly improve LZW_CLEAR handling.
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 40de269..895e748 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -872,6 +872,7 @@ typedef ptrdiff_t  FT_PtrDist;
                               const FT_Vector*  to )
   {
     TPos        dx, dy;
+    TPos        min, max, y;
     int         top, level;
     int*        levels;
     FT_Vector*  arc;
@@ -884,45 +885,45 @@ typedef ptrdiff_t  FT_PtrDist;
     arc[1].y = UPSCALE( control->y );
     arc[2].x = ras.x;
     arc[2].y = ras.y;
+    top      = 0;
 
     dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
     dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
     if ( dx < dy )
       dx = dy;
 
+    if ( dx < ONE_PIXEL / 4 )
+      goto Draw;
+
+    /* 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;
+
+    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+      goto Draw;
+
     level = 0;
-    while ( dx > ONE_PIXEL / 6 )
+    do
     {
       dx >>= 2;
       level++;
-    }
+    } while ( dx > ONE_PIXEL / 4 );
 
     levels    = ras.lev_stack;
     levels[0] = level;
-    top       = 0;
 
     do
     {
       level = levels[top];
-      if ( level > 1 )
+      if ( level > 0 )
       {
-        /* check that the arc crosses the current band */
-        TPos  min, max, y;
-
-
-        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;
-
-        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
-          goto Draw;
-
         gray_split_conic( arc );
         arc += 2;
         top++;
@@ -973,6 +974,7 @@ typedef ptrdiff_t  FT_PtrDist;
                               const FT_Vector*  to )
   {
     FT_Vector*  arc;
+    TPos        min, max, y;
 
 
     arc      = ras.bez_stack;
@@ -985,35 +987,32 @@ typedef ptrdiff_t  FT_PtrDist;
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    for (;;)
-    {
-      /* Check that the arc crosses the current band. */
-      TPos  min, max, y;
-
-
-      min = max = arc[0].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[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[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;
+    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;
+    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                                                      */