http://packetstormsecurity.org/UNIX/admin/xscreensaver-3.30.tar.gz
[xscreensaver] / hacks / rotzoomer.c
diff --git a/hacks/rotzoomer.c b/hacks/rotzoomer.c
new file mode 100644 (file)
index 0000000..3397322
--- /dev/null
@@ -0,0 +1,317 @@
+/* rotzoomer - creates a collage of rotated and scaled portions of the screen
+ * Copyright (C) 2001 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
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XSHM_EXTENSION
+#include "xshm.h"
+static Bool use_shm;
+static XShmSegmentInfo shm_info;
+#endif
+
+struct zoom_area {
+       int w, h;               /* rectangle width and height */
+       int inc1, inc2;         /* rotation and zoom angle increments */
+       int dx, dy;             /* translation increments */
+       int a1, a2;             /* rotation and zoom angular variables */
+       int ox, oy;             /* origin in the background copy */
+       int xx, yy;             /* left-upper corner position (* 256) */
+       int x, y;               /* left-upper corner position */
+       int ww, hh;             /* valid area to place left-upper corner */
+       int n;                  /* number of iteractions */
+};
+
+static Window window;
+static Display *display;
+static GC gc;
+static Visual *visual;
+static XImage *orig_map, *buffer_map;
+static Colormap colormap;
+
+static int width, height;
+static struct zoom_area **zoom_box;
+static int num_zoom = 2;
+static int move = 1;
+static int delay = 0;
+
+
+static void rotzoom (struct zoom_area *za)
+{
+       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;
+
+       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 += width;
+                       while (oy < 0)
+                               oy += height;
+                       while (ox >= width)
+                               ox -= width;
+                       while (oy >= height)
+                               oy -= height;
+
+                       XPutPixel (buffer_map, x, y, XGetPixel (orig_map, ox, oy));
+               }
+       }
+
+       za->a1 += za->inc1;             /* Rotation angle */
+       za->a1 &= 0x3fff;;
+
+       za->a2 += za->inc2;             /* Zoom */
+       za->a2 &= 0x3fff;
+
+       za->ox = ox;                    /* Save state for next iteration */
+       za->oy = oy;
+}
+
+
+static void reset_zoom (struct zoom_area *za)
+{
+       za->w = 50 + random() % 300;
+       za->h = 50 + random() % 300;
+
+       if (za->w > width / 3)
+               za->w = width / 3;
+
+       if (za->h > height / 3)
+               za->h = height / 3;
+
+       za->ww = width - za->w;
+       za->hh = height - za->h;
+
+       za->x = (random() % za->ww);
+       za->y = (random() % za->hh);
+       za->xx = za->x * 256;
+       za->yy = za->y * 256;
+
+       za->a1 = 0;
+       za->a2 = 0;
+       za->dx = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
+       za->dy = ((2 * (random() & 1)) - 1) * (100 + random() % 300);
+       za->inc1 = ((2 * (random() & 1)) - 1) * (random () % 30);
+       za->inc2 = ((2 * (random() & 1)) - 1) * (random () % 30);
+       za->n = 50 + random() % 1000;
+}
+
+
+static struct zoom_area *create_zoom (void)
+{
+       struct zoom_area *za;
+
+       za = malloc (sizeof (struct zoom_area));
+       reset_zoom (za);
+
+       return za;
+}
+
+
+static void update_position (struct zoom_area *za)
+{
+       za->xx += za->dx;
+       za->yy += za->dy;
+
+       za->x = za->xx >> 8;
+       za->y = za->yy >> 8;
+
+       if (za->x < 0) {
+               za->x = 0;
+               za->dx = 100 + random() % 100;
+       }
+               
+       if (za->y < 0) {
+               za->y = 0;
+               za->dy = 100 + random() % 100;
+       }
+               
+       if (za->x > za->ww) {
+               za->x = za->ww;
+               za->dx = -(100 + random() % 100);
+       }
+
+       if (za->y > za->hh) {
+               za->y = za->hh;
+               za->dy = -(100 + random() % 100);
+       }
+}
+
+
+static void DisplayImage (int x, int y, int w, int h)
+{
+#ifdef HAVE_XSHM_EXTENSION
+       if (use_shm)
+               XShmPutImage (display, window, gc, buffer_map, x, y, x, y,
+                       w, h, False);
+       else
+#endif /* HAVE_XSHM_EXTENSION */
+               XPutImage(display, window, gc, buffer_map, x, y, x, y, w, h);
+}
+
+
+static void hack_main (void)
+{
+       int i;
+
+       for (i = 0; i < num_zoom; i++) {
+               if (move)
+                       update_position (zoom_box[i]);
+
+               if (zoom_box[i]->n) {
+                       rotzoom (zoom_box[i]);
+                       zoom_box[i]->n--;
+               } else {
+                       reset_zoom (zoom_box[i]);
+               }
+       }
+
+       for (i = 0; i < num_zoom; i++) {
+               DisplayImage(zoom_box[i]->x, zoom_box[i]->y,
+                       zoom_box[i]->w, zoom_box[i]->h);
+       }
+
+       XSync(display,False);
+       screenhack_handle_events(display);
+}
+
+
+static void init_hack (void)
+{
+       int i;
+
+       zoom_box = calloc (num_zoom, sizeof (struct zoom_area *));
+       for (i = 0; i < num_zoom; i++) {
+               zoom_box[i] = create_zoom ();
+       }
+
+       memcpy (buffer_map->data, orig_map->data,
+               height * buffer_map->bytes_per_line);
+
+       DisplayImage(0, 0, width, height);
+       XSync(display,False);
+}
+
+
+static void setup_X (Display * disp, Window win)
+{
+       XWindowAttributes xwa;
+       int depth;
+       XGCValues gcv;
+       long gcflags;
+
+       XGetWindowAttributes (disp, win, &xwa);
+       window = win;
+       display = disp;
+       depth = xwa.depth;
+       colormap = xwa.colormap;
+       width = xwa.width;
+       height = xwa.height;
+       visual = xwa.visual;
+
+       if (width % 2)
+               width++;
+       if (height % 2)
+               height++;
+
+       gcv.function = GXcopy;
+       gcv.subwindow_mode = IncludeInferiors;
+       gcflags = GCForeground | GCFunction;
+       if (use_subwindow_mode_p (xwa.screen, window))  /* see grabscreen.c */
+               gcflags |= GCSubwindowMode;
+       gc = XCreateGC (display, window, gcflags, &gcv);
+       grab_screen_image (xwa.screen, window);
+
+       orig_map = XGetImage (display, window, 0, 0, width, height, ~0L, ZPixmap);
+
+       if (!gc) {
+               fprintf(stderr, "XCreateGC failed\n");
+               exit(1);
+       }
+
+       buffer_map = 0;
+
+#ifdef HAVE_XSHM_EXTENSION
+       if (use_shm) {
+               buffer_map = create_xshm_image(display, xwa.visual, depth,
+                       ZPixmap, 0, &shm_info, width, height);
+               if (!buffer_map) {
+                       use_shm = False;
+                       fprintf(stderr, "create_xshm_image failed\n");
+               }
+       }
+#endif /* HAVE_XSHM_EXTENSION */
+
+       if (!buffer_map) {
+               buffer_map = XCreateImage(display, xwa.visual,
+                       depth, ZPixmap, 0, 0, width, height, 8, 0);
+               buffer_map->data = (char *)calloc (buffer_map->height,
+                       buffer_map->bytes_per_line);
+       }
+}
+
+
+
+char *progclass = "Rotzoomer";
+
+char *defaults[] = {
+#ifdef HAVE_XSHM_EXTENSION
+       "*useSHM: True",
+#endif
+       "*delay: 10000",
+       "*move: False",
+       "*numboxes: 2",
+       0
+};
+
+
+XrmOptionDescRec options[] = {
+#ifdef HAVE_XSHM_EXTENSION
+       { "-shm",       ".useSHM",      XrmoptionNoArg, "True" },
+       { "-no-shm",    ".useSHM",      XrmoptionNoArg, "False" },
+#endif
+       { "-move",      ".move",        XrmoptionNoArg, "True"},
+       { "-no-move",   ".move",        XrmoptionNoArg, "False"},
+       { "-delay",     ".delay",       XrmoptionSepArg, 0},
+       { "-n",         ".numboxes",    XrmoptionSepArg, 0},
+       { 0, 0, 0, 0 }
+};
+
+
+void screenhack(Display *disp, Window win)
+{
+#ifdef HAVE_XSHM_EXTENSION
+       use_shm = get_boolean_resource ("useSHM", "Boolean");
+#endif
+       num_zoom = get_integer_resource("numboxes", "Integer");
+       move = get_boolean_resource("move", "Boolean");
+       delay = get_integer_resource("delay", "Integer");
+
+       setup_X (disp, win);
+
+       init_hack ();
+
+       /* Main drawing loop */
+       while (42) {
+               hack_main ();
+               usleep (delay);
+       }
+}