[smooth] Reduce copying during integration phase. We now record `cover' and `area' directly into the linked list. This makes rendering faster by 10% or even more at larger sizes. * src/smooth/ftgrays.c (FT_INTEGRATE): Write directly. (gray_TWorker): Add direct cell reference and remove unused fields. (gray_set_cell): Consolidate the linked list management and pointers. (gray_convert_glyph, gray_convert_glyph_inner): Updated.
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
diff --git a/ChangeLog b/ChangeLog
index bc4d291..ef2a65d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2021-03-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Reduce copying during integration phase.
+
+ We now record `cover' and `area' directly into the linked list. This
+ makes rendering faster by 10% or even more at larger sizes.
+
+ * src/smooth/ftgrays.c (FT_INTEGRATE): Write directly.
+ (gray_TWorker): Add direct cell reference and remove unused fields.
+ (gray_set_cell): Consolidate the linked list management and pointers.
+ (gray_convert_glyph, gray_convert_glyph_inner): Updated.
+
2021-03-10 Alexei Podtelezhnikov <apodtele@gmail.com>
* src/smooth/ftgrays.c (FT_INTEGRATE): New convenience macro.
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 5e3d453..8ea7230 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -447,14 +447,10 @@ typedef ptrdiff_t FT_PtrDist;
{
ft_jmp_buf jump_buffer;
- TCoord ex, ey;
TCoord min_ex, max_ex;
TCoord min_ey, max_ey;
- TArea area;
- TCoord cover;
- int invalid;
-
+ PCell cell;
PCell* ycells;
PCell cells;
FT_PtrDist max_cells;
@@ -483,8 +479,9 @@ typedef ptrdiff_t FT_PtrDist;
static gray_TWorker ras;
#endif
-#define FT_INTEGRATE( ras, a, b ) \
- ras.cover += (a), ras.area += (a) * (TArea)(b)
+#define FT_INTEGRATE( ras, a, b ) \
+ if ( ras.cell ) \
+ ras.cell->cover += (a), ras.cell->area += (a) * (TArea)(b)
typedef struct gray_TRaster_
@@ -523,59 +520,15 @@ typedef ptrdiff_t FT_PtrDist;
/**************************************************************************
*
- * Record the current cell in the linked list.
- */
- static void
- gray_record_cell( RAS_ARG )
- {
- PCell *pcell, cell;
- TCoord x = ras.ex;
-
-
- pcell = &ras.ycells[ras.ey - ras.min_ey];
- while ( ( cell = *pcell ) )
- {
- if ( cell->x > x )
- break;
-
- if ( cell->x == x )
- goto Found;
-
- pcell = &cell->next;
- }
-
- if ( ras.num_cells >= ras.max_cells )
- ft_longjmp( ras.jump_buffer, 1 );
-
- /* insert new cell */
- cell = ras.cells + ras.num_cells++;
- cell->x = x;
- cell->area = ras.area;
- cell->cover = ras.cover;
-
- cell->next = *pcell;
- *pcell = cell;
-
- return;
-
- Found:
- /* update old cell */
- cell->area += ras.area;
- cell->cover += ras.cover;
- }
-
-
- /**************************************************************************
- *
* Set the current cell to a new position.
*/
static void
gray_set_cell( RAS_ARG_ TCoord ex,
TCoord ey )
{
- /* Move the cell pointer to a new position. We set the `invalid' */
- /* flag to indicate that the cell isn't part of those we're interested */
- /* in during the render phase. This means that: */
+ /* 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 */
+ /* during the render phase. This means that: */
/* */
/* . the new vertical position must be within min_ey..max_ey-1. */
/* . the new horizontal position must be strictly less than max_ex */
@@ -583,17 +536,42 @@ typedef ptrdiff_t FT_PtrDist;
/* 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 the current one if it is valid and substantial */
- if ( !ras.invalid && ( ras.area || ras.cover ) )
- gray_record_cell( RAS_VAR );
+ if ( ey >= ras.max_ey || ey < ras.min_ey || ex >= ras.max_ex )
+ ras.cell = NULL;
+ else
+ {
+ PCell *pcell, cell;
+
- ras.area = 0;
- ras.cover = 0;
- ras.ex = FT_MAX( ex, ras.min_ex - 1 );
- ras.ey = ey;
+ ex = FT_MAX( ex, ras.min_ex - 1 );
+
+ pcell = &ras.ycells[ey - ras.min_ey];
+ while ( ( cell = *pcell ) )
+ {
+ if ( cell->x > ex )
+ break;
- ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
- ex >= ras.max_ex );
+ if ( cell->x == ex )
+ goto Found;
+
+ pcell = &cell->next;
+ }
+
+ if ( ras.num_cells >= ras.max_cells )
+ ft_longjmp( ras.jump_buffer, 1 );
+
+ /* insert new cell */
+ cell = ras.cells + ras.num_cells++;
+ cell->x = ex;
+ cell->area = 0;
+ cell->cover = 0;
+
+ cell->next = *pcell;
+ *pcell = cell;
+
+ Found:
+ ras.cell = cell;
+ }
}
@@ -1631,9 +1609,6 @@ typedef ptrdiff_t FT_PtrDist;
if ( continued )
FT_Trace_Enable();
- if ( !ras.invalid )
- gray_record_cell( RAS_VAR );
-
FT_TRACE7(( "band [%d..%d]: %ld cell%s\n",
ras.min_ey,
ras.max_ey,
@@ -1702,7 +1677,7 @@ typedef ptrdiff_t FT_PtrDist;
FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
ras.num_cells = 0;
- ras.invalid = 1;
+ ras.cell = NULL;
ras.min_ey = band[1];
ras.max_ey = band[0];