summaryrefslogtreecommitdiffstats
path: root/hacks/moire2.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/moire2.c')
-rw-r--r--hacks/moire2.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/hacks/moire2.c b/hacks/moire2.c
new file mode 100644
index 0000000..dad9d66
--- /dev/null
+++ b/hacks/moire2.c
@@ -0,0 +1,356 @@
+/* xscreensaver, Copyright (c) 1997-2013 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.
+ */
+
+#include "screenhack.h"
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# include "xdbe.h"
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+struct state {
+ Display *dpy;
+ Window window;
+
+ int ncolors;
+ XColor *colors;
+ int fg_pixel, bg_pixel;
+ Pixmap p0, p1, p2, p3;
+ GC copy_gc, erase_gc, window_gc;
+ int width, height, size;
+ int x1, x2, y1, y2, x3, y3;
+ int dx1, dx2, dx3, dy1, dy2, dy3;
+ int othickness, thickness;
+ Bool do_three;
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ XdbeBackBuffer back_buf;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+ Bool flip_a, flip_b;
+ int pix;
+ int delay, color_shift;
+
+ int reset;
+ int iterations, iteration;
+};
+
+static void
+moire2_init_1 (struct state *st)
+{
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+
+ st->othickness = get_integer_resource(st->dpy, "thickness", "Thickness");
+
+ if (mono_p)
+ st->ncolors = 2;
+ else
+ st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
+ if (st->ncolors < 2) st->ncolors = 2;
+ if (st->ncolors <= 2) mono_p = True;
+
+ if (mono_p)
+ st->colors = 0;
+ else
+ st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));
+
+ if (mono_p)
+ ;
+ else
+ make_smooth_colormap (xgwa.screen, xgwa.visual, xgwa.colormap,
+ st->colors, &st->ncolors,
+ True, 0, True);
+
+ st->bg_pixel = get_pixel_resource(st->dpy,
+ xgwa.colormap, "background", "Background");
+ st->fg_pixel = get_pixel_resource(st->dpy,
+ xgwa.colormap, "foreground", "Foreground");
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ st->back_buf = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+}
+
+
+static void
+reset_moire2 (struct state *st)
+{
+ GC gc;
+ XWindowAttributes xgwa;
+ XGCValues gcv;
+ Bool xor;
+ XGetWindowAttributes (st->dpy, st->window, &xgwa);
+
+ st->do_three = (0 == (random() % 3));
+
+ st->width = xgwa.width;
+ st->height = xgwa.height;
+ st->size = st->width > st->height ? st->width : st->height;
+
+ if (st->p0) XFreePixmap(st->dpy, st->p0);
+ if (st->p1) XFreePixmap(st->dpy, st->p1);
+ if (st->p2) XFreePixmap(st->dpy, st->p2);
+ if (st->p3) XFreePixmap(st->dpy, st->p3);
+
+ st->p0 = XCreatePixmap(st->dpy, st->window, st->width, st->height, 1);
+ st->p1 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
+ st->p2 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
+ if (st->do_three)
+ st->p3 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
+ else
+ st->p3 = 0;
+
+ st->thickness = (st->othickness > 0 ? st->othickness : (1 + (random() % 4)));
+
+ gcv.foreground = 0;
+ gcv.line_width = (st->thickness == 1 ? 0 : st->thickness);
+ gc = XCreateGC (st->dpy, st->p1, GCForeground|GCLineWidth, &gcv);
+
+ XFillRectangle(st->dpy, st->p1, gc, 0, 0, st->width*2, st->height*2);
+ XFillRectangle(st->dpy, st->p2, gc, 0, 0, st->width*2, st->height*2);
+ if (st->do_three)
+ XFillRectangle(st->dpy, st->p3, gc, 0, 0, st->width*2, st->height*2);
+
+ XSetForeground(st->dpy, gc, 1);
+
+ xor = (st->do_three || (st->thickness == 1) || (random() & 1));
+
+ {
+ int i, ii, maxx, maxy;
+
+#define FROB(P) do { \
+ maxx = (st->size*4); \
+ maxy = (st->size*4); \
+ if (0 == (random() % 5)) { \
+ float f = 1.0 + frand(0.05); \
+ if (random() & 1) maxx *= f; \
+ else maxy *= f; \
+ } \
+ ii = (st->thickness + 1 + (xor ? 0 : 1) + (random() % (4 * st->thickness))); \
+ for (i = 0; i < (st->size*2); i += ii) \
+ XDrawArc(st->dpy, (P), gc, i-st->size, i-st->size, maxx-i-i, maxy-i-i, 0, 360*64); \
+ if (0 == (random() % 5)) \
+ { \
+ XSetFunction(st->dpy, gc, GXxor); \
+ XFillRectangle(st->dpy, (P), gc, 0, 0, st->width*2, st->height*2); \
+ XSetFunction(st->dpy, gc, GXcopy); \
+ } \
+ } while(0)
+
+ FROB(st->p1);
+ FROB(st->p2);
+ if (st->do_three)
+ FROB(st->p3);
+#undef FROB
+ }
+
+ XFreeGC(st->dpy, gc);
+
+ if (st->copy_gc) XFreeGC(st->dpy, st->copy_gc);
+ gcv.function = (xor ? GXxor : GXor);
+ gcv.foreground = 1;
+ gcv.background = 0;
+
+ st->copy_gc = XCreateGC (st->dpy, st->p0, GCFunction|GCForeground|GCBackground, &gcv);
+
+ gcv.foreground = 0;
+ if (st->erase_gc) XFreeGC(st->dpy, st->erase_gc);
+ st->erase_gc = XCreateGC (st->dpy, st->p0, GCForeground, &gcv);
+
+ gcv.foreground = st->fg_pixel;
+ gcv.background = st->bg_pixel;
+ if (st->window_gc) XFreeGC(st->dpy, st->window_gc);
+ st->window_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
+
+#define FROB(N,DN,MAX) \
+ N = (MAX/2) + (random() % MAX); \
+ DN = ((1 + (random() % (7*st->thickness))) * ((random() & 1) ? 1 : -1))
+
+ FROB(st->x1,st->dx1,st->width);
+ FROB(st->x2,st->dx2,st->width);
+ FROB(st->x3,st->dx3,st->width);
+ FROB(st->y1,st->dy1,st->height);
+ FROB(st->y2,st->dy2,st->height);
+ FROB(st->y3,st->dy3,st->height);
+#undef FROB
+}
+
+
+
+static void
+moire2 (struct state *st)
+{
+#define FROB(N,DN,MAX) \
+ N += DN; \
+ if (N <= 0) N = 0, DN = -DN; \
+ else if (N >= MAX) N = MAX, DN = -DN; \
+ else if (0 == (random() % 100)) DN = -DN; \
+ else if (0 == (random() % 50)) \
+ DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1)))
+
+ FROB(st->x1,st->dx1,st->width);
+ FROB(st->x2,st->dx2,st->width);
+ FROB(st->x3,st->dx3,st->width);
+ FROB(st->y1,st->dy1,st->height);
+ FROB(st->y2,st->dy2,st->height);
+ FROB(st->y3,st->dy3,st->height);
+#undef FROB
+
+ XFillRectangle(st->dpy, st->p0, st->erase_gc, 0, 0, st->width, st->height);
+ XCopyArea(st->dpy, st->p1, st->p0, st->copy_gc, st->x1, st->y1, st->width, st->height, 0, 0);
+ XCopyArea(st->dpy, st->p2, st->p0, st->copy_gc, st->x2, st->y2, st->width, st->height, 0, 0);
+ if (st->do_three)
+ XCopyArea(st->dpy, st->p3, st->p0, st->copy_gc, st->x3, st->y3, st->width, st->height, 0, 0);
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ if (st->back_buf)
+ {
+ XdbeSwapInfo info[1];
+ info[0].swap_window = st->window;
+ info[0].swap_action = XdbeUndefined;
+ XCopyPlane (st->dpy, st->p0, st->back_buf, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
+ XdbeSwapBuffers (st->dpy, info, 1);
+ }
+ else
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+ XCopyPlane (st->dpy, st->p0, st->window, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
+
+#if 0
+ XCopyPlane(st->dpy, st->p1, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
+ st->width/2, st->height/2,
+ 0, st->height/2, 1L);
+ XCopyPlane(st->dpy, st->p2, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
+ st->width/2, st->height/2,
+ st->width/2, st->height/2, 1L);
+#endif
+}
+
+
+
+static void *
+moire2_init (Display *dpy, Window window)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ st->dpy = dpy;
+ st->window = window;
+ st->reset = 1;
+
+ st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer");
+
+ if (st->color_shift <= 0) st->color_shift = 1;
+ moire2_init_1 (st);
+ return st;
+}
+
+static unsigned long
+moire2_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+
+ if (st->reset)
+ {
+ st->reset = 0;
+
+ st->iteration = 0;
+ st->iterations = 30 + (random() % 70) + (random() % 70);
+ reset_moire2 (st);
+
+ st->flip_a = mono_p ? False : (random() & 1);
+ st->flip_b = mono_p ? False : (random() & 1);
+
+ if (st->flip_b)
+ {
+ XSetForeground(st->dpy, st->window_gc, st->bg_pixel);
+ XSetBackground(st->dpy, st->window_gc, st->fg_pixel);
+ }
+ else
+ {
+ XSetForeground(st->dpy, st->window_gc, st->fg_pixel);
+ XSetBackground(st->dpy, st->window_gc, st->bg_pixel);
+ }
+ }
+
+ if (!mono_p)
+ {
+ st->pix++;
+ st->pix = st->pix % st->ncolors;
+
+ if (st->flip_a)
+ XSetBackground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
+ else
+ XSetForeground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
+ }
+
+
+ moire2 (st);
+ st->iteration++;
+ if (st->iteration >= st->color_shift)
+ {
+ st->iteration = 0;
+ st->iterations--;
+ if (st->iterations <= 0)
+ st->reset = 1;
+ }
+
+ return st->delay;
+}
+
+static void
+moire2_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ st->reset = 1;
+}
+
+static Bool
+moire2_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ return False;
+}
+
+static void
+moire2_free (Display *dpy, Window window, void *closure)
+{
+}
+
+static const char *moire2_defaults [] = {
+ ".lowrez: true",
+ ".background: black",
+ ".foreground: white",
+ "*delay: 50000",
+ "*thickness: 0",
+ "*colors: 150",
+ "*colorShift: 5",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+ /* Off by default, since it slows it down a lot, and the flicker isn't really
+ all that bad without it... Or rather, it flickers just as badly with it.
+ The XFree86 implementation of the XDBE extension totally blows! There is
+ just *no* excuse for the "swap buffers" operation to flicker like it does.
+ */
+ "*useDBE: False",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+ 0
+};
+
+static XrmOptionDescRec moire2_options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-ncolors", ".colors", XrmoptionSepArg, 0 },
+ { "-thickness", ".thickness", XrmoptionSepArg, 0 },
+ { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("Moire2", moire2)