1 /* coral, by "Frederick G.M. Roeber" <roeber@netscape.com>, 15-jul-97.
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #include "screenhack.h"
16 #define NCOLORSMAX 200
23 unsigned int default_fg_pixel;
24 XColor colors[NCOLORSMAX];
45 #define getdot(x,y) (st->board[(y*st->widthb)+(x>>5)] & (1<<(x & 31)))
46 #define setdot(x,y) (st->board[(y*st->widthb)+(x>>5)] |= (1<<(x & 31)))
50 init_coral(struct state *st)
54 XWindowAttributes xgwa;
55 Bool writeable = False;
60 XClearWindow(st->dpy, st->window);
61 XGetWindowAttributes(st->dpy, st->window, &xgwa);
62 st->width = xgwa.width;
63 st->widthb = ((xgwa.width + 31) >> 5);
64 st->height = xgwa.height;
65 if (st->board) free(st->board);
66 st->board = (unsigned int *)calloc(st->widthb * xgwa.height, sizeof(unsigned int));
67 if(!st->board) exit(1);
70 free_colors(xgwa.screen, cmap, st->colors, st->ncolors);
73 gcv.foreground = st->default_fg_pixel = get_pixel_resource(st->dpy, cmap, "foreground", "Foreground");
74 st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
75 gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background");
76 st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
77 st->ncolors = NCOLORSMAX;
78 make_uniform_colormap(xgwa.screen, xgwa.visual, cmap,
79 st->colors, &st->ncolors, True, &writeable, False);
80 if (st->ncolors <= 0) {
82 st->colors[0].red = st->colors[0].green = st->colors[0].blue = 0;
83 st->colors[1].red = st->colors[1].green = st->colors[1].blue = 0xFFFF;
84 XAllocColor(st->dpy, cmap, &st->colors[0]);
85 XAllocColor(st->dpy, cmap, &st->colors[1]);
87 st->colorindex = random()%st->ncolors;
89 density = get_integer_resource(st->dpy, "density", "Integer");
90 if( density < 1 ) density = 1;
91 if( density > 100 ) density = 90; /* more like mold than coral */
92 st->nwalkers = (st->width*st->height*density)/100;
93 if (st->walkers) free(st->walkers);
94 st->walkers = (XPoint *)calloc(st->nwalkers, sizeof(XPoint));
95 if( (XPoint *)0 == st->walkers ) exit(1);
97 seeds = get_integer_resource(st->dpy, "seeds", "Integer");
98 if( seeds < 1 ) seeds = 1;
99 if( seeds > 1000 ) seeds = 1000;
101 st->colorsloth = st->nwalkers*2/st->ncolors;
102 XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel);
104 if ((st->width <= 2) || (st->height <= 2)) return;
106 for( i = 0; i < seeds; i++ ) {
110 x = 1 + random() % (st->width - 2);
111 y = 1 + random() % (st->height - 2);
112 } while( getdot(x, y) && max_repeat--);
114 setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
115 setdot((x-1), y ); setdot(x, y ); setdot((x+1), y );
116 setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
117 XDrawPoint(st->dpy, st->window, st->draw_gc, x, y);
120 for( i = 0; i < st->nwalkers; i++ ) {
121 st->walkers[i].x = (random() % (st->width-2)) + 1;
122 st->walkers[i].y = (random() % (st->height-2)) + 1;
127 /* returns 2 bits of randomness (conserving calls to random()).
128 This speeds things up a little, but not a lot (5-10% or so.)
143 register int j = (r & 3);
151 coral(struct state *st)
155 for( i = 0; i < st->nwalkers; i++ ) {
156 int x = st->walkers[i].x;
157 int y = st->walkers[i].y;
164 /* XDrawPoint(dpy, window, draw_gc, x, y); */
165 st->pointbuf[st->npoints].x = x;
166 st->pointbuf[st->npoints].y = y;
169 /* Mark the surrounding area as "sticky" */
170 setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
171 setdot((x-1), y ); setdot((x+1), y );
172 setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
174 st->walkers[i].x = st->walkers[st->nwalkers].x;
175 st->walkers[i].y = st->walkers[st->nwalkers].y;
177 ((st->colorsloth ? st->nwalkers%st->colorsloth : 0)) ) {
181 if (flush || color || 0 == st->nwalkers || st->npoints >= st->max_points) {
182 XDrawPoints(st->dpy, st->window, st->draw_gc, st->pointbuf, st->npoints,
189 if( st->colorindex == st->ncolors )
191 XSetForeground(st->dpy, st->draw_gc, st->colors[st->colorindex].pixel);
194 /* move it a notch */
198 if( 1 == x ) continue;
202 if( st->width-2 == x ) continue;
206 if( 1 == y ) continue;
209 default: /* case 3: */
210 if( st->height-2 == y ) continue;
220 return (0 == st->nwalkers);
224 coral_init (Display *dpy, Window window)
226 struct state *st = (struct state *) calloc (1, sizeof(*st));
229 st->max_points = 200;
230 st->pointbuf = (XPoint *) calloc(sizeof(XPoint), st->max_points+2);
231 if (!st->pointbuf) exit(-1);
233 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
234 st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
241 coral_draw (Display *dpy, Window window, void *closure)
243 struct state *st = (struct state *) closure;
245 if (st->eraser || st->done)
248 st->eraser = erase_window (st->dpy, st->window, st->eraser);
254 st->reset = st->done = coral(st);
257 ? (st->delay * 1000000)
262 coral_reshape (Display *dpy, Window window, void *closure,
263 unsigned int w, unsigned int h)
265 struct state *st = (struct state *) closure;
270 coral_event (Display *dpy, Window window, void *closure, XEvent *event)
276 coral_free (Display *dpy, Window window, void *closure)
278 struct state *st = (struct state *) closure;
280 if (st->walkers) free (st->walkers);
281 if (st->board) free (st->board);
285 static const char *coral_defaults[] = {
286 ".background: black",
287 ".foreground: white",
290 "*seeds: 20", /* too many for 640x480, too few for 1280x1024 */
294 "*ignoreRotation: True",
299 static XrmOptionDescRec coral_options[] = {
300 { "-density", ".density", XrmoptionSepArg, 0 },
301 { "-seeds", ".seeds", XrmoptionSepArg, 0 },
302 { "-delay", ".delay", XrmoptionSepArg, 0 },
303 { "-delay2", ".delay2", XrmoptionSepArg, 0 },
307 XSCREENSAVER_MODULE ("Coral", coral)