Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <event.h>
5
 
6
enum {
7
	Edge = 5,
8
	Maxmag = 16
9
};
10
 
11
enum {
12
	Mzoom,
13
	Munzoom,
14
	Mgrid,
15
	Mredraw,
16
	Mexit
17
};
18
 
19
char *menustr[] = {
20
	"zoom",
21
	"unzoom",
22
	"grid",
23
	"redraw",
24
	"exit",
25
	nil
26
};
27
 
28
Menu menu = {
29
	menustr,
30
	nil,
31
	-1
32
};
33
 
34
Point lastp;
35
Image *red;
36
Image *tmp;
37
Image *grid;
38
Image *chequer;
39
int	screenfd;
40
int	mag = 4;
41
int	showgrid = 0;
42
Rectangle	screenr;
43
uchar	*screenbuf;
44
 
45
void	magnify(void);
46
void makegrid(void);
47
 
48
void
49
drawit(void)
50
{
51
	Rectangle r;
52
	border(screen, screen->r, Edge, red, ZP);
53
	magnify();
54
	r = insetrect(screen->r, Edge);
55
	draw(screen, r, tmp, nil, tmp->r.min);
56
	flushimage(display, 1);
57
}
58
 
59
int bypp;
60
 
61
void
62
main(int argc, char *argv[])
63
{
64
	Event e;
65
	char buf[5*12];
66
	ulong chan;
67
	int d;
68
 
69
	USED(argc, argv);
70
	if(initdraw(nil, nil, "lens") < 0){
71
		fprint(2, "lens: initdraw failed: %r\n");
72
		exits("initdraw");
73
	}
74
	einit(Emouse|Ekeyboard);
75
	red = allocimage(display, Rect(0, 0, 1, 1), CMAP8, 1, DRed);
76
	chequer = allocimage(display, Rect(0, 0, 2, 2), GREY1, 1, DBlack);
77
	draw(chequer, Rect(0, 0, 1, 1), display->white, nil, ZP);
78
	draw(chequer, Rect(1, 1, 2, 2), display->white, nil, ZP);
79
	lastp = divpt(addpt(screen->r.min, screen->r.max), 2);
80
	screenfd = open("/dev/screen", OREAD);
81
	if(screenfd < 0){
82
		fprint(2, "lens: can't open /dev/screen: %r\n");
83
		exits("screen");
84
	}
85
	if(read(screenfd, buf, sizeof buf) != sizeof buf){
86
		fprint(2, "lens: can't read /dev/screen: %r\n");
87
		exits("screen");
88
	}
89
	chan = strtochan(buf);
90
	d = chantodepth(chan);
91
	if(d < 8){
92
		fprint(2, "lens: can't handle screen format %11.11s\n", buf);
93
		exits("screen");
94
	}
95
	bypp = d/8;
96
	screenr.min.x = atoi(buf+1*12);
97
	screenr.min.y = atoi(buf+2*12);
98
	screenr.max.x = atoi(buf+3*12);
99
	screenr.max.y = atoi(buf+4*12);
100
	screenbuf = malloc(bypp*Dx(screenr)*Dy(screenr));
101
	if(screenbuf == nil){
102
		fprint(2, "lens: buffer malloc failed: %r\n");
103
		exits("malloc");
104
	}
105
	eresized(0);
106
 
107
	for(;;)
108
		switch(event(&e)){
109
		case Ekeyboard:
110
			switch(e.kbdc){
111
			case 'q':
112
			case 0x7f:
113
			case '\04':
114
			caseexit:
115
				exits(nil);
116
			case '=':
117
			case '+':
118
			casezoom:
119
				if(mag < Maxmag){
120
					mag++;
121
					makegrid();
122
					drawit();
123
				}
124
				break;
125
			case 'g':
126
			casegrid:
127
				showgrid = !showgrid;
128
				makegrid();
129
				drawit();
130
				break;
131
			case '-':
132
			case '_':
133
			caseunzoom:
134
				if(mag > 1){
135
					mag--;
136
					makegrid();
137
					drawit();
138
				}
139
				break;
140
			case '.':
141
			case ' ':
142
			caseredraw:
143
				drawit();
144
				break;
145
			case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case'0':
146
				mag = e.kbdc-'0';
147
				if(mag == 0)
148
					mag = 10;
149
				makegrid();
150
				drawit();
151
				break;
152
			}
153
			break;
154
		case Emouse:
155
			if(e.mouse.buttons & 1){
156
				lastp = e.mouse.xy;
157
				drawit();
158
			}
159
			if(e.mouse.buttons & 4)
160
				switch(emenuhit(3, &e.mouse, &menu)){
161
				case Mzoom:
162
					goto casezoom;
163
				case Munzoom:
164
					goto caseunzoom;
165
				case Mgrid:
166
					goto casegrid;
167
				case Mredraw:
168
					goto caseredraw;
169
				case Mexit:
170
					goto caseexit;
171
				}
172
			break;
173
		}
174
}
175
 
