mirror of
https://github.com/netsurf-browser/netsurf
synced 2025-02-04 16:44:14 +03:00
add simplistic filled polygon plotter
svn path=/trunk/netsurf/; revision=6557
This commit is contained in:
parent
f7e971cad0
commit
afbc77dd07
@ -31,6 +31,9 @@
|
||||
#include "framebuffer/fb_font.h"
|
||||
#include "framebuffer/fb_frontend.h"
|
||||
|
||||
/* max height the poly plotter can cope with */
|
||||
#define WINDOW_HEIGHT (2048)
|
||||
|
||||
/* Currently selected ploting routines. */
|
||||
struct plotter_table plot;
|
||||
|
||||
@ -224,20 +227,194 @@ colour fb_plotters_ablend(colour pixel, colour scrpixel)
|
||||
return r | (g << 8) | (b << 16);
|
||||
}
|
||||
|
||||
bool
|
||||
fb_plotters_polygon(const int *p, unsigned int n, colour fill,bool (linefn)(int x0, int y0, int x1, int y1, int width, colour c, bool dotted, bool dashed))
|
||||
typedef bool (linefn_t)(int x0, int y0, int x1, int y1, int width, colour c, bool dotted, bool dashed);
|
||||
|
||||
typedef struct dcPt_s {
|
||||
int x;
|
||||
int y;
|
||||
} dcPt;
|
||||
|
||||
typedef struct tEdge {
|
||||
int yUpper;
|
||||
float xIntersect, dxPerScan;
|
||||
struct tEdge *next;
|
||||
} Edge;
|
||||
|
||||
static void insertEdge(Edge *list, Edge *edge)
|
||||
{
|
||||
unsigned int pnt;
|
||||
const int *cur = p;
|
||||
|
||||
for (pnt = 1; pnt < n; pnt++) {
|
||||
cur = p + (pnt << 1);
|
||||
linefn(cur[-2], cur[-1], cur[0], cur[1], 1, fill, false, false);
|
||||
Edge *p, *q = list;
|
||||
|
||||
p = q->next;
|
||||
while (p != NULL) {
|
||||
if (edge->xIntersect < p->xIntersect) {
|
||||
p = NULL;
|
||||
} else {
|
||||
q = p;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
edge->next = q->next;
|
||||
q->next = edge;
|
||||
}
|
||||
|
||||
linefn(cur[0], cur[1], p[0], p[1], 1, fill, false, false);
|
||||
static int yNext(int k, int cnt, dcPt *pts)
|
||||
{
|
||||
int j;
|
||||
if ((k+1) > (cnt-1))
|
||||
j = 0;
|
||||
else
|
||||
j = k +1;
|
||||
|
||||
return true;
|
||||
while (pts[k].y == pts[j].y) {
|
||||
if ((j+1) > (cnt-1))
|
||||
j = 0;
|
||||
else
|
||||
j++;
|
||||
}
|
||||
return (pts[j].y);
|
||||
}
|
||||
|
||||
static void makeEdgeRec(dcPt lower, dcPt upper, int yComp, Edge **edges)
|
||||
{
|
||||
Edge *edge;
|
||||
edge = malloc(sizeof(Edge));
|
||||
|
||||
edge->dxPerScan = (float)(upper.x - lower.x) / (upper.y - lower.y);
|
||||
edge->xIntersect = lower.x;
|
||||
|
||||
if (upper.y < yComp)
|
||||
edge->yUpper = upper.y - 1;
|
||||
else
|
||||
edge->yUpper = upper.y;
|
||||
|
||||
if (!fb_plotters_clip_line_ctx(&lower.x, &lower.y,
|
||||
&upper.x, &edge->yUpper)) {
|
||||
free(edge);
|
||||
} else {
|
||||
insertEdge(edges[lower.y], edge);
|
||||
}
|
||||
}
|
||||
|
||||
static void buildEdgeList(int cnt, dcPt *pts, Edge **edges)
|
||||
{
|
||||
dcPt v1, v2;
|
||||
int i, yPrev = pts[cnt - 2].y;
|
||||
|
||||
v1.x = pts[cnt - 1].x;
|
||||
v1.y = pts[cnt - 1].y;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
v2 = pts[i];
|
||||
if (v1.y != v2.y) {
|
||||
/* line is not horizontal */
|
||||
if (v1.y < v2.y)
|
||||
makeEdgeRec(v1, v2, yNext(i,cnt,pts), edges); /* up going edge */
|
||||
else
|
||||
makeEdgeRec(v2, v1, yPrev, edges); /* down going edge */
|
||||
}
|
||||
yPrev = v1.y;
|
||||
v1 = v2;
|
||||
}
|
||||
}
|
||||
|
||||
static void buildActiveList(int scan, Edge *active, Edge **edges)
|
||||
{
|
||||
Edge *p,*q;
|
||||
|
||||
p = edges[scan]->next;
|
||||
|
||||
while (p) {
|
||||
q = p->next;
|
||||
insertEdge(active, p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
static void fillScan(int scan, Edge *active, colour fill, linefn_t linefn)
|
||||
{
|
||||
Edge *p1, *p2;
|
||||
|
||||
p1 = active->next;
|
||||
while (p1) {
|
||||
p2 = p1->next;
|
||||
if (p2 == NULL) {
|
||||
LOG(("only one active edge!"));
|
||||
break;
|
||||
} else {
|
||||
linefn(p1->xIntersect, scan,
|
||||
p2->xIntersect, scan,
|
||||
1, fill, false, false);
|
||||
}
|
||||
p1 = p2->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void deleteAfter(Edge *q)
|
||||
{
|
||||
Edge *p = q->next;
|
||||
q->next = p->next;
|
||||
free (p);
|
||||
}
|
||||
|
||||
static void updateActiveList(int scan, Edge *active)
|
||||
{
|
||||
Edge *q = active, *p = active->next;
|
||||
while (p) {
|
||||
if (scan >= p->yUpper) {
|
||||
p = p->next;
|
||||
deleteAfter(q);
|
||||
} else {
|
||||
p->xIntersect = p->xIntersect + p->dxPerScan;
|
||||
q = p;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void resortActiveList(Edge * active)
|
||||
{
|
||||
Edge *q, *p = active->next;
|
||||
|
||||
active->next = NULL;
|
||||
while (p) {
|
||||
q = p->next;
|
||||
insertEdge(active, p);
|
||||
p = q;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scanFill(int cnt, dcPt *pts, colour fill, linefn_t linefn)
|
||||
{
|
||||
Edge *edges[WINDOW_HEIGHT], *active;
|
||||
int i, scan;
|
||||
|
||||
for (i = 0; i < WINDOW_HEIGHT; i++) {
|
||||
edges[i] = malloc(sizeof(Edge));
|
||||
edges[i]->next = NULL;
|
||||
}
|
||||
buildEdgeList(cnt, pts, edges);
|
||||
|
||||
active = malloc(sizeof(Edge));
|
||||
active->next = NULL;
|
||||
for (scan = 0; scan < WINDOW_HEIGHT; scan++) {
|
||||
buildActiveList (scan, active, edges);
|
||||
if (active->next) {
|
||||
fillScan(scan, active, fill, linefn);
|
||||
updateActiveList (scan, active);
|
||||
resortActiveList(active);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < WINDOW_HEIGHT; i++) {
|
||||
free(edges[i]);
|
||||
}
|
||||
free(active);
|
||||
}
|
||||
|
||||
bool
|
||||
fb_plotters_polygon(const int *p, unsigned int n, colour fill, linefn_t linefn)
|
||||
{
|
||||
scanFill(n, (dcPt *)p, fill, linefn);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fb_plotters_bitmap_tile(int x, int y,
|
||||
|
Loading…
x
Reference in New Issue
Block a user