68 lines
1.7 KiB
C
68 lines
1.7 KiB
C
#include <gint/defs/util.h>
|
|
#include <gint/display.h>
|
|
#include <stdlib.h>
|
|
|
|
static int compare(void const *ptr1, void const *ptr2)
|
|
{
|
|
return *(int const *)ptr1 - *(int const *)ptr2;
|
|
}
|
|
|
|
static void dpoly_fill(int const *x, int const *y, int N, int color)
|
|
{
|
|
int *nodeX = malloc(N * sizeof *nodeX);
|
|
|
|
/* Find vertical bounds */
|
|
int ymin = y[0], ymax = y[0];
|
|
for(int i = 1; i < N; i++)
|
|
{
|
|
ymin = min(ymin, y[i]);
|
|
ymax = max(ymax, y[i]);
|
|
}
|
|
ymin = max(ymin, dwindow.top);
|
|
ymax = min(ymax, dwindow.bottom);
|
|
|
|
/* For each row, find vertical cuts from the segments and fill in-between
|
|
the cuts. */
|
|
for(int pixelY = ymin; pixelY <= ymax; pixelY++) {
|
|
|
|
/* Build a list of nodes */
|
|
int nodes = 0;
|
|
int j = N - 1;
|
|
for(int i = 0; i < N; i++)
|
|
{
|
|
if((y[i] < pixelY) != (y[j] < pixelY))
|
|
nodeX[nodes++] = x[i]+(pixelY-y[i])*(x[j]-x[i])/(y[j]-y[i]);
|
|
j = i;
|
|
}
|
|
|
|
/* Sort the cuts' positions */
|
|
qsort(nodeX, nodes, sizeof nodeX[0], compare);
|
|
|
|
/* Fill the pixels between cut pairs */
|
|
for(int i = 0; i < nodes; i += 2)
|
|
{
|
|
if(nodeX[i] >= dwindow.right || nodeX[i+1] < dwindow.left) break;
|
|
nodeX[i] = max(nodeX[i], dwindow.left);
|
|
nodeX[i+1] = min(nodeX[i+1], dwindow.right);
|
|
dline(nodeX[i], pixelY, nodeX[i+1], pixelY, color);
|
|
}
|
|
}
|
|
|
|
free(nodeX);
|
|
}
|
|
|
|
static void dpoly_border(int const *x, int const *y, int N, int color)
|
|
{
|
|
for(int i = 0; i < N - 1; i++)
|
|
dline(x[i], y[i], x[i+1], y[i+1], color);
|
|
dline(x[N-1], y[N-1], x[0], y[0], color);
|
|
}
|
|
|
|
void dpoly(int const *x, int const *y, int N, int fill_color, int border_color)
|
|
{
|
|
if(N > 2 && fill_color != C_NONE)
|
|
dpoly_fill(x, y, N, fill_color);
|
|
if(N >= 2 && border_color != C_NONE)
|
|
dpoly_border(x, y, N, border_color);
|
|
}
|