paint: cleanup floodfill
This commit is contained in:
parent
b3d7231013
commit
03806e9c17
1 changed files with 71 additions and 53 deletions
|
@ -269,20 +269,27 @@ restore(int n)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Rectangle r;
|
Rectangle r;
|
||||||
Rectangle r0;
|
Rectangle r0;
|
||||||
Image *iscan;
|
Image* dst;
|
||||||
uchar *bscan;
|
|
||||||
uchar *bmask;
|
int yscan; /* current scanline */
|
||||||
int wmask;
|
int wscan; /* bscan width in bytes */
|
||||||
int wscan;
|
Image* iscan; /* scanline image */
|
||||||
int yscan;
|
uchar* bscan; /* scanline buffer */
|
||||||
uchar color[4];
|
|
||||||
} Floodfill;
|
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
|
void
|
||||||
floodscan(Floodfill *f, Point p0)
|
fillscan(Filldata *f, Point p0)
|
||||||
{
|
{
|
||||||
uchar *b;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
uchar *b;
|
||||||
|
|
||||||
x = p0.x;
|
x = p0.x;
|
||||||
y = p0.y;
|
y = p0.y;
|
||||||
|
@ -291,18 +298,19 @@ floodscan(Floodfill *f, Point p0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(f->yscan != y){
|
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;
|
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--){
|
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;
|
break;
|
||||||
b[x/8] |= 0x80>>(x%8);
|
b[x/8] |= 0x80>>(x%8);
|
||||||
}
|
}
|
||||||
for(x = p0.x+1; x < f->r0.max.x; x++){
|
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;
|
break;
|
||||||
b[x/8] |= 0x80>>(x%8);
|
b[x/8] |= 0x80>>(x%8);
|
||||||
}
|
}
|
||||||
|
@ -312,12 +320,12 @@ floodscan(Floodfill *f, Point p0)
|
||||||
for(x = p0.x; x >= 0; x--){
|
for(x = p0.x; x >= 0; x--){
|
||||||
if((b[x/8] & 0x80>>(x%8)) == 0)
|
if((b[x/8] & 0x80>>(x%8)) == 0)
|
||||||
break;
|
break;
|
||||||
floodscan(f, Pt(x, y));
|
fillscan(f, Pt(x, y));
|
||||||
}
|
}
|
||||||
for(x = p0.x+1; x < f->r0.max.x; x++){
|
for(x = p0.x+1; x < f->r0.max.x; x++){
|
||||||
if((b[x/8] & 0x80>>(x%8)) == 0)
|
if((b[x/8] & 0x80>>(x%8)) == 0)
|
||||||
break;
|
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--){
|
for(x = p0.x; x >= 0; x--){
|
||||||
if((b[x/8] & 0x80>>(x%8)) == 0)
|
if((b[x/8] & 0x80>>(x%8)) == 0)
|
||||||
break;
|
break;
|
||||||
floodscan(f, Pt(x, y));
|
fillscan(f, Pt(x, y));
|
||||||
}
|
}
|
||||||
for(x = p0.x+1; x < f->r0.max.x; x++){
|
for(x = p0.x+1; x < f->r0.max.x; x++){
|
||||||
if((b[x/8] & 0x80>>(x%8)) == 0)
|
if((b[x/8] & 0x80>>(x%8)) == 0)
|
||||||
break;
|
break;
|
||||||
floodscan(f, Pt(x, y));
|
fillscan(f, Pt(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
floodfill(Point p, Image *fill)
|
floodfill(Image *dst, Rectangle r, Point p, Image *src)
|
||||||
{
|
{
|
||||||
Floodfill f;
|
Filldata f;
|
||||||
Image *imask;
|
|
||||||
int nmask;
|
|
||||||
|
|
||||||
f.r = canvas->r;
|
if(!rectclip(&r, dst->r))
|
||||||
f.r0 = rectsubpt(f.r, f.r.min);
|
return;
|
||||||
|
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.wmask = bytesperline(f.r0, 1);
|
||||||
nmask = f.wmask*f.r0.max.y;
|
f.nmask = f.wmask*f.r0.max.y;
|
||||||
if((f.bmask = mallocz(nmask, 1)) == nil)
|
if((f.bmask = mallocz(f.nmask, 1)) == nil)
|
||||||
return;
|
goto out;
|
||||||
if((f.iscan = allocimage(display, Rect(0, 0, f.r0.max.x, 1), RGB24, 0, DNofill)) == nil){
|
if((f.imask = allocimage(display, f.r0, GREY1, 0, DNofill)) == nil)
|
||||||
free(f.bmask);
|
goto out;
|
||||||
return;
|
|
||||||
}
|
r = f.r0;
|
||||||
|
r.max.y = 1;
|
||||||
|
if((f.iscan = allocimage(display, r, RGB24, 0, DNofill)) == nil)
|
||||||
|
goto out;
|
||||||
f.yscan = -1;
|
f.yscan = -1;
|
||||||
f.wscan = bytesperline(f.iscan->r, 24);
|
f.wscan = bytesperline(f.iscan->r, f.iscan->depth);
|
||||||
if((f.bscan = mallocz(f.wscan, 1)) == nil){
|
if((f.bscan = mallocz(f.wscan, 0)) == nil)
|
||||||
freeimage(f.iscan);
|
goto out;
|
||||||
free(f.bmask);
|
|
||||||
return;
|
r = Rect(0,0,1,1);
|
||||||
}
|
f.ncmp = (f.iscan->depth+7) / 8;
|
||||||
memset(f.color, 0, sizeof(f.color));
|
draw(f.iscan, r, dst, nil, p);
|
||||||
draw(f.iscan, Rect(0,0,1,1), canvas, nil, p);
|
if(unloadimage(f.iscan, r, f.bcmp, sizeof(f.bcmp)) < 0)
|
||||||
unloadimage(f.iscan, Rect(0,0,1,1), f.color, sizeof(f.color));
|
goto out;
|
||||||
floodscan(&f, subpt(p, f.r.min));
|
|
||||||
freeimage(f.iscan);
|
fillscan(&f, subpt(p, f.r.min));
|
||||||
free(f.bscan);
|
|
||||||
if((imask = allocimage(display, f.r0, GREY1, 0, DNofill)) == nil){
|
loadimage(f.imask, f.imask->r, f.bmask, f.nmask);
|
||||||
free(f.bmask);
|
draw(f.dst, f.r, src, f.imask, f.imask->r.min);
|
||||||
return;
|
out:
|
||||||
}
|
|
||||||
loadimage(imask, imask->r, f.bmask, nmask);
|
|
||||||
free(f.bmask);
|
free(f.bmask);
|
||||||
draw(canvas, canvas->r, fill, imask, imask->r.min);
|
free(f.bscan);
|
||||||
freeimage(imask);
|
if(f.iscan)
|
||||||
|
freeimage(f.iscan);
|
||||||
|
if(f.imask)
|
||||||
|
freeimage(f.imask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -606,9 +622,11 @@ main(int argc, char *argv[])
|
||||||
update(nil);
|
update(nil);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
save(canvas->r, 1);
|
r = canvas->r;
|
||||||
floodfill(p, img);
|
save(r, 1);
|
||||||
update(nil);
|
floodfill(canvas, r, p, img);
|
||||||
|
update(&r);
|
||||||
|
|
||||||
/* wait for mouse release */
|
/* wait for mouse release */
|
||||||
while(event(&e) == Emouse && (e.mouse.buttons & 7) != 0)
|
while(event(&e) == Emouse && (e.mouse.buttons & 7) != 0)
|
||||||
;
|
;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue