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