1 /* rotzoomer - creates a collage of rotated and scaled portions of the screen
2 * Copyright (C) 2001 Claudio Matsuoka <claudio@helllabs.org>
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
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
27 #include "screenhack.h"
29 #ifdef HAVE_XSHM_EXTENSION
34 int w, h; /* rectangle width and height */
35 int inc1, inc2; /* rotation and zoom angle increments */
36 int dx, dy; /* translation increments */
37 int a1, a2; /* rotation and zoom angular variables */
38 int ox, oy; /* origin in the background copy */
39 int xx, yy; /* left-upper corner position (* 256) */
40 int x, y; /* left-upper corner position */
41 int ww, hh; /* valid area to place left-upper corner */
42 int n; /* number of iteractions */
43 int count; /* current iteraction */
52 XImage *orig_map, *buffer_map;
56 struct zoom_area **zoom_box;
65 async_load_state *img_loader;
67 #ifdef HAVE_XSHM_EXTENSION
69 XShmSegmentInfo shm_info;
75 rotzoom (struct state *st, struct zoom_area *za)
77 int x, y, c, s, zoom, z;
78 int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
81 z = 8100 * sin (M_PI * za->a2 / 8192);
84 c = zoom * cos (M_PI * za->a1 / 8192);
85 s = zoom * sin (M_PI * za->a1 / 8192);
86 for (y = za->y; y <= y2; y++) {
87 for (x = za->x; x <= x2; x++) {
88 ox = (x * c + y * s) >> 13;
89 oy = (-x * s + y * c) >> 13;
95 while (ox >= st->width)
97 while (oy >= st->height)
100 XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
104 za->a1 += za->inc1; /* Rotation angle */
107 za->a2 += za->inc2; /* Zoom */
110 za->ox = ox; /* Save state for next iteration */
118 reset_zoom (struct state *st, struct zoom_area *za)
121 int speed = random () % 100 + 100;
122 switch (random () % 4) {
130 za->n = (st->height - 10) * 256 / speed;
135 za->x = st->width - 10;
139 za->n = (st->width - 10) * 256 / speed;
145 za->y = st->height - 10;
148 za->n = (st->height - 10) * 256 / speed;
157 za->n = (st->width - 10) * 256 / speed;
160 za->ww = st->width - za->w;
161 za->hh = st->height - za->h;
163 /* We want smaller angle increments in sweep mode (looks better) */
167 za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
168 za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
170 za->w = 50 + random() % 300;
171 za->h = 50 + random() % 300;
173 if (za->w > st->width / 3)
174 za->w = st->width / 3;
175 if (za->h > st->height / 3)
176 za->h = st->height / 3;
178 za->ww = st->width - za->w;
179 za->hh = st->height - za->h;
181 za->x = (za->ww ? random() % za->ww : 0);
182 za->y = (za->hh ? random() % za->hh : 0);
184 za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
185 za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
188 za->n = 50 + random() % 1000;
192 za->n = 5 + random() % 10;
197 za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
198 za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
201 za->xx = za->x * 256;
202 za->yy = za->y * 256;
208 static struct zoom_area *
209 create_zoom (struct state *st)
211 struct zoom_area *za;
213 za = malloc (sizeof (struct zoom_area));
221 update_position (struct zoom_area *za)
231 za->dx = 100 + random() % 100;
236 za->dy = 100 + random() % 100;
239 if (za->x > za->ww) {
241 za->dx = -(100 + random() % 100);
244 if (za->y > za->hh) {
246 za->dy = -(100 + random() % 100);
252 DisplayImage (struct state *st, int x, int y, int w, int h)
254 #ifdef HAVE_XSHM_EXTENSION
256 XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
259 #endif /* HAVE_XSHM_EXTENSION */
260 XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h);
265 init_hack (struct state *st)
269 st->start_time = time ((time_t) 0);
270 st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
271 for (i = 0; i < st->num_zoom; i++) {
272 st->zoom_box[i] = create_zoom (st);
275 if (st->height && st->orig_map->data)
276 memcpy (st->buffer_map->data, st->orig_map->data,
277 st->height * st->buffer_map->bytes_per_line);
279 DisplayImage(st, 0, 0, st->width, st->height);
284 rotzoomer_draw (Display *disp, Window win, void *closure)
286 struct state *st = (struct state *) closure;
287 int delay = st->delay;
290 if (st->img_loader) /* still loading */
292 st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
293 if (! st->img_loader) { /* just finished */
294 st->orig_map = XGetImage (st->dpy, st->window, 0, 0,
295 st->width, st->height, ~0L, ZPixmap);
301 if (!st->img_loader &&
302 st->start_time + st->duration < time ((time_t) 0)) {
303 XWindowAttributes xgwa;
304 XGetWindowAttributes(st->dpy, st->window, &xgwa);
305 st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
307 st->start_time = time ((time_t) 0);
311 for (i = 0; i < st->num_zoom; i++) {
312 if (st->move || st->sweep)
313 update_position (st->zoom_box[i]);
315 if (st->zoom_box[i]->n > 0) {
316 if (st->anim || st->zoom_box[i]->count == 0) {
317 rotzoom (st, st->zoom_box[i]);
321 st->zoom_box[i]->n--;
323 reset_zoom (st, st->zoom_box[i]);
327 for (i = 0; i < st->num_zoom; i++) {
328 DisplayImage(st, st->zoom_box[i]->x, st->zoom_box[i]->y,
329 st->zoom_box[i]->w, st->zoom_box[i]->h);
337 setup_X (struct state *st)
339 XWindowAttributes xgwa;
344 XGetWindowAttributes (st->dpy, st->window, &xgwa);
346 st->colormap = xgwa.colormap;
347 st->width = xgwa.width;
348 st->height = xgwa.height;
349 st->visual = xgwa.visual;
356 gcv.function = GXcopy;
357 gcv.subwindow_mode = IncludeInferiors;
358 gcflags = GCFunction;
359 if (use_subwindow_mode_p (xgwa.screen, st->window)) /* see grabscreen.c */
360 gcflags |= GCSubwindowMode;
361 st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
362 st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
367 #ifdef HAVE_XSHM_EXTENSION
369 st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth,
370 ZPixmap, 0, &st->shm_info, st->width, st->height);
371 if (!st->buffer_map) {
373 fprintf(stderr, "create_xshm_image failed\n");
376 #endif /* HAVE_XSHM_EXTENSION */
378 if (!st->buffer_map) {
379 st->buffer_map = XCreateImage(st->dpy, xgwa.visual,
380 depth, ZPixmap, 0, 0, st->width, st->height, 8, 0);
381 st->buffer_map->data = (char *)calloc (st->buffer_map->height,
382 st->buffer_map->bytes_per_line);
388 rotzoomer_init (Display *dpy, Window window)
390 struct state *st = (struct state *) calloc (1, sizeof(*st));
394 #ifdef HAVE_XSHM_EXTENSION
395 st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean");
397 st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
399 s = get_string_resource (dpy, "mode", "Mode");
400 if (!s || !*s || !strcasecmp (s, "stationary"))
402 else if (!strcasecmp (s, "move"))
404 else if (!strcasecmp (s, "sweep"))
407 fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
409 st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
410 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
411 st->duration = get_integer_resource (st->dpy, "duration", "Seconds");
412 if (st->delay < 0) st->delay = 0;
413 if (st->duration < 1) st->duration = 1;
415 /* In sweep or static mode, we want only one box */
416 if (st->sweep || !st->anim)
419 /* Can't have static sweep mode */
423 st->start_time = time ((time_t) 0);
431 rotzoomer_reshape (Display *dpy, Window window, void *closure,
432 unsigned int w, unsigned int h)
437 rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
443 rotzoomer_free (Display *dpy, Window window, void *closure)
445 struct state *st = (struct state *) closure;
450 static const char *rotzoomer_defaults[] = {
451 ".background: black",
452 ".foreground: white",
454 #ifdef HAVE_XSHM_EXTENSION
468 static XrmOptionDescRec rotzoomer_options[] = {
469 { "-shm", ".useSHM", XrmoptionNoArg, "True" },
470 { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
471 { "-mode", ".mode", XrmoptionSepArg, 0 },
472 { "-move", ".mode", XrmoptionNoArg, "move" },
473 { "-sweep", ".mode", XrmoptionNoArg, "sweep" },
474 { "-anim", ".anim", XrmoptionNoArg, "True" },
475 { "-no-anim", ".anim", XrmoptionNoArg, "False" },
476 { "-delay", ".delay", XrmoptionSepArg, 0 },
477 {"-duration", ".duration", XrmoptionSepArg, 0 },
478 { "-n", ".numboxes", XrmoptionSepArg, 0 },
483 XSCREENSAVER_MODULE ("RotZoomer", rotzoomer)