8 i_mmarray_cr(i_mmarray *ar,int l) {
12 ar->data=mymalloc(sizeof(minmax)*l);
13 for(i=0;i<l;i++) { ar->data[i].max=-1; ar->data[i].min=MAXINT; }
17 i_mmarray_dst(i_mmarray *ar) {
19 if (ar->data != NULL) { myfree(ar->data); ar->data=NULL; }
23 i_mmarray_add(i_mmarray *ar,int x,int y) {
24 if (y>-1 && y<ar->lines)
26 if (x<ar->data[y].min) ar->data[y].min=x;
27 if (x>ar->data[y].max) ar->data[y].max=x;
32 i_mmarray_gmin(i_mmarray *ar,int y) {
33 if (y>-1 && y<ar->lines) return ar->data[y].min;
38 i_mmarray_getm(i_mmarray *ar,int y) {
39 if (y>-1 && y<ar->lines) return ar->data[y].max;
44 i_mmarray_render(i_img *im,i_mmarray *ar,i_color *val) {
46 for(i=0;i<ar->lines;i++) if (ar->data[i].max!=-1) for(x=ar->data[i].min;x<ar->data[i].max;x++) i_ppix(im,x,i,val);
52 i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar) {
56 alpha=(double)(y2-y1)/(double)(x2-x1);
59 if (x2<x1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
64 i_mmarray_add(ar,x1,(int)(dsec+0.5));
71 if (y2<y1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
76 i_mmarray_add(ar,(int)(dsec+0.5),y1);
83 i_mmarray_info(i_mmarray *ar) {
85 for(i=0;i<ar->lines;i++)
86 if (ar->data[i].max!=-1) printf("line %d: min=%d, max=%d.\n",i,ar->data[i].min,ar->data[i].max);
91 i_arc(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val) {
96 mm_log((1,"i_arc(im* 0x%x,x %d,y %d,rad %.2f,d1 %.2f,d2 %.2f,val 0x%x)\n",im,x,y,rad,d1,d2,val));
98 i_mmarray_cr(&dot,im->ysize);
100 x1=(int)(x+0.5+rad*cos(d1*PI/180.0));
101 y1=(int)(y+0.5+rad*sin(d1*PI/180.0));
102 fx=(float)x1; fy=(float)y1;
104 /* printf("x1: %d.\ny1: %d.\n",x1,y1); */
105 i_arcdraw(x, y, x1, y1, &dot);
107 x1=(int)(x+0.5+rad*cos(d2*PI/180.0));
108 y1=(int)(y+0.5+rad*sin(d2*PI/180.0));
110 for(f=d1;f<=d2;f+=0.01) i_mmarray_add(&dot,(int)(x+0.5+rad*cos(f*PI/180.0)),(int)(y+0.5+rad*sin(f*PI/180.0)));
112 /* printf("x1: %d.\ny1: %d.\n",x1,y1); */
113 i_arcdraw(x, y, x1, y1, &dot);
116 i_mmarray_render(im,&dot,val);
121 /* Temporary AA HACK */
125 static frac float_to_frac(float x) { return (frac)(0.5+x*16.0); }
126 static int frac_sub (frac x) { return (x%16); }
127 static int frac_int (frac x) { return (x/16); }
128 static float frac_to_float(float x) { return (float)x/16.0; }
132 polar_to_plane(float cx, float cy, float angle, float radius, frac *x, frac *y) {
133 *x = float_to_frac(cx+radius*cos(angle));
134 *y = float_to_frac(cy+radius*sin(angle));
139 order_pair(frac *x, frac *y) {
152 make_minmax_list(i_mmarray *dot, float x, float y, float radius) {
154 float astep = radius>0.1 ? .5/radius : 10;
155 frac cx, cy, lx, ly, sx, sy;
157 mm_log((1, "make_minmax_list(dot %p, x %.2f, y %.2f, radius %.2f)\n", dot, x, y, radius));
159 polar_to_plane(x, y, angle, radius, &sx, &sy);
161 for(angle = 0.0; angle<361; angle +=astep) {
164 polar_to_plane(x, y, angle, radius, &cx, &cy);
167 if (fabs(cx-lx) > fabs(cy-ly)) {
170 ccx = lx; lx = cx; cx = ccx;
171 ccy = ly; ly = cy; cy = ccy;
174 for(ccx=lx; ccx<=cx; ccx++) {
175 ccy = ly + ((cy-ly)*(ccx-lx))/(cx-lx);
176 i_mmarray_add(dot, ccx, ccy);
182 ccy = ly; ly = cy; cy = ccy;
183 ccx = lx; lx = cx; cx = ccx;
186 for(ccy=ly; ccy<=cy; ccy++) {
187 if (cy-ly) ccx = lx + ((cx-lx)*(ccy-ly))/(cy-ly); else ccx = lx;
188 i_mmarray_add(dot, ccx, ccy);
194 /* Get the number of subpixels covered */
198 i_pixel_coverage(i_mmarray *dot, int x, int y) {
204 for(cy=y*16; cy<(y+1)*16; cy++) {
205 frac tmin = dot->data[cy].min;
206 frac tmax = dot->data[cy].max;
208 if (tmax == -1 || tmin > maxx || tmax < minx) continue;
210 if (tmin < minx) tmin = minx;
211 if (tmax > maxx) tmax = maxx;
219 i_circle_aa(i_img *im, float x, float y, float rad, i_color *val) {
224 mm_log((1, "i_circle_aa(im %p, x %d, y %d, rad %.2f, val %p)\n", im, x, y, rad, val));
226 i_mmarray_cr(&dot,16*im->ysize);
227 make_minmax_list(&dot, x, y, rad);
229 for(ly = 0; ly<im->ysize; ly++) {
230 int ix, cy, cnt = 0, minx = INT_MAX, maxx = INT_MIN;
232 /* Find the left/rightmost set subpixels */
233 for(cy = 0; cy<16; cy++) {
234 frac tmin = dot.data[ly*16+cy].min;
235 frac tmax = dot.data[ly*16+cy].max;
236 if (tmax == -1) continue;
238 if (minx > tmin) minx = tmin;
239 if (maxx < tmax) maxx = tmax;
242 if (maxx == INT_MIN) continue; /* no work to be done for this row of pixels */
246 for(ix=minx; ix<=maxx; ix++) {
247 int cnt = i_pixel_coverage(&dot, ix, ly);
248 if (cnt>255) cnt = 255;
249 if (cnt) { /* should never be true */
251 float ratio = (float)cnt/255.0;
252 i_gpix(im, ix, ly, &temp);
253 for(ch=0;ch<im->channels; ch++) temp.channel[ch] = (unsigned char)((float)val->channel[ch]*ratio + (float)temp.channel[ch]*(1.0-ratio));
254 i_ppix(im, ix, ly, &temp);
266 i_box(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
268 mm_log((1,"i_box(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
269 for(x=x1;x<x2+1;x++) {
273 for(y=y1;y<y2+1;y++) {
280 i_box_filled(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
282 mm_log((1,"i_box_filled(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
283 for(x=x1;x<x2+1;x++) for (y=y1;y<y2+1;y++) i_ppix(im,x,y,val);
288 i_draw(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
293 mm_log((1,"i_draw(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
295 alpha=(double)(y2-y1)/(double)(x2-x1);
298 if (x2<x1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
303 i_ppix(im,x1,(int)(dsec+0.5),val);
310 if (y2<y1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
315 i_ppix(im,(int)(dsec+0.5),y1,val);
319 mm_log((1,"i_draw: alpha=%f.\n",alpha));
323 i_line_aa(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
327 int temp,dx,dy,isec,ch;
329 mm_log((1,"i_draw(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
334 if (abs(dx)>abs(dy)) { /* alpha < 1 */
335 if (x2<x1) { temp=x1; x1=x2; x2=temp; temp=y1; y1=y2; y2=temp; }
336 alpha=(float)(y2-y1)/(float)(x2-x1);
342 /* dfrac=1-(1-dfrac)*(1-dfrac); */
343 /* This is something we can play with to try to get better looking lines */
345 i_gpix(im,x1,isec,&tval);
346 for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(dfrac*(float)tval.channel[ch]+(1-dfrac)*(float)val->channel[ch]);
347 i_ppix(im,x1,isec,&tval);
349 i_gpix(im,x1,isec+1,&tval);
350 for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)((1-dfrac)*(float)tval.channel[ch]+dfrac*(float)val->channel[ch]);
351 i_ppix(im,x1,isec+1,&tval);
357 if (y2<y1) { temp=y1; y1=y2; y2=temp; temp=x1; x1=x2; x2=temp; }
358 alpha=(float)(x2-x1)/(float)(y2-y1);
363 /* dfrac=sqrt(dfrac); */
364 /* This is something we can play with */
365 i_gpix(im,isec,y1,&tval);
366 for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)(dfrac*(float)tval.channel[ch]+(1-dfrac)*(float)val->channel[ch]);
367 i_ppix(im,isec,y1,&tval);
369 i_gpix(im,isec+1,y1,&tval);
370 for(ch=0;ch<im->channels;ch++) tval.channel[ch]=(unsigned char)((1-dfrac)*(float)tval.channel[ch]+dfrac*(float)val->channel[ch]);
371 i_ppix(im,isec+1,y1,&tval);
384 for(i=k+1;i<=n;i++) r*=i;
385 for(i=1;i<=(n-k);i++) r/=i;
390 /* Note in calculating t^k*(1-t)^(n-k)
391 we can start by using t^0=1 so this simplifies to
392 t^0*(1-t)^n - we want to multiply that with t/(1-t) each iteration
393 to get a new level - this may lead to errors who knows lets test it */
396 i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val) {
405 bzcoef=mymalloc(sizeof(double)*l);
406 for(k=0;k<l;k++) bzcoef[k]=perm(n,k);
410 /* for(k=0;k<l;k++) printf("bzcoef: %d -> %f\n",k,bzcoef[k]); */
412 for(t=0;t<=1;t+=0.005) {
417 /* cx+=bzcoef[k]*x[k]*pow(t,k)*pow(1-t,n-k);
418 cy+=bzcoef[k]*y[k]*pow(t,k)*pow(1-t,n-k);*/
420 cx+=bzcoef[k]*x[k]*ccoef;
421 cy+=bzcoef[k]*y[k]*ccoef;
424 /* printf("%f -> (%d,%d)\n",t,(int)(0.5+cx),(int)(0.5+cy)); */
426 i_line_aa(im,lx,ly,(int)(0.5+cx),(int)(0.5+cy),val);
428 /* i_ppix(im,(int)(0.5+cx),(int)(0.5+cy),val); */
440 REF: Graphics Gems I. page 282+
459 /* This should be moved into a seperate file? */
461 /* This is the truncation used:
463 a double is multiplied by 16 and then truncated.
464 This means that 0 -> 0
465 So a triangle of (0,0) (10,10) (10,0) Will look like it's
466 not filling the (10,10) point nor the (10,0)-(10,10) line segment
473 #define IMTRUNC(x) ((int)(x*16))
502 p_compy(const struct p_point *p1, const struct p_point *p2) {
503 if (p1->y > p2->y) return 1;
504 if (p1->y < p2->y) return -1;
509 p_compx(const struct p_slice *p1, const struct p_slice *p2) {
510 if (p1->x > p2->x) return 1;
511 if (p1->x < p2->x) return -1;
515 /* Change this to int? and round right goddamn it! */
518 p_eval_aty(struct p_line *l,pcord y) {
521 if (t) return ( (y-l->y1)*l->x2 + (l->y2-y)*l->x1 )/t;
522 return (l->x1+l->x2)/2.0;
526 p_eval_atx(struct p_line *l,pcord x) {
529 if (t) return ( (x-l->x1)*l->y2 + (l->x2-x)*l->y1 )/t;
530 return (l->y1+l->y2)/2.0;
534 /* Algorithm to count the pixels covered by line going through pixel (x,y)
540 p_eval_coverage(struct p_line *l, int lc, int x, pcord y1, pcord y2) {
547 /* Antialiasing polygon algorithm
549 1. only nice polygons - no crossovers
550 2. 1/16 pixel resolution # previously - floating point co-ordinates
551 3. full antialiasing ( complete spectrum of blends )
552 4. uses hardly any memory
553 5. no subsampling phase
555 For each interval we must:
556 1. find which lines are in it
557 2. order the lines from in increasing x order.
558 since we are assuming no crossovers it is sufficent
559 to check a single point on each line.
565 1. Interval: A vertical segment in which no lines cross nor end.
566 2. Scanline: A physical line, contains 16 subpixels in the horizontal direction
567 3. Slice: A start stop line pair.
573 The variable tempflush describes if there is anything in the templine array or not.
575 if tempflush is 0 then the array is clean.
576 if tempflush is 1 then the array contains a partial filled scanline
580 /* Rendering of a single start stop pair:
584 The rendering is split in three parts
585 1. From the first start pixel to the first stop pixel
586 2. Area from the first end pixel to the last start pixel
587 3. Area from the first end pixel to the last start pixel
593 i_poly_aa(i_img *im,int l,double *x,double *y,i_color *val) {
594 int i,k; /* Index variables */
595 int clc; /* Index of next item on interval linelist */
596 int tx; /* Coarse x coord within a scanline */
597 pcord miny,maxy; /* Min and max values of the current slice in the subcord system */
598 pcord minacy,maxacy; /* Min and max values of the current scanline bounded by the slice
599 in the subcord system */
600 int cscl; /* Current scanline */
601 pcord cc; /* Current vertical centerpoint of interval */
603 int minsx,minex,maxsx,maxex; /* The horizontal stretches of the lines beloning to the current slice within a scanline */
604 int *templine; /* Line accumulator */
606 struct p_point *pset; /* List of points in polygon */
607 struct p_line *lset; /* List of lines in polygon */
608 struct p_slice *tllist; /* List of slices */
610 i_color red,blue,yellow;
623 if ( (pset=mymalloc(sizeof(struct p_point)*l)) == NULL) { m_fatal(2,"malloc failed\n"); return; }
624 if ( (lset=mymalloc(sizeof(struct p_line)*l)) == NULL) { m_fatal(2,"malloc failed\n"); return; }
625 if ( (tllist=mymalloc(sizeof(struct p_slice)*l)) == NULL) { m_fatal(2,"malloc failed\n"); return; }
626 if ( (templine=mymalloc(sizeof(int)*im->xsize)) == NULL) { m_fatal(2,"malloc failed\n"); return; }
628 /* insert the lines into the line list */
632 pset[i].x=IMTRUNC(x[i]);
633 pset[i].y=IMTRUNC(y[i]);
635 lset[i].x1=IMTRUNC(x[i]);
636 lset[i].y1=IMTRUNC(y[i]);
637 lset[i].x2=IMTRUNC(x[(i+1)%l]);
638 lset[i].y2=IMTRUNC(y[(i+1)%l]);
639 lset[i].miny=min(lset[i].y1,lset[i].y2);
640 lset[i].maxy=max(lset[i].y1,lset[i].y2);
643 qsort(pset,l,sizeof(struct p_point),(int(*)(const void *,const void *))p_compy);
645 printf("post point list (sorted in ascending y order)\n");
647 printf("%d [ %d ] %d %d\n",i,pset[i].n,pset[i].x,pset[i].y);
650 printf("line list\n");
652 printf("%d [ %d ] (%d , %d) -> (%d , %d) yspan ( %d , %d )\n",i,lset[i].n,lset[i].x1,lset[i].y1,lset[i].x2,lset[i].y2,lset[i].miny,lset[i].maxy);
655 printf("MAIN LOOP\n\n");
657 /* Zero templine buffer */
658 /* Templine buffer flushed everytime a scan line ends */
659 for(i=0;i<im->xsize;i++) templine[i]=0;
662 /* loop on intervals */
664 cc=(pset[i].y+pset[i+1].y)/2;
665 printf("current slice is: %d to %d ( cpoint %d )\n",pset[i].y,pset[i+1].y,cc);
668 /* stuff this in a function ?? */
670 /* Check what lines belong to interval */
672 printf("checking line: %d [ %d ] (%d , %d) -> (%d, %d) yspan ( %d , %d )",
673 k,lset[k].n,lset[k].x1,lset[k].y1,lset[k].x2,lset[k].y2,lset[k].miny,lset[k].maxy);
674 if (cc >= lset[k].miny && cc <= lset[k].maxy) {
675 if (lset[k].miny == lset[k].maxy) printf(" HORIZONTAL - skipped\n");
678 tllist[clc].x=p_eval_aty(&lset[k],cc);
681 } else printf(" OUTSIDE\n");
685 at this point a table of pixels that need special care should
686 be generated from the line list - it should be ordered so that only
687 one needs to be checked - options: rendering to a list then order - or
688 rendering in the right order might be possible to do nicely with the
691 1. Draw leftmost pixel for this line
692 2. If preceeding pixel was occupied check next one else go to 1 again.
695 printf("lines in current interval:");
696 for(k=0;k<clc;k++) printf(" %d (%.2f)",tllist[k].n,tllist[k].x);
699 /* evaluate the lines in the middle of the slice */
701 printf("Sort lines left to right within interval\n");
702 qsort(tllist,clc,sizeof(struct p_slice),(int(*)(const void *,const void *))p_compx);
704 printf("sorted lines in interval - output:");
705 for(k=0;k<clc;k++) printf(" %d",tllist[k].n);
711 /* iterate over scanlines */
712 for(cscl=(miny)/16;cscl<=maxy/16;cscl++) {
713 minacy=max(miny,cscl*16);
714 maxacy=min(maxy,cscl*16+15);
716 printf("Scanline bound %d - %d\n",minacy, maxacy);
718 /* iterate over line pairs (slices) within interval */
719 for(k=0;k<clc-1;k+=2) {
721 mt1=p_eval_aty(&lset[tllist[k].n],minacy); /* upper corner */
722 mt2=p_eval_aty(&lset[tllist[k].n],maxacy); /* lower corner */
725 mt1=p_eval_aty(&lset[tllist[k+1].n],minacy); /* upper corner */
726 mt2=p_eval_aty(&lset[tllist[k+1].n],maxacy); /* lower corner */
730 printf("minsx: %d minex: %d\n",minsx,minex);
731 printf("maxsx: %d maxex: %d\n",maxsx,maxex);
733 if (minex/16<maxsx/16) printf("Scan slice is simple!\n");
734 else printf("Scan slice is complicated!\n");
736 if (minsx/16 == minex/16) { /* The line starts and ends in the same pixel */
737 printf("Low slant start pixel\n");
738 templine[minsx/16]=(maxacy-minacy+1)*(minex-minsx+1)/2+((minex | 0xF)-minex)*(maxacy-minacy+1);
740 for(tx=minsx/16;tx<minex/16+1;tx++) {
741 int minx,maxx,minxy,maxxy;
742 minx=max(minsx, tx*16 );
743 maxx=min(minex, tx*16+15);
746 templine[tx]=(maxacy-minacy+1);
749 minxy=p_eval_atx(&lset[tllist[k].n], minx);
750 maxxy=p_eval_atx(&lset[tllist[k].n], maxx);
752 templine[tx]+=(abs(minxy-maxxy)+1)*(minex-minsx+1)/2; /* The triangle between the points */
753 if (mt1 < mt2) { /* \ slant */
754 /* ((minex | 0xF)-minex)*(maxacy-minacy+1); FIXME: unfinished */
759 templine[tx]+=((minex | 0xF)-minex)*(maxacy-minacy+1);
766 for(tx=maxsx/16;tx<maxex/16+1;tx++) templine[tx]+=16*(maxacy-minacy+1);
768 /* for(tx=minex/16+1;tx<maxsx/16;tx++) 0; */
771 printf("line %d: painting %d - %d\n",cscl,minex/16+1,maxsx/16);
772 if ( (minacy != cscl*16) || (maxacy != cscl*16+15) ) {
773 for(tx=minsx/16;tx<maxex/16+1;tx++) {
774 i_ppix(im,tx,cscl,&yellow);
778 for(tx=minsx/16;tx<minex/16+1;tx++) i_ppix(im,tx,cscl,&red);
779 for(tx=maxsx/16;tx<maxex/16+1;tx++) i_ppix(im,tx,cscl,&blue);
780 for(tx=minex/16+1;tx<maxsx/16;tx++) i_ppix(im,tx,cscl,val);
794 /* Flood fill algorithm - based on the Ken Fishkins (pixar) gem in
809 struct stack_element {
817 /* create the link data to put push onto the stack */
820 struct stack_element*
821 crdata(int left,int right,int dadl,int dadr,int y, int dir) {
822 struct stack_element *ste;
823 ste=(struct stack_element*)mymalloc(sizeof(struct stack_element));
829 ste->myDirection=dir;
833 /* i_ccomp compares two colors and gives true if they are the same */
836 i_ccomp(i_color *val1,i_color *val2,int ch) {
838 for(i=0;i<ch;i++) if (val1->channel[i] !=val2->channel[i]) return 0;
844 i_lspan(i_img *im,int seedx,int seedy,i_color *val) {
847 if (seedx-1 < 0) break;
848 i_gpix(im,seedx-1,seedy,&cval);
849 if (!i_ccomp(val,&cval,im->channels)) break;
856 i_rspan(i_img *im,int seedx,int seedy,i_color *val) {
859 if (seedx+1 > im->xsize-1) break;
860 i_gpix(im,seedx+1,seedy,&cval);
861 if (!i_ccomp(val,&cval,im->channels)) break;
867 /* Macro to create a link and push on to the list */
869 #define ST_PUSH(left,right,dadl,dadr,y,dir) { struct stack_element *s=crdata(left,right,dadl,dadr,y,dir); llist_push(st,&s);}
871 /* pops the shadow on TOS into local variables lx,rx,y,direction,dadLx and dadRx */
872 /* No overflow check! */
874 #define ST_POP() { struct stack_element *s; llist_pop(st,&s); lx=s->myLx; rx=s->myRx; dadLx=s->dadLx; dadRx=s->dadRx; y=s->myY; direction=s->myDirection; myfree(s); }
876 #define ST_STACK(dir,dadLx,dadRx,lx,rx,y) { int pushrx=rx+1; int pushlx=lx-1; ST_PUSH(lx,rx,pushlx,pushrx,y+dir,dir); if (rx > dadRx) ST_PUSH(dadRx+1,rx,pushlx,pushrx,y-dir,-dir); if (lx < dadLx) ST_PUSH(lx,dadLx-1,pushlx,pushrx,y-dir,-dir); }
878 #define SET(x,y) btm_set(btm,x,y);
880 #define INSIDE(x,y) ((!btm_test(btm,x,y) && ( i_gpix(im,x,y,&cval),i_ccomp(&val,&cval,channels) ) ))
883 i_flood_fill(i_img *im,int seedx,int seedy,i_color *dcol) {
895 int bxmin=seedx,bxmax=seedx,bymin=seedy,bymax=seedy;
898 struct i_bitmap *btm;
900 int channels,xsize,ysize;
903 channels=im->channels;
907 btm=btm_new(xsize,ysize);
908 st=llist_new(100,sizeof(struct stack_element*));
910 /* Get the reference color */
911 i_gpix(im,seedx,seedy,&val);
913 /* Find the starting span and fill it */
914 lx=i_lspan(im,seedx,seedy,&val);
915 rx=i_rspan(im,seedx,seedy,&val);
917 /* printf("span: %d %d \n",lx,rx); */
919 for(x=lx;x<=rx;x++) SET(x,seedy);
921 ST_PUSH(lx,rx,lx,rx,seedy+1,1);
922 ST_PUSH(lx,rx,lx,rx,seedy-1,-1);
927 if (y<0 || y>ysize-1) continue;
929 if (bymin > y) bymin=y; /* in the worst case an extra line */
930 if (bymax < y) bymax=y;
932 /* printf("start of scan - on stack : %d \n",st->count); */
935 /* printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction); */
939 for(tx=0;tx<xsize;tx++) printf("%d",tx%10);
941 for(ty=0;ty<ysize;ty++) {
943 for(tx=0;tx<xsize;tx++) printf("%d",!!btm_test(btm,tx,ty));
952 if ( (wasIn = INSIDE(lx,y)) ) {
955 while(INSIDE(lx,y) && lx > 0) {
961 if (bxmin > lx) bxmin=lx;
963 while(x <= xsize-1) {
964 /* printf("x=%d\n",x); */
968 /* case 1: was inside, am still inside */
971 /* case 2: was inside, am no longer inside: just found the
972 right edge of a span */
973 ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
975 if (bxmax < x) bxmax=x;
983 /* case 3: Wasn't inside, am now: just found the start of a new run */
987 /* case 4: Wasn't inside, still isn't */
992 EXT: /* out of loop */
994 /* hit an edge of the frame buffer while inside a run */
995 ST_STACK(direction,dadLx,dadRx,lx,(x-1),y);
996 if (bxmax < x) bxmax=x;
1000 /* printf("lx=%d rx=%d dadLx=%d dadRx=%d y=%d direction=%d\n",lx,rx,dadLx,dadRx,y,direction);
1001 printf("bounding box: [%d,%d] - [%d,%d]\n",bxmin,bymin,bxmax,bymax); */
1003 for(y=bymin;y<=bymax;y++) for(x=bxmin;x<=bxmax;x++) if (btm_test(btm,x,y)) i_ppix(im,x,y,dcol);