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 "*fpsSolid: true \n" \
44 # define SMOOTH_COLORS
45 # define reshape_spiral 0
46 # define spiral_handle_event 0
47 # include "xlockmore.h" /* from the xscreensaver distribution */
48 #else /* !STANDALONE */
49 # include "xlock.h" /* from the xlockmore distribution */
50 #endif /* !STANDALONE */
54 ENTRYPOINT ModeSpecOpt spiral_opts =
55 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
58 ModStruct spiral_description =
59 {"spiral", "init_spiral", "draw_spiral", "release_spiral",
60 "refresh_spiral", "init_spiral", (char *) NULL, &spiral_opts,
61 5000, -40, 350, 1, 64, 1.0, "",
62 "Shows a helical locus of points", 0, NULL};
66 #define MAXTRAIL 512 /* The length of the trail */
69 #define TWOPI (2.0*M_PI) /* for convienence */
70 #define JAGGINESS 4 /* This sets the "Craziness" of the spiral (I like 4) */
73 /* How many segments to draw per cycle when redrawing */
92 float top, bottom, left, right;
94 int redrawing, redrawpos;
97 static spiralstruct *spirals = (spiralstruct *) NULL;
99 static void draw_dots(ModeInfo * mi, int in);
101 #define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width))
102 #define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height))
105 draw_dots(ModeInfo * mi, int in)
111 spiralstruct *sp = &spirals[MI_SCREEN(mi)];
113 inc = TWOPI / (float) sp->dots;
114 for (i = 0.0; i < TWOPI; i += inc) {
115 x = sp->traildots[in].hx + COSF(i + sp->traildots[in].ha) *
116 sp->traildots[in].hr;
117 y = sp->traildots[in].hy + SINF(i + sp->traildots[in].ha) *
118 sp->traildots[in].hr;
119 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
120 TFX(sp, x), TFY(sp, y));
125 init_spiral(ModeInfo * mi)
130 if (spirals == NULL) {
131 if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi),
132 sizeof (spiralstruct))) == NULL)
135 sp = &spirals[MI_SCREEN(mi)];
138 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
141 sp->width = MI_WIDTH(mi);
142 sp->height = MI_HEIGHT(mi);
147 sp->nlength = MI_CYCLES(mi);
150 if ((sp->traildots = (Traildots *) malloc(sp->nlength *
151 sizeof (Traildots))) == NULL) {
155 /* initialize the allocated array */
156 for (i = 0; i < sp->nlength; i++) {
157 sp->traildots[i].hx = 0.0;
158 sp->traildots[i].hy = 0.0;
159 sp->traildots[i].ha = 0.0;
160 sp->traildots[i].hr = 0.0;
164 /* keep the window parameters proportional */
167 sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0);
170 /* assign the initial values */
171 sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right;
172 sp->cy = (float) (5000.0 - NRAND(2000));
173 sp->radius = (float) (NRAND(200) + 200);
175 sp->dx = (float) (10 - NRAND(20)) * SPEED;
176 sp->dy = (float) (10 - NRAND(20)) * SPEED;
177 sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2));
178 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
179 if (MI_NPIXELS(mi) > 2)
180 sp->colors = (float) NRAND(MI_NPIXELS(mi));
183 sp->traildots[sp->inc].hx = sp->cx;
184 sp->traildots[sp->inc].hy = sp->cy;
185 sp->traildots[sp->inc].ha = sp->angle;
186 sp->traildots[sp->inc].hr = sp->radius;
189 sp->dots = MI_COUNT(mi);
190 if (sp->dots < -MINDOTS)
191 sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS;
192 /* Absolute minimum */
193 if (sp->dots < MINDOTS)
198 draw_spiral(ModeInfo * mi)
200 Display *display = MI_DISPLAY(mi);
207 sp = &spirals[MI_SCREEN(mi)];
208 if (sp->traildots == NULL)
211 MI_IS_DRAWN(mi) = True;
212 if (sp->erase == 1) {
213 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
214 draw_dots(mi, sp->inc);
217 sp->traildots[sp->inc].hx = sp->cx;
219 if ((sp->cx > 9000.0) || (sp->cx < 1000.0))
223 sp->traildots[sp->inc].hy = sp->cy;
225 if ((sp->cy > 9000.0) || (sp->cy < 1000.0))
228 sp->radius += sp->dr;
229 sp->traildots[sp->inc].hr = sp->radius;
231 if ((sp->radius > 2500.0) && (sp->dr > 0.0))
233 else if ((sp->radius < 50.0) && (sp->radius < 0.0))
236 /* Randomly give some variations to: */
238 /* spiral direction (if it is within the boundaries) */
239 if ((NRAND(3000) < 1 * JAGGINESS) &&
240 (((sp->cx > 2000.0) && (sp->cx < 8000.0)) &&
241 ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) {
242 sp->dx = (float) (10 - NRAND(20)) * SPEED;
243 sp->dy = (float) (10 - NRAND(20)) * SPEED;
245 /* The speed of the change in size of the spiral */
246 if (NRAND(3000) < 1 * JAGGINESS) {
248 sp->dr += (float) (NRAND(3) + 1);
250 sp->dr -= (float) (NRAND(3) + 1);
252 /* don't let it get too wild */
255 else if (sp->dr < 4.0)
258 /* The speed of rotation */
259 if (NRAND(3000) < 1 * JAGGINESS)
260 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
262 /* Reverse rotation */
263 if (NRAND(3000) < 1 * JAGGINESS)
267 sp->traildots[sp->inc].ha = sp->angle;
269 if (sp->angle > TWOPI)
271 else if (sp->angle < 0.0)
274 sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength));
275 if (sp->colors >= (float) MI_NPIXELS(mi))
278 if (MI_NPIXELS(mi) > 2)
279 XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors));
281 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
282 draw_dots(mi, sp->inc);
285 if (sp->inc > sp->nlength - 1) {
286 sp->inc -= sp->nlength;
290 for (i = 0; i < REDRAWSTEP; i++) {
291 j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength;
294 if (++(sp->redrawpos) >= sp->nlength) {
303 release_spiral(ModeInfo * mi)
305 if (spirals != NULL) {
308 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
309 spiralstruct *sp = &spirals[screen];
312 (void) free((void *) sp->traildots);
314 (void) free((void *) spirals);
315 spirals = (spiralstruct *) NULL;
320 refresh_spiral(ModeInfo * mi)
326 sp = &spirals[MI_SCREEN(mi)];
333 XSCREENSAVER_MODULE ("Spiral", spiral)
335 #endif /* MODE_spiral */