source: trunk/third/xscreensaver/hacks/rotzoomer.c @ 20148

Revision 20148, 8.8 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
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/*
14 * Options:
15 *
16 * -shm         enable MIT shared memory extension
17 * -no-shm      disable MIT shared memory extension
18 * -n <num>     number of zoomboxes
19 * -move        enable mobile zoomboxes
20 * -sweep       enable sweep mode
21 * -anim        enable snapshot mode
22 * -no-anim     enable snapshot mode
23 * -delay       delay in milliseconds
24 */
25
26#include <math.h>
27#include "screenhack.h"
28#include <X11/Xutil.h>
29
30#ifdef HAVE_XSHM_EXTENSION
31#include "xshm.h"
32static Bool use_shm;
33static XShmSegmentInfo shm_info;
34#endif
35
36struct zoom_area {
37        int w, h;               /* rectangle width and height */
38        int inc1, inc2;         /* rotation and zoom angle increments */
39        int dx, dy;             /* translation increments */
40        int a1, a2;             /* rotation and zoom angular variables */
41        int ox, oy;             /* origin in the background copy */
42        int xx, yy;             /* left-upper corner position (* 256) */
43        int x, y;               /* left-upper corner position */
44        int ww, hh;             /* valid area to place left-upper corner */
45        int n;                  /* number of iteractions */
46        int count;              /* current iteraction */
47};
48
49static Window window;
50static Display *display;
51static GC gc;
52static Visual *visual;
53static XImage *orig_map, *buffer_map;
54static Colormap colormap;
55
56static int width, height;
57static struct zoom_area **zoom_box;
58static int num_zoom = 2;
59static int move = 0;
60static int sweep = 0;
61static int delay = 10;
62static int anim = 1;
63
64
65static void rotzoom (struct zoom_area *za)
66{
67        int x, y, c, s, zoom, z;
68        int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
69        int ox = 0, oy = 0;
70
71        z = 8100 * sin (M_PI * za->a2 / 8192);
72        zoom = 8192 + z;
73
74        c = zoom * cos (M_PI * za->a1 / 8192);
75        s = zoom * sin (M_PI * za->a1 / 8192);
76        for (y = za->y; y <= y2; y++) {
77                for (x = za->x; x <= x2; x++) {
78                        ox = (x * c + y * s) >> 13;
79                        oy = (-x * s + y * c) >> 13;
80
81                        while (ox < 0)
82                                ox += width;
83                        while (oy < 0)
84                                oy += height;
85                        while (ox >= width)
86                                ox -= width;
87                        while (oy >= height)
88                                oy -= height;
89
90                        XPutPixel (buffer_map, x, y, XGetPixel (orig_map, ox, oy));
91                }
92        }
93
94        za->a1 += za->inc1;             /* Rotation angle */
95        za->a1 &= 0x3fff;;
96
97        za->a2 += za->inc2;             /* Zoom */
98        za->a2 &= 0x3fff;
99
100        za->ox = ox;                    /* Save state for next iteration */
101        za->oy = oy;
102
103        za->count++;
104}
105
106
107static void reset_zoom (struct zoom_area *za)
108{
109        if (sweep) {
110                int speed = random () % 100 + 100;
111                switch (random () % 4) {
112                case 0:
113                        za->w = width;
114                        za->h = 10;
115                        za->x = 0;
116                        za->y = 0;
117                        za->dx = 0;
118                        za->dy = speed;
119                        za->n = (height - 10) * 256 / speed;
120                        break;
121                case 1:
122                        za->w = 10;
123                        za->h = height;
124                        za->x = width - 10;
125                        za->y = 0;
126                        za->dx = -speed;
127                        za->dy = 0;
128                        za->n = (width - 10) * 256 / speed;
129                        break;
130                case 2:
131                        za->w = width;
132                        za->h = 10;
133                        za->x = 0;
134                        za->y = height - 10;
135                        za->dx = 0;
136                        za->dy = -speed;
137                        za->n = (height - 10) * 256 / speed;
138                        break;
139                case 3:
140                        za->w = 10;
141                        za->h = height;
142                        za->x = 0;
143                        za->y = 0;
144                        za->dx = speed;
145                        za->dy = 0;
146                        za->n = (width - 10) * 256 / speed;
147                        break;
148                }
149                za->ww = width - za->w;
150                za->hh = height - za->h;
151
152                /* We want smaller angle increments in sweep mode (looks better) */
153
154                za->a1 = 0;
155                za->a2 = 0;
156                za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
157                za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
158        } else {
159                za->w = 50 + random() % 300;
160                za->h = 50 + random() % 300;
161
162                if (za->w > width / 3)
163                        za->w = width / 3;
164                if (za->h > height / 3)
165                        za->h = height / 3;
166
167                za->ww = width - za->w;
168                za->hh = height - za->h;
169
170                za->x = (random() % za->ww);
171                za->y = (random() % za->hh);
172
173                za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
174                za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
175
176                if (anim) {
177                        za->n = 50 + random() % 1000;
178                        za->a1 = 0;
179                        za->a2 = 0;
180                } else {
181                        za->n = 5 + random() % 10;
182                        za->a1 = random ();
183                        za->a2 = random ();
184                }
185
186                za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
187                za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
188        }
189
190        za->xx = za->x * 256;
191        za->yy = za->y * 256;
192
193        za->count = 0;
194}
195
196
197static struct zoom_area *create_zoom (void)
198{
199        struct zoom_area *za;
200
201        za = malloc (sizeof (struct zoom_area));
202        reset_zoom (za);
203
204        return za;
205}
206
207
208static void update_position (struct zoom_area *za)
209{
210        za->xx += za->dx;
211        za->yy += za->dy;
212
213        za->x = za->xx >> 8;
214        za->y = za->yy >> 8;
215
216        if (za->x < 0) {
217                za->x = 0;
218                za->dx = 100 + random() % 100;
219        }
220               
221        if (za->y < 0) {
222                za->y = 0;
223                za->dy = 100 + random() % 100;
224        }
225               
226        if (za->x > za->ww) {
227                za->x = za->ww;
228                za->dx = -(100 + random() % 100);
229        }
230
231        if (za->y > za->hh) {
232                za->y = za->hh;
233                za->dy = -(100 + random() % 100);
234        }
235}
236
237
238static void DisplayImage (int x, int y, int w, int h)
239{
240#ifdef HAVE_XSHM_EXTENSION
241        if (use_shm)
242                XShmPutImage (display, window, gc, buffer_map, x, y, x, y,
243                        w, h, False);
244        else
245#endif /* HAVE_XSHM_EXTENSION */
246                XPutImage(display, window, gc, buffer_map, x, y, x, y, w, h);
247}
248
249
250static void hack_main (void)
251{
252        int i;
253
254        for (i = 0; i < num_zoom; i++) {
255                if (move || sweep)
256                        update_position (zoom_box[i]);
257
258                if (zoom_box[i]->n > 0) {
259                        if (anim || zoom_box[i]->count == 0) {
260                                rotzoom (zoom_box[i]);
261                        } else {
262                                sleep (1);
263                        }
264                        zoom_box[i]->n--;
265                } else {
266                        reset_zoom (zoom_box[i]);
267                }
268        }
269
270        for (i = 0; i < num_zoom; i++) {
271                DisplayImage(zoom_box[i]->x, zoom_box[i]->y,
272                        zoom_box[i]->w, zoom_box[i]->h);
273        }
274
275        XSync(display,False);
276        screenhack_handle_events(display);
277}
278
279
280static void init_hack (void)
281{
282        int i;
283
284        zoom_box = calloc (num_zoom, sizeof (struct zoom_area *));
285        for (i = 0; i < num_zoom; i++) {
286                zoom_box[i] = create_zoom ();
287        }
288
289        memcpy (buffer_map->data, orig_map->data,
290                height * buffer_map->bytes_per_line);
291
292        DisplayImage(0, 0, width, height);
293        XSync(display,False);
294}
295
296
297static void setup_X (Display * disp, Window win)
298{
299        XWindowAttributes xwa;
300        int depth;
301        XGCValues gcv;
302        long gcflags;
303
304        XGetWindowAttributes (disp, win, &xwa);
305        window = win;
306        display = disp;
307        depth = xwa.depth;
308        colormap = xwa.colormap;
309        width = xwa.width;
310        height = xwa.height;
311        visual = xwa.visual;
312
313        if (width % 2)
314                width--;
315        if (height % 2)
316                height--;
317
318        gcv.function = GXcopy;
319        gcv.subwindow_mode = IncludeInferiors;
320        gcflags = GCForeground | GCFunction;
321        if (use_subwindow_mode_p (xwa.screen, window))  /* see grabscreen.c */
322                gcflags |= GCSubwindowMode;
323        gc = XCreateGC (display, window, gcflags, &gcv);
324        load_random_image (xwa.screen, window, window, NULL);
325
326        orig_map = XGetImage (display, window, 0, 0, width, height, ~0L, ZPixmap);
327
328        if (!gc) {
329                fprintf(stderr, "XCreateGC failed\n");
330                exit(1);
331        }
332
333        buffer_map = 0;
334
335#ifdef HAVE_XSHM_EXTENSION
336        if (use_shm) {
337                buffer_map = create_xshm_image(display, xwa.visual, depth,
338                        ZPixmap, 0, &shm_info, width, height);
339                if (!buffer_map) {
340                        use_shm = False;
341                        fprintf(stderr, "create_xshm_image failed\n");
342                }
343        }
344#endif /* HAVE_XSHM_EXTENSION */
345
346        if (!buffer_map) {
347                buffer_map = XCreateImage(display, xwa.visual,
348                        depth, ZPixmap, 0, 0, width, height, 8, 0);
349                buffer_map->data = (char *)calloc (buffer_map->height,
350                        buffer_map->bytes_per_line);
351        }
352}
353
354
355char *progclass = "Rotzoomer";
356
357char *defaults[] = {
358#ifdef HAVE_XSHM_EXTENSION
359        "*useSHM: True",
360#endif
361        "*move: False",
362        "*sweep: False",
363        "*anim: True",
364        "*numboxes: 2",
365        "*delay: 10",
366        0
367};
368
369
370XrmOptionDescRec options[] = {
371#ifdef HAVE_XSHM_EXTENSION
372        { "-shm",       ".useSHM",      XrmoptionNoArg, "True"  },
373        { "-no-shm",    ".useSHM",      XrmoptionNoArg, "False" },
374#endif
375        { "-move",      ".move",        XrmoptionNoArg, "True"  },
376        { "-sweep",     ".sweep",       XrmoptionNoArg, "True"  },
377        { "-anim",      ".anim",        XrmoptionNoArg, "True"  },
378        { "-no-anim",   ".anim",        XrmoptionNoArg, "False" },
379        { "-delay",     ".delay",       XrmoptionSepArg, 0      },
380        { "-n",         ".numboxes",    XrmoptionSepArg, 0      },
381        { 0, 0, 0, 0 }
382};
383
384
385void screenhack(Display *disp, Window win)
386{
387#ifdef HAVE_XSHM_EXTENSION
388        use_shm = get_boolean_resource ("useSHM", "Boolean");
389#endif
390        num_zoom = get_integer_resource ("numboxes", "Integer");
391        move = get_boolean_resource ("move", "Boolean");
392        delay = get_integer_resource ("delay", "Integer");
393        sweep = get_boolean_resource ("sweep", "Boolean");
394        anim = get_boolean_resource ("anim", "Boolean");
395
396        /* In sweep or static mode, we want only one box */
397        if (sweep || !anim)
398                num_zoom = 1;
399
400        /* Can't have static sweep mode */
401        if (!anim)
402                sweep = 0;
403
404        setup_X (disp, win);
405
406        init_hack ();
407
408        /* Main drawing loop */
409        while (42) {
410                hack_main ();
411                usleep (delay * 1000);
412        }
413}
Note: See TracBrowser for help on using the repository browser.