4c562f9d344811170efe55db40f374382269cfb3
[xscreensaver] / hacks / vines.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  * vines --- another geometric pattern generator.
3  */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)vines.c       4.02 97/04/01 xlockmore";
6 #endif
7
8 /* xlockmore mode written by Tracy Camp
9  * campt@hurrah.com 1997
10  * released to the public domain
11  *
12  * This was modifed from a 'screen saver' that a friend and I
13  * wrote on our TI-8x calculators in high school physics one day
14  * Basically another geometric pattern generator, this ones claim
15  * to fame is a pseudo-fractal looking vine like pattern that creates
16  * nifty whorls and loops.
17  *
18  * Revision History:
19  * 10-May-97: jwz@jwz.org: turned into a standalone program.
20  * 21-Mar-97:  David Hansen <dhansen@metapath.com>
21  *             Updated mode to draw complete patterns on every
22  *             iteration instead of growing the vine.  Also made
23  *             adjustments to randomization and changed variable
24  *             names to make logic easier to follow.
25  */
26
27 #ifdef STANDALONE
28 # define PROGCLASS                                      "Vines"
29 # define HACK_INIT                                      init_vines
30 # define HACK_DRAW                                      draw_vines
31 # define vines_opts                                     xlockmore_opts
32 # define DEFAULTS               "*delay:        200000 \n"                      \
33                                                 "*ncolors:      64     \n"                      \
34                                                 "*eraseSpeed:   400 \n"                 \
35                                                 "*eraseMode:    -1 \n"
36 # include "xlockmore.h"                         /* from the xscreensaver distribution */
37 # include "erase.h"
38 #else  /* !STANDALONE */
39 # include "xlock.h"                                     /* from the xlockmore distribution */
40 #endif /* !STANDALONE */
41
42 ModeSpecOpt vines_opts = {
43   0, NULL, 0, NULL, NULL };
44
45 typedef struct {
46         int         a;
47         int         x1;
48         int         y1;
49         int         x2;
50         int         y2;
51         int         length;
52         int         iterations;
53         int         constant;
54         int         ang;
55         int         centerx;
56         int         centery;
57 } vinestruct;
58
59 static vinestruct *vines = NULL;
60
61 void
62 refresh_vines(ModeInfo * mi)
63 {
64 }
65
66 void
67 init_vines(ModeInfo * mi)
68 {
69         Display    *display = MI_DISPLAY(mi);
70         vinestruct *fp;
71
72         if (vines == NULL) {
73                 if ((vines = (vinestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (vinestruct))) == NULL) {
74                         return;
75                 }
76         }
77         fp = &vines[MI_SCREEN(mi)];
78
79         fp->iterations = 30 + NRAND(100);
80
81         XClearWindow(display, MI_WINDOW(mi));
82 }
83
84 void
85 draw_vines(ModeInfo * mi)
86 {
87         vinestruct *fp = &vines[MI_SCREEN(mi)];
88         Display    *display = MI_DISPLAY(mi);
89         GC          gc = MI_GC(mi);
90         int         i;
91
92         if (--(fp->iterations) == 0) {
93 #ifdef STANDALONE
94           erase_full_window(MI_DISPLAY(mi), MI_WINDOW(mi));
95 #endif /* STANDALONE */
96           init_vines(mi);
97         }
98
99         fp->centerx = NRAND(MI_WIN_WIDTH(mi));
100         fp->centery = NRAND(MI_WIN_HEIGHT(mi));
101
102         fp->ang = 60 + NRAND(720);
103         fp->length = 100 + NRAND(3000);
104         fp->constant = fp->length * (10 + NRAND(10));
105
106         fp->a = 0;
107         fp->x1 = 0;
108         fp->y1 = 0;
109         fp->x2 = 1;
110         fp->y2 = 0;
111
112         if (MI_NPIXELS(mi) > 2)
113                 XSetForeground(display, gc, MI_PIXEL(mi, NRAND(MI_NPIXELS(mi))));
114         else
115                 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
116
117
118         for (i = 0; i < fp->length; i++) {
119                 XDrawLine(display, MI_WINDOW(mi), gc,
120                           fp->centerx + (fp->x1 / fp->constant),
121                           fp->centery - (fp->y1 / fp->constant),
122                           fp->centerx + (fp->x2 / fp->constant),
123                           fp->centery - (fp->y2 / fp->constant));
124
125                 fp->a += (fp->ang * i);
126
127                 fp->x1 = fp->x2;
128                 fp->y1 = fp->y2;
129
130                 fp->x2 += (int) (i * ((cos(fp->a) * 360) / (2 * M_PI)));
131                 fp->y2 += (int) (i * ((sin(fp->a) * 360) / (2 * M_PI)));
132         }
133 }
134
135 void
136 release_vines(ModeInfo * mi)
137 {
138         if (vines != NULL) {
139                 (void) free((void *) vines);
140                 vines = NULL;
141         }
142 }