summaryrefslogtreecommitdiffstats
path: root/hacks/rorschach.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/rorschach.c')
-rw-r--r--hacks/rorschach.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/hacks/rorschach.c b/hacks/rorschach.c
new file mode 100644
index 0000000..6b2d7a3
--- /dev/null
+++ b/hacks/rorschach.c
@@ -0,0 +1,214 @@
+/* xscreensaver, Copyright (c) 1992-2014 Jamie Zawinski <jwz@jwz.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.
+ *
+ * 19971004: Johannes Keukelaar <johannes@nada.kth.se>: Use helix screen
+ * eraser.
+ */
+
+#include "screenhack.h"
+#include "erase.h"
+
+struct state {
+ GC draw_gc;
+ unsigned int default_fg_pixel;
+ int iterations, offset;
+ Bool xsym, ysym;
+ int sleep_time;
+ int xlim, ylim;
+ XColor color;
+ int current_x, current_y, remaining_iterations;
+ eraser_state *eraser;
+};
+
+
+static void *
+rorschach_init (Display *dpy, Window window)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ XGCValues gcv;
+ Colormap cmap;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ gcv.foreground = st->default_fg_pixel =
+ get_pixel_resource (dpy, cmap, "foreground", "Foreground");
+ st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource (dpy, cmap, "background", "Background");
+ st->iterations = get_integer_resource (dpy, "iterations", "Integer");
+ st->offset = get_integer_resource (dpy, "offset", "Integer");
+ if (st->offset <= 0) st->offset = 3;
+ if (st->iterations < 10) st->iterations = 10;
+ st->sleep_time = get_integer_resource (dpy, "delay", "Delay");
+ st->xsym = get_boolean_resource (dpy, "xsymmetry", "Symmetry");
+ st->ysym = get_boolean_resource (dpy, "ysymmetry", "Symmetry");
+ st->remaining_iterations = -1;
+ st->color.pixel = 0;
+ return st;
+}
+
+static void
+rorschach_reshape (Display *dpy, Window window, void *closure,
+ unsigned int width, unsigned int height)
+{
+ struct state *st = (struct state *) closure;
+ st->xlim = width;
+ st->ylim = height;
+}
+
+
+static void
+rorschach_draw_start (Display *dpy, Window window, struct state *st)
+{
+ Colormap cmap;
+ XWindowAttributes xgwa;
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ st->xlim = xgwa.width;
+ st->ylim = xgwa.height;
+ cmap = xgwa.colormap;
+
+ if (st->color.pixel) XFreeColors (dpy, cmap, &st->color.pixel, 1, 0);
+
+ if (! mono_p)
+ hsv_to_rgb (random()%360, 1.0, 1.0, &st->color.red, &st->color.green, &st->color.blue);
+ if ((!mono_p) && XAllocColor (dpy, cmap, &st->color))
+ XSetForeground (dpy, st->draw_gc, st->color.pixel);
+ else
+ XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
+
+ st->current_x = st->xlim/2;
+ st->current_y = st->ylim/2;
+ st->remaining_iterations = st->iterations;
+}
+
+
+static void
+rorschach_draw_step (Display *dpy, Window window, struct state *st)
+{
+# define ITER_CHUNK 300
+ XPoint points [4 * ITER_CHUNK];
+ int x = st->current_x;
+ int y = st->current_y;
+ int i, j = 0;
+
+ int this_iterations = ITER_CHUNK;
+ if (this_iterations > st->remaining_iterations)
+ this_iterations = st->remaining_iterations;
+
+ for (i = 0; i < this_iterations; i++)
+ {
+ x += ((random () % (1 + (st->offset << 1))) - st->offset);
+ y += ((random () % (1 + (st->offset << 1))) - st->offset);
+ points [j].x = x;
+ points [j].y = y;
+ j++;
+ if (st->xsym)
+ {
+ points [j].x = st->xlim - x;
+ points [j].y = y;
+ j++;
+ }
+ if (st->ysym)
+ {
+ points [j].x = x;
+ points [j].y = st->ylim - y;
+ j++;
+ }
+ if (st->xsym && st->ysym)
+ {
+ points [j].x = st->xlim - x;
+ points [j].y = st->ylim - y;
+ j++;
+ }
+ }
+ XDrawPoints (dpy, window, st->draw_gc, points, j, CoordModeOrigin);
+ st->remaining_iterations -= this_iterations;
+ if (st->remaining_iterations < 0) st->remaining_iterations = 0;
+ st->current_x = x;
+ st->current_y = y;
+}
+
+
+static unsigned long
+rorschach_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ unsigned long delay = 20000;
+
+ if (st->eraser) {
+ st->eraser = erase_window (dpy, window, st->eraser);
+ goto END;
+ }
+
+ if (st->remaining_iterations > 0)
+ {
+ rorschach_draw_step (dpy, window, st);
+ if (st->remaining_iterations == 0)
+ delay = st->sleep_time * 1000000;
+ }
+ else
+ {
+ if (st->remaining_iterations == 0)
+ st->eraser = erase_window (dpy, window, st->eraser);
+
+ rorschach_draw_start (dpy, window, st);
+ }
+ END:
+ return delay;
+}
+
+
+static Bool
+rorschach_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ struct state *st = (struct state *) closure;
+ if (screenhack_event_helper (dpy, window, event))
+ {
+ st->remaining_iterations = 0;
+ return True;
+ }
+ return False;
+}
+
+static void
+rorschach_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st);
+}
+
+
+static const char *rorschach_defaults [] = {
+ ".background: black",
+ ".foreground: white",
+ "*fpsSolid: true",
+ "*xsymmetry: true",
+ "*ysymmetry: false",
+ "*iterations: 4000",
+ "*offset: 7",
+ "*delay: 5",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+ 0
+};
+
+static XrmOptionDescRec rorschach_options [] = {
+ { "-iterations", ".iterations", XrmoptionSepArg, 0 },
+ { "-offset", ".offset", XrmoptionSepArg, 0 },
+ { "-xsymmetry", ".xsymmetry", XrmoptionNoArg, "true" },
+ { "-ysymmetry", ".ysymmetry", XrmoptionNoArg, "true" },
+ { "-no-xsymmetry", ".xsymmetry", XrmoptionNoArg, "false" },
+ { "-no-ysymmetry", ".ysymmetry", XrmoptionNoArg, "false" },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("Rorschach", rorschach)