diff --git a/src/modules/Image/polyfill.c b/src/modules/Image/polyfill.c index 9e1a2c2fa1c8b377555c0c59ebfde831033c694f..dac374ff6dacce292133a2056aa4155371e80407 100644 --- a/src/modules/Image/polyfill.c +++ b/src/modules/Image/polyfill.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: polyfill.c,v 1.20 1998/04/08 15:41:21 mirar Exp $"); +RCSID("$Id: polyfill.c,v 1.21 1998/04/09 02:00:23 mirar Exp $"); /* Prototypes are needed for these */ extern double floor(double); @@ -27,12 +27,12 @@ extern double floor(double); #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) -#undef POLYDEBUG +#define POLYDEBUG /* **! module Image **! note -**! $Id: polyfill.c,v 1.20 1998/04/08 15:41:21 mirar Exp $ +**! $Id: polyfill.c,v 1.21 1998/04/09 02:00:23 mirar Exp $ **! class image */ @@ -58,11 +58,11 @@ extern double floor(double); **! see also: setcolor */ -struct vertex_list +struct line_list { struct vertex *above,*below; float dx,dy; - struct vertex_list *next; + struct line_list *next; float xmin,xmax,yxmin,yxmax; /* temporary storage */ }; @@ -70,7 +70,7 @@ struct vertex { float x,y; struct vertex *next; /* total list, sorted downwards */ - struct vertex_list *below,*above; /* childs */ + struct line_list *below,*above; /* childs */ int done; }; @@ -85,6 +85,8 @@ struct vertex *vertex_new(float x,float y,struct vertex **top) (*top)->x==x && (*top)->y==y) return *top; /* found one */ c=malloc(sizeof(struct vertex)); +fprintf(stderr,"alloc %lx\n",c); + if (!c) return NULL; c->x=x; c->y=y; c->next=*top; @@ -98,12 +100,14 @@ struct vertex *vertex_new(float x,float y,struct vertex **top) static void vertex_connect(struct vertex *above, struct vertex *below) { - struct vertex_list *c,*d; + struct line_list *c,*d; float diff; if (below==above) return; - c = malloc(sizeof(struct vertex_list)); + c = malloc(sizeof(struct line_list)); +fprintf(stderr,"alloc con: %lx %lx<->%lx\n",c,above,below); + if (!c) return; c->above = above; c->below = below; c->next = above->below; if (((diff = (below->y - above->y)) < 1.0e-10) && @@ -118,7 +122,8 @@ static void vertex_connect(struct vertex *above, c->dy = (below->y - above->y)/diff; above->below = c; - d = malloc(sizeof(struct vertex_list)); + d = malloc(sizeof(struct line_list)); +fprintf(stderr,"alloc con: %lx %lx<->%lx\n",d,above,below); d->above = above; d->below = below; d->next = below->above; d->dx = c->dx; @@ -126,7 +131,7 @@ static void vertex_connect(struct vertex *above, below->above = d; } -static INLINE float vertex_xmax(struct vertex_list *v,float yp,float *ydest) +static INLINE float line_xmax(struct line_list *v,float yp,float *ydest) { if (v->dx>0.0) { if (v->below->y>yp+1.0+1e-10) @@ -144,7 +149,7 @@ static INLINE float vertex_xmax(struct vertex_list *v,float yp,float *ydest) return (*ydest=v->below->y),v->below->x; } -static INLINE float vertex_xmin(struct vertex_list *v,float yp,float *ydest) +static INLINE float line_xmin(struct line_list *v,float yp,float *ydest) { if (v->dx<0.0) { if (v->below->y>yp+1.0+1e-10) @@ -162,29 +167,27 @@ static INLINE float vertex_xmin(struct vertex_list *v,float yp,float *ydest) return (*ydest=v->above->y),v->above->x; } -static void add_vertices(struct vertex_list **first, - struct vertex_list *what, +static void add_vertices(struct line_list **first, + struct line_list *what, float yp) { - struct vertex_list **ins,*c; - - c=*first; - while (c) - { - c->xmin=vertex_xmin(c,yp,&c->yxmin); - c->xmax=vertex_xmax(c,yp,&c->yxmax); - c=c->next; - } + struct line_list **ins,*c; +#ifdef POLYDEBUG + char *why="unknown"; +#define BECAUSE(X) (why=(X)) +#else +#define BECAUSE(X) +#endif while (what) { - what->xmin=vertex_xmin(what,yp,&what->yxmin); - what->xmax=vertex_xmax(what,yp,&what->yxmax); + what->xmin=line_xmin(what,yp,&what->yxmin); + what->xmax=line_xmax(what,yp,&what->yxmax); ins=first; #ifdef POLYDEBUG - fprintf(stderr,"insert %g,%g - %g,%g %g,%g - %g,%g\n", + fprintf(stderr," insert %g,%g - %g,%g %g,%g - %g,%g\n", what->above->x,what->above->y, what->below->x,what->below->y, what->xmin,what->yxmin, @@ -203,25 +206,39 @@ static void add_vertices(struct vertex_list **first, while (*ins) { /* case: -what-> <-ins- */ - if ((*ins)->xmin>=what->xmax) break; /* place left of */ + BECAUSE("what is left of ins"); + if ((*ins)->xmin>=what->xmax) + break; /* place left of */ /* case: -what- */ /* <-ins- */ if ((*ins)->xmin>what->xmin) - { if ((*ins)->yxmin>VY(what,(*ins)->xmin)) break; } + { + BECAUSE("ins is below (right) what"); + if ((*ins)->yxmin>VY(what,(*ins)->xmin)) break; + } /* case: <-what- */ /* -ins- */ else - { if (VY((*ins),what->xmin)>what->yxmin) break; } + { + BECAUSE("what is above ins (left)"); + if (VY((*ins),what->xmin)>what->yxmin) break; + } /* case: -what-> */ /* -ins- */ if ((*ins)->xmax>what->xmax) - { if (VY((*ins),what->xmax)>what->yxmax) break; } + { + BECAUSE("what is above ins (right)"); + if (VY((*ins),what->xmax)>what->yxmax) break; + } /* case: -what- */ /* -ins-> */ else - { if ((*ins)->yxmax>VY(what,(*ins)->xmax)) break; } + { + BECAUSE("ins is below (left) what"); + if ((*ins)->yxmax>VY(what,(*ins)->xmax)) break; + } ins=&((*ins)->next); } @@ -229,15 +246,17 @@ static void add_vertices(struct vertex_list **first, #ifdef POLYDEBUG if (*ins) - fprintf(stderr," before %g,%g - %g,%g %g,%g - %g,%g\n", + fprintf(stderr," before %g,%g - %g,%g %g,%g - %g,%g because %s\n", (*ins)->above->x,(*ins)->above->y, (*ins)->below->x,(*ins)->below->y, (*ins)->xmin,(*ins)->yxmin, - (*ins)->xmax,(*ins)->yxmax); + (*ins)->xmax,(*ins)->yxmax, + why); #endif - c=malloc(sizeof(struct vertex_list)); + c=malloc(sizeof(struct line_list)); +fprintf(stderr,"alloc %lx %lx<->%lx\n",c,what->above,what->below); *c=*what; c->next=*ins; *ins=c; @@ -246,524 +265,324 @@ static void add_vertices(struct vertex_list **first, } } -static void sub_vertices(struct vertex_list **first, +static void sub_vertices(struct line_list **first, struct vertex *below, float yp) { - struct vertex_list **ins,*c; + struct line_list **ins,*c; ins=first; #ifdef POLYDEBUG - fprintf(stderr,"remove %lx %g,%g\n",below,below->x,below->y); + fprintf(stderr," remove %lx <-%g,%g\n",below,below->x,below->y); #endif while (*ins) { if ((*ins)->below==below) { +#ifdef POLYDEBUG + fprintf(stderr," removing %lx,[%g,%g-%g,%g] %lx,%lx \n", + *ins, + (*ins)->above->x,(*ins)->above->y, + (*ins)->below->x,(*ins)->below->y, + (*ins)->above,(*ins)->below); +#endif c=*ins; *ins=(*ins)->next; free(c); } else { -#ifdef POLYDEBUG - fprintf(stderr,"%g,%g-%g,%g %lx,%lx\n", - (*ins)->above->x,(*ins)->above->y, - (*ins)->below->x,(*ins)->below->y, - (*ins)->above,(*ins)->below); -#endif ins=&((*ins)->next); } } } -static void polyfill_row_fill(float *buf, - float xmin,float xmax) +static INLINE void polyfill_row_add(float *buf, + float xmin,float xmax, + float add) { int i; int xmin_i = (int)floor(xmin); int xmax_i = (int)floor(xmax); if (xmax_i<0) return; if (xmin_i == xmax_i) - buf[xmin_i] += xmax-xmin; + buf[xmin_i] += (xmax-xmin)*add; else if (xmin_i>=0) { - buf[xmin_i] += 1-(xmin-((float)xmin_i)); - for (i=xmin_i+1; i<xmax_i; i++) buf[i]=1.0; - buf[xmax_i] += xmax-((float)xmax_i); + buf[xmin_i] += (1-(xmin-((float)xmin_i)))*add; + for (i=xmin_i+1; i<xmax_i; i++) buf[i]+=add; + buf[xmax_i] += add*(xmax-((float)xmax_i)); } else { - for (i=0; i<xmax_i; i++) buf[i]=1.0; - buf[xmax_i] += xmax-((float)xmax_i); + for (i=0; i<xmax_i; i++) buf[i]+=add; + buf[xmax_i] += add*(xmax-((float)xmax_i)); } } -static int polyfill_row_vertices(float *buf, - struct vertex_list *v1, - struct vertex_list *v2, - float xmin, - float xmax, - float yp, - int fill) +static INLINE void polyfill_slant_add(float *buf, + float xmin,float xmax, + float lot, + float y1, + float dy) { - struct vertex_list *v; - int xofill=1; - int xmax_i, xmin_i; - float x; + int i; + int xmin_i = (int)floor(xmin); + int xmax_i = (int)floor(xmax); + if (xmax_i<0) return; + if (xmin_i == xmax_i) + buf[xmin_i] += (xmax-xmin)*(y1+dy*(xmax-xmin)/2)*lot; + else if (xmin_i>=0) + { + buf[xmin_i] += + lot*(y1+dy*(1-(xmin-((float)xmin_i)))/2)*(1-(xmin-((float)xmin_i))); + y1+=dy*(1-(xmin-((float)xmin_i))); + for (i=xmin_i+1; i<xmax_i; i++) + buf[i]+=lot*(y1+dy/2),y1+=dy; + buf[xmax_i] += + lot*(y1+dy*(xmax-((float)xmax_i))/2)*(xmax-((float)xmax_i)); + } + else + { + y1+=dy*(0.0-xmin); + for (i=0; i<xmax_i; i++) + buf[i]+=lot*(y1+dy/2),y1+=dy; + buf[xmax_i] += + lot*(y1+dy*(xmax-((float)xmax_i))/2)*(xmax-((float)xmax_i)); + } +} + +static int polyfill_event(float xmin, + float xmax, + struct line_list **pll, + int tog, + float yp, + float *buf) +{ + struct line_list *c; + struct line_list *ll=*pll; + int mtog; #ifdef POLYDEBUG - int i; - fprintf(stderr,"aa %g..%g fill %d\n",xmin,xmax,fill); + fprintf(stderr," event %g,%g - %g,%g tog=%d\n",xmin,yp,xmax,yp+1.0,tog); #endif - xmax_i = (int)floor(xmax); - xmin_i = (int)floor(xmin); - fill=fill?-1:1; - -#if 1 - v=v1; - while (v) + /* toggle for lines ended at xmin,yp */ + c=ll; + while (c) { - if (v->xmin==xmin && v->yxmin==yp && v->above->y<yp - && v->xmin<xmax && v->xmax>xmin) + if ( (c->above->y < yp) && + ( (c->xmax==xmin && c->yxmax==yp) || + (c->xmin==xmin && c->yxmin==yp) ) ) { - fill=-fill; #ifdef POLYDEBUG - fprintf(stderr,"aa toggle fill: %d->%d on %g,%g-%g,%g\n", - -fill,fill,v->xmin,v->yxmin,v->xmax,v->yxmax); + fprintf(stderr," toggle for %g,%g - %g,%g [%g,%g - %g,%g]\n", + c->xmin,c->yxmin,c->xmax,c->yxmax, + c->above->x,c->above->y,c->below->x,c->below->y); #endif + tog=!tog; } - v=v->next; + c=c->next; } -#endif - - if (fill<0) polyfill_row_fill(buf,xmin,xmax); - v=v1; - while (v!=v2) + /* sanity check */ + c=ll; + while (c && c->next) { -#ifdef POLYDEBUG - fprintf(stderr,"aa << %g,%g-%g,%g %g,%g-%g,%g fill=%d xofill=%d xmin=%g xmax=%g xmin_i=%d xmax_i=%d\n", - v->above->x,v->above->y, - v->below->x,v->below->y, - v->xmin,v->yxmin, - v->xmax,v->yxmax, - fill,xofill, - xmin,xmax,xmin_i,xmax_i); -#endif - - if (xmin!=xmax && v->xmin<xmax && v->xmax>xmin) + if (c->xmin > c->next->xmax || + ( c->xmin!=c->xmax && + c->next->xmin!=c->next->xmax && + c->xmax>=xmin && + c->xmin<=xmin && + c->next->xmax>=xmin && + c->next->xmin<=xmin && + (VY(c,xmin)>VY(c->next,xmin) || + VY(c,xmax)>VY(c->next,xmax))) ) { + struct line_list *l1; + /* resort */ #ifdef POLYDEBUG -#define CALC_AREA(FILL,X,Y1,Y2,YP) \ - (fprintf(stderr," [area: %d*%g*%g y1=%g y2=%g yp=%g]\n", FILL,X,( 1-0.5*(Y1+Y2)+YP ),Y1,Y2,YP), \ - ((FILL)*(X)*( 1.0-0.5*((Y1)+(Y2))+(YP) ))) -#else -#define CALC_AREA(FILL,X,Y1,Y2,YP) \ - ((FILL)*(X)*( 1.0-0.5*((Y1)+(Y2))+(YP) )) + fprintf(stderr," !!! resort !!!\n"); #endif + l1=NULL; + add_vertices(&l1,ll,yp); - - - if (xmin_i == xmax_i) - buf[xmin_i]+= - CALC_AREA(fill*xofill,(xmax-xmin), VY(v,xmin),VY(v,xmax),yp); - else + while ((c=*pll)) { - int xx; - buf[xmin_i]+= - CALC_AREA(xofill*fill, (1+((float)xmin_i)-xmin), - VY(v,xmin),VY(v,1+((float)xmin_i)), yp); - - for (x=(float)(xx=1+xmin_i); xx<xmax_i; xx++, x+=1.0) - buf[xx] += - CALC_AREA(fill*xofill,1.0, VY(v,x),VY(v,x+1.0),yp); - -#if 0 - fprintf(stderr,"buf[%d] = %g", xmax_i, buf[xmax_i]); - fflush(stderr); -#endif - buf[xmax_i] += - CALC_AREA(fill*xofill, xmax-((float)xmax_i), - VY(v,xmax),VY(v,((float)xmax_i)),yp); -#if 0 - fprintf(stderr," ok\n"); -#endif + *pll=c->next; + free(c); } -#ifdef POLYDEBUG - fprintf(stderr,"aa "); - for (i=0; i<10; i++) fprintf(stderr,"%5.3f,",buf[i]); - fprintf(stderr,"\n"); -#endif - } - if (v->xmin<=xmin && v->xmax>=xmax) - xofill=-xofill; + ll=*pll=l1; - v=v->next; - } -#ifdef POLYDEBUG - if (fill<0) fprintf(stderr,"aa fill is on\n"); -#endif - return fill<0; -} - -static int toggle_fill(struct vertex_list *v1, - float xmin,float xmax, - float yp,int fill) -{ - struct vertex_list *v; - v=v1; -#ifdef POLYDEBUG - fprintf(stderr,"try toggle %g..%g\n",xmin,xmax); -#endif - while (v) - { - if (v->above->y<yp-1e-10 && - ( (v->xmin==xmin && v->yxmin<=yp+1e-10) - || (v->xmax==xmin && v->yxmax<=yp+1e-10) - || (v->xmax==xmax && v->xmin<=xmin && v->yxmax<=yp+1e-10))) - { - fill=!fill; -#ifdef POLYDEBUG - fprintf(stderr," toggle fill %d=>%d on %g,%g-%g,%g\n", - !fill,fill,v->xmin,v->yxmin,v->xmax,v->yxmax); -#endif + break; } - -#ifdef POLYDEBUG - else fprintf(stderr," dont toggle fill %d=>%d on %g,%g-%g,%g (%g<%g) (%d%d%d)\n", - fill,fill,v->xmin,v->yxmin,v->xmax,v->yxmax, - v->above->y,yp-1e-10, - v->xmax==xmax,v->yxmax==yp+1,v->above->y<yp-1e-10); -#endif - - v=v->next; + c=c->next; } - return fill; -} -static void polyfill_row(struct image *img, - float *buf, - struct vertex_list **vertices, - float yp, - int *pixmin,int *pixmax) -{ - struct vertex_list *v,*v1; - float xmax,xmin,nxmax,rxmax,yl,xl; - int fill=0,i; - int ixmin,ixmax; - - xmin=1e10; - xmax=-1e10; - rxmax=0; - - v=*vertices; - while (v) + /* paint if needed */ + if (tog) { - v->xmin=vertex_xmin(v,yp,&v->yxmin); - v->xmax=vertex_xmax(v,yp,&v->yxmax); - if (v->xmin<xmin) xmin=v->xmin; - if (v->xmax>xmax) xmax=v->xmax; - v=v->next; +#ifdef POLYDEBUG + fprintf(stderr," fill %g..%g with 1.0\n",xmin,xmax); +#endif + polyfill_row_add(buf,xmin,xmax,1.0); } - *pixmin=ixmin=floor(xmin); - *pixmax=ixmax=ceil(xmax); - - rxmax=xmax; - if (rxmax>img->xsize) rxmax=img->xsize; + /* loop over events */ + mtog=tog; + c=ll; - if (ixmin<0) + while (c) { - *pixmin=ixmin=xmin=0; - v=*vertices; - while (v) + if (c->xmin<=xmin && c->xmax>=xmax) { - if (v->xmin<0 && v->yxmin==yp) fill=!fill; - if (v->xmax<0 && v->yxmax==yp) fill=!fill; - v=v->next; + float y1=VY(c,xmin); +#ifdef POLYDEBUG + float y2=VY(c,xmax); + fprintf(stderr," use line %g,%g - %g,%g [%g,%g - %g,%g] : %g,%g - %g,%g = %+g\n", + c->xmin,c->yxmin,c->xmax,c->yxmax, + c->above->x,c->above->y,c->below->x,c->below->y, + xmin,y1,xmax,y2,(tog?-1.0:1.0)*((y1+y2)/2.0-yp)); +#endif + polyfill_slant_add(buf,xmin,xmax,(tog?-1.0:1.0),(yp+1)-y1,-c->dy); + tog=!tog; } + if (c->xmin>xmax) break; /* skip the rest */ + c=c->next; } - else if (ixmin>=img->xsize) { *pixmax=ixmin; return; } - if (ixmax>=img->xsize) *pixmax=ixmax=img->xsize; - else if (ixmax<0) { *pixmax=ixmin; return; } + - for (i=ixmin; i<=ixmax; i++) buf[i]=0.0; + return mtog; +} - v=*vertices; - nxmax=xmax=v->xmax; - v1=v; +static void polyfill_some(struct image *img, + struct vertex *v, + float *buf) +{ + struct line_list *ll=NULL; + int y=0; + float ixmax=(float)img->xsize; + struct vertex *to_add=v,*to_loose=v; + /* beat row for row */ - v1=v=*vertices; + if (y+1.0+1e-10<v->y) + y=(int)v->y; -#ifdef POLYDEBUG - while (v) - fprintf(stderr," >> %g,%g-%g,%g %g,%g-%g,%g\n", - v->above->x,v->above->y, - v->below->x,v->below->y, - v->xmin,v->yxmin, - v->xmax,v->yxmax),v=v->next; - - v=*vertices; -#endif - - for (;;) + while (y<img->ysize && (to_loose||to_add) ) { -#ifdef POLYDEBUG - fprintf(stderr,">>>again...xmin=%g xmax=%g nxmax=%g\n", - xmin,xmax,nxmax); + float yp=y; + struct line_list *c; + float xmin,xmax; + int tog=0; + int i; + rgb_group *d; + +#ifdef POLYDEBUG + fprintf(stderr,"line %d..%d\n",y,y+1); #endif - if (!v1) break; /* sanity check */ - - /* get next start or end */ - - v=v1; - nxmax=0; - xmax=v->xmax; - while (v) + /* update values for current lines */ + c=ll; + while (c) { -#ifdef POLYDEBUG - fprintf(stderr," ++ %g,%g-%g,%g %g,%g-%g,%g xmin=%g xmax=%g nxmax=%g -> ", - v->above->x,v->above->y, - v->below->x,v->below->y, - v->xmin,v->yxmin, - v->xmax,v->yxmax,xmin,xmax,nxmax); -#endif - if (v->xmin>xmin && v->xmin<xmax) - xmax=v->xmin; - if (v->xmax>xmin && v->xmax<xmax) - xmax=v->xmax; - if (v->xmin<=xmax && v->xmax>nxmax) nxmax=v->xmax; -#ifdef POLYDEBUG - fprintf(stderr,"xmin=%g xmax=%g nxmax=%g\n", - xmin,xmax,nxmax); -#endif - - v=v->next; + c->xmin=line_xmin(c,yp,&c->yxmin); + c->xmax=line_xmax(c,yp,&c->yxmax); + c=c->next; } -#ifdef POLYDEBUG - fprintf(stderr," xmax=%g nxmax=%g xmin=%g xmax=%g ixmax=%d fill=%d\n", - xmax,nxmax,xmin,xmax,ixmax,fill); -#endif - - if (xmax>ixmax) xmax=ixmax; - -#ifdef POLYDEBUG - fprintf(stderr,"--> xmax=%g nxmax=%g xmin=%g xmax=%g ixmax=%d fill=%d\n", - xmax,nxmax,xmin,xmax,ixmax,fill); - - fprintf(stderr,"--- %g..%g --------------------------------------\n", - xmin,xmax); -#endif - - /* sort sanity check (needed, since sort is based on one line) */ - - v=v1; - yl=0; - xl=0; - while (v) + /* add any new vertices */ + while (to_add && to_add->y<yp+1.0) { - if (v->xmax>=xmin && v->xmin<=xmin) - { - float y=VY(v,xmin); - if (y<yl) - { -resort: - /* resort */ -#ifdef POLYDEBUG - fprintf(stderr,"!!! resort !!!\n"); -#endif - v1=NULL; - add_vertices(&v1,*vertices,yp); - - while ((v=*vertices)) - { - *vertices=v->next; - free(v); - } - - *vertices=v1; - - /* forget the already done stuff */ - - while (v1 && v1->xmax<xmin) v1=v1->next; - - break; - } - yl=y; - } - if (xl>v->xmax) goto resort; - xl=v->xmin; - v=v->next; + struct vertex *vx=to_add; + to_add=to_add->next; + add_vertices(&ll,vx->below,yp); } - if (xmin!=nxmax) - polyfill_row_vertices(buf,v1,v,xmin,xmax,yp,fill); - - fill=toggle_fill(v1,xmin,xmax,yp,fill); - -#ifdef POLYEDEBUG - fprintf(stderr,"v1=%lx xmax=%g nxmax=%g xmax==nxmax:%d\n", - (unsigned long)v1,xmax,nxmax,xmax==nxmax); -#endif - - /* skip uninteresting, ends < v->xmin */ - while (v1 && v1->xmax<=xmax && v1->xmin<xmax) v1=v1->next; - if (!v1) break; - - if (v1 && xmax==nxmax && xmax<rxmax) /* jump */ +#ifdef POLYDEBUG + c=ll; + while (c) { - float xminf=rxmax; - v=v1; - while (v) - { - if (v->xmax>nxmax && v->xmin<xminf) xminf=v->xmin; - v=v->next; - } - if (xmin!=xmax) fill=toggle_fill(v1,xmax,xminf,yp,fill); -#ifdef POLYDEBUG - fprintf(stderr,"aa jump %g..%g fill %d\n", - nxmax,xminf,fill); -#endif - if (fill) - polyfill_row_fill(buf,xmax,xminf); - if (xminf==ixmax) break; - - xmin=xminf; + fprintf(stderr," line %g,%g - %g,%g [%g,%g - %g,%g]\n", + c->xmin,c->yxmin,c->xmax,c->yxmax, + c->above->x,c->above->y,c->below->x,c->below->y); + c=c->next; } - else xmin=xmax; - - if (xmin>=rxmax) break; - - /* skip uninteresting, ends < v->xmin */ - while (v1 && v1->xmax==xmax) v1=v1->next; - if (!v1) break; - - - } - -#ifdef POLYDEBUG - fprintf(stderr,"== "); - for (i=0; i<10; i++) fprintf(stderr,"%5.3f,",buf[i]); - fprintf(stderr,"\n"); -#endif -} - -static void polyfill_some(struct image *img, - struct vertex *top) -{ - struct vertex_list *vertices; - struct vertex *next,*nextb; - float yp; - int i; - - rgb_group *dest=img->img,rgb=img->rgb; - float *buf=(float *)alloca(sizeof(float)*(img->xsize+1)); - - if (!buf) error("out of stack, typ\n"); - for (i=0; i<img->xsize+1; i++) buf[i]=0.0; - -#ifdef POLYDEBUG - next=top; - while (next) - { - fprintf(stderr,"%lx %g,%g\n",(unsigned long)next,next->x,next->y); - next=next->next; - } -#endif - - - nextb=next=top; - - yp=floor(top->y); - vertices=NULL; - - if (yp>0) dest+=((int)yp)*img->xsize; - - while (next) - { -#ifdef POLYDEBUG - struct vertex_list *v1; -fprintf(stderr,"\n\nrow y=%g..%g\n",yp,yp+1); + #endif -/* add new vertices if any */ - - while (next && next->y<=yp+1.0-1e-10) + if (!ll) { - add_vertices(&vertices,next->below,yp); - next=next->next; + y++; + continue; } -/* POLYDEBUG */ + /* begin with zeros */ + for (i=0; i<img->xsize; i++) buf[i]=0.0; -#ifdef POLYDEBUG - fprintf(stderr,"vertices:\n"); - v1=vertices; - while (v1) + /* loop through all horisontal events */ + xmin=ll->xmin-1.0; + while (xmin<ixmax) { - fprintf(stderr," (%g,%g)-(%g,%g) at ", - v1->above->x,v1->above->y, - v1->below->x,v1->below->y); - if (v1->above->y>yp) - fprintf(stderr,"(%g,%g), ",v1->above->x,v1->above->y); - else - fprintf(stderr,"(%g,%g), ",v1->above->x+v1->dx*(yp-v1->above->y),yp); - - if (v1->below->y<yp+1.0) - fprintf(stderr,"(%g,%g)\n",v1->below->x,v1->below->y); - else - fprintf(stderr,"(%g,%g)\n",v1->above->x+v1->dx*(1+yp-v1->above->y), - (yp+1.0)); + xmax=1e10; + c=ll; + while (c) + { + /* each line has two events: beginning and end */ + if (c->xmin<xmax && c->xmin>xmin) xmax=c->xmin; + if (c->xmax<xmax && c->xmax>xmin) xmax=c->xmax; + c=c->next; + } + if (xmax==1e10) break; /* no more events */ + + if (xmax>ixmax) xmax=ixmax; + tog=polyfill_event(xmin,xmax,&ll,tog,yp,buf); - v1=v1->next; + /* shift to get next event */ + xmin=xmax; + xmax=xmin-1.0; } -#endif - -/* find out what to antialias, and what to fill, and if to resort stuff */ - - if (yp>=0 && yp<img->ysize) + + + /* remove any old vertices */ + while (to_loose!=to_add && to_loose->y<yp+1.0-1e-10) { - int xmin,xmax; - - polyfill_row(img, buf, &vertices,yp, &xmin,&xmax); - -#ifdef POLYDEBUG - fprintf(stderr,"yp=%g dest=&%lx (&%lx..&%lx) xmin=%d xmax=%d; ", - yp,(int)dest,(int)img->img, - (int)img->img+img->xsize*img->ysize, - xmin,xmax); - fprintf(stderr,"\n"); -#endif - - for (;xmin<xmax;xmin++) - dest[xmin].r=(unsigned char)(dest[xmin].r*(1.0-buf[xmin])+rgb.r*buf[xmin]), - dest[xmin].g=(unsigned char)(dest[xmin].g*(1.0-buf[xmin])+rgb.g*buf[xmin]), - dest[xmin].b=(unsigned char)(dest[xmin].b*(1.0-buf[xmin])+rgb.b*buf[xmin]); - dest+=img->xsize; + struct vertex *vx=to_loose; + to_loose=to_loose->next; + sub_vertices(&ll,vx,yp); } -/* remove done vertices if any */ - - while (nextb && nextb->y<yp+1.0-1e-10) + /* write this row */ + d=img->img+img->xsize*y; + for (i=0; i<img->xsize; i++) { - sub_vertices(&vertices,nextb,yp); - nextb=nextb->next; +#ifdef POLYDEBUG + fprintf(stderr,"%3.2f ",buf[i]); +#endif + d->r=(COLORTYPE)((d->r*(1.0-buf[i]))+(img->rgb.r*buf[i])); + d->g=(COLORTYPE)((d->g*(1.0-buf[i]))+(img->rgb.g*buf[i])); + d->b=(COLORTYPE)((d->b*(1.0-buf[i]))+(img->rgb.b*buf[i])); + d++; } +#ifdef POLYDEBUG + fprintf(stderr,"\n"); +#endif - yp+=1.0; + y++; + } + while (ll) + { + struct line_list *c; + ll=(c=ll)->next; + free(c); } } static INLINE void polyfill_free(struct vertex *top) { - struct vertex_list *v,*vn; + struct line_list *v,*vn; struct vertex *tn; while (top) @@ -800,19 +619,26 @@ static INLINE struct vertex *polyfill_add(struct vertex *top, return NULL; } - if (a->size<6) { + if (a->size<6) + { + return top; +#if 0 polyfill_free(top); error("Illegal argument %d to %s, too few vertices (min 3)\n", arg, what); return NULL; /* no polygon with less then tree corners */ +#endif } #define POINT(A,N) (((A)->item[N].type==T_FLOAT)?((A)->item[N].u.float_number):((float)((A)->item[N].u.integer))) last=first=vertex_new(POINT(a,0),POINT(a,1),&top); + if (!last) return NULL; + for (n=2; n+1<a->size; n+=2) { cur=vertex_new(POINT(a,n),POINT(a,n+1),&top); + if (!cur) return NULL; if (cur->y<last->y) vertex_connect(cur,last); else if (cur->y>last->y) @@ -840,9 +666,14 @@ static INLINE struct vertex *polyfill_add(struct vertex *top, void image_polyfill(INT32 args) { struct vertex *v; + float *buf; if (!THIS->img) - error("No image when calling Image.image->polyfill()\n"); + error("Image.image->polyfill: no image\n"); + + buf=malloc(sizeof(float)*(THIS->xsize+1)); + if (!buf) + error("Image.image->polyfill: out of memory\n"); v=polyfill_begin(); @@ -853,25 +684,33 @@ void image_polyfill(INT32 args) if (sp[-1].type!=T_ARRAY) { polyfill_free(v); - error("Illegal argument %d to Image.image->polyfill(), expected array\n", + error("Image.image->polyfill: Illegal argument %d, expected array\n", args); } if ((v_tmp=polyfill_add(v, sp[-1].u.array, args, "Image.image->polyfill()"))) { v = v_tmp; } else { polyfill_free(v); - error("Bad argument %d to Image.image->polyfill(), bad vertice\n", args); + error("Image.image->polyfill: Bad argument %d, bad vertex\n", args); } args--; pop_stack(); } +fprintf(stderr,"foo\n"); + if (!v) return; /* no vertices */ - polyfill_some(THIS,v); +fprintf(stderr,"bar\n"); + + polyfill_some(THIS,v,buf); + +fprintf(stderr,"gazonk\n"); polyfill_free(v); + free(buf); + THISOBJ->refs++; push_object(THISOBJ); }