diff options
Diffstat (limited to 'hacks/moire.c')
-rw-r--r-- | hacks/moire.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/hacks/moire.c b/hacks/moire.c new file mode 100644 index 0000000..4add457 --- /dev/null +++ b/hacks/moire.c @@ -0,0 +1,245 @@ +/* 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. + * + * Concept snarfed from Michael D. Bayne in + * http://samskivert.com/internet/deep/1997/04/16/body.html + */ + +#include "screenhack.h" +#include "xshm.h" + +struct state { + Display *dpy; + Window window; + XShmSegmentInfo shm_info; + + int delay; + int offset; + XColor *colors; + int ncolors; + GC gc; + unsigned long fg_pixel; + unsigned long bg_pixel; + int depth; + + int draw_y, draw_xo, draw_yo; + int draw_factor; + XImage *draw_image; + XWindowAttributes xgwa; +}; + +static void +moire_init_1 (struct state *st) +{ + int oncolors; + int i; + int fgh, bgh; + double fgs, fgv, bgs, bgv; + XWindowAttributes xgwa; + XColor fgc, bgc; + XGCValues gcv; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->delay = get_integer_resource (st->dpy, "delay", "Integer"); + st->offset = get_integer_resource (st->dpy, "offset", "Integer"); + if (st->offset < 2) st->offset = 2; + + MONO: + if (st->colors) + { + for (i = 0; i < st->ncolors; i++) + XFreeColors (st->dpy, xgwa.colormap, &st->colors[i].pixel, 1, 0); + free(st->colors); + st->colors = 0; + } + + if (mono_p) + { + st->fg_pixel = WhitePixelOfScreen (DefaultScreenOfDisplay(st->dpy)); + st->bg_pixel = BlackPixelOfScreen (DefaultScreenOfDisplay(st->dpy)); + } + else + { + st->fg_pixel = get_pixel_resource (st->dpy, + xgwa.colormap, "foreground", "Foreground"); + st->bg_pixel = get_pixel_resource (st->dpy, + xgwa.colormap, "background", "Background"); + } + + if (mono_p) + { + st->offset *= 20; /* compensate for lack of shading */ + gcv.foreground = st->fg_pixel; + } + else + { + st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer"); + if (st->ncolors < 2) st->ncolors = 2; + oncolors = st->ncolors; + + fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue; + if (get_boolean_resource(st->dpy, "random","Boolean")) + { + fgc.red = random() & 0xFFFF; + fgc.green = random() & 0xFFFF; + fgc.blue = random() & 0xFFFF; + bgc.red = random() & 0xFFFF; + bgc.green = random() & 0xFFFF; + bgc.blue = random() & 0xFFFF; + } + else + { + fgc.pixel = st->fg_pixel; + bgc.pixel = st->bg_pixel; + XQueryColor (st->dpy, xgwa.colormap, &fgc); + XQueryColor (st->dpy, xgwa.colormap, &bgc); + } + rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv); + rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv); + + st->colors = (XColor *) malloc (sizeof (XColor) * (st->ncolors+2)); + memset(st->colors, 0, (sizeof (XColor) * (st->ncolors+2))); + make_color_ramp (xgwa.screen, xgwa.visual, xgwa.colormap, + fgh, fgs, fgv, bgh, bgs, bgv, + st->colors, &st->ncolors, + True, True, False); + if (st->ncolors != oncolors) + fprintf(stderr, "%s: got %d of %d requested colors.\n", + progname, st->ncolors, oncolors); + + if (st->ncolors <= 2) + { + mono_p = True; + goto MONO; + } + + gcv.foreground = st->colors[0].pixel; + } + st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv); +} + + +static void * +moire_init (Display *dpy, Window window) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; + moire_init_1 (st); + return st; +} + + +static unsigned long +moire_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + XGCValues gcv; + int chunk_size = 20, ii; + + if (st->draw_y == 0) + { + moire_init_1 (st); + + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + + st->draw_xo = (random() % st->xgwa.width) - st->xgwa.width/2; + st->draw_yo = (random() % st->xgwa.height) - st->xgwa.height/2; + st->draw_factor = (random() % st->offset) + 1; + + st->depth = visual_depth(DefaultScreenOfDisplay(st->dpy), st->xgwa.visual); + + st->draw_image = create_xshm_image(st->dpy, st->xgwa.visual, + st->depth, ZPixmap, &st->shm_info, /* depth, format, shm_info */ + st->xgwa.width, chunk_size); /* w, h */ + } + + /* for (y = 0; y < st->xgwa.height; y++) */ + for (ii = 0; ii < chunk_size; ii++) + { + int x; + for (x = 0; x < st->xgwa.width; x++) + { + double xx = x + st->draw_xo; + double yy = st->draw_y + ii + st->draw_yo; + double i = ((xx * xx) + (yy * yy)) / (double) st->draw_factor; + if (mono_p) + gcv.foreground = ((((long) i) & 1) ? st->fg_pixel : st->bg_pixel); + else + gcv.foreground = st->colors[((long) i) % st->ncolors].pixel; + XPutPixel (st->draw_image, x, ii, gcv.foreground); + } + + if (st->draw_y + ii >= st->xgwa.height) + break; + } + + put_xshm_image(st->dpy, st->window, st->gc, st->draw_image, 0, 0, 0, st->draw_y, st->xgwa.width, chunk_size, &st->shm_info); + st->draw_y += chunk_size; + + if (st->draw_y >= st->xgwa.height) + { + st->draw_y = 0; + + destroy_xshm_image (st->dpy, st->draw_image, &st->shm_info); + st->draw_image = 0; + + return st->delay * 1000000; + } + + return st->delay * 10000; +} + + +static const char *moire_defaults [] = { + ".background: blue", + ".foreground: red", + "*fpsSolid: true", + "*random: true", + "*delay: 5", + "*ncolors: 64", + "*offset: 50", + "*useSHM: True", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + 0 +}; + +static XrmOptionDescRec moire_options [] = { + { "-random", ".random", XrmoptionNoArg, "True" }, + { "-no-random", ".random", XrmoptionNoArg, "False" }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-offset", ".offset", XrmoptionSepArg, 0 }, + { "-shm", ".useSHM", XrmoptionNoArg, "True" }, + { "-no-shm", ".useSHM", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + +static void +moire_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +moire_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +moire_free (Display *dpy, Window window, void *closure) +{ +} + +XSCREENSAVER_MODULE ("Moire", moire) |