V10/vol2/Faces/How/matte.c

#include <u.h>
#include <gnot.h>
#include <event.h>

Bitmap display;
Font *defont;
int w,h;

main(argc,argv)
char *argv[];
{
	Bitmap *b,*m;
	int fd;
	ginit();
	einit();
	if (argc != 4) {
		fprint(2,"usage: matte w h file\n");
		exit(0);
	}
	w = atoi(argv[1]);
	h = atoi(argv[2]);
	if ((fd = open(argv[3],0)) < 0) {
		fprint(2,"can't open %s\n",argv[3]);
		exit(0);
	}
	b = balloc(Rect(0,0,w,h),3);
	m = balloc(Rect(0,0,w,h),1);
	bitblt(m,m->rect.min,m,m->rect,F);
	myread(fd,b->base,w*h);
	close(fd);
	dispfs(b,m);
	edit(b,m,argv[3]);
}

dispfs(b,m)
Bitmap *b,*m;
{
	Bitmap *r;
	r = balloc(b->rect,b->ldepth);
	bitblt(r,r->rect.min,b,b->rect,S);
	bitblt(r,r->rect.min,m,m->rect,S&D);
	fs(r);
	bitblt(&display,display.rect.min,r,r->rect,S);
	bfree(r);
}

char *fsizes[] = {"4", "7", "12", "25", "80", "150", 0};
Menu sizes = {fsizes};

enum {REMOVE, RESTORE, WRITE, EXIT};
char *fmenu[] = {"remove", "restore", "write", "exit", 0};
Menu commands = {fmenu};

#define DR(n)	raddp(Rect(0,0,n,n),display.rect.min)

edit(b,m,file)
Bitmap *b,*m;
char *file;
{
	Event *e;
	Point p;
	Bitmap *res,*brush=0;
	int i,fd,size=25,wannago = 0;
	int mode=0;
	while (1) {
		switch ((e = getevent())->type) {
		case MOUSE:
			if (mouse.buttons&1) {
				p = sub(mouse.xy,Pt(size/2,size/2));
				docursor(0);
				bitblt(&display,p,&display,DR(size),F-mode);
				docursor(size);
				bitblt(m,sub(p,display.rect.min),m,Rect(0,0,size,size),mode);
			}
			else if (mouse.buttons&2) {
				if ((i = menuhit(&sizes,2)) == -1)
					break;
				size = atoi(fsizes[i]);
				docursor(size);
			}
			else if (mouse.buttons&4)
				switch (menuhit(&commands,3)) {
				case -1:
					break;
				case REMOVE:
					mode = 0;
					docursor(0);
					dispfs(b,m);
					docursor(size);
					break;
				case RESTORE:
					mode = F;
					docursor(0);
					bitblt(&display,display.rect.min,m,m->rect,notS);
					docursor(size);
					break;
				case WRITE:
					res = balloc(Rect(0,0,w,h),3);
/*
					bitblt(res,Pt(0,0),b,b->rect,S);
					bitblt(res,Pt(0,0),m,m->rect,S&D);
*/
					bitblt(res,Pt(0,0),m,m->rect,S);
					if ((fd = create("matte",1,0666)) < 0) {
						fprint("can't create matte file\n");
						continue;
					}
					mywrite(fd,res->base,w*h);
					close(fd);
					bfree(res);
					break;
				case EXIT:
					if (wannago)
						exit(0);
					else {
						wannago = 1;
						continue;
					}
					break;
				}
			wannago = 0;
			docursor(size);
		default:
			break;
		}
	}
}

docursor(n)
{
	static Point pt;
	static size;
	if (size != 0)
		cursoroff();
	bitblt(&display,sub(pt,Pt(size/2,size/2)),&display,DR(size),notD);
	pt = mouse.xy;
	size = n;
	bitblt(&display,sub(pt,Pt(size/2,size/2)),&display,DR(size),notD);
	if (size != 0)
		cursoron();
}	

ushort prop[1024];
uchar bright[] = {192,128,64,0};

fs(b)
Bitmap *b;
{
	int i,j,w,h,save,next,e,x;
	uchar *p;
	ushort *q;
	w = b->rect.max.x;
	h = b->rect.max.y;
	for (i = 0; i < h; i++) {
		p = (uchar *) addr(b,Pt(0,i));
		save = next = 0;
		q = prop;
		for (j = 0; j < w; j++) {
			x = *p + *q + next;
			if (x > 255)
				x = 255;
			e = x&0x3f;
			next = (e + (e<<1))>>3;
			*q++ = save + next;
			save = e>>2;
			*p++ = ~x;
		}
	}
}

myread(fd,buf,n)
uchar *buf;
{
	int i;
	do {
		i = read(fd,buf,n);
		if(i<=0)
			return;		/* let it overrun */
		buf += i;
		n -= i;
	} while (n > 0);
}

mywrite(fd,buf,n)
uchar *buf;
{
	int i;
	do {
		i = write(fd,buf,(n>4096)?4096:n);
		if (i<=0) {
			fprint(2,"bad write of %d\n",n);
			exit(1);
		}
		buf += i;
		n -= i;
	} while (n > 0);
}