8
8
9
9
#include " pretty_poly.hpp"
10
10
11
+ #include " hardware/interp.h"
11
12
12
13
#ifdef PP_DEBUG
13
14
#define debug (...) printf(__VA_ARGS__)
@@ -79,35 +80,63 @@ namespace pretty_poly {
79
80
std::swap (sx, ex);
80
81
}
81
82
82
- /* sx <<= settings::antialias;
83
- ex <<= settings::antialias;
84
- sy <<= settings::antialias;
85
- ey <<= settings::antialias;*/
83
+ // Early out if line is completely outside the tile, or has no lines
84
+ if (ey < 0 || sy >= (int )node_buffer_size || sy == ey) return ;
86
85
86
+ debug (" + line segment from %d, %d to %d, %d\n " , sx, sy, ex, ey);
87
+
88
+ // Determine how many in-bounds lines to render
89
+ int y = std::max (0 , sy);
90
+ int count = std::min ((int )node_buffer_size, ey) - y;
91
+
92
+ // Handle cases where x is completely off to one side or other
93
+ if (std::max (sx, ex) <= 0 ) {
94
+ while (count--) {
95
+ nodes[y][node_counts[y]++] = 0 ;
96
+ ++y;
97
+ }
98
+ return ;
99
+ }
100
+
101
+ const int full_tile_width = (tile_bounds.w << settings::antialias);
102
+ if (std::min (sx, ex) >= full_tile_width) {
103
+ while (count--) {
104
+ nodes[y][node_counts[y]++] = full_tile_width;
105
+ ++y;
106
+ }
107
+ return ;
108
+ }
109
+
110
+ // Normal case
87
111
int x = sx;
88
- int y = sy;
89
112
int e = 0 ;
90
113
91
- int xinc = sign (ex - sx);
92
- int einc = abs (ex - sx) + 1 ;
114
+ const int xinc = sign (ex - sx);
115
+ const int einc = abs (ex - sx) + 1 ;
116
+ const int dy = ey - sy;
117
+
118
+ // If sy < 0 jump to the start, note this does use a divide
119
+ // but potentially saves many wasted loops below, so is likely worth it.
120
+ if (sy < 0 ) {
121
+ e = einc * -sy;
122
+ int xjump = e / dy;
123
+ e -= dy * xjump;
124
+ x += xinc * xjump;
125
+ }
126
+
127
+ interp1->base [1 ] = full_tile_width;
128
+ interp1->accum [0 ] = x;
93
129
94
- // todo: preclamp sy and ey (and therefore count) no need to perform
95
- // that test inside the loop
96
- int dy = ey - sy;
97
- int count = dy;
98
- debug (" + line segment from %d, %d to %d, %d\n " , sx, sy, ex, ey);
99
130
// loop over scanlines
100
131
while (count--) {
101
132
// consume accumulated error
102
- while (e > dy) {e -= dy; x += xinc;}
103
-
104
- if (y >= 0 && y < (int )node_buffer_size) {
105
- // clamp node x value to tile bounds
106
- int nx = std::max (std::min (x, (int )(tile_bounds.w << settings::antialias)), 0 );
107
- debug (" + adding node at %d, %d\n " , x, y);
108
- // add node to node list
109
- nodes[y][node_counts[y]++] = nx;
110
- }
133
+ while (e > dy) {e -= dy; interp1->add_raw [0 ] = xinc;}
134
+
135
+ // clamp node x value to tile bounds
136
+ const int nx = interp1->peek [0 ];
137
+ debug (" + adding node at %d, %d\n " , x, y);
138
+ // add node to node list
139
+ nodes[y][node_counts[y]++] = nx;
111
140
112
141
// step to next scanline and accumulate error
113
142
y++;
@@ -138,14 +167,23 @@ namespace pretty_poly {
138
167
}
139
168
}
140
169
141
- void render_nodes (const tile_t &tile) {
170
+ void render_nodes (const tile_t &tile, rect_t &bounds) {
171
+ int maxy = -1 ;
172
+ bounds.y = 0 ;
173
+ bounds.x = tile.bounds .w ;
174
+ int maxx = 0 ;
175
+ int anitialias_mask = (1 << settings::antialias) - 1 ;
176
+
142
177
for (auto y = 0 ; y < (int )node_buffer_size; y++) {
143
178
if (node_counts[y] == 0 ) {
179
+ if (y == bounds.y ) ++bounds.y ;
144
180
continue ;
145
181
}
146
182
147
183
std::sort (&nodes[y][0 ], &nodes[y][0 ] + node_counts[y]);
148
184
185
+ uint8_t * row_data = &tile.data [(y >> settings::antialias) * tile.stride ];
186
+ bool rendered_any = false ;
149
187
for (auto i = 0u ; i < node_counts[y]; i += 2 ) {
150
188
int sx = nodes[y][i + 0 ];
151
189
int ex = nodes[y][i + 1 ];
@@ -154,13 +192,55 @@ namespace pretty_poly {
154
192
continue ;
155
193
}
156
194
195
+ rendered_any = true ;
196
+
197
+ maxx = std::max ((ex - 1 ) >> settings::antialias, maxx);
198
+
157
199
debug (" - render span at %d from %d to %d\n " , y, sx, ex);
158
200
159
- for (int x = sx; x < ex; x++) {
160
- tile.data [(x >> settings::antialias) + (y >> settings::antialias) * tile.stride ]++;
161
- }
201
+ if (settings::antialias) {
202
+ int ax = sx >> settings::antialias;
203
+ const int aex = ex >> settings::antialias;
204
+
205
+ bounds.x = std::min (ax, bounds.x );
206
+
207
+ if (ax == aex) {
208
+ row_data[ax] += ex - sx;
209
+ continue ;
210
+ }
211
+
212
+ row_data[ax] += (1 << settings::antialias) - (sx & anitialias_mask);
213
+ for (ax++; ax < aex; ax++) {
214
+ row_data[ax] += (1 << settings::antialias);
215
+ }
216
+
217
+ // This might add 0 to the byte after the end of the row, we pad the tile data
218
+ // by 1 byte to ensure that is OK
219
+ row_data[ax] += ex & anitialias_mask;
220
+ }
221
+ else {
222
+ bounds.x = std::min (sx, bounds.x );
223
+ for (int x = sx; x < ex; x++) {
224
+ row_data[x]++;
225
+ }
226
+ }
227
+ }
228
+
229
+ if (rendered_any) {
230
+ debug (" - rendered line %d\n " , y);
231
+ maxy = y;
232
+ }
233
+ else if (y == bounds.y ) {
234
+ debug (" - render nothing on line %d\n " , y);
235
+ ++bounds.y ;
162
236
}
163
237
}
238
+
239
+ bounds.y >>= settings::antialias;
240
+ maxy >>= settings::antialias;
241
+ bounds.w = (maxx >= bounds.x ) ? maxx + 1 - bounds.x : 0 ;
242
+ bounds.h = (maxy >= bounds.y ) ? maxy + 1 - bounds.y : 0 ;
243
+ debug (" - rendered tile bounds %d, %d (%d x %d)\n " , bounds.x , bounds.y , bounds.w , bounds.h );
164
244
}
165
245
166
246
template <typename T>
@@ -172,7 +252,7 @@ namespace pretty_poly {
172
252
}
173
253
174
254
template <typename T>
175
- void draw_polygon (std::vector<contour_t <T>> contours, point_t <int > origin, int scale) {
255
+ void draw_polygon (const std::vector<contour_t <T>>& contours, point_t <int > origin, int scale) {
176
256
177
257
debug (" > draw polygon with %lu contours\n " , contours.size ());
178
258
@@ -194,8 +274,16 @@ namespace pretty_poly {
194
274
debug (" - bounds %d, %d (%d x %d)\n " , polygon_bounds.x , polygon_bounds.y , polygon_bounds.w , polygon_bounds.h );
195
275
debug (" - clip %d, %d (%d x %d)\n " , settings::clip.x , settings::clip.y , settings::clip.w , settings::clip.h );
196
276
277
+ interp_hw_save_t interp1_save;
278
+ interp_save (interp1, &interp1_save);
279
+
280
+ interp_config cfg = interp_default_config ();
281
+ interp_config_set_clamp (&cfg, true );
282
+ interp_config_set_signed (&cfg, true );
283
+ interp_set_config (interp1, 0 , &cfg);
284
+ interp1->base [0 ] = 0 ;
197
285
198
- memset (nodes, 0 , node_buffer_size * sizeof (unsigned ) * 32 );
286
+ // memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
199
287
200
288
// iterate over tiles
201
289
debug (" - processing tiles\n " );
@@ -218,22 +306,34 @@ namespace pretty_poly {
218
306
memset (tile.data , 0 , tile_buffer_size);
219
307
220
308
// build the nodes for each contour
221
- for (contour_t <T> &contour : contours) {
309
+ for (const contour_t <T> &contour : contours) {
222
310
debug (" : build nodes for contour\n " );
223
311
build_nodes (contour, tile, origin, scale);
224
312
}
225
313
226
314
debug (" : render the tile\n " );
227
315
// render the tile
228
- render_nodes (tile);
316
+ rect_t bounds;
317
+ render_nodes (tile, bounds);
318
+ if (bounds.empty ()) {
319
+ continue ;
320
+ }
321
+
322
+ tile.data += bounds.x + tile.stride * bounds.y ;
323
+ tile.bounds .x += bounds.x ;
324
+ tile.bounds .y += bounds.y ;
325
+ tile.bounds .w = bounds.w ;
326
+ tile.bounds .h = bounds.h ;
229
327
230
328
settings::callback (tile);
231
329
}
232
330
}
331
+
332
+ interp_restore (interp1, &interp1_save);
233
333
}
234
334
}
235
335
236
- template void pretty_poly::draw_polygon<int >(std::vector<contour_t <int >> contours, point_t <int > origin, int scale);
237
- template void pretty_poly::draw_polygon<float >(std::vector<contour_t <float >> contours, point_t <int > origin, int scale);
238
- template void pretty_poly::draw_polygon<uint8_t >(std::vector<contour_t <uint8_t >> contours, point_t <int > origin, int scale);
239
- template void pretty_poly::draw_polygon<int8_t >(std::vector<contour_t <int8_t >> contours, point_t <int > origin, int scale);
336
+ template void pretty_poly::draw_polygon<int >(const std::vector<contour_t <int >>& contours, point_t <int > origin, int scale);
337
+ template void pretty_poly::draw_polygon<float >(const std::vector<contour_t <float >>& contours, point_t <int > origin, int scale);
338
+ template void pretty_poly::draw_polygon<uint8_t >(const std::vector<contour_t <uint8_t >>& contours, point_t <int > origin, int scale);
339
+ template void pretty_poly::draw_polygon<int8_t >(const std::vector<contour_t <int8_t >>& contours, point_t <int > origin, int scale);
0 commit comments