summaryrefslogtreecommitdiffstats
path: root/hacks/coral.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/coral.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/coral.c')
-rw-r--r--hacks/coral.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/hacks/coral.c b/hacks/coral.c
new file mode 100644
index 0000000..9cfcf50
--- /dev/null
+++ b/hacks/coral.c
@@ -0,0 +1,314 @@
+/* coral, by "Frederick G.M. Roeber" <roeber@netscape.com>, 15-jul-97.
+ *
+ * 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"
+#include "colors.h"
+#include "erase.h"
+
+#define NCOLORSMAX 200
+
+struct state {
+ Display *dpy;
+ Window window;
+
+ GC draw_gc, erase_gc;
+ unsigned int default_fg_pixel;
+ XColor colors[NCOLORSMAX];
+ int ncolors;
+ int colorindex;
+ int colorsloth;
+
+ XPoint *walkers;
+ int nwalkers;
+ int width, widthb;
+ int height;
+ int delay, delay2;
+ int max_points;
+ XPoint *pointbuf;
+
+ unsigned int *board;
+
+ int done, reset;
+ int npoints;
+ eraser_state *eraser;
+};
+
+
+#define getdot(x,y) (st->board[(y*st->widthb)+(x>>5)] & (1<<(x & 31)))
+#define setdot(x,y) (st->board[(y*st->widthb)+(x>>5)] |= (1<<(x & 31)))
+
+
+static void
+init_coral(struct state *st)
+{
+ XGCValues gcv;
+ Colormap cmap;
+ XWindowAttributes xgwa;
+ Bool writeable = False;
+ int seeds;
+ int density;
+ int i;
+
+ XClearWindow(st->dpy, st->window);
+ XGetWindowAttributes(st->dpy, st->window, &xgwa);
+ st->width = xgwa.width;
+ st->widthb = ((xgwa.width + 31) >> 5);
+ st->height = xgwa.height;
+ if (st->board) free(st->board);
+ st->board = (unsigned int *)calloc(st->widthb * xgwa.height, sizeof(unsigned int));
+ if(!st->board) exit(1);
+ cmap = xgwa.colormap;
+ if( st->ncolors ) {
+ free_colors(xgwa.screen, cmap, st->colors, st->ncolors);
+ st->ncolors = 0;
+ }
+ gcv.foreground = st->default_fg_pixel = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground");
+ st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background");
+ st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
+ st->ncolors = NCOLORSMAX;
+ make_uniform_colormap(xgwa.screen, xgwa.visual, cmap,
+ st->colors, &st->ncolors, True, &writeable, False);
+ if (st->ncolors <= 0) {
+ st->ncolors = 2;
+ st->colors[0].red = st->colors[0].green = st->colors[0].blue = 0;
+ st->colors[1].red = st->colors[1].green = st->colors[1].blue = 0xFFFF;
+ XAllocColor(st->dpy, cmap, &st->colors[0]);
+ XAllocColor(st->dpy, cmap, &st->colors[1]);
+ }
+ st->colorindex = random()%st->ncolors;
+
+ density = get_integer_resource(st->dpy, "density", "Integer");
+ if( density < 1 ) density = 1;
+ if( density > 100 ) density = 90; /* more like mold than coral */
+ st->nwalkers = (st->width*st->height*density)/100;
+ if (st->walkers) free(st->walkers);
+ st->walkers = (XPoint *)calloc(st->nwalkers, sizeof(XPoint));
+ if( (XPoint *)0 == st->walkers ) exit(1);
+
+ seeds = get_integer_resource(st->dpy, "seeds", "Integer");
+ if( seeds < 1 ) seeds = 1;
+ if( seeds > 1000 ) seeds = 1000;
+
+ st->colorsloth = st->nwalkers*2/st->ncolors;
+ XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel);
+
+ if ((st->width <= 2) || (st->height <= 2)) return;
+
+ for( i = 0; i < seeds; i++ ) {
+ int x, y;
+ int max_repeat = 10;
+ do {
+ x = 1 + random() % (st->width - 2);
+ y = 1 + random() % (st->height - 2);
+ } while( getdot(x, y) && max_repeat--);
+
+ setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
+ setdot((x-1), y ); setdot(x, y ); setdot((x+1), y );
+ setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
+ XDrawPoint(st->dpy, st->window, st->draw_gc, x, y);
+ }
+
+ for( i = 0; i < st->nwalkers; i++ ) {
+ st->walkers[i].x = (random() % (st->width-2)) + 1;
+ st->walkers[i].y = (random() % (st->height-2)) + 1;
+ }
+}
+
+
+/* returns 2 bits of randomness (conserving calls to random()).
+ This speeds things up a little, but not a lot (5-10% or so.)
+ */
+static int
+rand_2(void)
+{
+ static int i = 0;
+ static int r = 0;
+ if (i != 0) {
+ i--;
+ } else {
+ i = 15;
+ r = random();
+ }
+
+ {
+ register int j = (r & 3);
+ r = r >> 2;
+ return j;
+ }
+}
+
+
+static int
+coral(struct state *st)
+{
+ int i = 0;
+
+ for( i = 0; i < st->nwalkers; i++ ) {
+ int x = st->walkers[i].x;
+ int y = st->walkers[i].y;
+
+ if( getdot(x, y) ) {
+
+ Bool flush = False;
+ Bool color = False;
+
+ /* XDrawPoint(dpy, window, draw_gc, x, y); */
+ st->pointbuf[st->npoints].x = x;
+ st->pointbuf[st->npoints].y = y;
+ st->npoints++;
+
+ /* Mark the surrounding area as "sticky" */
+ setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
+ setdot((x-1), y ); setdot((x+1), y );
+ setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
+ st->nwalkers--;
+ st->walkers[i].x = st->walkers[st->nwalkers].x;
+ st->walkers[i].y = st->walkers[st->nwalkers].y;
+ if( 0 ==
+ ((st->colorsloth ? st->nwalkers%st->colorsloth : 0)) ) {
+ color = True;
+ }
+
+ if (flush || color || 0 == st->nwalkers || st->npoints >= st->max_points) {
+ XDrawPoints(st->dpy, st->window, st->draw_gc, st->pointbuf, st->npoints,
+ CoordModeOrigin);
+ st->npoints = 0;
+ }
+
+ if (color) {
+ st->colorindex++;
+ if( st->colorindex == st->ncolors )
+ st->colorindex = 0;
+ XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel);
+ }
+ } else {
+ /* move it a notch */
+ do {
+ switch(rand_2()) {
+ case 0:
+ if( 1 == x ) continue;
+ st->walkers[i].x--;
+ break;
+ case 1:
+ if( st->width-2 == x ) continue;
+ st->walkers[i].x++;
+ break;
+ case 2:
+ if( 1 == y ) continue;
+ st->walkers[i].y--;
+ break;
+ default: /* case 3: */
+ if( st->height-2 == y ) continue;
+ st->walkers[i].y++;
+ break;
+ /* default:
+ abort(); */
+ }
+ } while(0);
+ }
+ }
+
+ return (0 == st->nwalkers);
+}
+
+static void *
+coral_init (Display *dpy, Window window)
+{
+ struct state *st = (struct state *) calloc (1, sizeof(*st));
+ st->dpy = dpy;
+ st->window = window;
+ st->max_points = 200;
+ st->pointbuf = (XPoint *) calloc(sizeof(XPoint), st->max_points+2);
+ if (!st->pointbuf) exit(-1);
+
+ st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
+ st->reset = 1;
+ return st;
+}
+
+
+static unsigned long
+coral_draw (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+
+ if (st->eraser || st->done)
+ {
+ st->done = 0;
+ st->eraser = erase_window (st->dpy, st->window, st->eraser);
+ return st->delay2;
+ }
+
+ if (st->reset)
+ init_coral(st);
+ st->reset = st->done = coral(st);
+
+ return (st->reset
+ ? (st->delay * 1000000)
+ : st->delay2);
+}
+
+static void
+coral_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ init_coral(st);
+}
+
+static Bool
+coral_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+ struct state *st = (struct state *) closure;
+ if (screenhack_event_helper (dpy, window, event))
+ {
+ st->reset = 1;
+ return True;
+ }
+ return False;
+}
+
+static void
+coral_free (Display *dpy, Window window, void *closure)
+{
+ struct state *st = (struct state *) closure;
+ free (st->pointbuf);
+ if (st->walkers) free (st->walkers);
+ if (st->board) free (st->board);
+ free (st);
+}
+
+static const char *coral_defaults[] = {
+ ".lowrez: true",
+ ".background: black",
+ ".foreground: white",
+ "*fpsSolid: true",
+ "*density: 25",
+ "*seeds: 20", /* too many for 640x480, too few for 1280x1024 */
+ "*delay: 5",
+ "*delay2: 20000",
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+ 0
+};
+
+static XrmOptionDescRec coral_options[] = {
+ { "-density", ".density", XrmoptionSepArg, 0 },
+ { "-seeds", ".seeds", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-delay2", ".delay2", XrmoptionSepArg, 0 },
+ { 0, 0, 0, 0 }
+};
+
+XSCREENSAVER_MODULE ("Coral", coral)