Skip to content

Commit 41eb2b5

Browse files
committed
Additional improvements to pretty_poly
1 parent 581481c commit 41eb2b5

File tree

1 file changed

+76
-19
lines changed

1 file changed

+76
-19
lines changed

libraries/pico_vector/pretty_poly.cpp

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -79,39 +79,57 @@ namespace pretty_poly {
7979
std::swap(sx, ex);
8080
}
8181

82+
// Early out if line is completely outside the tile
8283
if (ey < 0 || sy >= (int)node_buffer_size) return;
8384

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+
}
8899

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
89110
int x = sx;
90111
int e = 0;
91112

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;
95116

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.
96119
if (sy < 0) {
97120
e = einc * -sy;
98121
int xjump = e / dy;
99122
e -= dy * xjump;
100123
x += xinc * xjump;
101-
sy = 0;
102124
}
103125

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);
108126
// loop over scanlines
109127
while(count--) {
110128
// consume accumulated error
111129
while(e > dy) {e -= dy; x += xinc;}
112130

113131
// 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);
115133
debug(" + adding node at %d, %d\n", x, y);
116134
// add node to node list
117135
nodes[y][node_counts[y]++] = nx;
@@ -150,15 +168,18 @@ namespace pretty_poly {
150168
bounds.y = 0;
151169
bounds.x = tile.bounds.w;
152170
int maxx = 0;
171+
int anitialias_mask = (1 << settings::antialias) - 1;
172+
153173
for(auto y = 0; y < (int)node_buffer_size; y++) {
154174
if(node_counts[y] == 0) {
155175
if (y == bounds.y) ++bounds.y;
156176
continue;
157177
}
158-
maxy = y;
159178

160179
std::sort(&nodes[y][0], &nodes[y][0] + node_counts[y]);
161180

181+
uint8_t* row_data = &tile.data[(y >> settings::antialias) * tile.stride];
182+
bool rendered_any = false;
162183
for(auto i = 0u; i < node_counts[y]; i += 2) {
163184
int sx = nodes[y][i + 0];
164185
int ex = nodes[y][i + 1];
@@ -167,19 +188,55 @@ namespace pretty_poly {
167188
continue;
168189
}
169190

170-
bounds.x = std::min(sx >> settings::antialias, bounds.x);
191+
rendered_any = true;
192+
171193
maxx = std::max((ex - 1) >> settings::antialias, maxx);
172194

173195
debug(" - render span at %d from %d to %d\n", y, sx, ex);
174196

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;
178232
}
179233
}
180234

235+
bounds.y >>= settings::antialias;
236+
maxy >>= settings::antialias;
181237
bounds.w = (maxx >= bounds.x) ? maxx + 1 - bounds.x : 0;
182238
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);
183240
}
184241

185242
template<typename T>
@@ -214,7 +271,7 @@ namespace pretty_poly {
214271
debug(" - clip %d, %d (%d x %d)\n", settings::clip.x, settings::clip.y, settings::clip.w, settings::clip.h);
215272

216273

217-
memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
274+
//memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
218275

219276
// iterate over tiles
220277
debug(" - processing tiles\n");

0 commit comments

Comments
 (0)