http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / sierpinski.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* sierpinski --- Sierpinski's triangle fractal */
3
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)sierpinski.c  5.00 2000/11/01 xlockmore";
6
7 #endif
8
9 /*-
10  * Copyright (c) 1996 by Desmond Daignault
11  *
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose and without fee is hereby granted,
14  * provided that the above copyright notice appear in all copies and that
15  * both that copyright notice and this permission notice appear in
16  * supporting documentation.
17  *
18  * This file is provided AS IS with no warranties of any kind.  The author
19  * shall have no liability with respect to the infringement of copyrights,
20  * trade secrets or any patents by this file or any part thereof.  In no
21  * event will the author be liable for any lost revenue or profits or
22  * other special, indirect and consequential damages.
23  *
24  * Dots initially appear where they "should not".  Later they get
25  * "focused".  This is correct behavior.
26  *
27  * Revision History:
28  * 01-Nov-2000: Allocation checks
29  * 18-Sep-1997: 3D version Antti Kuntsi <kuntsi@iki.fi>.
30  * 20-May-1997: Changed the name tri to sierpinski for more compatiblity
31  * 10-May-1997: Jamie Zawinski <jwz@jwz.org> compatible with xscreensaver
32  * 05-Sep-1996: Desmond Daignault Datatimes Incorporated
33  *            <tekdd@dtol.datatimes.com> .
34  */
35
36 #ifdef STANDALONE
37 #define MODE_sierpinski
38 #define PROGCLASS "Sierpinski"
39 #define HACK_INIT init_sierpinski
40 #define HACK_DRAW draw_sierpinski
41 #define sierpinski_opts xlockmore_opts
42 #define DEFAULTS "*delay: 400000 \n" \
43  "*count: 2000 \n" \
44  "*cycles: 100 \n" \
45  "*ncolors: 64 \n"
46 #define BRIGHT_COLORS
47 #include "xlockmore.h"          /* in xscreensaver distribution */
48 #else /* STANDALONE */
49 #include "xlock.h"              /* in xlockmore distribution */
50 #endif /* STANDALONE */
51
52 #ifdef MODE_sierpinski
53
54 ModeSpecOpt sierpinski_opts =
55 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
56
57 #ifdef USE_MODULES
58 ModStruct   sierpinski_description =
59 {"sierpinski", "init_sierpinski", "draw_sierpinski", "release_sierpinski",
60  "refresh_sierpinski", "init_sierpinski", (char *) NULL, &sierpinski_opts,
61  400000, 2000, 100, 1, 64, 1.0, "",
62  "Shows Sierpinski's triangle", 0, NULL};
63
64 #endif
65
66 #define MAXCORNERS 4
67
68 typedef struct {
69         int         width, height;
70         int         time;
71         int         px, py;
72         int         total_npoints;
73         int         corners;
74         int         npoints[MAXCORNERS];
75         unsigned long colors[MAXCORNERS];
76         XPoint     *pointBuffer[MAXCORNERS];
77         XPoint      vertex[MAXCORNERS];
78 } sierpinskistruct;
79
80 static sierpinskistruct *tris = (sierpinskistruct *) NULL;
81
82 static void
83 startover(ModeInfo * mi)
84 {
85         int         j;
86         sierpinskistruct *sp = &tris[MI_SCREEN(mi)];
87
88         if (MI_NPIXELS(mi) > 2) {
89                 if (sp->corners == 3) {
90                         sp->colors[0] = (NRAND(MI_NPIXELS(mi)));
91                         sp->colors[1] = (sp->colors[0] + MI_NPIXELS(mi) / 7 +
92                          NRAND(2 * MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi);
93                         sp->colors[2] = (sp->colors[0] + 4 * MI_NPIXELS(mi) / 7 +
94                          NRAND(2 * MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi);
95                 } else if (sp->corners == 4) {
96                         sp->colors[0] = (NRAND(MI_NPIXELS(mi)));
97                         sp->colors[1] = (sp->colors[0] + MI_NPIXELS(mi) / 7 +
98                              NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi);
99                         sp->colors[2] = (sp->colors[0] + 3 * MI_NPIXELS(mi) / 7 +
100                              NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi);
101                         sp->colors[3] = (sp->colors[0] + 5 * MI_NPIXELS(mi) / 7 +
102                              NRAND(MI_NPIXELS(mi) / 7 + 1)) % MI_NPIXELS(mi);
103                 } else {
104                         (void) fprintf(stderr, "colors not set for %d corners\n", sp->corners);
105                 }
106         }
107         for (j = 0; j < sp->corners; j++) {
108                 sp->vertex[j].x = NRAND(sp->width);
109                 sp->vertex[j].y = NRAND(sp->height);
110         }
111         sp->px = NRAND(sp->width);
112         sp->py = NRAND(sp->height);
113         sp->time = 0;
114
115         MI_CLEARWINDOW(mi);
116 }
117
118 static void
119 free_sierpinski(sierpinskistruct *sp)
120 {
121         int corner;
122
123         for (corner = 0; corner < MAXCORNERS; corner++)
124                 if (sp->pointBuffer[corner] != NULL) {
125                         (void) free((void *) sp->pointBuffer[corner]);
126                         sp->pointBuffer[corner] = (XPoint *) NULL;
127                 }
128 }
129
130 void
131 init_sierpinski(ModeInfo * mi)
132 {
133         int         i;
134         sierpinskistruct *sp;
135
136         if (tris == NULL) {
137                 if ((tris = (sierpinskistruct *) calloc(MI_NUM_SCREENS(mi),
138                                          sizeof (sierpinskistruct))) == NULL)
139                         return;
140         }
141         sp = &tris[MI_SCREEN(mi)];
142
143         sp->width = MI_WIDTH(mi);
144         sp->height = MI_HEIGHT(mi);
145
146         sp->total_npoints = MI_COUNT(mi);
147         if (sp->total_npoints < 1)
148                 sp->total_npoints = 1;
149         sp->corners = MI_SIZE(mi);
150         if (sp->corners < 3 || sp->corners > 4) {
151                 sp->corners = (int) (LRAND() & 1) + 3;
152         }
153         for (i = 0; i < sp->corners; i++) {
154                 if (!sp->pointBuffer[i])
155                         if ((sp->pointBuffer[i] = (XPoint *) malloc(sp->total_npoints *
156                                         sizeof (XPoint))) == NULL) {
157                                 free_sierpinski(sp);
158                                 return;
159                         }
160         }
161         startover(mi);
162 }
163
164 void
165 draw_sierpinski(ModeInfo * mi)
166 {
167         Display    *display = MI_DISPLAY(mi);
168         GC          gc = MI_GC(mi);
169         XPoint     *xp[MAXCORNERS];
170         int         i, v;
171         sierpinskistruct *sp;
172
173         if (tris == NULL)
174                 return;
175         sp = &tris[MI_SCREEN(mi)];
176         if (sp->pointBuffer[0] == NULL)
177                 return;
178
179         MI_IS_DRAWN(mi) = True;
180         if (MI_NPIXELS(mi) <= 2)
181                 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
182         for (i = 0; i < sp->corners; i++)
183                 xp[i] = sp->pointBuffer[i];
184         for (i = 0; i < sp->total_npoints; i++) {
185                 v = NRAND(sp->corners);
186                 sp->px = (sp->px + sp->vertex[v].x) / 2;
187                 sp->py = (sp->py + sp->vertex[v].y) / 2;
188                 xp[v]->x = sp->px;
189                 xp[v]->y = sp->py;
190                 xp[v]++;
191                 sp->npoints[v]++;
192         }
193         for (i = 0; i < sp->corners; i++) {
194                 if (MI_NPIXELS(mi) > 2)
195                         XSetForeground(display, gc, MI_PIXEL(mi, sp->colors[i]));
196                 XDrawPoints(display, MI_WINDOW(mi), gc, sp->pointBuffer[i], sp->npoints[i],
197                             CoordModeOrigin);
198                 sp->npoints[i] = 0;
199         }
200         if (++sp->time >= MI_CYCLES(mi))
201                 startover(mi);
202 }
203
204 void
205 release_sierpinski(ModeInfo * mi)
206 {
207         if (tris != NULL) {
208                 int         screen;
209
210                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
211                         free_sierpinski(&tris[screen]);
212                 (void) free((void *) tris);
213                 tris = (sierpinskistruct *) NULL;
214         }
215 }
216
217 void
218 refresh_sierpinski(ModeInfo * mi)
219 {
220         MI_CLEARWINDOW(mi);
221 }
222
223 #endif /* MODE_sierpinski */