]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/lens.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / lens.c
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 }