ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-1.27.tar.Z
[xscreensaver] / hacks / flame.c
1 /* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski <jwz@netscape.com>
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 /* This file was ported from xlock for use in xscreensaver (and standalone)
13  * by jwz on 18-Oct-93.  Original copyright reads:
14  *
15  *   static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK";
16  *
17  * flame.c - recursive fractal cosmic flames.
18  *
19  * Copyright (c) 1991 by Patrick J. Naughton.
20  *
21  * Permission to use, copy, modify, and distribute this software and its
22  * documentation for any purpose and without fee is hereby granted,
23  * provided that the above copyright notice appear in all copies and that
24  * both that copyright notice and this permission notice appear in
25  * supporting documentation.
26  *
27  * This file is provided AS IS with no warranties of any kind.  The author
28  * shall have no liability with respect to the infringement of copyrights,
29  * trade secrets or any patents by this file or any part thereof.  In no
30  * event will the author be liable for any lost revenue or profits or
31  * other special, indirect and consequential damages.
32  *
33  * Comments and additions should be sent to the author:
34  *
35  *                     naughton@eng.sun.com
36  *
37  *                     Patrick J. Naughton
38  *                     MS 21-14
39  *                     Sun Laboritories, Inc.
40  *                     2550 Garcia Ave
41  *                     Mountain View, CA  94043
42  *
43  * Revision History:
44  * 27-Jun-91: vary number of functions used.
45  * 24-Jun-91: fixed portability problem with integer mod (%).
46  * 06-Jun-91: Written. (received from Scott Graves, spot@cs.cmu.edu).
47  */
48
49 #include "screenhack.h"
50
51 #define POINT_BUFFER_SIZE 10
52 #define MAXLEV 4
53
54 static double f[2][3][MAXLEV];  /* three non-homogeneous transforms */
55 static int max_total;
56 static int max_levels;
57 static int max_points;
58 static int cur_level;
59 static int snum;
60 static int anum;
61 static int num_points;
62 static int total_points;
63 static int pixcol;
64 static int npixels;
65 static unsigned long *pixels;
66 static XPoint points [POINT_BUFFER_SIZE];
67 static GC gc;
68
69 static int delay, delay2;
70 static int width, height;
71
72 static short
73 halfrandom (mv)
74      int mv;
75 {
76   static short lasthalf = 0;
77   unsigned long r;
78
79   if (lasthalf)
80     {
81       r = lasthalf;
82       lasthalf = 0;
83     }
84   else
85     {
86       r = random ();
87       lasthalf = r >> 16;
88     }
89   return (r % mv);
90 }
91
92
93 static void
94 init_flame (dpy, window)
95      Display *dpy;
96      Window window;
97 {
98   XGCValues gcv;
99   XWindowAttributes xgwa;
100   Colormap cmap;
101   XGetWindowAttributes (dpy, window, &xgwa);
102   width = xgwa.width;
103   height = xgwa.height;
104   cmap = xgwa.colormap;
105
106   max_points = get_integer_resource ("iterations", "Integer");
107   if (max_points <= 0) max_points = 100;
108
109   max_levels = max_points;
110
111   max_total = get_integer_resource ("points", "Integer");
112   if (max_total <= 0) max_total = 10000;
113
114   delay = get_integer_resource ("delay", "Integer");
115   if (delay < 0) delay = 0;
116   delay2 = get_integer_resource ("delay2", "Integer");
117   if (delay2 < 0) delay2 = 0;
118
119   if (mono_p)
120     npixels = 0;
121   else
122     {
123       int i = get_integer_resource ("ncolors", "Integer");
124       double saturation = 1.0;
125       double value = 1.0;
126       XColor color;
127       if (i <= 0) i = 128;
128
129       pixels = (unsigned long *) malloc ((i+1) * sizeof (*pixels));
130       for (npixels = 0; npixels < i; npixels++)
131         {
132           hsv_to_rgb ((360*npixels)/i, saturation, value,
133                       &color.red, &color.green, &color.blue);
134           if (! XAllocColor (dpy, cmap, &color))
135             break;
136           pixels [npixels] = color.pixel;
137         }
138     }
139
140   gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
141   gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
142
143   if (! mono_p)
144     {
145       pixcol = halfrandom (npixels);
146       gcv.foreground = (pixels [pixcol]);
147     }
148
149   gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
150 }
151
152 static int
153 recurse (x, y, l, dpy, win)
154      register double x, y;
155      register int l;
156      Display *dpy;
157      Window win;
158 {
159   int xp, yp, i;
160   double nx, ny;
161
162   if (l == max_levels)
163     {
164       total_points++;
165       if (total_points > max_total) /* how long each fractal runs */
166         return 0;
167
168       if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0)
169         {
170           xp = points[num_points].x = (int) ((width / 2) * (x + 1.0));
171           yp = points[num_points].y = (int) ((height / 2) * (y + 1.0));
172           num_points++;
173           if (num_points >= POINT_BUFFER_SIZE)
174             {
175               XDrawPoints (dpy, win, gc, points, num_points, CoordModeOrigin);
176               num_points = 0;
177               /* if (delay) usleep (delay); */
178               /* XSync (dpy, True); */
179             }
180         }
181     }
182   else
183     {
184       for (i = 0; i < snum; i++)
185         {
186           nx = f[0][0][i] * x + f[0][1][i] * y + f[0][2][i];
187           ny = f[1][0][i] * x + f[1][1][i] * y + f[1][2][i];
188           if (i < anum)
189             {
190               nx = sin(nx);
191               ny = sin(ny);
192             }
193           if (!recurse (nx, ny, l + 1, dpy, win))
194             return 0;
195         }
196     }
197   return 1;
198 }
199
200
201 static void
202 flame (dpy, window)
203      Display *dpy;
204      Window window;
205 {
206   int i, j, k;
207   static int alt = 0;
208
209   if (!(cur_level++ % max_levels))
210     {
211       if (delay2) usleep (delay2);
212       XClearWindow (dpy, window);
213       alt = !alt;
214     }
215   else
216     {
217       if (npixels > 2)
218         {
219           XSetForeground (dpy, gc, pixels [pixcol]);
220           if (--pixcol < 0)
221             pixcol = npixels - 1;
222         }
223     }
224
225   /* number of functions */
226   snum = 2 + (cur_level % (MAXLEV - 1));
227
228   /* how many of them are of alternate form */
229   if (alt)
230     anum = 0;
231   else
232     anum = halfrandom (snum) + 2;
233
234   /* 6 coefs per function */
235   for (k = 0; k < snum; k++)
236     {
237       for (i = 0; i < 2; i++)
238         for (j = 0; j < 3; j++)
239           f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
240     }
241   num_points = 0;
242   total_points = 0;
243   (void) recurse (0.0, 0.0, 0, dpy, window);
244   XDrawPoints (dpy, window, gc, points, num_points, CoordModeOrigin);
245   XSync (dpy, True);
246   if (delay) usleep (delay);
247 }
248
249
250 #ifdef __hpux
251 /* I don't understand why this is necessary, but I'm told that this program
252    does nothing at all on HP-sUX without it.
253  */
254 #undef random
255 #undef srandom
256 #include <math.h>
257 int matherr(x)
258    register struct exception *x;
259 {
260   if (x->type == PLOSS) return 1;
261   else return 0;
262 }
263 #endif /* __hpux */
264
265
266 \f
267 char *progclass = "Flame";
268
269 char *defaults [] = {
270   "Flame.background:    black",         /* to placate SGI */
271   "Flame.foreground:    white",
272   "*colors:     128",
273   "*iterations: 25",
274   "*delay:      50000",
275   "*delay2:     2000000",
276   "*points:     10000",
277   0
278 };
279
280 XrmOptionDescRec options [] = {
281   { "-ncolors",         ".colors",      XrmoptionSepArg, 0 },
282   { "-iterations",      ".iterations",  XrmoptionSepArg, 0 },
283   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
284   { "-delay2",          ".delay2",      XrmoptionSepArg, 0 },
285   { "-points",          ".points",      XrmoptionSepArg, 0 }
286 };
287 int options_size = (sizeof (options) / sizeof (options[0]));
288
289 void
290 screenhack (dpy, window)
291      Display *dpy;
292      Window window;
293 {
294   init_flame (dpy, window);
295   while (1)
296     flame (dpy, window);
297 }