2011-03-30 12:46:40 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <draw.h>
|
|
|
|
#include <event.h>
|
2014-12-13 20:58:49 +00:00
|
|
|
#include <keyboard.h>
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
Edge = 5,
|
|
|
|
Maxmag = 16
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
Mzoom,
|
|
|
|
Munzoom,
|
|
|
|
Mgrid,
|
|
|
|
Mredraw,
|
|
|
|
Mexit
|
|
|
|
};
|
|
|
|
|
|
|
|
char *menustr[] = {
|
|
|
|
"zoom",
|
|
|
|
"unzoom",
|
|
|
|
"grid",
|
|
|
|
"redraw",
|
|
|
|
"exit",
|
|
|
|
nil
|
|
|
|
};
|
|
|
|
|
|
|
|
Menu menu = {
|
|
|
|
menustr,
|
|
|
|
nil,
|
|
|
|
-1
|
|
|
|
};
|
|
|
|
|
|
|
|
Point lastp;
|
|
|
|
Image *red;
|
|
|
|
Image *tmp;
|
|
|
|
Image *grid;
|
|
|
|
Image *chequer;
|
|
|
|
int screenfd;
|
|
|
|
int mag = 4;
|
|
|
|
int showgrid = 0;
|
|
|
|
Rectangle screenr;
|
|
|
|
uchar *screenbuf;
|
|
|
|
|
|
|
|
void magnify(void);
|
|
|
|
void makegrid(void);
|
|
|
|
|
|
|
|
void
|
|
|
|
drawit(void)
|
|
|
|
{
|
|
|
|
Rectangle r;
|
|
|
|
border(screen, screen->r, Edge, red, ZP);
|
|
|
|
magnify();
|
|
|
|
r = insetrect(screen->r, Edge);
|
|
|
|
draw(screen, r, tmp, nil, tmp->r.min);
|
|
|
|
flushimage(display, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int bypp;
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
Event e;
|
|
|
|
char buf[5*12];
|
|
|
|
ulong chan;
|
|
|
|
int d;
|
|
|
|
|
|
|
|
USED(argc, argv);
|
|
|
|
if(initdraw(nil, nil, "lens") < 0){
|
|
|
|
fprint(2, "lens: initdraw failed: %r\n");
|
|
|
|
exits("initdraw");
|
|
|
|
}
|
|
|
|
einit(Emouse|Ekeyboard);
|
|
|
|
red = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, DRed);
|
|
|
|
chequer = allocimage(display, Rect(0, 0, 2, 2), GREY1, 1, DBlack);
|
|
|
|
draw(chequer, Rect(0, 0, 1, 1), display->white, nil, ZP);
|
|
|
|
draw(chequer, Rect(1, 1, 2, 2), display->white, nil, ZP);
|
|
|
|
lastp = divpt(addpt(screen->r.min, screen->r.max), 2);
|
|
|
|
screenfd = open("/dev/screen", OREAD);
|
|
|
|
if(screenfd < 0){
|
|
|
|
fprint(2, "lens: can't open /dev/screen: %r\n");
|
|
|
|
exits("screen");
|
|
|
|
}
|
|
|
|
if(read(screenfd, buf, sizeof buf) != sizeof buf){
|
|
|
|
fprint(2, "lens: can't read /dev/screen: %r\n");
|
|
|
|
exits("screen");
|
|
|
|
}
|
|
|
|
chan = strtochan(buf);
|
|
|
|
d = chantodepth(chan);
|
|
|
|
if(d < 8){
|
|
|
|
fprint(2, "lens: can't handle screen format %11.11s\n", buf);
|
|
|
|
exits("screen");
|
|
|
|
}
|
|
|
|
bypp = d/8;
|
|
|
|
screenr.min.x = atoi(buf+1*12);
|
|
|
|
screenr.min.y = atoi(buf+2*12);
|
|
|
|
screenr.max.x = atoi(buf+3*12);
|
|
|
|
screenr.max.y = atoi(buf+4*12);
|
|
|
|
screenbuf = malloc(bypp*Dx(screenr)*Dy(screenr));
|
|
|
|
if(screenbuf == nil){
|
|
|
|
fprint(2, "lens: buffer malloc failed: %r\n");
|
|
|
|
exits("malloc");
|
|
|
|
}
|
|
|
|
eresized(0);
|
|
|
|
|
|
|
|
for(;;)
|
|
|
|
switch(event(&e)){
|
|
|
|
case Ekeyboard:
|
|
|
|
switch(e.kbdc){
|
|
|
|
case 'q':
|
2014-12-13 20:58:49 +00:00
|
|
|
case Kdel:
|
|
|
|
case Keof:
|
2011-03-30 12:46:40 +00:00
|
|
|
caseexit:
|
|
|
|
exits(nil);
|
|
|
|
case '=':
|
|
|
|
case '+':
|
|
|
|
casezoom:
|
|
|
|
if(mag < Maxmag){
|
|
|
|
mag++;
|
|
|
|
makegrid();
|
|
|
|
drawit();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
casegrid:
|
|
|
|
showgrid = !showgrid;
|
|
|
|
makegrid();
|
|
|
|
drawit();
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
case '_':
|
|
|
|
caseunzoom:
|
|
|
|
if(mag > 1){
|
|
|
|
mag--;
|
|
|
|
makegrid();
|
|
|
|
drawit();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '.':
|
|
|
|
case ' ':
|
|
|
|
caseredraw:
|
|
|
|
drawit();
|
|
|
|
break;
|
|
|
|
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case'0':
|
|
|
|
mag = e.kbdc-'0';
|
|
|
|
if(mag == 0)
|
|
|
|
mag = 10;
|
|
|
|
makegrid();
|
|
|
|
drawit();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Emouse:
|
|
|
|
if(e.mouse.buttons & 1){
|
|
|
|
lastp = e.mouse.xy;
|
|
|
|
drawit();
|
|
|
|
}
|
|
|
|
if(e.mouse.buttons & 4)
|
|
|
|
switch(emenuhit(3, &e.mouse, &menu)){
|
|
|
|
case Mzoom:
|
|
|
|
goto casezoom;
|
|
|
|
case Munzoom:
|
|
|
|
goto caseunzoom;
|
|
|
|
case Mgrid:
|
|
|
|
goto casegrid;
|
|
|
|
case Mredraw:
|
|
|
|
goto caseredraw;
|
|
|
|
case Mexit:
|
|
|
|
goto caseexit;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
makegrid(void)
|
|
|
|
{
|
|
|
|
int m;
|
|
|
|
if (grid != nil) {
|
|
|
|
freeimage(grid);
|
|
|
|
grid = nil;
|
|
|
|
}
|
|
|
|
if (showgrid) {
|
|
|
|
m = mag;
|
|
|
|
if (m < 5)
|
|
|
|
m *= 10;
|
|
|
|
grid = allocimage(display, Rect(0, 0, m, m),
|
|
|
|
CHAN2(CGrey, 8, CAlpha, 8), 1, DTransparent);
|
|
|
|
if (grid != nil){
|
|
|
|
draw(grid, Rect(0, 0, m, 1), chequer, nil, ZP);
|
|
|
|
draw(grid, Rect(0, 1, 1, m), chequer, nil, ZP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eresized(int new)
|
|
|
|
{
|
|
|
|
if(new && getwindow(display, Refnone) < 0){
|
|
|
|
fprint(2, "lens: can't reattach to window: %r\n");
|
|
|
|
exits("attach");
|
|
|
|
}
|
|
|
|
freeimage(tmp);
|
|
|
|
tmp = allocimage(display, Rect(0, 0, Dx(screen->r)-Edge, Dy(screen->r)-Edge+Maxmag), screen->chan, 0, DNofill);
|
|
|
|
if(tmp == nil){
|
|
|
|
fprint(2, "lens: allocimage failed: %r\n");
|
|
|
|
exits("allocimage");
|
|
|
|
}
|
|
|
|
drawit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
magnify(void)
|
|
|
|
{
|
|
|
|
int x, y, xx, yy, dd, i;
|
|
|
|
int dx, dy;
|
|
|
|
int xoff, yoff;
|
|
|
|
uchar out[8192];
|
|
|
|
uchar sp[4];
|
|
|
|
|
|
|
|
dx = (Dx(tmp->r)+mag-1)/mag;
|
|
|
|
dy = (Dy(tmp->r)+mag-1)/mag;
|
|
|
|
xoff = lastp.x-Dx(tmp->r)/(mag*2);
|
|
|
|
yoff = lastp.y-Dy(tmp->r)/(mag*2);
|
|
|
|
|
|
|
|
yy = yoff;
|
|
|
|
dd = dy;
|
|
|
|
if(yy < 0){
|
|
|
|
dd += dy;
|
|
|
|
yy = 0;
|
|
|
|
}
|
|
|
|
if(yy+dd > Dy(screenr))
|
|
|
|
dd = Dy(screenr)-yy;
|
|
|
|
seek(screenfd, 5*12+bypp*yy*Dx(screenr), 0);
|
|
|
|
if(readn(screenfd, screenbuf+bypp*yy*Dx(screenr), bypp*Dx(screenr)*dd) != bypp*Dx(screenr)*dd){
|
|
|
|
fprint(2, "lens: can't read screen: %r\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(y=0; y<dy; y++){
|
|
|
|
yy = yoff+y;
|
|
|
|
if(yy>=0 && yy<Dy(screenr))
|
|
|
|
for(x=0; x<dx; x++){
|
|
|
|
xx = xoff+x;
|
|
|
|
if(xx>=0 && xx<Dx(screenr)) /* snarf pixel at xx, yy */
|
|
|
|
for(i=0; i<bypp; i++)
|
|
|
|
sp[i] = screenbuf[bypp*(yy*Dx(screenr)+xx)+i];
|
|
|
|
else
|
|
|
|
sp[0] = sp[1] = sp[2] = sp[3] = 0;
|
|
|
|
|
|
|
|
for(xx=0; xx<mag; xx++)
|
|
|
|
if(x*mag+xx < tmp->r.max.x)
|
|
|
|
for(i=0; i<bypp; i++)
|
|
|
|
out[(x*mag+xx)*bypp+i] = sp[i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
memset(out, 0, bypp*Dx(tmp->r));
|
|
|
|
for(yy=0; yy<mag && y*mag+yy<Dy(tmp->r); yy++){
|
|
|
|
werrstr("no error");
|
|
|
|
if(loadimage(tmp, Rect(0, y*mag+yy, Dx(tmp->r), y*mag+yy+1), out, bypp*Dx(tmp->r)) != bypp*Dx(tmp->r)){
|
|
|
|
exits("load");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (showgrid && mag && grid)
|
|
|
|
draw(tmp, tmp->r, grid, nil, mulpt(Pt(xoff, yoff), mag));
|
|
|
|
}
|