Don't use fstat for readable pipe chars in dtexec.
[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 #include <stdlib.h>
48
49 #define MAXTOTAL        10000
50 #define MAXBATCH        10
51 #define MAXLEV          4
52
53 typedef struct {
54     double      f[2][3][MAXLEV];/* three non-homogeneous transforms */
55     int         max_levels;
56     int         cur_level;
57     int         snum;
58     int         anum;
59     int         width, height;
60     int         num_points;
61     int         total_points;
62     int         pixcol;
63     perwindow  *pwin;
64     XPoint      pts[MAXBATCH];
65 }           flamestruct;
66
67 static short
68 halfrandom(mv)
69     int         mv;
70 {
71     static short lasthalf = 0;
72     unsigned long r;
73
74     if (lasthalf) {
75         r = lasthalf;
76         lasthalf = 0;
77     } else {
78         r = random();
79         lasthalf = r >> 16;
80     }
81     return r % mv;
82 }
83
84 void
85 initflame(pwin)
86     perwindow      *pwin;
87 {
88     XWindowAttributes xwa;
89     flamestruct *fs;
90
91     if (pwin->data) free(pwin->data);
92     pwin->data = (void *)malloc(sizeof(flamestruct));
93     memset(pwin->data, '\0', sizeof(flamestruct));
94     fs = (flamestruct *)pwin->data;
95
96     srandom(time((time_t *) 0));
97
98     XGetWindowAttributes(dsp, pwin->w, &xwa);
99     fs->width = xwa.width;
100     fs->height = xwa.height;
101
102     fs->max_levels = batchcount;
103     fs->pwin = pwin;
104
105     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
106     XFillRectangle(dsp, pwin->w, pwin->gc, 0, 0, fs->width, fs->height);
107
108     if (pwin->perscreen->npixels > 2) {
109       fs->pixcol = halfrandom(pwin->perscreen->npixels);
110       XSetForeground(dsp, pwin->gc, pwin->perscreen->pixels[fs->pixcol]);
111     } else {
112       XSetForeground(dsp, pwin->gc, WhitePixelOfScreen(pwin->perscreen->screen));
113     }
114 }
115
116 static      Bool
117 recurse(fs, x, y, l)
118     flamestruct *fs;
119     register double x, y;
120     register int l;
121 {
122     int         xp, yp, i;
123     double      nx, ny;
124
125     if (l == fs->max_levels) {
126         fs->total_points++;
127         if (fs->total_points > MAXTOTAL)        /* how long each fractal runs */
128             return False;
129
130         if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) {
131             xp = fs->pts[fs->num_points].x = (int) ((fs->width / 2)
132                                                     * (x + 1.0));
133             yp = fs->pts[fs->num_points].y = (int) ((fs->height / 2)
134                                                     * (y + 1.0));
135             fs->num_points++;
136             if (fs->num_points > MAXBATCH) {    /* point buffer size */
137                 XDrawPoints(dsp, fs->pwin->w, fs->pwin->gc, fs->pts,
138                             fs->num_points, CoordModeOrigin);
139                 fs->num_points = 0;
140             }
141         }
142     } else {
143         for (i = 0; i < fs->snum; i++) {
144             nx = fs->f[0][0][i] * x + fs->f[0][1][i] * y + fs->f[0][2][i];
145             ny = fs->f[1][0][i] * x + fs->f[1][1][i] * y + fs->f[1][2][i];
146             if (i < fs->anum) {
147                 nx = sin(nx);
148                 ny = sin(ny);
149             }
150             if (!recurse(fs, nx, ny, l + 1))
151                 return False;
152         }
153     }
154     return True;
155 }
156
157
158 void
159 drawflame(pwin)
160     perwindow *pwin;
161 {
162     flamestruct *fs = (flamestruct *)pwin->data;
163
164     int         i, j, k;
165     static      alt = 0;
166
167     if (!(fs->cur_level++ % fs->max_levels)) {
168         XClearWindow(dsp, fs->pwin->w);
169         alt = !alt;
170     } else {
171         if (pwin->perscreen->npixels > 2) {
172             XSetForeground(dsp, pwin->gc,
173                            pwin->perscreen->pixels[fs->pixcol]);
174             if (--fs->pixcol < 0)
175                 fs->pixcol = pwin->perscreen->npixels - 1;
176         }
177     }
178
179     /* number of functions */
180     fs->snum = 2 + (fs->cur_level % (MAXLEV - 1));
181
182     /* how many of them are of alternate form */
183     if (alt)
184         fs->anum = 0;
185     else
186         fs->anum = halfrandom(fs->snum) + 2;
187
188     /* 6 dtfs per function */
189     for (k = 0; k < fs->snum; k++) {
190         for (i = 0; i < 2; i++)
191             for (j = 0; j < 3; j++)
192                 fs->f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
193     }
194     fs->num_points = 0;
195     fs->total_points = 0;
196     (void) recurse(fs, 0.0, 0.0, 0);
197     XDrawPoints(dsp, pwin->w, pwin->gc,
198                 fs->pts, fs->num_points, CoordModeOrigin);
199 }