tfill.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tfill.c (4097B)
       ---
            1 /*
            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.
            7  */
            8 #include "mplot.h"
            9 typedef enum{
           10         Odd=1,
           11         Nonzero=~0
           12 }Windrule;
           13 typedef struct edge Edge;
           14 struct 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 */
           25 };
           26 static void insert(Edge *ep, Edge **yp){
           27         while(*yp && (*yp)->p.x<ep->p.x) yp=&(*yp)->next;
           28         ep->next=*yp;
           29         *yp=ep;
           30         if(ep->next){
           31                 ep->prev=ep->next->prev;
           32                 ep->next->prev=ep;
           33                 if(ep->prev)
           34                         ep->prev->next=ep;
           35         }
           36         else
           37                 ep->prev=0;
           38 }
           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;
           43         int *cntp;
           44         double **ptsp, *xp;
           45         nvert=0;
           46         for(cntp=cnt;*cntp;cntp++) nvert+=*cntp;
           47         edges=(Edge *)malloc(nvert*sizeof(Edge));
           48         if(edges==0){
           49         NoSpace:
           50                 fprintf(stderr, "polygon: no space\n");
           51                 exits("malloc failed");
           52         }
           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;
           57         ep=edges;
           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]);
           61                 nvert=*cntp;
           62                 for(xp=*ptsp,i=0;i!=nvert;xp+=2,i++){
           63                         q=p;
           64                         p.x=SCX(xp[0]);
           65                         p.y=SCY(xp[1]);
           66                         if(p.y==q.y) continue;
           67                         if(p.y<q.y){
           68                                 p0=p;
           69                                 p1=q;
           70                                 ep->dwind=1;
           71                         }
           72                         else{
           73                                 p0=q;
           74                                 p1=p;
           75                                 ep->dwind=-1;
           76                         }
           77                         if(p1.y<=screen->r.min.y) continue;
           78                         if(p0.y>=screen->r.max.y) continue;
           79                         ep->p=p0;
           80                         if(p1.y>screen->r.max.y)
           81                                 ep->maxy=screen->r.max.y;
           82                         else
           83                                 ep->maxy=p1.y;
           84                         p10=subpt(p1, p0);
           85                         if(p10.x>=0){
           86                                 ep->dx=p10.x/p10.y;
           87                                 ep->dx1=ep->dx+1;
           88                         }
           89                         else{
           90                                 p10.x=-p10.x;
           91                                 ep->dx=-(p10.x/p10.y); /* this nonsense rounds toward zero */
           92                                 ep->dx1=ep->dx-1;
           93                         }
           94                         ep->x=0;
           95                         ep->num=p10.x%p10.y;
           96                         ep->den=p10.y;
           97                         if(ep->p.y<screen->r.min.y){
           98                                 dy=screen->r.min.y-ep->p.y;
           99                                 ep->x+=dy*ep->num;
          100                                 nbig=ep->x/ep->den;
          101                                 ep->p.x+=ep->dx1*nbig+ep->dx*(dy-nbig);
          102                                 ep->x%=ep->den;
          103                                 ep->p.y=screen->r.min.y;
          104                         }
          105                         insert(ep, ylist+(ep->p.y-screen->r.min.y));
          106                         ep++;
          107                 }
          108         }
          109         left = 0;
          110         for(yp=ylist,y=screen->r.min.y;yp!=eylist;yp++,y++){
          111                 wind=0;
          112                 for(ep=*yp;ep;ep=nextep){
          113                         nwind=wind+ep->dwind;
          114                         if(nwind&w){        /* inside */
          115                                 if(!(wind&w)){
          116                                         left=ep->p.x;
          117                                         if(left<screen->r.min.x) left=screen->r.min.x;
          118                                 }
          119                         }
          120                         else if(wind&w){
          121                                 right=ep->p.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
          125                                 if(right>left)
          126                                         line(screen, Pt(left, y), Pt(right, y), Endsquare, Endsquare, 0, getcolor(v), ZP);
          127 #else
          128                                 if(right>left){
          129                                         switch(v){
          130                                         default:
          131                                                 segment(&screen, Pt(left, y), Pt(right, y),
          132                                                         ~0, D&~S);
          133                                                 segment(&screen, Pt(left, y), Pt(right, y),
          134                                                         v, f);
          135                                                 break;
          136                                         case 0:
          137                                                 segment(&screen, Pt(left, y), Pt(right, y),
          138                                                         ~0, D&~S);
          139                                                 break;
          140                                         case 3:
          141                                                 segment(&screen, Pt(left, y), Pt(right, y),
          142                                                         v, f);
          143                                                 break;
          144                                         }
          145                                 }
          146 #endif
          147                         }
          148                         wind=nwind;
          149                         nextep=ep->next;
          150                         if(++ep->p.y!=ep->maxy){
          151                                 ep->x+=ep->num;
          152                                 if(ep->x>=ep->den){
          153                                         ep->x-=ep->den;
          154                                         ep->p.x+=ep->dx1;
          155                                 }
          156                                 else
          157                                         ep->p.x+=ep->dx;
          158                                 insert(ep, yp+1);
          159                         }
          160                 }
          161         }
          162         free((char *)edges);
          163         free((char *)ylist);
          164 }
          165 void fill(int num[], double *ff[]){
          166         polygon(num, ff, Odd, e1->foregr);
          167 }