Commit 772e55d38eadd78ace6301034d90c4bb31317e80

David Turner 2006-09-05T09:45:15

* src/smooth/ftgrays.c (gray_sweep): Avoid buffer overwrites when to the end of a bitmap scanline. The fun never ends ;-)

diff --git a/ChangeLog b/ChangeLog
index ef5e34d..ab3762a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2006-09-05  David Turner  <david@freetype.org>
+
+        * src/smooth/ftgrays.c (gray_sweep): Avoid buffer overwrites
+        when to the end of a bitmap scanline. The fun never ends ;-)
+
 2006-09-04  David Turner  <david@freetype.org>
 
 	* src/smooth/ftgrays.c (gray_convert_glyphs): Make it work with
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 08b797e..bb590c6 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -381,32 +381,25 @@ typedef struct TCell_
   /*                                                                       */
   /* Record the current cell in the table.                                 */
   /*                                                                       */
-  static PCell*
+  static PCell
   gray_find_cell( RAS_ARG_ TCoord  x,
                            TCoord  y )
   {
-    PCell  *pnode, node;
+    PCell  *pcell, cell;
 
 
-    pnode = &ras.ycells[y];
+    pcell = &ras.ycells[y];
     for (;;)
     {
-      node = *pnode;
-      if ( node == NULL || node->x >= x )
+      cell = *pcell;
+      if ( cell == NULL || cell->x > x )
         break;
 
-      pnode = &node->next;
-    }
-
-    return pnode;
-  }
-
-
-  static PCell
-  gray_alloc_cell( RAS_ARG_ TCoord  x )
-  {
-    PCell  cell;
+      if ( cell->x == x )
+        goto Exit;
 
+      pcell = &cell->next;
+    }
 
     if ( ras.num_cells >= ras.max_cells )
       ft_longjmp( ras.jump_buffer, 1 );
@@ -416,6 +409,10 @@ typedef struct TCell_
     cell->area  = 0;
     cell->cover = 0;
 
+    cell->next  = *pcell;
+    *pcell      = cell;
+
+  Exit:
     return cell;
   }
 
@@ -423,19 +420,11 @@ typedef struct TCell_
   static void
   gray_record_cell( RAS_ARG )
   {
-    if ( !ras.invalid && ( ras.area | ras.cover ) )
+    if ( !ras.invalid && (ras.area | ras.cover) )
     {
-      TCoord  x       = (TCoord)( ras.ex - ras.min_ex );
-      TCoord  y       = (TCoord)( ras.ey - ras.min_ey );
-      PCell  *pparent = gray_find_cell( RAS_VAR_ x, y );
-      PCell   cell    = *pparent;
-
-      if ( cell == NULL || cell->x != x )
-      {
-        cell = gray_alloc_cell( RAS_VAR_ x );
-        cell->next  = *pparent;
-        *pparent    = cell;
-      }
+      TCoord  x    = (TCoord)( ras.ex - ras.min_ex );
+      TCoord  y    = (TCoord)( ras.ey - ras.min_ey );
+      PCell   cell = gray_find_cell( RAS_VAR_ x, y );
 
       cell->area  += ras.area;
       cell->cover += ras.cover;
@@ -464,37 +453,23 @@ typedef struct TCell_
     /* Note that if a cell is to the left of the clipping region, it is    */
     /* actually set to the (min_ex-1) horizontal position.                 */
 
-    record  = 0;
-    clean   = 1;
+    /* All cells that are on the left of the clipping region go to the */
+    /* min_ex - 1 horizontal position.                                 */
+    if ( ex < ras.min_ex )
+      ex = (TCoord)(ras.min_ex - 1);
 
-    invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
-    if ( !invalid )
+    /* are we moving to a different cell ? */
+    if ( ex != ras.ex || ey != ras.ey )
     {
-      /* All cells that are on the left of the clipping region go to the */
-      /* min_ex - 1 horizontal position.                                 */
-      if ( ex < ras.min_ex )
-        ex = (TCoord)(ras.min_ex - 1);
-
-      /* if our position is new, then record the previous cell */
-      if ( ex != ras.ex || ey != ras.ey )
-        record = 1;
-      else
-        clean = ras.invalid;  /* do not clean if we didn't move from */
-                              /* a valid cell                        */
-    }
+      /* record the current one if it is valid */
+      if ( !ras.invalid )
+        gray_record_cell( RAS_VAR );
 
-    /* record the previous cell if needed (i.e., if we changed the cell */
-    /* position, or changed the `invalid' flag)                         */
-    if ( ras.invalid != invalid || record )
-      gray_record_cell( RAS_VAR );
-
-    if ( clean )
-    {
       ras.area  = 0;
       ras.cover = 0;
     }
 
-    ras.invalid = invalid;
+    ras.invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
     ras.ex      = ex;
     ras.ey      = ey;
   }
@@ -1248,6 +1223,24 @@ typedef struct TCell_
   }
 
 
+#if 1
+  gray_dump_cells( RAS_ARG )
+  {
+    int  yindex;
+
+    for ( yindex = 0; yindex < ras.ycount; yindex++ )
+    {
+      PCell  cell;
+
+      printf( "%3d:", yindex );
+
+      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
+        printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area );
+      printf( "\n" );
+    }
+  }
+#endif
+
   static void
   gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
   {
@@ -1288,7 +1281,7 @@ typedef struct TCell_
 
       if ( cover != 0 )
         gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
-                    ras.max_ex - x );
+                    (ras.max_ex - ras.min_ex) - x );
     }
 
     if ( ras.render_span && ras.num_gray_spans > 0 )