http://www.jwz.org/xscreensaver/xscreensaver-5.13.tar.gz
[xscreensaver] / hacks / vines.c
1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* vines --- vine fractals */
3
4 #if 0
5 static const char sccsid[] = "@(#)vines.c       5.00 2000/11/01 xlockmore";
6 #endif
7
8 /*-
9  * Copyright (c) 1997 by Tracy Camp campt@hurrah.com
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  * If you make a modification I would of course appreciate a copy.
24  *
25  * Revision History:
26  * 01-Nov-2000: Allocation checks
27  * 11-Jul-1997: David Hansen <dhansen@metapath.com>
28  *              Changed names to vines and modified draw loop
29  *              to honor batchcount so vines can be grown or plotted.
30  * 10-May-1997: Compatible with xscreensaver
31  * 21-Mar-1997: David Hansen <dhansen@metapath.com>
32  *              Updated mode to draw complete patterns on every
33  *              iteration instead of growing the vine.  Also made
34  *              adjustments to randomization and changed variable
35  *              names to make logic easier to follow.
36  */
37
38 /*-
39  * This was modifed from a 'screen saver' that a friend and I
40  * wrote on our TI-8x calculators in high school physics one day
41  * Basically another geometric pattern generator, this ones claim
42  * to fame is a pseudo-fractal looking vine like pattern that creates
43  * nifty whorls and loops.
44  */
45
46 #ifdef STANDALONE
47 # define MODE_vines
48 # define DEFAULTS       "*delay: 200000 \n" \
49                                         "*count: 0 \n" \
50                                         "*ncolors: 64 \n" \
51                                         "*fpsSolid: true \n" \
52
53 # include "xlockmore.h"         /* in xscreensaver distribution */
54 # define reshape_vines 0
55 # define vines_handle_event 0
56 # include "erase.h"
57 #else /* STANDALONE */
58 # include "xlock.h"             /* in xlockmore distribution */
59 #endif /* STANDALONE */
60
61 #ifdef MODE_vines
62
63 ENTRYPOINT ModeSpecOpt vines_opts =
64 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
65
66 #ifdef USE_MODULES
67 ModStruct   vines_description =
68 {"vines", "init_vines", "draw_vines", "release_vines",
69  "refresh_vines", "init_vines", (char *) NULL, &vines_opts,
70  200000, 0, 1, 1, 64, 1.0, "",
71  "Shows fractals", 0, NULL};
72
73 #endif
74
75 typedef struct {
76         int         a;
77         int         x1;
78         int         y1;
79         int         x2;
80         int         y2;
81         int         i;
82         int         length;
83         int         iterations;
84         int         constant;
85         int         ang;
86         int         centerx;
87         int         centery;
88 #ifdef STANDALONE
89   eraser_state *eraser;
90 #endif
91 } vinestruct;
92
93 static vinestruct *vines = (vinestruct *) NULL;
94
95 ENTRYPOINT void
96 refresh_vines(ModeInfo * mi)
97 {
98         MI_CLEARWINDOW(mi);
99 }                               /* refresh_vines */
100
101 ENTRYPOINT void
102 init_vines(ModeInfo * mi)
103 {
104         vinestruct *fp;
105
106         if (vines == NULL) {
107                 if ((vines = (vinestruct *) calloc(MI_NUM_SCREENS(mi),
108                                              sizeof (vinestruct))) == NULL) {
109                         return;
110                 }
111         }
112         fp = &vines[MI_SCREEN(mi)];
113
114         fp->i = 0;
115         fp->length = 0;
116         fp->iterations = 30 + NRAND(100);
117
118 #ifndef STANDALONE
119         MI_CLEARWINDOW(mi);
120 #endif
121 }                               /* init_vines */
122
123 ENTRYPOINT void
124 draw_vines(ModeInfo * mi)
125 {
126         Display    *display = MI_DISPLAY(mi);
127         GC          gc = MI_GC(mi);
128         int         count;
129         vinestruct *fp;
130
131         if (vines == NULL)
132                 return;
133         fp = &vines[MI_SCREEN(mi)];
134
135 #ifdef STANDALONE
136     if (fp->eraser) {
137       fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser);
138       return;
139     }
140 #endif
141
142         /* MI_IS_DRAWN(mi) = True; */
143         if (fp->i >= fp->length) {
144                 if (--(fp->iterations) == 0) {
145 #ifdef STANDALONE
146           fp->eraser = erase_window (MI_DISPLAY(mi), MI_WINDOW(mi), fp->eraser);
147 #endif /* STANDALONE */
148                         init_vines(mi);
149                 }
150                 fp->centerx = NRAND(MI_WIDTH(mi));
151                 fp->centery = NRAND(MI_HEIGHT(mi));
152
153                 fp->ang = 60 + NRAND(720);
154                 fp->length = 100 + NRAND(3000);
155                 fp->constant = fp->length * (10 + NRAND(10));
156
157                 fp->i = 0;
158                 fp->a = 0;
159                 fp->x1 = 0;
160                 fp->y1 = 0;
161                 fp->x2 = 1;
162                 fp->y2 = 0;
163
164                 if (MI_NPIXELS(mi) > 2)
165                         XSetForeground(display, gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))));
166                 else
167                         XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
168         }
169         count = fp->i + MI_COUNT(mi);
170         if ((count <= fp->i) || (count > fp->length))
171                 count = fp->length;
172
173         while (fp->i < count) {
174                 XDrawLine(display, MI_WINDOW(mi), gc,
175                           fp->centerx + (fp->x1 / fp->constant),
176                           fp->centery - (fp->y1 / fp->constant),
177                           fp->centerx + (fp->x2 / fp->constant),
178                           fp->centery - (fp->y2 / fp->constant));
179
180                 fp->a += (fp->ang * fp->i);
181
182                 fp->x1 = fp->x2;
183                 fp->y1 = fp->y2;
184
185                 fp->x2 += (int) (fp->i * (cos((double) fp->a) * 360.0) / (2.0 * M_PI));
186                 fp->y2 += (int) (fp->i * (sin((double) fp->a) * 360.0) / (2.0 * M_PI));
187                 fp->i++;
188         }
189 }                               /* draw_vines */
190
191 ENTRYPOINT void
192 release_vines(ModeInfo * mi)
193 {
194         if (vines != NULL) {
195                 (void) free((void *) vines);
196                 vines = (vinestruct *) NULL;
197         }
198 }                               /* release_vines */
199
200
201 XSCREENSAVER_MODULE ("Vines", vines)
202
203 #endif /* MODE_vines */