176
void
177
makegrid(void)
178
{
179
	int m;
180
	if (grid != nil) {
181
		freeimage(grid);
182
		grid = nil;
183
	}
184
	if (showgrid) {
185
		m = mag;
186
		if (m < 5)
187
			m *= 10;
188
		grid = allocimage(display, Rect(0, 0, m, m),
189
			CHAN2(CGrey, 8, CAlpha, 8), 1, DTransparent);
190
		if (grid != nil){
191
			draw(grid, Rect(0, 0, m, 1), chequer, nil, ZP);
192
			draw(grid, Rect(0, 1, 1, m), chequer, nil, ZP);
193
		}
194
	}
195
}
196
 
197
void
198
eresized(int new)
199
{
200
	if(new && getwindow(display, Refnone) < 0){
201
		fprint(2, "lens: can't reattach to window: %r\n");
202
		exits("attach");
203
	}
204
	freeimage(tmp);
205
	tmp = allocimage(display, Rect(0, 0, Dx(screen->r)-Edge, Dy(screen->r)-Edge+Maxmag), screen->chan, 0, DNofill);
206
	if(tmp == nil){
207
		fprint(2, "lens: allocimage failed: %r\n");
208
		exits("allocimage");
209
	}
210
	drawit();
211
}
212
 
213
void
214
magnify(void)
215
{
216
	int x, y, xx, yy, dd, i;
217
	int dx, dy;
218
	int xoff, yoff;
219
	uchar out[8192];
220
	uchar sp[4];
221
 
222
	dx = (Dx(tmp->r)+mag-1)/mag;
223
	dy = (Dy(tmp->r)+mag-1)/mag;
224
	xoff = lastp.x-Dx(tmp->r)/(mag*2);
225
	yoff  = lastp.y-Dy(tmp->r)/(mag*2);
226
 
227
	yy = yoff;
228
	dd = dy;
229
	if(yy < 0){
230
		dd += dy;
231
		yy = 0;
232
	}
233
	if(yy+dd > Dy(screenr))
234
		dd = Dy(screenr)-yy;
235
	seek(screenfd, 5*12+bypp*yy*Dx(screenr), 0);
236
	if(readn(screenfd, screenbuf+bypp*yy*Dx(screenr), bypp*Dx(screenr)*dd) != bypp*Dx(screenr)*dd){
237
		fprint(2, "lens: can't read screen: %r\n");
238
		return;
239
	}
240
 
241
	for(y=0; y<dy; y++){
242
		yy = yoff+y;
243
		if(yy>=0 && yy<Dy(screenr))
244
			for(x=0; x<dx; x++){
245
				xx = xoff+x;
246
				if(xx>=0 && xx<Dx(screenr))	/* snarf pixel at xx, yy */
247
					for(i=0; i<bypp; i++)
248
						sp[i] = screenbuf[bypp*(yy*Dx(screenr)+xx)+i];
249
				else
250
					sp[0] = sp[1] = sp[2] = sp[3] = 0;
251
 
252
				for(xx=0; xx<mag; xx++)
253
					if(x*mag+xx < tmp->r.max.x)
254
						for(i=0; i<bypp; i++)
255
							out[(x*mag+xx)*bypp+i] = sp[i];
256
			}
257
		else
258
			memset(out, 0, bypp*Dx(tmp->r));
259
		for(yy=0; yy<mag && y*mag+yy<Dy(tmp->r); yy++){
260
			werrstr("no error");
261
			if(loadimage(tmp, Rect(0, y*mag+yy, Dx(tmp->r), y*mag+yy+1), out, bypp*Dx(tmp->r)) != bypp*Dx(tmp->r)){
262
				exits("load");
263
			}
264
		}
265
	}
266
	if (showgrid && mag && grid)
267
		draw(tmp, tmp->r, grid, nil, mulpt(Pt(xoff, yoff), mag));
268
}