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;
63 async_load_state *img_loader;
65 #ifdef HAVE_XSHM_EXTENSION
67 XShmSegmentInfo shm_info;
73 rotzoom (struct state *st, struct zoom_area *za)
75 int x, y, c, s, zoom, z;
76 int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
79 z = 8100 * sin (M_PI * za->a2 / 8192);
82 c = zoom * cos (M_PI * za->a1 / 8192);
83 s = zoom * sin (M_PI * za->a1 / 8192);
84 for (y = za->y; y <= y2; y++) {
85 for (x = za->x; x <= x2; x++) {
86 ox = (x * c + y * s) >> 13;
87 oy = (-x * s + y * c) >> 13;
93 while (ox >= st->width)
95 while (oy >= st->height)
98 XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
102 za->a1 += za->inc1; /* Rotation angle */
105 za->a2 += za->inc2; /* Zoom */
108 za->ox = ox; /* Save state for next iteration */
116 reset_zoom (struct state *st, struct zoom_area *za)
119 int speed = random () % 100 + 100;
120 switch (random () % 4) {
128 za->n = (st->height - 10) * 256 / speed;
133 za->x = st->width - 10;
137 za->n = (st->width - 10) * 256 / speed;
143 za->y = st->height - 10;
146 za->n = (st->height - 10) * 256 / speed;
155 za->n = (st->width - 10) * 256 / speed;
158 za->ww = st->width - za->w;
159 za->hh = st->height - za->h;
161 /* We want smaller angle increments in sweep mode (looks better) */
165 za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
166 za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
168 za->w = 50 + random() % 300;
169 za->h = 50 + random() % 300;
171 if (za->w > st->width / 3)
172 za->w = st->width / 3;
173 if (za->h > st->height / 3)
174 za->h = st->height / 3;
176 za->ww = st->width - za->w;
177 za->hh = st->height - za->h;
179 za->x = (za->ww ? random() % za->ww : 0);
180 za->y = (za->hh ? random() % za->hh : 0);
182 za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
183 za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
186 za->n = 50 + random() % 1000;
190 za->n = 5 + random() % 10;
195 za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
196 za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
199 za->xx = za->x * 256;
200 za->yy = za->y * 256;
206 static struct zoom_area *
207 create_zoom (struct state *st)
209 struct zoom_area *za;
211 za = malloc (sizeof (struct zoom_area));
219 update_position (struct zoom_area *za)
229 za->dx = 100 + random() % 100;
234 za->dy = 100 + random() % 100;
237 if (za->x > za->ww) {
239 za->dx = -(100 + random() % 100);
242 if (za->y > za->hh) {
244 za->dy = -(100 + random() % 100);
250 DisplayImage (struct state *st, int x, int y, int w, int h)
252 #ifdef HAVE_XSHM_EXTENSION
254 XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
257 #endif /* HAVE_XSHM_EXTENSION */
258 XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h);
263 init_hack (struct state *st)
267 st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
268 for (i = 0; i < st->num_zoom; i++) {
269 st->zoom_box[i] = create_zoom (st);
272 if (st->height && st->orig_map->data)
273 memcpy (st->buffer_map->data, st->orig_map->data,
274 st->height * st->buffer_map->bytes_per_line);
276 DisplayImage(st, 0, 0, st->width, st->height);
281 rotzoomer_draw (Display *disp, Window win, void *closure)
283 struct state *st = (struct state *) closure;
284 int delay = (st->delay * 1000);
287 if (st->img_loader) /* still loading */
289 st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
290 if (! st->img_loader) { /* just finished */
291 st->orig_map = XGetImage (st->dpy, st->window, 0, 0,
292 st->width, st->height, ~0L, ZPixmap);
298 for (i = 0; i < st->num_zoom; i++) {
299 if (st->move || st->sweep)
300 update_position (st->zoom_box[i]);
302 if (st->zoom_box[i]->n > 0) {
303 if (st->anim || st->zoom_box[i]->count == 0) {
304 rotzoom (st, st->zoom_box[i]);
308 st->zoom_box[i]->n--;
310 reset_zoom (st, st->zoom_box[i]);
314 for (i = 0; i < st->num_zoom; i++) {
315 DisplayImage(st, st->zoom_box[i]->x, st->zoom_box[i]->y,
316 st->zoom_box[i]->w, st->zoom_box[i]->h);
324 setup_X (struct state *st)
326 XWindowAttributes xgwa;
331 XGetWindowAttributes (st->dpy, st->window, &xgwa);
333 st->colormap = xgwa.colormap;
334 st->width = xgwa.width;
335 st->height = xgwa.height;
336 st->visual = xgwa.visual;
343 gcv.function = GXcopy;
344 gcv.subwindow_mode = IncludeInferiors;
345 gcflags = GCFunction;
346 if (use_subwindow_mode_p (xgwa.screen, st->window)) /* see grabscreen.c */
347 gcflags |= GCSubwindowMode;
348 st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
349 st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
354 #ifdef HAVE_XSHM_EXTENSION
356 st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth,
357 ZPixmap, 0, &st->shm_info, st->width, st->height);
358 if (!st->buffer_map) {
360 fprintf(stderr, "create_xshm_image failed\n");
363 #endif /* HAVE_XSHM_EXTENSION */
365 if (!st->buffer_map) {
366 st->buffer_map = XCreateImage(st->dpy, xgwa.visual,
367 depth, ZPixmap, 0, 0, st->width, st->height, 8, 0);
368 st->buffer_map->data = (char *)calloc (st->buffer_map->height,
369 st->buffer_map->bytes_per_line);
375 rotzoomer_init (Display *dpy, Window window)
377 struct state *st = (struct state *) calloc (1, sizeof(*st));
381 #ifdef HAVE_XSHM_EXTENSION
382 st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean");
384 st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
386 s = get_string_resource (dpy, "mode", "Mode");
387 if (!s || !*s || !strcasecmp (s, "stationary"))
389 else if (!strcasecmp (s, "move"))
391 else if (!strcasecmp (s, "sweep"))
394 fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
396 st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
397 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
399 /* In sweep or static mode, we want only one box */
400 if (st->sweep || !st->anim)
403 /* Can't have static sweep mode */
413 rotzoomer_reshape (Display *dpy, Window window, void *closure,
414 unsigned int w, unsigned int h)
419 rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
425 rotzoomer_free (Display *dpy, Window window, void *closure)
427 struct state *st = (struct state *) closure;
432 static const char *rotzoomer_defaults[] = {
433 ".background: black",
434 ".foreground: white",
435 #ifdef HAVE_XSHM_EXTENSION
448 static XrmOptionDescRec rotzoomer_options[] = {
449 { "-shm", ".useSHM", XrmoptionNoArg, "True" },
450 { "-no-shm", ".useSHM", XrmoptionNoArg, "False" },
451 { "-mode", ".mode", XrmoptionSepArg, 0 },
452 { "-move", ".mode", XrmoptionNoArg, "move" },
453 { "-sweep", ".mode", XrmoptionNoArg, "sweep" },
454 { "-anim", ".anim", XrmoptionNoArg, "True" },
455 { "-no-anim", ".anim", XrmoptionNoArg, "False" },
456 { "-delay", ".delay", XrmoptionSepArg, 0 },
457 { "-n", ".numboxes", XrmoptionSepArg, 0 },
462 XSCREENSAVER_MODULE ("Rotzoomer", rotzoomer)