[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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index d433e09..3179602 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -479,14 +479,11 @@ typedef ptrdiff_t FT_PtrDist;
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,22 +504,10 @@ typedef ptrdiff_t FT_PtrDist;
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 ), \
@@ -553,7 +538,7 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
/* 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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
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 @@ typedef ptrdiff_t FT_PtrDist;
for ( w = 0; w < width; ++w )
- ras.ycells[w] = null_cell;
+ ras.ycells[w] = ras.cell_null;
+
+ /* memory management: skip ycells */
+ n = ( width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
+ sizeof ( TCell );
- ras.cell_free = ras.cells + 1; /* NOTE: Skip over the null cell. */
- ras.cell = null_cell;
+ ras.cell_free = buffer + n;
+ ras.cell = ras.cell_null;
ras.min_ey = band[1];
ras.max_ey = band[0];
ras.count_ey = width;