1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* spiral --- spiraling dots */
5 static const char sccsid[] = "@(#)spiral.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1994 by Darrick Brown.
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.
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.
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: jwz@jwz.org: turned into a standalone program.
26 * 24-Jul-1995: Fix to allow cycles not to have an arbitrary value by
27 * Peter Schmitzberger (schmitz@coma.sbg.ac.at).
28 * 06-Mar-1995: Finished cleaning up and final testing.
29 * 03-Mar-1995: Cleaned up code.
30 * 12-Jul-1994: Written.
33 * Idea based on a graphics demo I saw a *LONG* time ago.
38 #define DEFAULTS "*delay: 50000 \n" \
42 # define SMOOTH_COLORS
43 # define reshape_spiral 0
44 # define spiral_handle_event 0
45 # include "xlockmore.h" /* from the xscreensaver distribution */
46 #else /* !STANDALONE */
47 # include "xlock.h" /* from the xlockmore distribution */
48 #endif /* !STANDALONE */
52 ENTRYPOINT ModeSpecOpt spiral_opts =
53 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
56 ModStruct spiral_description =
57 {"spiral", "init_spiral", "draw_spiral", "release_spiral",
58 "refresh_spiral", "init_spiral", (char *) NULL, &spiral_opts,
59 5000, -40, 350, 1, 64, 1.0, "",
60 "Shows a helical locus of points", 0, NULL};
64 #define MAXTRAIL 512 /* The length of the trail */
67 #define TWOPI (2.0*M_PI) /* for convienence */
68 #define JAGGINESS 4 /* This sets the "Craziness" of the spiral (I like 4) */
71 /* How many segments to draw per cycle when redrawing */
90 float top, bottom, left, right;
92 int redrawing, redrawpos;
95 static spiralstruct *spirals = (spiralstruct *) NULL;
97 static void draw_dots(ModeInfo * mi, int in);
99 #define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width))
100 #define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height))
103 draw_dots(ModeInfo * mi, int in)
109 spiralstruct *sp = &spirals[MI_SCREEN(mi)];
111 inc = TWOPI / (float) sp->dots;
112 for (i = 0.0; i < TWOPI; i += inc) {
113 x = sp->traildots[in].hx + COSF(i + sp->traildots[in].ha) *
114 sp->traildots[in].hr;
115 y = sp->traildots[in].hy + SINF(i + sp->traildots[in].ha) *
116 sp->traildots[in].hr;
117 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
118 TFX(sp, x), TFY(sp, y));
123 init_spiral(ModeInfo * mi)
128 if (spirals == NULL) {
129 if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi),
130 sizeof (spiralstruct))) == NULL)
133 sp = &spirals[MI_SCREEN(mi)];
136 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
139 sp->width = MI_WIDTH(mi);
140 sp->height = MI_HEIGHT(mi);
145 sp->nlength = MI_CYCLES(mi);
148 if ((sp->traildots = (Traildots *) malloc(sp->nlength *
149 sizeof (Traildots))) == NULL) {
153 /* initialize the allocated array */
154 for (i = 0; i < sp->nlength; i++) {
155 sp->traildots[i].hx = 0.0;
156 sp->traildots[i].hy = 0.0;
157 sp->traildots[i].ha = 0.0;
158 sp->traildots[i].hr = 0.0;
162 /* keep the window parameters proportional */
165 sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0);
168 /* assign the initial values */
169 sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right;
170 sp->cy = (float) (5000.0 - NRAND(2000));
171 sp->radius = (float) (NRAND(200) + 200);
173 sp->dx = (float) (10 - NRAND(20)) * SPEED;
174 sp->dy = (float) (10 - NRAND(20)) * SPEED;
175 sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2));
176 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
177 if (MI_NPIXELS(mi) > 2)
178 sp->colors = (float) NRAND(MI_NPIXELS(mi));
181 sp->traildots[sp->inc].hx = sp->cx;
182 sp->traildots[sp->inc].hy = sp->cy;
183 sp->traildots[sp->inc].ha = sp->angle;
184 sp->traildots[sp->inc].hr = sp->radius;
187 sp->dots = MI_COUNT(mi);
188 if (sp->dots < -MINDOTS)
189 sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS;
190 /* Absolute minimum */
191 if (sp->dots < MINDOTS)
196 draw_spiral(ModeInfo * mi)
198 Display *display = MI_DISPLAY(mi);
205 sp = &spirals[MI_SCREEN(mi)];
206 if (sp->traildots == NULL)
209 MI_IS_DRAWN(mi) = True;
210 if (sp->erase == 1) {
211 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
212 draw_dots(mi, sp->inc);
215 sp->traildots[sp->inc].hx = sp->cx;
217 if ((sp->cx > 9000.0) || (sp->cx < 1000.0))
221 sp->traildots[sp->inc].hy = sp->cy;
223 if ((sp->cy > 9000.0) || (sp->cy < 1000.0))
226 sp->radius += sp->dr;
227 sp->traildots[sp->inc].hr = sp->radius;
229 if ((sp->radius > 2500.0) && (sp->dr > 0.0))
231 else if ((sp->radius < 50.0) && (sp->radius < 0.0))
234 /* Randomly give some variations to: */
236 /* spiral direction (if it is within the boundaries) */
237 if ((NRAND(3000) < 1 * JAGGINESS) &&
238 (((sp->cx > 2000.0) && (sp->cx < 8000.0)) &&
239 ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) {
240 sp->dx = (float) (10 - NRAND(20)) * SPEED;
241 sp->dy = (float) (10 - NRAND(20)) * SPEED;
243 /* The speed of the change in size of the spiral */
244 if (NRAND(3000) < 1 * JAGGINESS) {
246 sp->dr += (float) (NRAND(3) + 1);
248 sp->dr -= (float) (NRAND(3) + 1);
250 /* don't let it get too wild */
253 else if (sp->dr < 4.0)
256 /* The speed of rotation */
257 if (NRAND(3000) < 1 * JAGGINESS)
258 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
260 /* Reverse rotation */
261 if (NRAND(3000) < 1 * JAGGINESS)
265 sp->traildots[sp->inc].ha = sp->angle;
267 if (sp->angle > TWOPI)
269 else if (sp->angle < 0.0)
272 sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength));
273 if (sp->colors >= (float) MI_NPIXELS(mi))
276 if (MI_NPIXELS(mi) > 2)
277 XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors));
279 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
280 draw_dots(mi, sp->inc);
283 if (sp->inc > sp->nlength - 1) {
284 sp->inc -= sp->nlength;
288 for (i = 0; i < REDRAWSTEP; i++) {
289 j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength;
292 if (++(sp->redrawpos) >= sp->nlength) {
301 release_spiral(ModeInfo * mi)
303 if (spirals != NULL) {
306 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
307 spiralstruct *sp = &spirals[screen];
310 (void) free((void *) sp->traildots);
312 (void) free((void *) spirals);
313 spirals = (spiralstruct *) NULL;
318 refresh_spiral(ModeInfo * mi)
324 sp = &spirals[MI_SCREEN(mi)];
331 XSCREENSAVER_MODULE ("Spiral", spiral)
333 #endif /* MODE_spiral */