/* xscreensaver, Copyright (c) 2007-2014 Jamie Zawinski * * 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. * * cwaves -- languid sinusoidal colors. */ #include "screenhack.h" #include #include "ximage-loader.h" #define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) typedef struct { double scale; double offset; double delta; } wave; typedef struct { Display *dpy; Window window; XWindowAttributes xgwa; GC gc; int delay; int scale; int ncolors; XColor *colors; int nwaves; wave *waves; int debug_p; } state; static void * cwaves_init (Display *dpy, Window window) { int i; XGCValues gcv; state *st = (state *) calloc (1, sizeof (*st)); st->dpy = dpy; st->window = window; XGetWindowAttributes (st->dpy, st->window, &st->xgwa); st->debug_p = get_boolean_resource (dpy, "debug", "Boolean"); st->scale = get_integer_resource (dpy, "scale", "Integer"); if (st->scale <= 0) st->scale = 1; st->ncolors = get_integer_resource (dpy, "ncolors", "Integer"); if (st->ncolors < 4) st->ncolors = 4; st->colors = (XColor *) malloc (sizeof(*st->colors) * (st->ncolors+1)); make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, True, 0, False); st->gc = XCreateGC (st->dpy, st->window, 0, &gcv); st->delay = get_integer_resource (dpy, "delay", "Integer"); st->nwaves = get_integer_resource (dpy, "nwaves", "Integer"); st->waves = (wave *) calloc (st->nwaves, sizeof(*st->waves)); for (i = 0; i < st->nwaves; i++) { st->waves[i].scale = frand(0.03) + 0.005; st->waves[i].offset = frand(M_PI); st->waves[i].delta = (BELLRAND(2)-1) / 15.0; } return st; } static unsigned long cwaves_draw (Display *dpy, Window window, void *closure) { state *st = (state *) closure; int i, x; for (i = 0; i < st->nwaves; i++) st->waves[i].offset += st->waves[i].delta; for (x = 0; x < st->xgwa.width; x += st->scale) { double v = 0; int j; for (i = 0; i < st->nwaves; i++) v += cos ((x * st->waves[i].scale) - st->waves[i].offset); v /= st->nwaves; j = st->ncolors * (v/2 + 0.5); if (j < 0 || j >= st->ncolors) abort(); XSetForeground (st->dpy, st->gc, st->colors[j].pixel); XFillRectangle (st->dpy, st->window, st->gc, x, 0, st->scale, st->xgwa.height); } if (st->debug_p) { int wh = (st->xgwa.height / (st->nwaves + 1)) * 0.9; int i; XSetLineAttributes (st->dpy, st->gc, 2, LineSolid, CapRound, JoinRound); XSetForeground (st->dpy, st->gc, BlackPixelOfScreen (st->xgwa.screen)); for (i = 0; i < st->nwaves; i++) { int y = st->xgwa.height * i / (st->nwaves + 1); int ox = -1, oy = -1; for (x = 0; x < st->xgwa.width; x += st->scale) { int yy; double v = 0; v = cos ((x * st->waves[i].scale) - st->waves[i].offset); v /= 2; yy = y + wh/2 + (wh * v); if (ox == -1) ox = x, oy = yy; XDrawLine (st->dpy, st->window, st->gc, ox, oy, x, yy); ox = x; oy = yy; } } { int y = st->xgwa.height * i / (st->nwaves + 1); int ox = -1, oy = -1; for (x = 0; x < st->xgwa.width; x += st->scale) { int yy; double v = 0; for (i = 0; i < st->nwaves; i++) v += cos ((x * st->waves[i].scale) - st->waves[i].offset); v /= st->nwaves; v /= 2; yy = y + wh/2 + (wh * v); if (ox == -1) ox = x, oy = yy; XDrawLine (st->dpy, st->window, st->gc, ox, oy, x, yy); ox = x; oy = yy; } } } return st->delay; } static void cwaves_reshape (Display *dpy, Window window, void *closure, unsigned int w, unsigned int h) { state *st = (state *) closure; XGetWindowAttributes (st->dpy, st->window, &st->xgwa); } static Bool cwaves_event (Display *dpy, Window window, void *closure, XEvent *event) { state *st = (state *) closure; if (screenhack_event_helper (dpy, window, event)) { make_smooth_colormap (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, True, 0, False); return True; } return False; } static void cwaves_free (Display *dpy, Window window, void *closure) { } static const char *cwaves_defaults [] = { ".background: black", ".foreground: white", "*ncolors: 600", "*nwaves: 15", "*scale: 2", "*debug: False", "*delay: 20000", #ifdef HAVE_MOBILE "*ignoreRotation: True", #endif 0 }; static XrmOptionDescRec cwaves_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, { "-waves", ".nwaves", XrmoptionSepArg, 0 }, { "-colors", ".ncolors", XrmoptionSepArg, 0 }, { "-scale", ".scale", XrmoptionSepArg, 0 }, { "-debug", ".debug", XrmoptionNoArg, "True" }, { 0, 0, 0, 0 } }; XSCREENSAVER_MODULE ("CWaves", cwaves)