Skip to content

Commit

Permalink
fix polygon rendering memory bug
Browse files Browse the repository at this point in the history
  • Loading branch information
coolbutuseless committed Jun 25, 2024
1 parent 8eac46f commit 70cedb7
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 3 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: nara
Type: Package
Title: Native Raster Image Tools
Version: 0.1.1.9019
Version: 0.1.1.9020
Authors@R: c(
person("Mike", "Cheng", role = c("aut", "cre", 'cph'), email = "[email protected]")
)
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# nara 0.1.1.9019 2024-06-24
# nara 0.1.1.9020 2024-06-26

* Remove 'isocubes()'
* Remove 'op' argument.
Expand Down Expand Up @@ -37,6 +37,7 @@
* `nr_rect()`
* added `nr_blit_list()` and `nr_blit_grid()`.
* added `nr_resize_nn()` and `nr_resize_bilinear()`. `nr_scale()` is now a wrapper around `nr_resize_nn()`
* Fixed bug in polygon rendering

# nara 0.1.1 2022-07-30

Expand Down
72 changes: 71 additions & 1 deletion src/nr-draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,76 @@ void fill_polygon_c(uint32_t *nr, int height, int width, uint32_t color, int *x,
free(nodeX);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Draw polygon [C interface]
// public domain code from
// https://www.alienryderflex.com/polygon_fill/
// not as efficient as something with an active edge table but it
// get me 30fps in "Another World" so I'm moving on. Patches/PR welcomed!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void fill_polygon_c_new(uint32_t *nr, int height, int width, uint32_t color, int *x, int *y, int npoints) {
// int nodes, pixelX, pixelY, i, j, swap ;

int *nodeX = (int *)malloc((size_t)npoints * sizeof(int));
if (nodeX == NULL) {
error("fill_polygon_c(): memory allocation failed for 'nodeX'");
}

int ymin = INT_MAX;
int ymax = INT_MIN;
for (int i = 0; i < npoints; i++) {
if (y[i] < ymin) {
ymin = y[i];
}
if (y[i] > ymax) {
ymax = y[i];
}
}

// Loop through the rows of the image.
for (int pixelY = 0; pixelY < height; pixelY++) {

// Build a list of nodes.
int nodes=0;
int j = npoints - 1;
for (int i=0; i < npoints; i++) {
if (((y[i] < (double)pixelY) && (y[j] >= (double) pixelY)) ||
((y[j] < (double)pixelY) && (y[i] >= (double) pixelY))) {
nodeX[nodes++] = (int) (x[i] + (pixelY - y[i])/(double)(y[j] - y[i]) * (x[j] - x[i]));
}
j = i;
}

// Sort the nodes, via a simple “Bubble” sort.
int i = 0;
while (i < nodes - 1) {
if (nodeX[i] > nodeX[i + 1]) {
int swap = nodeX[i];
nodeX[i] = nodeX[i+1];
nodeX[i + 1] = swap;
if (i) {
i--;
}
} else {
i++;
}
}

// Fill the pixels between node pairs.
for (i = 0; i < nodes; i += 2) {
if (nodeX[i] >= width) break;
if (nodeX[i + 1] > 0 ) {
if (nodeX[i] < 0) nodeX[i] = 0;
if (nodeX[i + 1] >= width) nodeX[i + 1] = width - 1;
// for (pixelX=nodeX[i]; pixelX<nodeX[i+1]; pixelX++) fillPixel(pixelX,pixelY); }}}
draw_point_sequence_c(nr, height, width, color, nodeX[i], nodeX[i+1], pixelY);
}
}
} // end for(pixelY)
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// R Polygon [R interface]
Expand Down Expand Up @@ -574,7 +644,7 @@ SEXP draw_polygon_(SEXP nr_, SEXP x_, SEXP y_, SEXP fill_, SEXP color_) {
int *y = as_int32_vec(y_, N, &freey);

// Rprintf("Polygon Fill: %i\n", fill);
fill_polygon_c(nr, height, width, fill, x, y, length(x_));
fill_polygon_c_new(nr, height, width, fill, x, y, length(x_));

// outline
if (!is_transparent(color)) {
Expand Down

0 comments on commit 70cedb7

Please sign in to comment.