shithub: freetype+ttf2subf

Download patch

ref: d62d583d9228fda1d9b6509d44d0293d7aaaa62e
parent: 6e9d8d314ff6ab23177b9162c0b96616460bb84e
author: Alexei Podtelezhnikov <[email protected]>
date: Fri Aug 20 19:40:49 EDT 2021

[smooth] Clean up the null cell usage.

Put the null cell at the end of the pool and store it explicitly so that
we can use it as both the limit and the dumpster.

* src/smooth/ftgrays.c (gray_TWorker): Store the last `cell_null` and
remove unnecesary fields.
(NULL_CELL_PTR, CELL_IS_NULL): Remove in favor of explicit `cell_null`.
(gray_dump_cells, gray_set_cell, gray_sweep{,_direct}): Update callers.
(gray_convert_glyph_inner): Trace remaining cells (oh well).
(gray_convert_glyph): Set up `cell_null` and slightly improve the pool
management.

git/fs: mount .git/fs: mount/attach disallowed
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -479,14 +479,11 @@
 
     PCell       cell;        /* current cell                             */
     PCell       cell_free;   /* call allocation next free slot           */
-    PCell       cell_limit;  /* cell allocation limit                    */
+    PCell       cell_null;   /* last cell, used as dumpster and limit    */
 
     PCell*      ycells;      /* array of cell linked-lists; one per      */
                              /* vertical coordinate in the current band  */
 
-    PCell       cells;       /* cell storage area     */
-    FT_PtrDist  max_cells;   /* cell storage capacity */
-
     TPos        x,  y;       /* last point position */
 
     FT_Outline  outline;     /* input outline */
@@ -507,23 +504,11 @@
   static gray_TWorker  ras;
 #endif
 
-  /*
-   * Return a pointer to the 'null cell', used as a sentinel at the end of
-   * all `ycells` linked lists.  Its x coordinate should be maximal to
-   * ensure no NULL checks are necessary when looking for an insertion point
-   * in `gray_set_cell`.  Other loops should check the cell pointer with
-   * CELL_IS_NULL() to detect the end of the list.
-   */
-#define NULL_CELL_PTR( ras )  (ras).cells
-
   /* The |x| value of the null cell.  Must be the largest possible */
   /* integer value stored in a `TCell.x` field.                    */
 #define CELL_MAX_X_VALUE    INT_MAX
 
-  /* Return true iff |cell| points to the null cell. */
-#define CELL_IS_NULL( cell )  ( (cell)->x == CELL_MAX_X_VALUE )
 
-
 #define FT_INTEGRATE( ras, a, b )                                       \
           ras.cell->cover = ADD_INT( ras.cell->cover, a ),              \
           ras.cell->area  = ADD_INT( ras.cell->area, (a) * (TArea)(b) )
@@ -553,7 +538,7 @@
 
       printf( "%3d:", y );
 
-      for ( ; !CELL_IS_NULL( cell ); cell = cell->next )
+      for ( ; cell != ras.cell_null; cell = cell->next )
         printf( " (%3d, c:%4d, a:%6d)",
                 cell->x, cell->cover, cell->area );
       printf( "\n" );
@@ -572,7 +557,7 @@
                           TCoord  ey )
   {
     /* Move the cell pointer to a new position in the linked list. We use  */
-    /* NULL to indicate that the cell is outside of the clipping region    */
+    /* a dumpster null cell for everything outside of the clipping region  */
     /* during the render phase.  This means that:                          */
     /*                                                                     */
     /* . the new vertical position must be within min_ey..max_ey-1.        */
@@ -585,7 +570,7 @@
 
 
     if ( ey_index < 0 || ey_index >= ras.count_ey || ex >= ras.max_ex )
-      ras.cell = NULL_CELL_PTR( ras );
+      ras.cell = ras.cell_null;
     else
     {
       PCell*  pcell = ras.ycells + ey_index;
@@ -609,7 +594,7 @@
 
       /* insert new cell */
       cell = ras.cell_free++;
-      if ( cell >= ras.cell_limit )
+      if ( cell >= ras.cell_null )
         ft_longjmp( ras.jump_buffer, 1 );
 
       cell->x     = ex;
@@ -1483,7 +1468,7 @@
       unsigned char*  line = ras.target.origin - ras.target.pitch * y;
 
 
-      for ( ; !CELL_IS_NULL( cell ); cell = cell->next )
+      for ( ; cell != ras.cell_null; cell = cell->next )
       {
         TArea  area;
 
@@ -1534,7 +1519,7 @@
       TArea   cover = 0;
 
 
-      for ( ; !CELL_IS_NULL( cell ); cell = cell->next )
+      for ( ; cell != ras.cell_null; cell = cell->next )
       {
         TArea  area;
 
@@ -1914,11 +1899,11 @@
       if ( continued )
         FT_Trace_Enable();
 
-      FT_TRACE7(( "band [%d..%d]: %ld cell%s\n",
+      FT_TRACE7(( "band [%d..%d]: %ld cell%s remaining/\n",
                   ras.min_ey,
                   ras.max_ey,
-                  ras.cell_free - ras.cells,
-                  ras.cell_free - ras.cells == 1 ? "" : "s" ));
+                  ras.cell_null - ras.cell_free,
+                  ras.cell_null - ras.cell_free == 1 ? "" : "s" ));
     }
     else
     {
@@ -1948,7 +1933,16 @@
     int  continued = 0;
 
 
+    /* Initialize the null cell at the end of the poll. */
+    ras.cell_null        = buffer + FT_MAX_GRAY_POOL - 1;
+    ras.cell_null->x     = CELL_MAX_X_VALUE;
+    ras.cell_null->area  = 0;
+    ras.cell_null->cover = 0;
+    ras.cell_null->next  = NULL;;
+
     /* set up vertical bands */
+    ras.ycells     = (PCell*)buffer;
+
     if ( height > n )
     {
       /* two divisions rounded up */
@@ -1956,23 +1950,6 @@
       height  = ( height + n - 1 ) / n;
     }
 
-    /* memory management */
-    n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell );
-
-    ras.cells      = buffer + n;
-    ras.max_cells  = (FT_PtrDist)( FT_MAX_GRAY_POOL - n );
-    ras.cell_limit = ras.cells + ras.max_cells;
-    ras.ycells     = (PCell*)buffer;
-
-    /* Initialize the null cell at the start of the `cells` array.    */
-    /* Note that this requires `ras.cell_free` initialization to skip */
-    /* over the first entry in the array.                             */
-    PCell null_cell  = NULL_CELL_PTR( ras );
-    null_cell->x     = CELL_MAX_X_VALUE;
-    null_cell->area  = 0;
-    null_cell->cover = 0;
-    null_cell->next  = NULL;;
-
     for ( y = yMin; y < yMax; )
     {
       ras.min_ey = y;
@@ -1991,10 +1968,14 @@
 
 
         for ( w = 0; w < width; ++w )
-          ras.ycells[w] = null_cell;
+          ras.ycells[w] = ras.cell_null;
 
-        ras.cell_free = ras.cells + 1;  /* NOTE: Skip over the null cell. */
-        ras.cell      = null_cell;
+        /* memory management: skip ycells */
+        n = ( width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+                      sizeof ( TCell );
+
+        ras.cell_free = buffer + n;
+        ras.cell      = ras.cell_null;
         ras.min_ey    = band[1];
         ras.max_ey    = band[0];
         ras.count_ey  = width;