Refactored polygon functions to unify logic

The functions `polygon8`, `polygon32` and `polygon32rgba` all have exactly
the same logic in code, only changes the hline function called inside.

Now all the logic is contained in `polygon_generic` which gets a
function pointer to the hline handler, so there is no duplicated code
anymore.
This commit is contained in:
Terseus 2014-04-01 13:01:03 +02:00
parent 6e2075e25d
commit deecd8a137

View File

@ -61,6 +61,9 @@ typedef struct {
float dx;
} Edge;
/* Type used in "polygon*" functions */
typedef void (*hline_handler)(Imaging, int, int, int, int);
static inline void
point8(Imaging im, int x, int y, int ink)
{
@ -403,8 +406,10 @@ x_cmp(const void *x0, const void *x1)
return 0;
}
static inline int
polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill,
hline_handler handler)
{
int i, j;
float *xx;
@ -436,22 +441,23 @@ polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
for (;ymin <= ymax; ymin++) {
y = ymin+0.5F;
for (i = j = 0; i < n; i++)
for (i = j = 0; i < n; i++) {
if (y >= e[i].ymin && y <= e[i].ymax) {
if (e[i].d == 0)
hline8(im, e[i].xmin, ymin, e[i].xmax, ink);
(*handler)(im, e[i].xmin, ymin, e[i].xmax, ink);
else
xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
}
}
if (j == 2) {
if (xx[0] < xx[1])
hline8(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
(*handler)(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
else
hline8(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
(*handler)(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
} else {
qsort(xx, j, sizeof(float), x_cmp);
for (i = 0; i < j-1 ; i += 2)
hline8(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
(*handler)(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
}
}
@ -460,120 +466,22 @@ polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
return 0;
}
static inline int
polygon8(Imaging im, int n, Edge *e, int ink, int eofill)
{
return polygon_generic(im, n, e, ink, eofill, hline8);
}
static inline int
polygon32(Imaging im, int n, Edge *e, int ink, int eofill)
{
int i, j;
float *xx;
int ymin, ymax;
float y;
if (n <= 0)
return 0;
/* Find upper and lower polygon boundary (within image) */
ymin = e[0].ymin;
ymax = e[0].ymax;
for (i = 1; i < n; i++) {
if (e[i].ymin < ymin) ymin = e[i].ymin;
if (e[i].ymax > ymax) ymax = e[i].ymax;
}
if (ymin < 0)
ymin = 0;
if (ymax >= im->ysize)
ymax = im->ysize-1;
/* Process polygon edges */
xx = malloc(n * sizeof(float));
if (!xx)
return -1;
for (;ymin <= ymax; ymin++) {
y = ymin+0.5F;
for (i = j = 0; i < n; i++) {
if (y >= e[i].ymin && y <= e[i].ymax) {
if (e[i].d == 0)
hline32(im, e[i].xmin, ymin, e[i].xmax, ink);
else
xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
}
}
if (j == 2) {
if (xx[0] < xx[1])
hline32(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
else
hline32(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
} else {
qsort(xx, j, sizeof(float), x_cmp);
for (i = 0; i < j-1 ; i += 2)
hline32(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
}
}
free(xx);
return 0;
return polygon_generic(im, n, e, ink, eofill, hline32);
}
static inline int
polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill)
{
int i, j;
float *xx;
int ymin, ymax;
float y;
if (n <= 0)
return 0;
/* Find upper and lower polygon boundary (within image) */
ymin = e[0].ymin;
ymax = e[0].ymax;
for (i = 1; i < n; i++) {
if (e[i].ymin < ymin) ymin = e[i].ymin;
if (e[i].ymax > ymax) ymax = e[i].ymax;
}
if (ymin < 0)
ymin = 0;
if (ymax >= im->ysize)
ymax = im->ysize-1;
/* Process polygon edges */
xx = malloc(n * sizeof(float));
if (!xx)
return -1;
for (;ymin <= ymax; ymin++) {
y = ymin+0.5F;
for (i = j = 0; i < n; i++) {
if (y >= e[i].ymin && y <= e[i].ymax) {
if (e[i].d == 0)
hline32rgba(im, e[i].xmin, ymin, e[i].xmax, ink);
else
xx[j++] = (y-e[i].y0) * e[i].dx + e[i].x0;
}
}
if (j == 2) {
if (xx[0] < xx[1])
hline32rgba(im, CEIL(xx[0]-0.5), ymin, FLOOR(xx[1]+0.5), ink);
else
hline32rgba(im, CEIL(xx[1]-0.5), ymin, FLOOR(xx[0]+0.5), ink);
} else {
qsort(xx, j, sizeof(float), x_cmp);
for (i = 0; i < j-1 ; i += 2)
hline32rgba(im, CEIL(xx[i]-0.5), ymin, FLOOR(xx[i+1]+0.5), ink);
}
}
free(xx);
return 0;
return polygon_generic(im, n, e, ink, eofill, hline32rgba);
}
static inline void