/* rotzoomer - creates a collage of rotated and scaled portions of the screen
- * Copyright (C) 2001 Claudio Matsuoka <claudio@helllabs.org>
+ * Copyright (C) 2001-2016 Claudio Matsuoka <claudio@helllabs.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* implied warranty.
*/
-/* (circle-mode by jwz, 4-Jun-2014; not finished yet.) */
+/* Circle-mode by jwz, 2014, 2016. */
/*
* Options:
time_t start_time;
async_load_state *img_loader;
+ Pixmap pm;
#ifdef HAVE_XSHM_EXTENSION
Bool use_shm;
for (y = za->y; y <= y2; y++) {
for (x = za->x; x <= x2; x++) {
- c = zoom * cos (M_PI * za->a1 / 8192);
- s = zoom * sin (M_PI * za->a1 / 8192);
+ Bool copyp = True;
+ double a = M_PI * za->a1 / 8192;
+ c = zoom * cos (a);
+ s = zoom * sin (a);
if (st->circle) {
int cx = za->x + za->w / 2;
int cy = za->y + za->h / 2;
int d2 = (dx*dx) + (dy*dy);
if (d2 > w2) {
- ox = x;
- oy = y;
+ copyp = False;
} else {
double r = sqrt ((double) d2);
double th = atan ((double)dy / (double) (dx == 0 ? 1 : dx));
- th += M_PI * (za->a1 / 300.0);
- ox = 10 + cx + (int) (r * cos(th));
- oy = 10 + cy + (int) (r * sin(th));
+ copyp = 1;
+ if (dx < 0) th += M_PI;
+ th += M_PI * (za->a1 / 600.0);
+ ox = cx + (int) (r * cos(th));
+ oy = cy + (int) (r * sin(th));
}
} else {
ox = (x * c + y * s) >> 13;
oy = (-x * s + y * c) >> 13;
}
- while (ox < 0)
- ox += st->width;
- while (oy < 0)
- oy += st->height;
- while (ox >= st->width)
- ox -= st->width;
- while (oy >= st->height)
- oy -= st->height;
-
- XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
+ if (copyp) {
+ while (ox < 0)
+ ox += st->width;
+ while (oy < 0)
+ oy += st->height;
+ while (ox >= st->width)
+ ox -= st->width;
+ while (oy >= st->height)
+ oy -= st->height;
+
+ XPutPixel (st->buffer_map, x, y, XGetPixel (st->orig_map, ox, oy));
+ }
}
}
za->ox = ox; /* Save state for next iteration */
za->oy = oy;
+ if (st->circle && za->n <= 1)
+ {
+ /* Done rotating the circle: copy the bits from the working set back
+ into the origin, so that subsequent rotations pick up these changes.
+ */
+ int cx = za->x + za->w / 2;
+ int cy = za->y + za->h / 2;
+ int w2 = (za->w/2) * (za->w/2);
+ for (y = za->y; y < za->y + za->h; y++)
+ for (x = za->x; x < za->x + za->w; x++)
+ {
+ int dx = x - cx;
+ int dy = y - cy;
+ int d2 = (dx*dx) + (dy*dy);
+ if (d2 <= w2)
+ XPutPixel (st->orig_map, x, y, XGetPixel (st->buffer_map, x, y));
+ }
+ }
+
za->count++;
}
za->w = st->height / 3;
za->h = za->w;
- za->ww = st->width - za->w;
+ za->ww = st->width - za->w;
za->hh = st->height - za->h;
za->x = (za->ww ? random() % za->ww : 0);
za->y = (za->hh ? random() % za->hh : 0);
-
za->dx = 0;
za->dy = 0;
- za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
+ za->a1 = 0;
+ za->a2 = 0;
+ za->count = 0;
- if (st->anim) {
- za->n = 50 + random() % 1000;
- za->a1 = 0;
- za->a2 = 0;
- } else {
- za->n = 5 + random() % 10;
- za->a1 = random ();
- za->a2 = random ();
- }
+ /* #### If we go clockwise, it doesn't start rotating from 0.
+ So only go counter-clockwise for now. Sigh. */
+ za->inc1 = (random () % 30);
+ za->inc2 = 0;
+ za->n = 50 + random() % 100;
- za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
- za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
+ if (!st->anim) {
+ za->count = random() % (za->n / 2);
+ za->a1 = random();
+ }
} else {
za->w = 50 + random() % 300;
}
+static void
+set_mode(struct state *st)
+{
+ char *s = get_string_resource (st->dpy, "mode", "Mode");
+ if (!s || !*s || !strcasecmp (s, "random"))
+ {
+ switch (random() % 4) {
+ case 0: s = "stationary"; break;
+ case 1: s = "move"; break;
+ case 2: s = "sweep"; break;
+ case 3: s = "circle"; break;
+ default: abort();
+ }
+ }
+
+ st->move = False;
+ st->sweep = False;
+ st->circle = False;
+
+ if (!strcasecmp (s, "stationary"))
+ ;
+ else if (!strcasecmp (s, "move"))
+ st->move = True;
+ else if (!strcasecmp (s, "sweep"))
+ st->sweep = True;
+ else if (!strcasecmp (s, "circle"))
+ st->circle = True;
+ else
+ fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+}
+
+
static void
init_hack (struct state *st)
{
int i;
+ set_mode (st);
+
st->start_time = time ((time_t *) 0);
st->zoom_box = calloc (st->num_zoom, sizeof (struct zoom_area *));
for (i = 0; i < st->num_zoom; i++) {
{
st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
if (! st->img_loader) { /* just finished */
- st->orig_map = XGetImage (st->dpy, st->window, 0, 0,
- st->width, st->height, ~0L, ZPixmap);
+ if (! st->pm) abort();
+ st->orig_map = XGetImage (st->dpy, st->pm,
+ 0, 0, st->width, st->height,
+ ~0L, ZPixmap);
init_hack (st);
}
return st->delay;
st->start_time + st->duration < time ((time_t *) 0)) {
XWindowAttributes xgwa;
XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ /* On MacOS X11, XGetImage on a Window often gets an inexplicable BadMatch,
+ possibly due to the window manager having occluded something? It seems
+ nondeterministic. Loading the image into a pixmap instead fixes it. */
+ if (st->pm) XFreePixmap (st->dpy, st->pm);
+ st->pm = XCreatePixmap (st->dpy, st->window,
+ xgwa.width, xgwa.height, xgwa.depth);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
- st->window, 0, 0);
+ st->pm, 0, 0);
st->start_time = time ((time_t *) 0);
return st->delay;
}
if (use_subwindow_mode_p (xgwa.screen, st->window)) /* see grabscreen.c */
gcflags |= GCSubwindowMode;
st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
+ if (st->pm) XFreePixmap (st->dpy, st->pm);
+ st->pm = XCreatePixmap (st->dpy, st->window,
+ xgwa.width, xgwa.height, xgwa.depth);
st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
- st->window, 0, 0);
+ st->pm, 0, 0);
st->buffer_map = 0;
rotzoomer_init (Display *dpy, Window window)
{
struct state *st = (struct state *) calloc (1, sizeof(*st));
- char *s;
st->dpy = dpy;
st->window = window;
#ifdef HAVE_XSHM_EXTENSION
#endif
st->num_zoom = get_integer_resource (st->dpy, "numboxes", "Integer");
- s = get_string_resource (dpy, "mode", "Mode");
- if (!s || !*s || !strcasecmp (s, "stationary"))
- ;
- else if (!strcasecmp (s, "move"))
- st->move = True;
- else if (!strcasecmp (s, "sweep"))
- st->sweep = True;
- else if (!strcasecmp (s, "circle"))
- st->circle = True;
- else
- fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
+ set_mode(st);
st->anim = get_boolean_resource (st->dpy, "anim", "Boolean");
st->delay = get_integer_resource (st->dpy, "delay", "Integer");
rotzoomer_free (Display *dpy, Window window, void *closure)
{
struct state *st = (struct state *) closure;
+ if (st->pm) XFreePixmap (dpy, st->pm);
free (st);
}
"*useSHM: False",
#endif
"*anim: True",
- "*mode: stationary",
+ "*mode: random",
"*numboxes: 2",
"*delay: 10000",
"*duration: 120",