ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-2.07.tar.gz
[xscreensaver] / hacks / sierpinski.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  * tri --- Sierpinski triangle fractal.
3  */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)tri.c 4.00 97/01/01 xlockmore";
6 #endif
7
8 /* Copyright (c) 1988-91 by Patrick J. Naughton.
9  *
10  * Permission to use, copy, modify, and distribute this software and its
11  * documentation for any purpose and without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and that
13  * both that copyright notice and this permission notice appear in
14  * supporting documentation.
15  *
16  * This file is provided AS IS with no warranties of any kind.  The author
17  * shall have no liability with respect to the infringement of copyrights,
18  * trade secrets or any patents by this file or any part thereof.  In no
19  * event will the author be liable for any lost revenue or profits or
20  * other special, indirect and consequential damages.
21  *
22  * Revision History:
23  * 10-May-97: jwz@netscape.com: turned into a standalone program.
24  * 05-Sep-96: Desmond Daignault Datatimes Incorporated
25  *            <tekdd@dtol.datatimes.com> .
26  */
27
28 #ifdef STANDALONE
29 # define PROGCLASS                                      "Sierpinski"
30 # define HACK_INIT                                      init_tri
31 # define HACK_DRAW                                      draw_tri
32 # define tri_opts                                       xlockmore_opts
33 # define DEFAULTS       "*count:                2000    \n"                     \
34                                         "*cycles:               100     \n"                     \
35                                         "*delay:                400000  \n"                     \
36                                         "*ncolors:              64   \n"
37 # include "xlockmore.h"                         /* from the xscreensaver distribution */
38 #else  /* !STANDALONE */
39 # include "xlock.h"                                     /* from the xlockmore distribution */
40 #endif /* !STANDALONE */
41
42 ModeSpecOpt tri_opts = {
43   0, NULL, 0, NULL, NULL };
44
45 typedef struct {
46         int         width, height;
47         int         time;
48         int         px, py;
49         int         total_npoints;
50         int         npoints[3];
51         unsigned long colors[3];
52         XPoint     *pointBuffer[3];
53         XPoint      vertex[3];
54 } tristruct;
55
56 static tristruct *tris = NULL;
57
58 static void
59 startover(ModeInfo * mi)
60 {
61         int         j;
62         tristruct  *tp = &tris[MI_SCREEN(mi)];
63
64         if (MI_NPIXELS(mi) > 2) {
65                 tp->colors[0] = (NRAND(MI_NPIXELS(mi)));
66                 tp->colors[1] = (tp->colors[0] + MI_NPIXELS(mi) / 7 +
67                              NRAND(2 * MI_NPIXELS(mi) / 7)) % MI_NPIXELS(mi);
68                 tp->colors[2] = (tp->colors[0] + 4 * MI_NPIXELS(mi) / 7 +
69                              NRAND(2 * MI_NPIXELS(mi) / 7)) % MI_NPIXELS(mi);
70         }
71         for (j = 0; j < 3; j++) {
72                 tp->vertex[j].x = NRAND(tp->width);
73                 tp->vertex[j].y = NRAND(tp->height);
74         }
75         tp->px = NRAND(tp->width);
76         tp->py = NRAND(tp->height);
77         tp->time = 0;
78         XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
79 }
80
81 void
82 init_tri(ModeInfo * mi)
83 {
84         tristruct  *tp;
85         int         i;
86
87         if (tris == NULL) {
88                 if ((tris = (tristruct *) calloc(MI_NUM_SCREENS(mi),
89                                                  sizeof (tristruct))) == NULL)
90                         return;
91         }
92         tp = &tris[MI_SCREEN(mi)];
93
94         tp->width = MI_WIN_WIDTH(mi);
95         tp->height = MI_WIN_HEIGHT(mi);
96
97         tp->total_npoints = MI_BATCHCOUNT(mi);
98         if (tp->total_npoints < 1)
99                 tp->total_npoints = 1;
100         for (i = 0; i < 3; i++) {
101                 if (!tp->pointBuffer[i])
102                         tp->pointBuffer[i] = (XPoint *) malloc(tp->total_npoints *
103                                                             sizeof (XPoint));
104         }
105         startover(mi);
106 }
107
108 void
109 draw_tri(ModeInfo * mi)
110 {
111         Display    *display = MI_DISPLAY(mi);
112         GC          gc = MI_GC(mi);
113         tristruct  *tp = &tris[MI_SCREEN(mi)];
114         XPoint     *xp[3];
115         int         i = 0, v;
116
117         if (MI_NPIXELS(mi) <= 2)
118                 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
119         for (i = 0; i < 3; i++)
120                 xp[i] = tp->pointBuffer[i];
121         for (i = 0; i < tp->total_npoints; i++) {
122                 v = NRAND(3);
123                 tp->px = (tp->px + tp->vertex[v].x) / 2;
124                 tp->py = (tp->py + tp->vertex[v].y) / 2;
125                 xp[v]->x = tp->px;
126                 xp[v]->y = tp->py;
127                 xp[v]++;
128                 tp->npoints[v]++;
129         }
130         for (i = 0; i < 3; i++) {
131                 if (MI_NPIXELS(mi) > 2)
132                         XSetForeground(display, gc, MI_PIXEL(mi, tp->colors[i]));
133                 XDrawPoints(display, MI_WINDOW(mi), gc, tp->pointBuffer[i], tp->npoints[i],
134                             CoordModeOrigin);
135                 tp->npoints[i] = 0;
136         }
137         if (++tp->time >= MI_CYCLES(mi))
138                 startover(mi);
139 }
140
141 void
142 release_tri(ModeInfo * mi)
143 {
144         if (tris != NULL) {
145                 int         screen, i;
146
147                 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
148                         for (i = 0; i < 3; i++)
149                                 if (tris[screen].pointBuffer[i] != NULL) {
150                                         (void) free((void *) tris[screen].pointBuffer[i]);
151                                 }
152                 }
153                 (void) free((void *) tris);
154                 tris = NULL;
155         }
156 }
157
158 void
159 refresh_tri(ModeInfo * mi)
160 {
161         /* Do nothing, it will refresh by itself */
162 }