@@ -79,39 +79,57 @@ namespace pretty_poly {
79
79
std::swap (sx, ex);
80
80
}
81
81
82
+ // Early out if line is completely outside the tile
82
83
if (ey < 0 || sy >= (int )node_buffer_size) return ;
83
84
84
- /* sx <<= settings::antialias;
85
- ex <<= settings::antialias;
86
- sy <<= settings::antialias;
87
- ey <<= settings::antialias;*/
85
+ debug (" + line segment from %d, %d to %d, %d\n " , sx, sy, ex, ey);
86
+
87
+ // Determine how many in-bounds lines to render
88
+ int y = std::max (0 , sy);
89
+ int count = std::min ((int )node_buffer_size, ey) - y;
90
+
91
+ // Handle cases where x is completely off to one side or other
92
+ if (std::max (sx, ex) <= 0 ) {
93
+ while (count--) {
94
+ nodes[y][node_counts[y]++] = 0 ;
95
+ ++y;
96
+ }
97
+ return ;
98
+ }
88
99
100
+ const int full_tile_width = (tile_bounds.w << settings::antialias);
101
+ if (std::min (sx, ex) >= full_tile_width) {
102
+ while (count--) {
103
+ nodes[y][node_counts[y]++] = full_tile_width;
104
+ ++y;
105
+ }
106
+ return ;
107
+ }
108
+
109
+ // Normal case
89
110
int x = sx;
90
111
int e = 0 ;
91
112
92
- int xinc = sign (ex - sx);
93
- int einc = abs (ex - sx) + 1 ;
94
- int dy = ey - sy;
113
+ const int xinc = sign (ex - sx);
114
+ const int einc = abs (ex - sx) + 1 ;
115
+ const int dy = ey - sy;
95
116
117
+ // If sy < 0 jump to the start, note this does use a divide
118
+ // but potentially saves many wasted loops below, so is likely worth it.
96
119
if (sy < 0 ) {
97
120
e = einc * -sy;
98
121
int xjump = e / dy;
99
122
e -= dy * xjump;
100
123
x += xinc * xjump;
101
- sy = 0 ;
102
124
}
103
125
104
- int y = sy;
105
-
106
- int count = std::min ((int )node_buffer_size, ey) - sy;
107
- debug (" + line segment from %d, %d to %d, %d\n " , sx, sy, ex, ey);
108
126
// loop over scanlines
109
127
while (count--) {
110
128
// consume accumulated error
111
129
while (e > dy) {e -= dy; x += xinc;}
112
130
113
131
// clamp node x value to tile bounds
114
- int nx = std::max (std::min (x, ( int )(tile_bounds. w << settings::antialias) ), 0 );
132
+ int nx = std::max (std::min (x, full_tile_width ), 0 );
115
133
debug (" + adding node at %d, %d\n " , x, y);
116
134
// add node to node list
117
135
nodes[y][node_counts[y]++] = nx;
@@ -150,15 +168,18 @@ namespace pretty_poly {
150
168
bounds.y = 0 ;
151
169
bounds.x = tile.bounds .w ;
152
170
int maxx = 0 ;
171
+ int anitialias_mask = (1 << settings::antialias) - 1 ;
172
+
153
173
for (auto y = 0 ; y < (int )node_buffer_size; y++) {
154
174
if (node_counts[y] == 0 ) {
155
175
if (y == bounds.y ) ++bounds.y ;
156
176
continue ;
157
177
}
158
- maxy = y;
159
178
160
179
std::sort (&nodes[y][0 ], &nodes[y][0 ] + node_counts[y]);
161
180
181
+ uint8_t * row_data = &tile.data [(y >> settings::antialias) * tile.stride ];
182
+ bool rendered_any = false ;
162
183
for (auto i = 0u ; i < node_counts[y]; i += 2 ) {
163
184
int sx = nodes[y][i + 0 ];
164
185
int ex = nodes[y][i + 1 ];
@@ -167,19 +188,55 @@ namespace pretty_poly {
167
188
continue ;
168
189
}
169
190
170
- bounds.x = std::min (sx >> settings::antialias, bounds.x );
191
+ rendered_any = true ;
192
+
171
193
maxx = std::max ((ex - 1 ) >> settings::antialias, maxx);
172
194
173
195
debug (" - render span at %d from %d to %d\n " , y, sx, ex);
174
196
175
- for (int x = sx; x < ex; x++) {
176
- tile.data [(x >> settings::antialias) + (y >> settings::antialias) * tile.stride ]++;
177
- }
197
+ if (settings::antialias) {
198
+ int ax = sx >> settings::antialias;
199
+ const int aex = ex >> settings::antialias;
200
+
201
+ bounds.x = std::min (ax, bounds.x );
202
+
203
+ if (ax == aex) {
204
+ row_data[ax] += ex - sx;
205
+ continue ;
206
+ }
207
+
208
+ row_data[ax] += (1 << settings::antialias) - (sx & anitialias_mask);
209
+ for (ax++; ax < aex; ax++) {
210
+ row_data[ax] += (1 << settings::antialias);
211
+ }
212
+
213
+ // This might add 0 to the byte after the end of the row, we pad the tile data
214
+ // by 1 byte to ensure that is OK
215
+ row_data[ax] += ex & anitialias_mask;
216
+ }
217
+ else {
218
+ bounds.x = std::min (sx, bounds.x );
219
+ for (int x = sx; x < ex; x++) {
220
+ row_data[x]++;
221
+ }
222
+ }
223
+ }
224
+
225
+ if (rendered_any) {
226
+ debug (" - rendered line %d\n " , y);
227
+ maxy = y;
228
+ }
229
+ else if (y == bounds.y ) {
230
+ debug (" - render nothing on line %d\n " , y);
231
+ ++bounds.y ;
178
232
}
179
233
}
180
234
235
+ bounds.y >>= settings::antialias;
236
+ maxy >>= settings::antialias;
181
237
bounds.w = (maxx >= bounds.x ) ? maxx + 1 - bounds.x : 0 ;
182
238
bounds.h = (maxy >= bounds.y ) ? maxy + 1 - bounds.y : 0 ;
239
+ debug (" - rendered tile bounds %d, %d (%d x %d)\n " , bounds.x , bounds.y , bounds.w , bounds.h );
183
240
}
184
241
185
242
template <typename T>
@@ -214,7 +271,7 @@ namespace pretty_poly {
214
271
debug (" - clip %d, %d (%d x %d)\n " , settings::clip.x , settings::clip.y , settings::clip.w , settings::clip.h );
215
272
216
273
217
- memset (nodes, 0 , node_buffer_size * sizeof (unsigned ) * 32 );
274
+ // memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
218
275
219
276
// iterate over tiles
220
277
debug (" - processing tiles\n " );
0 commit comments