ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-1.25.tar.Z
[xscreensaver] / hacks / flame.c
1 /* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@mcom.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 /*#include <math.h>*/
52
53 #define POINT_BUFFER_SIZE 10
54 #define MAXLEV 4
55
56 static double f[2][3][MAXLEV];  /* three non-homogeneous transforms */
57 static int max_total;
58 static int max_levels;
59 static int max_points;
60 static int cur_level;
61 static int snum;
62 static int anum;
63 static int num_points;
64 static int total_points;
65 static int pixcol;
66 static int npixels;
67 static unsigned long *pixels;
68 static XPoint points [POINT_BUFFER_SIZE];
69 static GC gc;
70
71 static int delay, delay2;
72 static int width, height;
73
74 static short
75 halfrandom (mv)
76      int mv;
77 {
78   static short lasthalf = 0;
79   unsigned long r;
80
81   if (lasthalf)
82     {
83       r = lasthalf;
84       lasthalf = 0;
85     }
86   else
87     {
88       r = random ();
89       lasthalf = r >> 16;
90     }
91   return (r % mv);
92 }
93
94
95 static void
96 init_flame (dpy, window)
97      Display *dpy;
98      Window window;
99 {
100   XGCValues gcv;
101   XWindowAttributes xgwa;
102   Colormap cmap;
103   XGetWindowAttributes (dpy, window, &xgwa);
104   width = xgwa.width;
105   height = xgwa.height;
106   cmap = xgwa.colormap;
107
108   max_points = get_integer_resource ("iterations", "Integer");
109   if (max_points <= 0) max_points = 100;
110
111   max_levels = max_points;
112
113   max_total = get_integer_resource ("points", "Integer");
114   if (max_total <= 0) max_total = 10000;
115
116   delay = get_integer_resource ("delay", "Integer");
117   if (delay < 0) delay = 0;
118   delay2 = get_integer_resource ("delay2", "Integer");
119   if (delay2 < 0) delay2 = 0;
120
121   if (mono_p)
122     npixels = 0;
123   else
124     {
125       int i = get_integer_resource ("ncolors", "Integer");
126       double saturation = 1.0;
127       double value = 1.0;
128       XColor color;
129       if (i <= 0) i = 128;
130
131       pixels = (unsigned long *) malloc ((i+1) * sizeof (*pixels));
132       for (npixels = 0; npixels < i; npixels++)
133         {
134           hsv_to_rgb ((360*npixels)/i, saturation, value,
135                       &color.red, &color.green, &color.blue);
136           if (! XAllocColor (dpy, cmap, &color))
137             break;
138           pixels [npixels] = color.pixel;
139         }
140     }
141
142   gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
143   gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
144
145   if (! mono_p)
146     {
147       pixcol = halfrandom (npixels);
148       gcv.foreground = (pixels [pixcol]);
149     }
150
151   gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
152 }
153
154 static int
155 recurse (x, y, l, dpy, win)
156      register double x, y;
157      register int l;
158      Display *dpy;
159      Window win;
160 {
161   int xp, yp, i;
162   double nx, ny;
163
164   if (l == max_levels)
165     {
166       total_points++;
167       if (total_points > max_total) /* how long each fractal runs */
168         return 0;
169
170       if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0)
171         {
172           xp = points[num_points].x = (int) ((width / 2) * (x + 1.0));
173           yp = points[num_points].y = (int) ((height / 2) * (y + 1.0));
174           num_points++;
175           if (num_points >= POINT_BUFFER_SIZE)
176             {
177               XDrawPoints (dpy, win, gc, points, num_points, CoordModeOrigin);
178               num_points = 0;
179               /* if (delay) usleep (delay); */
180               /* XSync (dpy, True); */
181             }
182         }
183     }
184   else
185     {
186       for (i = 0; i < snum; i++)
187         {
188           nx = f[0][0][i] * x + f[0][1][i] * y + f[0][2][i];
189           ny = f[1][0][i] * x + f[1][1][i] * y + f[1][2][i];
190           if (i < anum)
191             {
192               nx = sin(nx);
193               ny = sin(ny);
194             }
195           if (!recurse (nx, ny, l + 1, dpy, win))
196             return 0;
197         }
198     }
199   return 1;
200 }
201
202
203 static void
204 flame (dpy, window)
205      Display *dpy;
206      Window window;
207 {
208   int i, j, k;
209   static int alt = 0;
210
211   if (!(cur_level++ % max_levels))
212     {
213       if (delay2) usleep (delay2);
214       XClearWindow (dpy, window);
215       alt = !alt;
216     }
217   else
218     {
219       if (npixels > 2)
220         {
221           XSetForeground (dpy, gc, pixels [pixcol]);
222           if (--pixcol < 0)
223             pixcol = npixels - 1;
224         }
225     }
226
227   /* number of functions */
228   snum = 2 + (cur_level % (MAXLEV - 1));
229
230   /* how many of them are of alternate form */
231   if (alt)
232     anum = 0;
233   else
234     anum = halfrandom (snum) + 2;
235
236   /* 6 coefs per function */
237   for (k = 0; k < snum; k++)
238     {
239       for (i = 0; i < 2; i++)
240         for (j = 0; j < 3; j++)
241           f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
242     }
243   num_points = 0;
244   total_points = 0;
245   (void) recurse (0.0, 0.0, 0, dpy, window);
246   XDrawPoints (dpy, window, gc, points, num_points, CoordModeOrigin);
247   XSync (dpy, True);
248   if (delay) usleep (delay);
249 }
250
251 \f
252 char *progclass = "Flame";
253
254 char *defaults [] = {
255   "Flame.background:    black",         /* to placate SGI */
256   "Flame.foreground:    white",
257   "*colors:     128",
258   "*iterations: 25",
259   "*delay:      50000",
260   "*delay2:     2000000",
261   "*points:     10000",
262   0
263 };
264
265 XrmOptionDescRec options [] = {
266   { "-ncolors",         ".colors",      XrmoptionSepArg, 0 },
267   { "-iterations",      ".iterations",  XrmoptionSepArg, 0 },
268   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
269   { "-delay2",          ".delay2",      XrmoptionSepArg, 0 },
270   { "-points",          ".points",      XrmoptionSepArg, 0 }
271 };
272 int options_size = (sizeof (options) / sizeof (options[0]));
273
274 void
275 screenhack (dpy, window)
276      Display *dpy;
277      Window window;
278 {
279   init_flame (dpy, window);
280   while (1)
281     flame (dpy, window);
282 }