Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtscreen / flame.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: flame.c /main/3 1995/11/02 16:07:01 rswiston $ */
24 /*
25  */
26 /*                                                                      *
27  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
28  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
29  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
30  * (c) Copyright 1993, 1994 Novell, Inc.                                *
31  */
32 /*-
33  * flame.c - recursive fractal cosmic flames.
34  *
35  * Copyright (c) 1991 by Patrick J. Naughton.
36  *
37  * See dtscreen.c for copying information.
38  *
39  * Revision History:
40  * 27-Jun-91: vary number of functions used.
41  * 24-Jun-91: fixed portability problem with integer mod (%).
42  * 06-Jun-91: Written. (received from Scott Graves, spot@cs.cmu.edu).
43  */
44
45 #include "dtscreen.h"
46 #include <math.h>
47
48 #define MAXTOTAL        10000
49 #define MAXBATCH        10
50 #define MAXLEV          4
51
52 typedef struct {
53     double      f[2][3][MAXLEV];/* three non-homogeneous transforms */
54     int         max_levels;
55     int         cur_level;
56     int         snum;
57     int         anum;
58     int         width, height;
59     int         num_points;
60     int         total_points;
61     int         pixcol;
62     perwindow  *pwin;
63     XPoint      pts[MAXBATCH];
64 }           flamestruct;
65
66 static short
67 halfrandom(mv)
68     int         mv;
69 {
70     static short lasthalf = 0;
71     unsigned long r;
72
73     if (lasthalf) {
74         r = lasthalf;
75         lasthalf = 0;
76     } else {
77         r = random();
78         lasthalf = r >> 16;
79     }
80     return r % mv;
81 }
82
83 void
84 initflame(pwin)
85     perwindow      *pwin;
86 {
87     XWindowAttributes xwa;
88     flamestruct *fs;
89
90     if (pwin->data) free(pwin->data);
91     pwin->data = (void *)malloc(sizeof(flamestruct));
92     memset(pwin->data, '\0', sizeof(flamestruct));
93     fs = (flamestruct *)pwin->data;
94
95     srandom(time((time_t *) 0));
96
97     XGetWindowAttributes(dsp, pwin->w, &xwa);
98     fs->width = xwa.width;
99     fs->height = xwa.height;
100
101     fs->max_levels = batchcount;
102     fs->pwin = pwin;
103
104     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
105     XFillRectangle(dsp, pwin->w, pwin->gc, 0, 0, fs->width, fs->height);
106
107     if (pwin->perscreen->npixels > 2) {
108       fs->pixcol = halfrandom(pwin->perscreen->npixels);
109       XSetForeground(dsp, pwin->gc, pwin->perscreen->pixels[fs->pixcol]);
110     } else {
111       XSetForeground(dsp, pwin->gc, WhitePixelOfScreen(pwin->perscreen->screen));
112     }
113 }
114
115 static      Bool
116 recurse(fs, x, y, l)
117     flamestruct *fs;
118     register double x, y;
119     register int l;
120 {
121     int         xp, yp, i;
122     double      nx, ny;
123
124     if (l == fs->max_levels) {
125         fs->total_points++;
126         if (fs->total_points > MAXTOTAL)        /* how long each fractal runs */
127             return False;
128
129         if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) {
130             xp = fs->pts[fs->num_points].x = (int) ((fs->width / 2)
131                                                     * (x + 1.0));
132             yp = fs->pts[fs->num_points].y = (int) ((fs->height / 2)
133                                                     * (y + 1.0));
134             fs->num_points++;
135             if (fs->num_points > MAXBATCH) {    /* point buffer size */
136                 XDrawPoints(dsp, fs->pwin->w, fs->pwin->gc, fs->pts,
137                             fs->num_points, CoordModeOrigin);
138                 fs->num_points = 0;
139             }
140         }
141     } else {
142         for (i = 0; i < fs->snum; i++) {
143             nx = fs->f[0][0][i] * x + fs->f[0][1][i] * y + fs->f[0][2][i];
144             ny = fs->f[1][0][i] * x + fs->f[1][1][i] * y + fs->f[1][2][i];
145             if (i < fs->anum) {
146                 nx = sin(nx);
147                 ny = sin(ny);
148             }
149             if (!recurse(fs, nx, ny, l + 1))
150                 return False;
151         }
152     }
153     return True;
154 }
155
156
157 void
158 drawflame(pwin)
159     perwindow *pwin;
160 {
161     flamestruct *fs = (flamestruct *)pwin->data;
162
163     int         i, j, k;
164     static      alt = 0;
165
166     if (!(fs->cur_level++ % fs->max_levels)) {
167         XClearWindow(dsp, fs->pwin->w);
168         alt = !alt;
169     } else {
170         if (pwin->perscreen->npixels > 2) {
171             XSetForeground(dsp, pwin->gc,
172                            pwin->perscreen->pixels[fs->pixcol]);
173             if (--fs->pixcol < 0)
174                 fs->pixcol = pwin->perscreen->npixels - 1;
175         }
176     }
177
178     /* number of functions */
179     fs->snum = 2 + (fs->cur_level % (MAXLEV - 1));
180
181     /* how many of them are of alternate form */
182     if (alt)
183         fs->anum = 0;
184     else
185         fs->anum = halfrandom(fs->snum) + 2;
186
187     /* 6 dtfs per function */
188     for (k = 0; k < fs->snum; k++) {
189         for (i = 0; i < 2; i++)
190             for (j = 0; j < 3; j++)
191                 fs->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
192     }
193     fs->num_points = 0;
194     fs->total_points = 0;
195     (void) recurse(fs, 0.0, 0.0, 0);
196     XDrawPoints(dsp, pwin->w, pwin->gc,
197                 fs->pts, fs->num_points, CoordModeOrigin);
198 }