diff options
Diffstat (limited to 'hacks/rorschach.c')
-rw-r--r-- | hacks/rorschach.c | 214 |
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) |