http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.30.tar.gz
[xscreensaver] / hacks / rotzoomer.c
1 /* rotzoomer - creates a collage of rotated and scaled portions of the screen
2  * Copyright (C) 2001 Claudio Matsuoka <claudio@helllabs.org>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or
10  * implied warranty.
11  */
12
13 #include <math.h>
14 #include "screenhack.h"
15 #include <X11/Xutil.h>
16
17 #ifdef HAVE_XSHM_EXTENSION
18 #include "xshm.h"
19 static Bool use_shm;
20 static XShmSegmentInfo shm_info;
21 #endif
22
23 struct zoom_area {
24         int w, h;               /* rectangle width and height */
25         int inc1, inc2;         /* rotation and zoom angle increments */
26         int dx, dy;             /* translation increments */
27         int a1, a2;             /* rotation and zoom angular variables */
28         int ox, oy;             /* origin in the background copy */
29         int xx, yy;             /* left-upper corner position (* 256) */
30         int x, y;               /* left-upper corner position */
31         int ww, hh;             /* valid area to place left-upper corner */
32         int n;                  /* number of iteractions */
33 };
34
35 static Window window;
36 static Display *display;
37 static GC gc;
38 static Visual *visual;
39 static XImage *orig_map, *buffer_map;
40 static Colormap colormap;
41
42 static int width, height;
43 static struct zoom_area **zoom_box;
44 static int num_zoom = 2;
45 static int move = 1;
46 static int delay = 0;
47
48
49 static void rotzoom (struct zoom_area *za)
50 {
51         int x, y, c, s, zoom, z;
52         int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
53         int ox = 0, oy = 0;
54
55         z = 8100 * sin (M_PI * za->a2 / 8192);
56         zoom = 8192 + z;
57
58         c = zoom * cos (M_PI * za->a1 / 8192);
59         s = zoom * sin (M_PI * za->a1 / 8192);
60         for (y = za->y; y <= y2; y++) {
61                 for (x = za->x; x <= x2; x++) {
62                         ox = (x * c + y * s) >> 13;
63                         oy = (-x * s + y * c) >> 13;
64
65                         while (ox < 0)
66                                 ox += width;
67                         while (oy < 0)
68                                 oy += height;
69                         while (ox >= width)
70                                 ox -= width;
71                         while (oy >= height)
72                                 oy -= height;
73
74                         XPutPixel (buffer_map, x, y, XGetPixel (orig_map, ox, oy));
75                 }
76         }
77
78         za->a1 += za->inc1;             /* Rotation angle */
79         za->a1 &= 0x3fff;;
80
81         za->a2 += za->inc2;             /* Zoom */
82         za->a2 &= 0x3fff;
83
84         za->ox = ox;                    /* Save state for next iteration */
85         za->oy = oy;
86 }
87
88
89 static void reset_zoom (struct zoom_area *za)
90 {
91         za->w = 50 + random() % 300;
92         za->h = 50 + random() % 300;
93
94         if (za->w > width / 3)
95                 za->w = width / 3;
96
97         if (za->h > height / 3)
98                 za->h = height / 3;
99
100         za->ww = width - za->w;
101         za->hh = height - za->h;
102
103         za->x = (random() % za->ww);
104         za->y = (random() % za->hh);
105         za->xx = za->x * 256;
106         za->yy = za->y * 256;
107
108         za->a1 = 0;
109         za->a2 = 0;
110         za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
111         za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
112         za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
113         za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
114         za->n = 50 + random() % 1000;
115 }
116
117
118 static struct zoom_area *create_zoom (void)
119 {
120         struct zoom_area *za;
121
122         za = malloc (sizeof (struct zoom_area));
123         reset_zoom (za);
124
125         return za;
126 }
127
128
129 static void update_position (struct zoom_area *za)
130 {
131         za->xx += za->dx;
132         za->yy += za->dy;
133
134         za->x = za->xx >> 8;
135         za->y = za->yy >> 8;
136
137         if (za->x < 0) {
138                 za->x = 0;
139                 za->dx = 100 + random() % 100;
140         }
141                 
142         if (za->y < 0) {
143                 za->y = 0;
144                 za->dy = 100 + random() % 100;
145         }
146                 
147         if (za->x > za->ww) {
148                 za->x = za->ww;
149                 za->dx = -(100 + random() % 100);
150         }
151
152         if (za->y > za->hh) {
153                 za->y = za->hh;
154                 za->dy = -(100 + random() % 100);
155         }
156 }
157
158
159 static void DisplayImage (int x, int y, int w, int h)
160 {
161 #ifdef HAVE_XSHM_EXTENSION
162         if (use_shm)
163                 XShmPutImage (display, window, gc, buffer_map, x, y, x, y,
164                         w, h, False);
165         else
166 #endif /* HAVE_XSHM_EXTENSION */
167                 XPutImage(display, window, gc, buffer_map, x, y, x, y, w, h);
168 }
169
170
171 static void hack_main (void)
172 {
173         int i;
174
175         for (i = 0; i < num_zoom; i++) {
176                 if (move)
177                         update_position (zoom_box[i]);
178
179                 if (zoom_box[i]->n) {
180                         rotzoom (zoom_box[i]);
181                         zoom_box[i]->n--;
182                 } else {
183                         reset_zoom (zoom_box[i]);
184                 }
185         }
186
187         for (i = 0; i < num_zoom; i++) {
188                 DisplayImage(zoom_box[i]->x, zoom_box[i]->y,
189                         zoom_box[i]->w, zoom_box[i]->h);
190         }
191
192         XSync(display,False);
193         screenhack_handle_events(display);
194 }
195
196
197 static void init_hack (void)
198 {
199         int i;
200
201         zoom_box = calloc (num_zoom, sizeof (struct zoom_area *));
202         for (i = 0; i < num_zoom; i++) {
203                 zoom_box[i] = create_zoom ();
204         }
205
206         memcpy (buffer_map->data, orig_map->data,
207                 height * buffer_map->bytes_per_line);
208
209         DisplayImage(0, 0, width, height);
210         XSync(display,False);
211 }
212
213
214 static void setup_X (Display * disp, Window win)
215 {
216         XWindowAttributes xwa;
217         int depth;
218         XGCValues gcv;
219         long gcflags;
220
221         XGetWindowAttributes (disp, win, &xwa);
222         window = win;
223         display = disp;
224         depth = xwa.depth;
225         colormap = xwa.colormap;
226         width = xwa.width;
227         height = xwa.height;
228         visual = xwa.visual;
229
230         if (width % 2)
231                 width++;
232         if (height % 2)
233                 height++;
234
235         gcv.function = GXcopy;
236         gcv.subwindow_mode = IncludeInferiors;
237         gcflags = GCForeground | GCFunction;
238         if (use_subwindow_mode_p (xwa.screen, window))  /* see grabscreen.c */
239                 gcflags |= GCSubwindowMode;
240         gc = XCreateGC (display, window, gcflags, &gcv);
241         grab_screen_image (xwa.screen, window);
242
243         orig_map = XGetImage (display, window, 0, 0, width, height, ~0L, ZPixmap);
244
245         if (!gc) {
246                 fprintf(stderr, "XCreateGC failed\n");
247                 exit(1);
248         }
249
250         buffer_map = 0;
251
252 #ifdef HAVE_XSHM_EXTENSION
253         if (use_shm) {
254                 buffer_map = create_xshm_image(display, xwa.visual, depth,
255                         ZPixmap, 0, &shm_info, width, height);
256                 if (!buffer_map) {
257                         use_shm = False;
258                         fprintf(stderr, "create_xshm_image failed\n");
259                 }
260         }
261 #endif /* HAVE_XSHM_EXTENSION */
262
263         if (!buffer_map) {
264                 buffer_map = XCreateImage(display, xwa.visual,
265                         depth, ZPixmap, 0, 0, width, height, 8, 0);
266                 buffer_map->data = (char *)calloc (buffer_map->height,
267                         buffer_map->bytes_per_line);
268         }
269 }
270
271
272
273 char *progclass = "Rotzoomer";
274
275 char *defaults[] = {
276 #ifdef HAVE_XSHM_EXTENSION
277         "*useSHM: True",
278 #endif
279         "*delay: 10000",
280         "*move: False",
281         "*numboxes: 2",
282         0
283 };
284
285
286 XrmOptionDescRec options[] = {
287 #ifdef HAVE_XSHM_EXTENSION
288         { "-shm",       ".useSHM",      XrmoptionNoArg, "True" },
289         { "-no-shm",    ".useSHM",      XrmoptionNoArg, "False" },
290 #endif
291         { "-move",      ".move",        XrmoptionNoArg, "True"},
292         { "-no-move",   ".move",        XrmoptionNoArg, "False"},
293         { "-delay",     ".delay",       XrmoptionSepArg, 0},
294         { "-n",         ".numboxes",    XrmoptionSepArg, 0},
295         { 0, 0, 0, 0 }
296 };
297
298
299 void screenhack(Display *disp, Window win)
300 {
301 #ifdef HAVE_XSHM_EXTENSION
302         use_shm = get_boolean_resource ("useSHM", "Boolean");
303 #endif
304         num_zoom = get_integer_resource("numboxes", "Integer");
305         move = get_boolean_resource("move", "Boolean");
306         delay = get_integer_resource("delay", "Integer");
307
308         setup_X (disp, win);
309
310         init_hack ();
311
312         /* Main drawing loop */
313         while (42) {
314                 hack_main ();
315                 usleep (delay);
316         }
317 }