Commit e7ac9288acde8ad21c96ad9c448ad2b2cfc9fe6a

Alexei Podtelezhnikov 2019-06-13T00:17:36

[smooth] Restore the span buffering for direct mode only. The buffer size FT_MAX_GRAY_SPANS is set to 10 spans, which should be enough to cover the entire scanline for simple glyphs in most cases: each slightly slanted edge needs up to two spans, plus a filling span in-between. This is not new, we used to do it before cb4388783cecc. * src/smooth/ftgrays.c (gray_TWorker): Add `spans' and `num_spans'. (gray_hline, gray_sweep): Implement the span buffering. (gray_raster_render): Use negative `num_spans' to avoid the direct mode.

diff --git a/ChangeLog b/ChangeLog
index f5bd68f..d5cf019 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2019-06-13  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth] Restore the span buffering for direct mode only.
+
+	The buffer size FT_MAX_GRAY_SPANS is set to 10 spans, which should be
+	enough to cover the entire scanline for simple glyphs in most cases:
+	each slightly slanted edge needs up to two spans, plus a filling span
+	in-between.  This is not new, we used to do it before cb4388783cecc.
+
+	* src/smooth/ftgrays.c (gray_TWorker): Add `spans' and `num_spans'.
+	(gray_hline, gray_sweep): Implement the span buffering.
+	(gray_raster_render): Use negative `num_spans' to avoid the direct
+	mode.
+
 2019-06-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	* include/freetype/ftmodapi.h (FT_DebugHook_Func): Return error.
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 6a824c4..fd357a5 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -432,6 +432,9 @@ typedef ptrdiff_t  FT_PtrDist;
 #define FT_MAX_GRAY_POOL  ( 2048 / sizeof ( TCell ) )
 #endif
 
+  /* FT_Span buffer size for direct rendering only */
+#define FT_MAX_GRAY_SPANS  10
+
 
 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
   /* We disable the warning `structure was padded due to   */
@@ -465,6 +468,8 @@ typedef ptrdiff_t  FT_PtrDist;
 
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
+    FT_Span              spans[FT_MAX_GRAY_SPANS];
+    int                  num_spans;
 
   } gray_TWorker, *gray_PWorker;
 
@@ -1226,16 +1231,21 @@ typedef ptrdiff_t  FT_PtrDist;
         coverage = 255;
     }
 
-    if ( ras.render_span )  /* for FT_RASTER_FLAG_DIRECT only */
+    if ( ras.num_spans >= 0 )  /* for FT_RASTER_FLAG_DIRECT only */
     {
-      FT_Span  span;
+      FT_Span*  span = ras.spans + ras.num_spans++;
 
 
-      span.x        = (short)x;
-      span.len      = (unsigned short)acount;
-      span.coverage = (unsigned char)coverage;
+      span->x        = (short)x;
+      span->len      = (unsigned short)acount;
+      span->coverage = (unsigned char)coverage;
 
-      ras.render_span( y, 1, &span, ras.render_span_data );
+      if ( ras.num_spans == FT_MAX_GRAY_SPANS )
+      {
+        /* flush the span buffer and reset the count */
+        ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
+        ras.num_spans = 0;
+      }
     }
     else
     {
@@ -1309,6 +1319,13 @@ typedef ptrdiff_t  FT_PtrDist;
 
       if ( cover != 0 )
         gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
+
+      if ( ras.num_spans > 0 )  /* for FT_RASTER_FLAG_DIRECT only */
+      {
+        /* flush the span buffer and reset the count */
+        ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
+        ras.num_spans = 0;
+      }
     }
   }
 
@@ -1778,6 +1795,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
+      ras.num_spans        = 0;
 
       ras.min_ex = params->clip_box.xMin;
       ras.min_ey = params->clip_box.yMin;
@@ -1807,6 +1825,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
       ras.render_span      = (FT_Raster_Span_Func)NULL;
       ras.render_span_data = NULL;
+      ras.num_spans        = -1;  /* invalid */
 
       ras.min_ex = 0;
       ras.min_ey = 0;