1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* spiral --- spiraling dots */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)spiral.c 5.00 2000/11/01 xlockmore";
10 * Copyright (c) 1994 by Darrick Brown.
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.
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.
25 * 01-Nov-2000: Allocation checks
26 * 10-May-1997: jwz@jwz.org: turned into a standalone program.
27 * 24-Jul-1995: Fix to allow cycles not to have an arbitrary value by
28 * Peter Schmitzberger (schmitz@coma.sbg.ac.at).
29 * 06-Mar-1995: Finished cleaning up and final testing.
30 * 03-Mar-1995: Cleaned up code.
31 * 12-Jul-1994: Written.
34 * Idea based on a graphics demo I saw a *LONG* time ago.
39 #define PROGCLASS "Spiral"
40 #define HACK_INIT init_spiral
41 #define HACK_DRAW draw_spiral
42 #define spiral_opts xlockmore_opts
43 #define DEFAULTS "*delay: 50000 \n" \
48 #include "xlockmore.h" /* from the xscreensaver distribution */
49 #else /* !STANDALONE */
50 #include "xlock.h" /* from the xlockmore distribution */
51 #endif /* !STANDALONE */
55 ModeSpecOpt spiral_opts =
56 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
59 ModStruct spiral_description =
60 {"spiral", "init_spiral", "draw_spiral", "release_spiral",
61 "refresh_spiral", "init_spiral", (char *) NULL, &spiral_opts,
62 5000, -40, 350, 1, 64, 1.0, "",
63 "Shows a helical locus of points", 0, NULL};
67 #define MAXTRAIL 512 /* The length of the trail */
70 #define TWOPI (2.0*M_PI) /* for convienence */
71 #define JAGGINESS 4 /* This sets the "Craziness" of the spiral (I like 4) */
74 /* How many segments to draw per cycle when redrawing */
93 float top, bottom, left, right;
95 int redrawing, redrawpos;
98 static spiralstruct *spirals = (spiralstruct *) NULL;
100 static void draw_dots(ModeInfo * mi, int in);
102 #define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width))
103 #define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height))
106 draw_dots(ModeInfo * mi, int in)
112 spiralstruct *sp = &spirals[MI_SCREEN(mi)];
114 inc = TWOPI / (float) sp->dots;
115 for (i = 0.0; i < TWOPI; i += inc) {
116 x = sp->traildots[in].hx + COSF(i + sp->traildots[in].ha) *
117 sp->traildots[in].hr;
118 y = sp->traildots[in].hy + SINF(i + sp->traildots[in].ha) *
119 sp->traildots[in].hr;
120 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
121 TFX(sp, x), TFY(sp, y));
126 init_spiral(ModeInfo * mi)
131 if (spirals == NULL) {
132 if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi),
133 sizeof (spiralstruct))) == NULL)
136 sp = &spirals[MI_SCREEN(mi)];
138 sp->width = MI_WIDTH(mi);
139 sp->height = MI_HEIGHT(mi);
144 sp->nlength = MI_CYCLES(mi);
147 if ((sp->traildots = (Traildots *) malloc(sp->nlength *
148 sizeof (Traildots))) == NULL) {
152 /* initialize the allocated array */
153 for (i = 0; i < sp->nlength; i++) {
154 sp->traildots[i].hx = 0.0;
155 sp->traildots[i].hy = 0.0;
156 sp->traildots[i].ha = 0.0;
157 sp->traildots[i].hr = 0.0;
161 /* keep the window parameters proportional */
164 sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0);
167 /* assign the initial values */
168 sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right;
169 sp->cy = (float) (5000.0 - NRAND(2000));
170 sp->radius = (float) (NRAND(200) + 200);
172 sp->dx = (float) (10 - NRAND(20)) * SPEED;
173 sp->dy = (float) (10 - NRAND(20)) * SPEED;
174 sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2));
175 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
176 if (MI_NPIXELS(mi) > 2)
177 sp->colors = (float) NRAND(MI_NPIXELS(mi));
180 sp->traildots[sp->inc].hx = sp->cx;
181 sp->traildots[sp->inc].hy = sp->cy;
182 sp->traildots[sp->inc].ha = sp->angle;
183 sp->traildots[sp->inc].hr = sp->radius;
186 sp->dots = MI_COUNT(mi);
187 if (sp->dots < -MINDOTS)
188 sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS;
189 /* Absolute minimum */
190 if (sp->dots < MINDOTS)
195 draw_spiral(ModeInfo * mi)
197 Display *display = MI_DISPLAY(mi);
204 sp = &spirals[MI_SCREEN(mi)];
205 if (sp->traildots == NULL)
208 MI_IS_DRAWN(mi) = True;
209 if (sp->erase == 1) {
210 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
211 draw_dots(mi, sp->inc);
214 sp->traildots[sp->inc].hx = sp->cx;
216 if ((sp->cx > 9000.0) || (sp->cx < 1000.0))
220 sp->traildots[sp->inc].hy = sp->cy;
222 if ((sp->cy > 9000.0) || (sp->cy < 1000.0))
225 sp->radius += sp->dr;
226 sp->traildots[sp->inc].hr = sp->radius;
228 if ((sp->radius > 2500.0) && (sp->dr > 0.0))
230 else if ((sp->radius < 50.0) && (sp->radius < 0.0))
233 /* Randomly give some variations to: */
235 /* spiral direction (if it is within the boundaries) */
236 if ((NRAND(3000) < 1 * JAGGINESS) &&
237 (((sp->cx > 2000.0) && (sp->cx < 8000.0)) &&
238 ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) {
239 sp->dx = (float) (10 - NRAND(20)) * SPEED;
240 sp->dy = (float) (10 - NRAND(20)) * SPEED;
242 /* The speed of the change in size of the spiral */
243 if (NRAND(3000) < 1 * JAGGINESS) {
245 sp->dr += (float) (NRAND(3) + 1);
247 sp->dr -= (float) (NRAND(3) + 1);
249 /* don't let it get too wild */
252 else if (sp->dr < 4.0)
255 /* The speed of rotation */
256 if (NRAND(3000) < 1 * JAGGINESS)
257 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
259 /* Reverse rotation */
260 if (NRAND(3000) < 1 * JAGGINESS)
264 sp->traildots[sp->inc].ha = sp->angle;
266 if (sp->angle > TWOPI)
268 else if (sp->angle < 0.0)
271 sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength));
272 if (sp->colors >= (float) MI_NPIXELS(mi))
275 if (MI_NPIXELS(mi) > 2)
276 XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors));
278 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
279 draw_dots(mi, sp->inc);
282 if (sp->inc > sp->nlength - 1) {
283 sp->inc -= sp->nlength;
287 for (i = 0; i < REDRAWSTEP; i++) {
288 j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength;
291 if (++(sp->redrawpos) >= sp->nlength) {
300 release_spiral(ModeInfo * mi)
302 if (spirals != NULL) {
305 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
306 spiralstruct *sp = &spirals[screen];
309 (void) free((void *) sp->traildots);
311 (void) free((void *) spirals);
312 spirals = (spiralstruct *) NULL;
317 refresh_spiral(ModeInfo * mi)
323 sp = &spirals[MI_SCREEN(mi)];
330 #endif /* MODE_spiral */