summaryrefslogtreecommitdiff
path: root/sys/src/cmd/paint.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-07-23 08:10:17 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-07-23 08:10:17 +0200
commit03806e9c178c0e8b0f551732e2d64b5813223fbb (patch)
treea2d8226bfc7846824308840b30a5e56c13581002 /sys/src/cmd/paint.c
parentb3d72310137266939589f2cdaff5671172bbb101 (diff)
paint: cleanup floodfill
Diffstat (limited to 'sys/src/cmd/paint.c')
-rw-r--r--sys/src/cmd/paint.c122
1 files changed, 70 insertions, 52 deletions
diff --git a/sys/src/cmd/paint.c b/sys/src/cmd/paint.c
index a24a70fbe..adac1afd6 100644
--- a/sys/src/cmd/paint.c
+++ b/sys/src/cmd/paint.c
@@ -269,20 +269,27 @@ restore(int n)
typedef struct {
Rectangle r;
Rectangle r0;
- Image *iscan;
- uchar *bscan;
- uchar *bmask;
- int wmask;
- int wscan;
- int yscan;
- uchar color[4];
-} Floodfill;
+ Image* dst;
+
+ int yscan; /* current scanline */
+ int wscan; /* bscan width in bytes */
+ Image* iscan; /* scanline image */
+ uchar* bscan; /* scanline buffer */
+
+ int nmask; /* size of bmask in bytes */
+ int wmask; /* width of bmask in bytes */
+ Image* imask; /* mask image */
+ uchar* bmask; /* mask buffer */
+
+ int ncmp;
+ uchar bcmp[4];
+} Filldata;
void
-floodscan(Floodfill *f, Point p0)
+fillscan(Filldata *f, Point p0)
{
- uchar *b;
int x, y;
+ uchar *b;
x = p0.x;
y = p0.y;
@@ -291,18 +298,19 @@ floodscan(Floodfill *f, Point p0)
return;
if(f->yscan != y){
+ draw(f->iscan, f->iscan->r, f->dst, nil, Pt(f->r.min.x, f->r.min.y+y));
+ if(unloadimage(f->iscan, f->iscan->r, f->bscan, f->wscan) < 0)
+ return;
f->yscan = y;
- draw(f->iscan, f->iscan->r, canvas, nil, Pt(f->r.min.x, f->r.min.y+y));
- unloadimage(f->iscan, f->iscan->r, f->bscan, f->wscan);
}
for(x = p0.x; x >= 0; x--){
- if(memcmp(f->bscan + x*3, f->color, 3))
+ if(memcmp(f->bscan + x*f->ncmp, f->bcmp, f->ncmp))
break;
b[x/8] |= 0x80>>(x%8);
}
for(x = p0.x+1; x < f->r0.max.x; x++){
- if(memcmp(f->bscan + x*3, f->color, 3))
+ if(memcmp(f->bscan + x*f->ncmp, f->bcmp, f->ncmp))
break;
b[x/8] |= 0x80>>(x%8);
}
@@ -312,12 +320,12 @@ floodscan(Floodfill *f, Point p0)
for(x = p0.x; x >= 0; x--){
if((b[x/8] & 0x80>>(x%8)) == 0)
break;
- floodscan(f, Pt(x, y));
+ fillscan(f, Pt(x, y));
}
for(x = p0.x+1; x < f->r0.max.x; x++){
if((b[x/8] & 0x80>>(x%8)) == 0)
break;
- floodscan(f, Pt(x, y));
+ fillscan(f, Pt(x, y));
}
}
@@ -326,54 +334,62 @@ floodscan(Floodfill *f, Point p0)
for(x = p0.x; x >= 0; x--){
if((b[x/8] & 0x80>>(x%8)) == 0)
break;
- floodscan(f, Pt(x, y));
+ fillscan(f, Pt(x, y));
}
for(x = p0.x+1; x < f->r0.max.x; x++){
if((b[x/8] & 0x80>>(x%8)) == 0)
break;
- floodscan(f, Pt(x, y));
+ fillscan(f, Pt(x, y));
}
}
}
void
-floodfill(Point p, Image *fill)
+floodfill(Image *dst, Rectangle r, Point p, Image *src)
{
- Floodfill f;
- Image *imask;
- int nmask;
+ Filldata f;
- f.r = canvas->r;
- f.r0 = rectsubpt(f.r, f.r.min);
- f.wmask = bytesperline(f.r0, 1);
- nmask = f.wmask*f.r0.max.y;
- if((f.bmask = mallocz(nmask, 1)) == nil)
+ if(!rectclip(&r, dst->r))
return;
- if((f.iscan = allocimage(display, Rect(0, 0, f.r0.max.x, 1), RGB24, 0, DNofill)) == nil){
- free(f.bmask);
+ if(!ptinrect(p, r))
return;
- }
+ memset(&f, 0, sizeof(f));
+ f.dst = dst;
+ f.r = r;
+ f.r0 = rectsubpt(r, r.min);
+ f.wmask = bytesperline(f.r0, 1);
+ f.nmask = f.wmask*f.r0.max.y;
+ if((f.bmask = mallocz(f.nmask, 1)) == nil)
+ goto out;
+ if((f.imask = allocimage(display, f.r0, GREY1, 0, DNofill)) == nil)
+ goto out;
+
+ r = f.r0;
+ r.max.y = 1;
+ if((f.iscan = allocimage(display, r, RGB24, 0, DNofill)) == nil)
+ goto out;
f.yscan = -1;
- f.wscan = bytesperline(f.iscan->r, 24);
- if((f.bscan = mallocz(f.wscan, 1)) == nil){
- freeimage(f.iscan);
- free(f.bmask);
- return;
- }
- memset(f.color, 0, sizeof(f.color));
- draw(f.iscan, Rect(0,0,1,1), canvas, nil, p);
- unloadimage(f.iscan, Rect(0,0,1,1), f.color, sizeof(f.color));
- floodscan(&f, subpt(p, f.r.min));
- freeimage(f.iscan);
- free(f.bscan);
- if((imask = allocimage(display, f.r0, GREY1, 0, DNofill)) == nil){
- free(f.bmask);
- return;
- }
- loadimage(imask, imask->r, f.bmask, nmask);
+ f.wscan = bytesperline(f.iscan->r, f.iscan->depth);
+ if((f.bscan = mallocz(f.wscan, 0)) == nil)
+ goto out;
+
+ r = Rect(0,0,1,1);
+ f.ncmp = (f.iscan->depth+7) / 8;
+ draw(f.iscan, r, dst, nil, p);
+ if(unloadimage(f.iscan, r, f.bcmp, sizeof(f.bcmp)) < 0)
+ goto out;
+
+ fillscan(&f, subpt(p, f.r.min));
+
+ loadimage(f.imask, f.imask->r, f.bmask, f.nmask);
+ draw(f.dst, f.r, src, f.imask, f.imask->r.min);
+out:
free(f.bmask);
- draw(canvas, canvas->r, fill, imask, imask->r.min);
- freeimage(imask);
+ free(f.bscan);
+ if(f.iscan)
+ freeimage(f.iscan);
+ if(f.imask)
+ freeimage(f.imask);
}
void
@@ -606,9 +622,11 @@ main(int argc, char *argv[])
update(nil);
break;
}
- save(canvas->r, 1);
- floodfill(p, img);
- update(nil);
+ r = canvas->r;
+ save(r, 1);
+ floodfill(canvas, r, p, img);
+ update(&r);
+
/* wait for mouse release */
while(event(&e) == Emouse && (e.mouse.buttons & 7) != 0)
;