xref: /plan9/sys/src/cmd/lens.c (revision 5e91980f0bca263e952809e3dc0cfc5dde74b999)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <event.h>
57dd7cddfSDavid du Colombier 
67dd7cddfSDavid du Colombier enum {
77dd7cddfSDavid du Colombier 	Edge = 5,
87dd7cddfSDavid du Colombier 	Maxmag = 16
97dd7cddfSDavid du Colombier };
107dd7cddfSDavid du Colombier 
11*5e91980fSDavid du Colombier enum {
12*5e91980fSDavid du Colombier 	Mzoom,
13*5e91980fSDavid du Colombier 	Munzoom,
14*5e91980fSDavid du Colombier 	Mgrid,
15*5e91980fSDavid du Colombier 	Mredraw,
16*5e91980fSDavid du Colombier 	Mexit
17*5e91980fSDavid du Colombier };
18*5e91980fSDavid du Colombier 
19*5e91980fSDavid du Colombier char *menustr[] = {
20*5e91980fSDavid du Colombier 	"zoom",
21*5e91980fSDavid du Colombier 	"unzoom",
22*5e91980fSDavid du Colombier 	"grid",
23*5e91980fSDavid du Colombier 	"redraw",
24*5e91980fSDavid du Colombier 	"exit",
25*5e91980fSDavid du Colombier 	nil
26*5e91980fSDavid du Colombier };
27*5e91980fSDavid du Colombier 
28*5e91980fSDavid du Colombier Menu menu = {
29*5e91980fSDavid du Colombier 	menustr,
30*5e91980fSDavid du Colombier 	nil,
31*5e91980fSDavid du Colombier 	-1
32*5e91980fSDavid du Colombier };
33*5e91980fSDavid du Colombier 
347dd7cddfSDavid du Colombier Point lastp;
357dd7cddfSDavid du Colombier Image *red;
367dd7cddfSDavid du Colombier Image *tmp;
373ff48bf5SDavid du Colombier Image *grid;
383ff48bf5SDavid du Colombier Image *chequer;
397dd7cddfSDavid du Colombier int	screenfd;
407dd7cddfSDavid du Colombier int	mag = 4;
413ff48bf5SDavid du Colombier int	showgrid = 0;
427dd7cddfSDavid du Colombier Rectangle	screenr;
437dd7cddfSDavid du Colombier uchar	*screenbuf;
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier void	magnify(void);
463ff48bf5SDavid du Colombier void makegrid(void);
477dd7cddfSDavid du Colombier 
487dd7cddfSDavid du Colombier void
drawit(void)497dd7cddfSDavid du Colombier drawit(void)
507dd7cddfSDavid du Colombier {
513ff48bf5SDavid du Colombier 	Rectangle r;
527dd7cddfSDavid du Colombier 	border(screen, screen->r, Edge, red, ZP);
537dd7cddfSDavid du Colombier 	magnify();
543ff48bf5SDavid du Colombier 	r = insetrect(screen->r, Edge);
553ff48bf5SDavid du Colombier 	draw(screen, r, tmp, nil, tmp->r.min);
567dd7cddfSDavid du Colombier 	flushimage(display, 1);
577dd7cddfSDavid du Colombier }
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier int bypp;
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier void
main(int argc,char * argv[])627dd7cddfSDavid du Colombier main(int argc, char *argv[])
637dd7cddfSDavid du Colombier {
647dd7cddfSDavid du Colombier 	Event e;
657dd7cddfSDavid du Colombier 	char buf[5*12];
667dd7cddfSDavid du Colombier 	ulong chan;
677dd7cddfSDavid du Colombier 	int d;
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier 	USED(argc, argv);
707dd7cddfSDavid du Colombier 	if(initdraw(nil, nil, "lens") < 0){
717dd7cddfSDavid du Colombier 		fprint(2, "lens: initdraw failed: %r\n");
727dd7cddfSDavid du Colombier 		exits("initdraw");
737dd7cddfSDavid du Colombier 	}
747dd7cddfSDavid du Colombier 	einit(Emouse|Ekeyboard);
757dd7cddfSDavid du Colombier 	red = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, DRed);
763ff48bf5SDavid du Colombier 	chequer = allocimage(display, Rect(0, 0, 2, 2), GREY1, 1, DBlack);
773ff48bf5SDavid du Colombier 	draw(chequer, Rect(0, 0, 1, 1), display->white, nil, ZP);
783ff48bf5SDavid du Colombier 	draw(chequer, Rect(1, 1, 2, 2), display->white, nil, ZP);
797dd7cddfSDavid du Colombier 	lastp = divpt(addpt(screen->r.min, screen->r.max), 2);
807dd7cddfSDavid du Colombier 	screenfd = open("/dev/screen", OREAD);
817dd7cddfSDavid du Colombier 	if(screenfd < 0){
827dd7cddfSDavid du Colombier 		fprint(2, "lens: can't open /dev/screen: %r\n");
837dd7cddfSDavid du Colombier 		exits("screen");
847dd7cddfSDavid du Colombier 	}
857dd7cddfSDavid du Colombier 	if(read(screenfd, buf, sizeof buf) != sizeof buf){
867dd7cddfSDavid du Colombier 		fprint(2, "lens: can't read /dev/screen: %r\n");
877dd7cddfSDavid du Colombier 		exits("screen");
887dd7cddfSDavid du Colombier 	}
897dd7cddfSDavid du Colombier 	chan = strtochan(buf);
907dd7cddfSDavid du Colombier 	d = chantodepth(chan);
917dd7cddfSDavid du Colombier 	if(d < 8){
927dd7cddfSDavid du Colombier 		fprint(2, "lens: can't handle screen format %11.11s\n", buf);
937dd7cddfSDavid du Colombier 		exits("screen");
947dd7cddfSDavid du Colombier 	}
957dd7cddfSDavid du Colombier 	bypp = d/8;
967dd7cddfSDavid du Colombier 	screenr.min.x = atoi(buf+1*12);
977dd7cddfSDavid du Colombier 	screenr.min.y = atoi(buf+2*12);
987dd7cddfSDavid du Colombier 	screenr.max.x = atoi(buf+3*12);
997dd7cddfSDavid du Colombier 	screenr.max.y = atoi(buf+4*12);
1007dd7cddfSDavid du Colombier 	screenbuf = malloc(bypp*Dx(screenr)*Dy(screenr));
1017dd7cddfSDavid du Colombier 	if(screenbuf == nil){
1027dd7cddfSDavid du Colombier 		fprint(2, "lens: buffer malloc failed: %r\n");
1037dd7cddfSDavid du Colombier 		exits("malloc");
1047dd7cddfSDavid du Colombier 	}
1057dd7cddfSDavid du Colombier 	eresized(0);
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier 	for(;;)
1087dd7cddfSDavid du Colombier 		switch(event(&e)){
1097dd7cddfSDavid du Colombier 		case Ekeyboard:
1107dd7cddfSDavid du Colombier 			switch(e.kbdc){
1117dd7cddfSDavid du Colombier 			case 'q':
112*5e91980fSDavid du Colombier 			case 0x7f:
1137dd7cddfSDavid du Colombier 			case '\04':
114*5e91980fSDavid du Colombier 			caseexit:
1157dd7cddfSDavid du Colombier 				exits(nil);
1167dd7cddfSDavid du Colombier 			case '=':
1177dd7cddfSDavid du Colombier 			case '+':
118*5e91980fSDavid du Colombier 			casezoom:
1197dd7cddfSDavid du Colombier 				if(mag < Maxmag){
1207dd7cddfSDavid du Colombier 					mag++;
1213ff48bf5SDavid du Colombier 					makegrid();
1227dd7cddfSDavid du Colombier 					drawit();
1237dd7cddfSDavid du Colombier 				}
1247dd7cddfSDavid du Colombier 				break;
1253ff48bf5SDavid du Colombier 			case 'g':
126*5e91980fSDavid du Colombier 			casegrid:
1273ff48bf5SDavid du Colombier 				showgrid = !showgrid;
1283ff48bf5SDavid du Colombier 				makegrid();
1293ff48bf5SDavid du Colombier 				drawit();
1303ff48bf5SDavid du Colombier 				break;
1317dd7cddfSDavid du Colombier 			case '-':
1327dd7cddfSDavid du Colombier 			case '_':
133*5e91980fSDavid du Colombier 			caseunzoom:
1347dd7cddfSDavid du Colombier 				if(mag > 1){
1357dd7cddfSDavid du Colombier 					mag--;
1363ff48bf5SDavid du Colombier 					makegrid();
1377dd7cddfSDavid du Colombier 					drawit();
1387dd7cddfSDavid du Colombier 				}
1397dd7cddfSDavid du Colombier 				break;
1407dd7cddfSDavid du Colombier 			case '.':
1417dd7cddfSDavid du Colombier 			case ' ':
142*5e91980fSDavid du Colombier 			caseredraw:
1437dd7cddfSDavid du Colombier 				drawit();
1447dd7cddfSDavid du Colombier 				break;
1457dd7cddfSDavid du Colombier 			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case'0':
1467dd7cddfSDavid du Colombier 				mag = e.kbdc-'0';
1477dd7cddfSDavid du Colombier 				if(mag == 0)
1487dd7cddfSDavid du Colombier 					mag = 10;
1493ff48bf5SDavid du Colombier 				makegrid();
1507dd7cddfSDavid du Colombier 				drawit();
1517dd7cddfSDavid du Colombier 				break;
1527dd7cddfSDavid du Colombier 			}
1537dd7cddfSDavid du Colombier 			break;
1547dd7cddfSDavid du Colombier 		case Emouse:
155*5e91980fSDavid du Colombier 			if(e.mouse.buttons & 1){
1567dd7cddfSDavid du Colombier 				lastp = e.mouse.xy;
1577dd7cddfSDavid du Colombier 				drawit();
1587dd7cddfSDavid du Colombier 			}
159*5e91980fSDavid du Colombier 			if(e.mouse.buttons & 4)
160*5e91980fSDavid du Colombier 				switch(emenuhit(3, &e.mouse, &menu)){
161*5e91980fSDavid du Colombier 				case Mzoom:
162*5e91980fSDavid du Colombier 					goto casezoom;
163*5e91980fSDavid du Colombier 				case Munzoom:
164*5e91980fSDavid du Colombier 					goto caseunzoom;
165*5e91980fSDavid du Colombier 				case Mgrid:
166*5e91980fSDavid du Colombier 					goto casegrid;
167*5e91980fSDavid du Colombier 				case Mredraw:
168*5e91980fSDavid du Colombier 					goto caseredraw;
169*5e91980fSDavid du Colombier 				case Mexit:
170*5e91980fSDavid du Colombier 					goto caseexit;
171*5e91980fSDavid du Colombier 				}
1727dd7cddfSDavid du Colombier 			break;
1737dd7cddfSDavid du Colombier 		}
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier void
makegrid(void)1773ff48bf5SDavid du Colombier makegrid(void)
1783ff48bf5SDavid du Colombier {
1796b6b9ac8SDavid du Colombier 	int m;
1803ff48bf5SDavid du Colombier 	if (grid != nil) {
1813ff48bf5SDavid du Colombier 		freeimage(grid);
1823ff48bf5SDavid du Colombier 		grid = nil;
1833ff48bf5SDavid du Colombier 	}
1843ff48bf5SDavid du Colombier 	if (showgrid) {
1856b6b9ac8SDavid du Colombier 		m = mag;
1866b6b9ac8SDavid du Colombier 		if (m < 5)
1876b6b9ac8SDavid du Colombier 			m *= 10;
1886b6b9ac8SDavid du Colombier 		grid = allocimage(display, Rect(0, 0, m, m),
1893ff48bf5SDavid du Colombier 			CHAN2(CGrey, 8, CAlpha, 8), 1, DTransparent);
1906b6b9ac8SDavid du Colombier 		if (grid != nil){
1916b6b9ac8SDavid du Colombier 			draw(grid, Rect(0, 0, m, 1), chequer, nil, ZP);
1926b6b9ac8SDavid du Colombier 			draw(grid, Rect(0, 1, 1, m), chequer, nil, ZP);
1933ff48bf5SDavid du Colombier 		}
1943ff48bf5SDavid du Colombier 	}
1953ff48bf5SDavid du Colombier }
1963ff48bf5SDavid du Colombier 
1973ff48bf5SDavid du Colombier void
eresized(int new)1987dd7cddfSDavid du Colombier eresized(int new)
1997dd7cddfSDavid du Colombier {
2007dd7cddfSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0){
2017dd7cddfSDavid du Colombier 		fprint(2, "lens: can't reattach to window: %r\n");
2027dd7cddfSDavid du Colombier 		exits("attach");
2037dd7cddfSDavid du Colombier 	}
2047dd7cddfSDavid du Colombier 	freeimage(tmp);
2057dd7cddfSDavid du Colombier 	tmp = allocimage(display, Rect(0, 0, Dx(screen->r)-Edge, Dy(screen->r)-Edge+Maxmag), screen->chan, 0, DNofill);
2067dd7cddfSDavid du Colombier 	if(tmp == nil){
2077dd7cddfSDavid du Colombier 		fprint(2, "lens: allocimage failed: %r\n");
2087dd7cddfSDavid du Colombier 		exits("allocimage");
2097dd7cddfSDavid du Colombier 	}
2107dd7cddfSDavid du Colombier 	drawit();
2117dd7cddfSDavid du Colombier }
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier void
magnify(void)2147dd7cddfSDavid du Colombier magnify(void)
2157dd7cddfSDavid du Colombier {
2167dd7cddfSDavid du Colombier 	int x, y, xx, yy, dd, i;
2177dd7cddfSDavid du Colombier 	int dx, dy;
2187dd7cddfSDavid du Colombier 	int xoff, yoff;
2197dd7cddfSDavid du Colombier 	uchar out[8192];
2207dd7cddfSDavid du Colombier 	uchar sp[4];
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier 	dx = (Dx(tmp->r)+mag-1)/mag;
2237dd7cddfSDavid du Colombier 	dy = (Dy(tmp->r)+mag-1)/mag;
2247dd7cddfSDavid du Colombier 	xoff = lastp.x-Dx(tmp->r)/(mag*2);
2257dd7cddfSDavid du Colombier 	yoff  = lastp.y-Dy(tmp->r)/(mag*2);
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier 	yy = yoff;
2287dd7cddfSDavid du Colombier 	dd = dy;
2297dd7cddfSDavid du Colombier 	if(yy < 0){
2307dd7cddfSDavid du Colombier 		dd += dy;
2317dd7cddfSDavid du Colombier 		yy = 0;
2327dd7cddfSDavid du Colombier 	}
2337dd7cddfSDavid du Colombier 	if(yy+dd > Dy(screenr))
2347dd7cddfSDavid du Colombier 		dd = Dy(screenr)-yy;
2357dd7cddfSDavid du Colombier 	seek(screenfd, 5*12+bypp*yy*Dx(screenr), 0);
2367dd7cddfSDavid du Colombier 	if(readn(screenfd, screenbuf+bypp*yy*Dx(screenr), bypp*Dx(screenr)*dd) != bypp*Dx(screenr)*dd){
2377dd7cddfSDavid du Colombier 		fprint(2, "lens: can't read screen: %r\n");
2387dd7cddfSDavid du Colombier 		return;
2397dd7cddfSDavid du Colombier 	}
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier 	for(y=0; y<dy; y++){
2427dd7cddfSDavid du Colombier 		yy = yoff+y;
2437dd7cddfSDavid du Colombier 		if(yy>=0 && yy<Dy(screenr))
2447dd7cddfSDavid du Colombier 			for(x=0; x<dx; x++){
2457dd7cddfSDavid du Colombier 				xx = xoff+x;
2467dd7cddfSDavid du Colombier 				if(xx>=0 && xx<Dx(screenr))	/* snarf pixel at xx, yy */
2477dd7cddfSDavid du Colombier 					for(i=0; i<bypp; i++)
2487dd7cddfSDavid du Colombier 						sp[i] = screenbuf[bypp*(yy*Dx(screenr)+xx)+i];
2497dd7cddfSDavid du Colombier 				else
2507dd7cddfSDavid du Colombier 					sp[0] = sp[1] = sp[2] = sp[3] = 0;
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier 				for(xx=0; xx<mag; xx++)
2537dd7cddfSDavid du Colombier 					if(x*mag+xx < tmp->r.max.x)
2547dd7cddfSDavid du Colombier 						for(i=0; i<bypp; i++)
2557dd7cddfSDavid du Colombier 							out[(x*mag+xx)*bypp+i] = sp[i];
2567dd7cddfSDavid du Colombier 			}
2577dd7cddfSDavid du Colombier 		else
2587dd7cddfSDavid du Colombier 			memset(out, 0, bypp*Dx(tmp->r));
2597dd7cddfSDavid du Colombier 		for(yy=0; yy<mag && y*mag+yy<Dy(tmp->r); yy++){
2607dd7cddfSDavid du Colombier 			werrstr("no error");
2617dd7cddfSDavid du Colombier 			if(loadimage(tmp, Rect(0, y*mag+yy, Dx(tmp->r), y*mag+yy+1), out, bypp*Dx(tmp->r)) != bypp*Dx(tmp->r)){
2627dd7cddfSDavid du Colombier 				exits("load");
2637dd7cddfSDavid du Colombier 			}
2647dd7cddfSDavid du Colombier 		}
2657dd7cddfSDavid du Colombier 	}
2666b6b9ac8SDavid du Colombier 	if (showgrid && mag && grid)
2676b6b9ac8SDavid du Colombier 		draw(tmp, tmp->r, grid, nil, mulpt(Pt(xoff, yoff), mag));
2687dd7cddfSDavid du Colombier }
269