source: trunk/third/xscreensaver/hacks/sierpinski.c @ 20148

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