2 * fill -- polygon tiler
3 * Updating the edgelist from scanline to scanline could be quicker if no
4 * edges cross: we can just merge the incoming edges. If the scan-line
5 * filling routine were a parameter, we could do textured
6 * polygons, polyblt, and other such stuff.
13 typedef struct edge Edge;
15 Point p; /* point of crossing current scan-line */
16 int maxy; /* scan line at which to discard edge */
17 int dx; /* x increment if x fraction<1 */
18 int dx1; /* x increment if x fraction>=1 */
19 int x; /* x fraction, scaled by den */
20 int num; /* x fraction increment for unit y change, scaled by den */
21 int den; /* x fraction increment for unit x change, scaled by num */
22 int dwind; /* increment of winding number on passing this edge */
23 Edge *next; /* next edge on current scanline */
24 Edge *prev; /* previous edge on current scanline */
26 static void insert(Edge *ep, Edge **yp){
27 while(*yp && (*yp)->p.x<ep->p.x) yp=&(*yp)->next;
31 ep->prev=ep->next->prev;
39 static void polygon(int cnt[], double *pts[], Windrule w, int v){
40 Edge *edges, *ep, *nextep, **ylist, **eylist, **yp;
41 Point p, q, p0, p1, p10;
42 int i, dy, nbig, y, left, right, wind, nwind, nvert;
46 for(cntp=cnt;*cntp;cntp++) nvert+=*cntp;
47 edges=(Edge *)malloc(nvert*sizeof(Edge));
50 fprintf(stderr, "polygon: no space\n");
51 exits("malloc failed");
53 ylist=(Edge **)malloc(Dy(screen->r)*sizeof(Edge *));
54 if(ylist==0) goto NoSpace;
55 eylist=ylist+Dy(screen->r);
56 for(yp=ylist;yp!=eylist;yp++) *yp=0;
58 for(cntp=cnt,ptsp=pts;*cntp;cntp++,ptsp++){
59 p.x=SCX((*ptsp)[*cntp*2-2]);
60 p.y=SCY((*ptsp)[*cntp*2-1]);
62 for(xp=*ptsp,i=0;i!=nvert;xp+=2,i++){
66 if(p.y==q.y) continue;
77 if(p1.y<=screen->r.min.y) continue;
78 if(p0.y>=screen->r.max.y) continue;
80 if(p1.y>screen->r.max.y)
81 ep->maxy=screen->r.max.y;
91 ep->dx=-(p10.x/p10.y); /* this nonsense rounds toward zero */
97 if(ep->p.y<screen->r.min.y){
98 dy=screen->r.min.y-ep->p.y;
101 ep->p.x+=ep->dx1*nbig+ep->dx*(dy-nbig);
103 ep->p.y=screen->r.min.y;
105 insert(ep, ylist+(ep->p.y-screen->r.min.y));
110 for(yp=ylist,y=screen->r.min.y;yp!=eylist;yp++,y++){
112 for(ep=*yp;ep;ep=nextep){
113 nwind=wind+ep->dwind;
114 if(nwind&w){ /* inside */
117 if(left<screen->r.min.x) left=screen->r.min.x;
122 if(right>=screen->r.max.x) right=screen->r.max.x;
123 #define BART_BUG_FIXED /* what goes on here?? -rob */
124 #ifdef BART_BUG_FIXED
126 line(screen, Pt(left, y), Pt(right, y), Endsquare, Endsquare, 0, getcolor(v), ZP);
131 segment(&screen, Pt(left, y), Pt(right, y),
133 segment(&screen, Pt(left, y), Pt(right, y),
137 segment(&screen, Pt(left, y), Pt(right, y),
141 segment(&screen, Pt(left, y), Pt(right, y),
150 if(++ep->p.y!=ep->maxy){
165 void fill(int num[], double *ff[]){
166 polygon(num, ff, Odd, e1->foregr);