/* 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, 2014, 2016. */
+
/*
* Options:
*
* -n <num> number of zoomboxes
* -move enable mobile zoomboxes
* -sweep enable sweep mode
+ * -circle enable circle mode
* -anim enable snapshot mode
* -no-anim enable snapshot mode
* -delay delay in milliseconds
#include <math.h>
#include "screenhack.h"
-
-#ifdef HAVE_XSHM_EXTENSION
#include "xshm.h"
-#endif
struct zoom_area {
int w, h; /* rectangle width and height */
int num_zoom;
int move;
int sweep;
+ int circle;
int delay;
int anim;
int duration;
time_t start_time;
async_load_state *img_loader;
+ Pixmap pm;
-#ifdef HAVE_XSHM_EXTENSION
- Bool use_shm;
XShmSegmentInfo shm_info;
-#endif
};
int x, y, c, s, zoom, z;
int x2 = za->x + za->w - 1, y2 = za->y + za->h - 1;
int ox = 0, oy = 0;
+ int w2 = (za->w/2) * (za->w/2);
z = 8100 * sin (M_PI * za->a2 / 8192);
zoom = 8192 + z;
- c = zoom * cos (M_PI * za->a1 / 8192);
- s = zoom * sin (M_PI * za->a1 / 8192);
for (y = za->y; y <= y2; y++) {
for (x = za->x; x <= x2; x++) {
- 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));
+ 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 dx = x - cx;
+ int dy = y - cy;
+ int d2 = (dx*dx) + (dy*dy);
+
+ if (d2 > w2) {
+ copyp = False;
+ } else {
+ double r = sqrt ((double) d2);
+ double th = atan ((double)dy / (double) (dx == 0 ? 1 : dx));
+ 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;
+ }
+
+ 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->a1 += za->inc1; /* Rotation angle */
- za->a1 &= 0x3fff;;
+ za->a1 &= 0x3fff;
za->a2 += za->inc2; /* Zoom */
za->a2 &= 0x3fff;
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->a2 = 0;
za->inc1 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
za->inc2 = ((2 * (random() & 1)) - 1) * (1 + random () % 7);
+ } else if (st->circle) {
+
+ za->w = 50 + random() % 300;
+ if (za->w > st->width / 3)
+ za->w = st->width / 3;
+ if (za->w > st->height / 3)
+ za->w = st->height / 3;
+ za->h = 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->a1 = 0;
+ za->a2 = 0;
+ za->count = 0;
+
+ /* #### 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;
+
+ if (!st->anim) {
+ za->count = random() % (za->n / 2);
+ za->a1 = random();
+ }
+
} else {
za->w = 50 + random() % 300;
za->h = 50 + random() % 300;
{
struct zoom_area *za;
- za = malloc (sizeof (struct zoom_area));
+ za = calloc (1, sizeof (struct zoom_area));
reset_zoom (st, za);
return za;
static void
DisplayImage (struct state *st, int x, int y, int w, int h)
{
-#ifdef HAVE_XSHM_EXTENSION
- if (st->use_shm)
- XShmPutImage (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
- w, h, False);
+ put_xshm_image (st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y,
+ w, h, &st->shm_info);
+}
+
+
+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
-#endif /* HAVE_XSHM_EXTENSION */
- XPutImage(st->dpy, st->window, st->gc, st->buffer_map, x, y, x, y, w, h);
+ fprintf (stderr, "%s: bogus mode: \"%s\"\n", progname, s);
}
{
int i;
- st->start_time = time ((time_t) 0);
+ 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->zoom_box[i] = create_zoom (st);
rotzoomer_draw (Display *disp, Window win, void *closure)
{
struct state *st = (struct state *) closure;
- int delay = (st->delay * 1000);
+ int delay = st->delay;
int i;
if (st->img_loader) /* still loading */
{
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;
}
if (!st->img_loader &&
- st->start_time + st->duration < time ((time_t) 0)) {
+ 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->start_time = time ((time_t) 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->buffer_map = 0;
-
-#ifdef HAVE_XSHM_EXTENSION
- if (st->use_shm) {
- st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth,
- ZPixmap, 0, &st->shm_info, st->width, st->height);
- if (!st->buffer_map) {
- st->use_shm = False;
- fprintf(stderr, "create_xshm_image failed\n");
- }
- }
-#endif /* HAVE_XSHM_EXTENSION */
+ st->pm, 0, 0);
- if (!st->buffer_map) {
- st->buffer_map = XCreateImage(st->dpy, xgwa.visual,
- depth, ZPixmap, 0, 0, st->width, st->height, 8, 0);
- st->buffer_map->data = (char *)calloc (st->buffer_map->height,
- st->buffer_map->bytes_per_line);
- }
+ st->buffer_map = create_xshm_image(st->dpy, xgwa.visual, depth,
+ ZPixmap, &st->shm_info, st->width, st->height);
}
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
- st->use_shm = get_boolean_resource (st->dpy, "useSHM", "Boolean");
-#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
- 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");
if (!st->anim)
st->sweep = 0;
- st->start_time = time ((time_t) 0);
+ if (st->circle) {
+ st->move = 0;
+ st->sweep = 0;
+ }
+
+ st->start_time = time ((time_t *) 0);
setup_X (st);
static Bool
rotzoomer_event (Display *dpy, Window window, void *closure, XEvent *event)
{
+ struct state *st = (struct state *) closure;
+ if (screenhack_event_helper (dpy, window, event))
+ {
+ st->start_time = 0;
+ return True;
+ }
return False;
}
rotzoomer_free (Display *dpy, Window window, void *closure)
{
struct state *st = (struct state *) closure;
+ if (st->pm) XFreePixmap (dpy, st->pm);
free (st);
}
static const char *rotzoomer_defaults[] = {
".background: black",
".foreground: white",
+ "*fpsSolid: true",
#ifdef HAVE_XSHM_EXTENSION
"*useSHM: True",
#else
"*useSHM: False",
#endif
"*anim: True",
- "*mode: stationary",
+ "*mode: random",
"*numboxes: 2",
- "*delay: 10",
+ "*delay: 10000",
"*duration: 120",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+ "*rotateImages: True",
+#endif
0
};
{ "-mode", ".mode", XrmoptionSepArg, 0 },
{ "-move", ".mode", XrmoptionNoArg, "move" },
{ "-sweep", ".mode", XrmoptionNoArg, "sweep" },
+ { "-circle", ".mode", XrmoptionNoArg, "circle"},
{ "-anim", ".anim", XrmoptionNoArg, "True" },
{ "-no-anim", ".anim", XrmoptionNoArg, "False" },
{ "-delay", ".delay", XrmoptionSepArg, 0 },
};
-XSCREENSAVER_MODULE ("Rotzoomer", rotzoomer)
+XSCREENSAVER_MODULE ("RotZoomer", rotzoomer)