ftp://ftp.sunet.se/pub/os/Linux/distributions/ultrapenguin/ultrapenguin-1.1/SRPMS...
[xscreensaver] / hacks / coral.c
1 /* coral, by "Frederick G.M. Roeber" <roeber@netscape.com>, 15-jul-97.
2  *
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 
9  * implied warranty.
10  */
11
12 #include "screenhack.h"
13 #include "colors.h"
14
15 static GC draw_gc;
16 static unsigned int default_fg_pixel;
17 #define NCOLORSMAX 200
18 static XColor colors[NCOLORSMAX];
19 static int ncolors = 0;
20 static int colorindex = 0;
21 static int colorsloth;
22
23 static XPoint *walkers;
24 static int nwalkers;
25 static int width, widthb;
26 static int height;
27
28 static unsigned int *board;
29 #define getdot(x,y) (board[(y*widthb)+(x>>5)] &  (1<<(x & 31)))
30 #define setdot(x,y) (board[(y*widthb)+(x>>5)] |= (1<<(x & 31)))
31
32
33 static void
34 init_coral(Display *dpy, Window window)
35 {
36     XGCValues gcv;
37     Colormap cmap;
38     XWindowAttributes xgwa;
39     Bool writeable = False;
40     int seeds;
41     int density;
42     int i;
43
44     XClearWindow(dpy, window);
45     XGetWindowAttributes(dpy, window, &xgwa);
46     width = xgwa.width;
47     widthb = ((xgwa.width + 31) >> 5);
48     height = xgwa.height;
49     board = (unsigned int *)calloc(widthb * xgwa.height, sizeof(unsigned int));
50     if(!board) exit(1);
51     cmap = xgwa.colormap;
52     if( ncolors ) {
53         free_colors(dpy, cmap, colors, ncolors);
54         ncolors = 0;
55     }
56     gcv.foreground = default_fg_pixel = get_pixel_resource("foreground", "Foreground", dpy, cmap);
57     draw_gc = XCreateGC(dpy, window, GCForeground, &gcv);
58     ncolors = NCOLORSMAX;
59     make_uniform_colormap(dpy, xgwa.visual, cmap, colors, &ncolors, True, &writeable, False);
60     colorindex = random()%ncolors;
61     
62     density = get_integer_resource("density", "Integer");
63     if( density < 1 ) density = 1;
64     if( density > 100 ) density = 90; /* more like mold than coral */
65     nwalkers = (width*height*density)/100;
66     walkers = (XPoint *)calloc(nwalkers, sizeof(XPoint));
67     if( (XPoint *)0 == walkers ) exit(1);
68
69     seeds = get_integer_resource("seeds", "Integer");
70     if( seeds < 1 ) seeds = 1;
71     if( seeds > 1000 ) seeds = 1000;
72
73     colorsloth = nwalkers*2/ncolors;
74     XSetForeground(dpy, draw_gc, colors[colorindex].pixel);
75
76     for( i = 0; i < seeds; i++ ) {
77         int x, y;
78         do {
79             x = random() % width;
80             y = random() % height;
81         } while( getdot(x, y) );
82
83         setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
84         setdot((x-1),  y   ); setdot(x,  y   ); setdot((x+1),  y   );
85         setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
86         XDrawPoint(dpy, window, draw_gc, x, y);
87     }
88
89     for( i = 0; i < nwalkers; i++ ) {
90         walkers[i].x = (random() % (width-2)) + 1;
91         walkers[i].y = (random() % (height-2)) + 1;
92     }
93 }
94
95
96 /* returns 2 bits of randomness (conserving calls to random()).
97    This speeds things up a little, but not a lot (5-10% or so.)
98  */
99 static int 
100 rand_2(void)
101 {
102   static int i = 0;
103   static int r = 0;
104   if (i != 0) {
105     i--;
106   } else {
107     i = 15;
108     r = random();
109   }
110
111   {
112     register int j = (r & 3);
113     r = r >> 2;
114     return j;
115   }
116 }
117
118
119 static void
120 coral(Display *dpy, Window window)
121 {
122     int delay2 = get_integer_resource ("delay2", "Integer");
123
124     int max_points = 200;
125     int npoints = 0;
126     XPoint *pointbuf = (XPoint *) calloc(sizeof(XPoint), max_points+2);
127     if (!pointbuf) exit(-1);
128
129     while( 1 ) {
130         int i;
131
132         for( i = 0; i < nwalkers; i++ ) {
133             int x = walkers[i].x;
134             int y = walkers[i].y;
135
136             if( getdot(x, y) ) {
137
138                 Bool flush = False;
139                 Bool color = False;
140
141                 /* XDrawPoint(dpy, window, draw_gc, x, y); */
142                 pointbuf[npoints].x = x;
143                 pointbuf[npoints].y = y;
144                 npoints++;
145
146                 /* Mark the surrounding area as "sticky" */
147                 setdot((x-1), (y-1)); setdot(x, (y-1)); setdot((x+1), (y-1));
148                 setdot((x-1),  y   );                   setdot((x+1),  y   );
149                 setdot((x-1), (y+1)); setdot(x, (y+1)); setdot((x+1), (y+1));
150                 nwalkers--;
151                 walkers[i].x = walkers[nwalkers].x;
152                 walkers[i].y = walkers[nwalkers].y;
153                 if( 0 == (nwalkers%colorsloth) ) {
154                   color = True;
155                 }
156                   
157                 if (flush || color || 0 == nwalkers || npoints >= max_points) {
158                   XDrawPoints(dpy, window, draw_gc, pointbuf, npoints,
159                               CoordModeOrigin);
160                   npoints = 0;
161                   XSync(dpy, True);
162                 }
163
164                 if (color) {
165                     colorindex++;
166                     if( colorindex == ncolors )
167                         colorindex = 0;
168                     XSetForeground(dpy, draw_gc, colors[colorindex].pixel);
169                 }
170
171                 if( 0 == nwalkers ) {
172                     XSync(dpy, True);
173                     free(pointbuf);
174                     return;
175                 }
176             } else {
177                 /* move it a notch */
178                 do {
179                     switch(rand_2()) {
180                     case 0:
181                         if( 1 == x ) continue;
182                         walkers[i].x--;
183                         break;
184                     case 1:
185                         if( width-2 == x ) continue;
186                         walkers[i].x++;
187                         break;
188                     case 2:
189                         if( 1 == y ) continue;
190                         walkers[i].y--;
191                         break;
192                     default: /* case 3: */
193                         if( height-2 == y ) continue;
194                         walkers[i].y++;
195                         break;
196                     /* default:
197                       abort(); */
198                     }
199                 } while(0);
200             }
201         }
202
203         if (delay2 > 0) {
204           if (npoints > 0) {
205             XDrawPoints(dpy, window, draw_gc, pointbuf, npoints,
206                         CoordModeOrigin);
207             npoints = 0;
208             XSync(dpy, True);
209           }
210           usleep(delay2);
211         }
212     }
213 }
214
215 char *progclass = "Coral";
216
217 char *defaults[] = {
218     "Coral.background: black",
219     "Coral.foreground: white",
220     "*density: 25",
221     "*seeds: 20", /* too many for 640x480, too few for 1280x1024 */
222     "*delay: 5",
223     "*delay2: 1000",
224     0
225 };
226
227 XrmOptionDescRec options[] = {
228     { "-density", ".density", XrmoptionSepArg, 0 },
229     { "-seeds", ".seeds", XrmoptionSepArg, 0 },
230     { "-delay", ".delay", XrmoptionSepArg, 0 },
231     { "-delay2", ".delay2", XrmoptionSepArg, 0 },
232     { 0, 0, 0, 0 }
233 };
234
235 void
236 screenhack(dpy, window)
237 Display *dpy;
238 Window window;
239 {
240     int delay = get_integer_resource ("delay", "Integer");
241
242     while( 1 ) {
243         init_coral(dpy, window);
244         coral(dpy, window);
245         if( delay ) sleep(delay);
246     }
247 }