Additional improvements to pretty_poly

pull/840/head
Mike Bell 2023-09-10 00:08:35 +01:00
rodzic 581481c2ef
commit 41eb2b503e
1 zmienionych plików z 76 dodań i 19 usunięć

Wyświetl plik

@ -79,39 +79,57 @@ namespace pretty_poly {
std::swap(sx, ex);
}
// Early out if line is completely outside the tile
if (ey < 0 || sy >= (int)node_buffer_size) return;
/*sx <<= settings::antialias;
ex <<= settings::antialias;
sy <<= settings::antialias;
ey <<= settings::antialias;*/
debug(" + line segment from %d, %d to %d, %d\n", sx, sy, ex, ey);
// Determine how many in-bounds lines to render
int y = std::max(0, sy);
int count = std::min((int)node_buffer_size, ey) - y;
// Handle cases where x is completely off to one side or other
if (std::max(sx, ex) <= 0) {
while (count--) {
nodes[y][node_counts[y]++] = 0;
++y;
}
return;
}
const int full_tile_width = (tile_bounds.w << settings::antialias);
if (std::min(sx, ex) >= full_tile_width) {
while (count--) {
nodes[y][node_counts[y]++] = full_tile_width;
++y;
}
return;
}
// Normal case
int x = sx;
int e = 0;
int xinc = sign(ex - sx);
int einc = abs(ex - sx) + 1;
int dy = ey - sy;
const int xinc = sign(ex - sx);
const int einc = abs(ex - sx) + 1;
const int dy = ey - sy;
// If sy < 0 jump to the start, note this does use a divide
// but potentially saves many wasted loops below, so is likely worth it.
if (sy < 0) {
e = einc * -sy;
int xjump = e / dy;
e -= dy * xjump;
x += xinc * xjump;
sy = 0;
}
int y = sy;
int count = std::min((int)node_buffer_size, ey) - sy;
debug(" + line segment from %d, %d to %d, %d\n", sx, sy, ex, ey);
// loop over scanlines
while(count--) {
// consume accumulated error
while(e > dy) {e -= dy; x += xinc;}
// clamp node x value to tile bounds
int nx = std::max(std::min(x, (int)(tile_bounds.w << settings::antialias)), 0);
int nx = std::max(std::min(x, full_tile_width), 0);
debug(" + adding node at %d, %d\n", x, y);
// add node to node list
nodes[y][node_counts[y]++] = nx;
@ -150,15 +168,18 @@ namespace pretty_poly {
bounds.y = 0;
bounds.x = tile.bounds.w;
int maxx = 0;
int anitialias_mask = (1 << settings::antialias) - 1;
for(auto y = 0; y < (int)node_buffer_size; y++) {
if(node_counts[y] == 0) {
if (y == bounds.y) ++bounds.y;
continue;
}
maxy = y;
std::sort(&nodes[y][0], &nodes[y][0] + node_counts[y]);
uint8_t* row_data = &tile.data[(y >> settings::antialias) * tile.stride];
bool rendered_any = false;
for(auto i = 0u; i < node_counts[y]; i += 2) {
int sx = nodes[y][i + 0];
int ex = nodes[y][i + 1];
@ -167,19 +188,55 @@ namespace pretty_poly {
continue;
}
bounds.x = std::min(sx >> settings::antialias, bounds.x);
rendered_any = true;
maxx = std::max((ex - 1) >> settings::antialias, maxx);
debug(" - render span at %d from %d to %d\n", y, sx, ex);
for(int x = sx; x < ex; x++) {
tile.data[(x >> settings::antialias) + (y >> settings::antialias) * tile.stride]++;
}
if (settings::antialias) {
int ax = sx >> settings::antialias;
const int aex = ex >> settings::antialias;
bounds.x = std::min(ax, bounds.x);
if (ax == aex) {
row_data[ax] += ex - sx;
continue;
}
row_data[ax] += (1 << settings::antialias) - (sx & anitialias_mask);
for(ax++; ax < aex; ax++) {
row_data[ax] += (1 << settings::antialias);
}
// This might add 0 to the byte after the end of the row, we pad the tile data
// by 1 byte to ensure that is OK
row_data[ax] += ex & anitialias_mask;
}
else {
bounds.x = std::min(sx, bounds.x);
for(int x = sx; x < ex; x++) {
row_data[x]++;
}
}
}
if (rendered_any) {
debug(" - rendered line %d\n", y);
maxy = y;
}
else if (y == bounds.y) {
debug(" - render nothing on line %d\n", y);
++bounds.y;
}
}
bounds.y >>= settings::antialias;
maxy >>= settings::antialias;
bounds.w = (maxx >= bounds.x) ? maxx + 1 - bounds.x : 0;
bounds.h = (maxy >= bounds.y) ? maxy + 1 - bounds.y : 0;
debug(" - rendered tile bounds %d, %d (%d x %d)\n", bounds.x, bounds.y, bounds.w, bounds.h);
}
template<typename T>
@ -214,7 +271,7 @@ namespace pretty_poly {
debug(" - clip %d, %d (%d x %d)\n", settings::clip.x, settings::clip.y, settings::clip.w, settings::clip.h);
memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
//memset(nodes, 0, node_buffer_size * sizeof(unsigned) * 32);
// iterate over tiles
debug(" - processing tiles\n");