1*3e12c5d1SDavid du Colombier /* 2*3e12c5d1SDavid du Colombier * fill -- polygon tiler 3*3e12c5d1SDavid du Colombier * Updating the edgelist from scanline to scanline could be quicker if no 4*3e12c5d1SDavid du Colombier * edges cross: we can just merge the incoming edges. If the scan-line 5*3e12c5d1SDavid du Colombier * filling routine were a parameter, we could do textured 6*3e12c5d1SDavid du Colombier * polygons, polyblt, and other such stuff. 7*3e12c5d1SDavid du Colombier */ 8*3e12c5d1SDavid du Colombier #include "mplot.h" 9*3e12c5d1SDavid du Colombier typedef enum{ 10*3e12c5d1SDavid du Colombier Odd=1, 11*3e12c5d1SDavid du Colombier Nonzero=~0 12*3e12c5d1SDavid du Colombier }Windrule; 13*3e12c5d1SDavid du Colombier typedef struct edge Edge; 14*3e12c5d1SDavid du Colombier struct edge{ 15*3e12c5d1SDavid du Colombier Point p; /* point of crossing current scan-line */ 16*3e12c5d1SDavid du Colombier int maxy; /* scan line at which to discard edge */ 17*3e12c5d1SDavid du Colombier int dx; /* x increment if x fraction<1 */ 18*3e12c5d1SDavid du Colombier int dx1; /* x increment if x fraction>=1 */ 19*3e12c5d1SDavid du Colombier int x; /* x fraction, scaled by den */ 20*3e12c5d1SDavid du Colombier int num; /* x fraction increment for unit y change, scaled by den */ 21*3e12c5d1SDavid du Colombier int den; /* x fraction increment for unit x change, scaled by num */ 22*3e12c5d1SDavid du Colombier int dwind; /* increment of winding number on passing this edge */ 23*3e12c5d1SDavid du Colombier Edge *next; /* next edge on current scanline */ 24*3e12c5d1SDavid du Colombier Edge *prev; /* previous edge on current scanline */ 25*3e12c5d1SDavid du Colombier }; 26*3e12c5d1SDavid du Colombier static void insert(Edge *ep, Edge **yp){ 27*3e12c5d1SDavid du Colombier while(*yp && (*yp)->p.x<ep->p.x) yp=&(*yp)->next; 28*3e12c5d1SDavid du Colombier ep->next=*yp; 29*3e12c5d1SDavid du Colombier *yp=ep; 30*3e12c5d1SDavid du Colombier if(ep->next){ 31*3e12c5d1SDavid du Colombier ep->prev=ep->next->prev; 32*3e12c5d1SDavid du Colombier ep->next->prev=ep; 33*3e12c5d1SDavid du Colombier if(ep->prev) 34*3e12c5d1SDavid du Colombier ep->prev->next=ep; 35*3e12c5d1SDavid du Colombier } 36*3e12c5d1SDavid du Colombier else 37*3e12c5d1SDavid du Colombier ep->prev=0; 38*3e12c5d1SDavid du Colombier } 39*3e12c5d1SDavid du Colombier static void polygon(int cnt[], double *pts[], Windrule w, int v, Fcode f){ 40*3e12c5d1SDavid du Colombier Edge *edges, *ep, *nextep, **ylist, **eylist, **yp; 41*3e12c5d1SDavid du Colombier Point p, q, p0, p1, p10; 42*3e12c5d1SDavid du Colombier int i, dy, nbig, y, left, right, wind, nwind, nvert; 43*3e12c5d1SDavid du Colombier int *cntp; 44*3e12c5d1SDavid du Colombier double **ptsp, *xp; 45*3e12c5d1SDavid du Colombier nvert=0; 46*3e12c5d1SDavid du Colombier for(cntp=cnt;*cntp;cntp++) nvert+=*cntp; 47*3e12c5d1SDavid du Colombier edges=(Edge *)malloc(nvert*sizeof(Edge)); 48*3e12c5d1SDavid du Colombier if(edges==0){ 49*3e12c5d1SDavid du Colombier NoSpace: 50*3e12c5d1SDavid du Colombier fprintf(stderr, "polygon: no space\n"); 51*3e12c5d1SDavid du Colombier exits("malloc failed"); 52*3e12c5d1SDavid du Colombier } 53*3e12c5d1SDavid du Colombier ylist=(Edge **)malloc((screen.r.max.y-screen.r.min.y)*sizeof(Edge *)); 54*3e12c5d1SDavid du Colombier if(ylist==0) goto NoSpace; 55*3e12c5d1SDavid du Colombier eylist=ylist+(screen.r.max.y-screen.r.min.y); 56*3e12c5d1SDavid du Colombier for(yp=ylist;yp!=eylist;yp++) *yp=0; 57*3e12c5d1SDavid du Colombier ep=edges; 58*3e12c5d1SDavid du Colombier for(cntp=cnt,ptsp=pts;*cntp;cntp++,ptsp++){ 59*3e12c5d1SDavid du Colombier p.x=SCX((*ptsp)[*cntp*2-2]); 60*3e12c5d1SDavid du Colombier p.y=SCY((*ptsp)[*cntp*2-1]); 61*3e12c5d1SDavid du Colombier nvert=*cntp; 62*3e12c5d1SDavid du Colombier for(xp=*ptsp,i=0;i!=nvert;xp+=2,i++){ 63*3e12c5d1SDavid du Colombier q=p; 64*3e12c5d1SDavid du Colombier p.x=SCX(xp[0]); 65*3e12c5d1SDavid du Colombier p.y=SCY(xp[1]); 66*3e12c5d1SDavid du Colombier if(p.y==q.y) continue; 67*3e12c5d1SDavid du Colombier if(p.y<q.y){ 68*3e12c5d1SDavid du Colombier p0=p; 69*3e12c5d1SDavid du Colombier p1=q; 70*3e12c5d1SDavid du Colombier ep->dwind=1; 71*3e12c5d1SDavid du Colombier } 72*3e12c5d1SDavid du Colombier else{ 73*3e12c5d1SDavid du Colombier p0=q; 74*3e12c5d1SDavid du Colombier p1=p; 75*3e12c5d1SDavid du Colombier ep->dwind=-1; 76*3e12c5d1SDavid du Colombier } 77*3e12c5d1SDavid du Colombier if(p1.y<=screen.r.min.y) continue; 78*3e12c5d1SDavid du Colombier if(p0.y>=screen.r.max.y) continue; 79*3e12c5d1SDavid du Colombier ep->p=p0; 80*3e12c5d1SDavid du Colombier if(p1.y>screen.r.max.y) 81*3e12c5d1SDavid du Colombier ep->maxy=screen.r.max.y; 82*3e12c5d1SDavid du Colombier else 83*3e12c5d1SDavid du Colombier ep->maxy=p1.y; 84*3e12c5d1SDavid du Colombier p10=sub(p1, p0); 85*3e12c5d1SDavid du Colombier if(p10.x>=0){ 86*3e12c5d1SDavid du Colombier ep->dx=p10.x/p10.y; 87*3e12c5d1SDavid du Colombier ep->dx1=ep->dx+1; 88*3e12c5d1SDavid du Colombier } 89*3e12c5d1SDavid du Colombier else{ 90*3e12c5d1SDavid du Colombier p10.x=-p10.x; 91*3e12c5d1SDavid du Colombier ep->dx=-(p10.x/p10.y); /* this nonsense rounds toward zero */ 92*3e12c5d1SDavid du Colombier ep->dx1=ep->dx-1; 93*3e12c5d1SDavid du Colombier } 94*3e12c5d1SDavid du Colombier ep->x=0; 95*3e12c5d1SDavid du Colombier ep->num=p10.x%p10.y; 96*3e12c5d1SDavid du Colombier ep->den=p10.y; 97*3e12c5d1SDavid du Colombier if(ep->p.y<screen.r.min.y){ 98*3e12c5d1SDavid du Colombier dy=screen.r.min.y-ep->p.y; 99*3e12c5d1SDavid du Colombier ep->x+=dy*ep->num; 100*3e12c5d1SDavid du Colombier nbig=ep->x/ep->den; 101*3e12c5d1SDavid du Colombier ep->p.x+=ep->dx1*nbig+ep->dx*(dy-nbig); 102*3e12c5d1SDavid du Colombier ep->x%=ep->den; 103*3e12c5d1SDavid du Colombier ep->p.y=screen.r.min.y; 104*3e12c5d1SDavid du Colombier } 105*3e12c5d1SDavid du Colombier insert(ep, ylist+(ep->p.y-screen.r.min.y)); 106*3e12c5d1SDavid du Colombier ep++; 107*3e12c5d1SDavid du Colombier } 108*3e12c5d1SDavid du Colombier } 109*3e12c5d1SDavid du Colombier left = 0; 110*3e12c5d1SDavid du Colombier for(yp=ylist,y=screen.r.min.y;yp!=eylist;yp++,y++){ 111*3e12c5d1SDavid du Colombier wind=0; 112*3e12c5d1SDavid du Colombier for(ep=*yp;ep;ep=nextep){ 113*3e12c5d1SDavid du Colombier nwind=wind+ep->dwind; 114*3e12c5d1SDavid du Colombier if(nwind&w){ /* inside */ 115*3e12c5d1SDavid du Colombier if(!(wind&w)){ 116*3e12c5d1SDavid du Colombier left=ep->p.x; 117*3e12c5d1SDavid du Colombier if(left<screen.r.min.x) left=screen.r.min.x; 118*3e12c5d1SDavid du Colombier } 119*3e12c5d1SDavid du Colombier } 120*3e12c5d1SDavid du Colombier else if(wind&w){ 121*3e12c5d1SDavid du Colombier right=ep->p.x; 122*3e12c5d1SDavid du Colombier if(right>=screen.r.max.x) right=screen.r.max.x; 123*3e12c5d1SDavid du Colombier #ifdef BART_BUG_FIXED 124*3e12c5d1SDavid du Colombier if(right>left) 125*3e12c5d1SDavid du Colombier segment(&screen, Pt(left, y), Pt(right, y), v, f); 126*3e12c5d1SDavid du Colombier #else 127*3e12c5d1SDavid du Colombier if(right>left){ 128*3e12c5d1SDavid du Colombier switch(v){ 129*3e12c5d1SDavid du Colombier default: 130*3e12c5d1SDavid du Colombier segment(&screen, Pt(left, y), Pt(right, y), 131*3e12c5d1SDavid du Colombier ~0, D&~S); 132*3e12c5d1SDavid du Colombier segment(&screen, Pt(left, y), Pt(right, y), 133*3e12c5d1SDavid du Colombier v, f); 134*3e12c5d1SDavid du Colombier break; 135*3e12c5d1SDavid du Colombier case 0: 136*3e12c5d1SDavid du Colombier segment(&screen, Pt(left, y), Pt(right, y), 137*3e12c5d1SDavid du Colombier ~0, D&~S); 138*3e12c5d1SDavid du Colombier break; 139*3e12c5d1SDavid du Colombier case 3: 140*3e12c5d1SDavid du Colombier segment(&screen, Pt(left, y), Pt(right, y), 141*3e12c5d1SDavid du Colombier v, f); 142*3e12c5d1SDavid du Colombier break; 143*3e12c5d1SDavid du Colombier } 144*3e12c5d1SDavid du Colombier } 145*3e12c5d1SDavid du Colombier #endif 146*3e12c5d1SDavid du Colombier } 147*3e12c5d1SDavid du Colombier wind=nwind; 148*3e12c5d1SDavid du Colombier nextep=ep->next; 149*3e12c5d1SDavid du Colombier if(++ep->p.y!=ep->maxy){ 150*3e12c5d1SDavid du Colombier ep->x+=ep->num; 151*3e12c5d1SDavid du Colombier if(ep->x>=ep->den){ 152*3e12c5d1SDavid du Colombier ep->x-=ep->den; 153*3e12c5d1SDavid du Colombier ep->p.x+=ep->dx1; 154*3e12c5d1SDavid du Colombier } 155*3e12c5d1SDavid du Colombier else 156*3e12c5d1SDavid du Colombier ep->p.x+=ep->dx; 157*3e12c5d1SDavid du Colombier insert(ep, yp+1); 158*3e12c5d1SDavid du Colombier } 159*3e12c5d1SDavid du Colombier } 160*3e12c5d1SDavid du Colombier } 161*3e12c5d1SDavid du Colombier free((char *)edges); 162*3e12c5d1SDavid du Colombier free((char *)ylist); 163*3e12c5d1SDavid du Colombier } 164*3e12c5d1SDavid du Colombier void fill(int num[], double *ff[]){ 165*3e12c5d1SDavid du Colombier polygon(num, ff, Odd, e1->foregr, S); 166*3e12c5d1SDavid du Colombier } 167