source: trunk/third/xscreensaver/hacks/coral.c @ 20158

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