1 /* -*- Mode: C; tab-width: 4 -*-
2 * spiral --- low cpu screen design.
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)spiral.c 4.00 97/01/01 xlockmore";
8 /* Copyright (c) 1994 Darrick Brown.
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted,
12 * provided that the above copyright notice appear in all copies and that
13 * both that copyright notice and this permission notice appear in
14 * supporting documentation.
16 * This file is provided AS IS with no warranties of any kind. The author
17 * shall have no liability with respect to the infringement of copyrights,
18 * trade secrets or any patents by this file or any part thereof. In no
19 * event will the author be liable for any lost revenue or profits or
20 * other special, indirect and consequential damages.
22 * Idea based on a graphics demo I saw a *LONG* time ago.
24 * See xlock.c for copying information.
27 * 10-May-97: jwz@jwz.org: turned into a standalone program.
28 * 24-Jul-95: Fix to allow cycles not to have an arbitrary value by
29 * Peter Schmitzberger (schmitz@coma.sbg.ac.at).
30 * 06-Mar-95: Finished cleaning up and final testing.
31 * Copyright (c) 1994 by Darrick Brown.
33 * 03-Mar-95: Cleaned up code.
38 # define PROGCLASS "Spiral"
39 # define HACK_INIT init_spiral
40 # define HACK_DRAW draw_spiral
41 # define spiral_opts xlockmore_opts
42 # define DEFAULTS "*count: 40 \n" \
46 # define SMOOTH_COLORS
47 # include "xlockmore.h" /* from the xscreensaver distribution */
48 #else /* !STANDALONE */
49 # include "xlock.h" /* from the xlockmore distribution */
50 #endif /* !STANDALONE */
52 ModeSpecOpt spiral_opts = {
53 0, NULL, 0, NULL, NULL };
55 #define MAXTRAIL 512 /* The length of the trail */
58 #define TWOPI (2.0*M_PI) /* for convienence */
59 #define JAGGINESS 4 /* This sets the "Craziness" of the spiral (I like 4) */
62 /* How many segments to draw per cycle when redrawing */
80 float top, bottom, left, right;
82 int redrawing, redrawpos;
85 static spiralstruct *spirals = NULL;
87 static void draw_dots(ModeInfo * mi, int in);
89 #define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width))
90 #define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height))
93 draw_dots(ModeInfo * mi, int in)
99 spiralstruct *sp = &spirals[MI_SCREEN(mi)];
101 inc = TWOPI / (float) sp->dots;
102 for (i = 0.0; i < TWOPI; i += inc) {
103 x = sp->traildots[in].hx + COSF(i + sp->traildots[in].ha) *
104 sp->traildots[in].hr;
105 y = sp->traildots[in].hy + SINF(i + sp->traildots[in].ha) *
106 sp->traildots[in].hr;
107 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
108 TFX(sp, x), TFY(sp, y));
113 init_spiral(ModeInfo * mi)
118 if (spirals == NULL) {
119 if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi),
120 sizeof (spiralstruct))) == NULL)
123 sp = &spirals[MI_SCREEN(mi)];
125 sp->width = MI_WIN_WIDTH(mi);
126 sp->height = MI_WIN_HEIGHT(mi);
128 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
131 sp->nlength = MI_CYCLES(mi);
134 sp->traildots = (Traildots *) malloc(sp->nlength * sizeof (Traildots));
136 /* initialize the allocated array */
137 for (i = 0; i < sp->nlength; i++) {
138 sp->traildots[i].hx = 0.0;
139 sp->traildots[i].hy = 0.0;
140 sp->traildots[i].ha = 0.0;
141 sp->traildots[i].hr = 0.0;
145 /* keep the window parameters proportional */
148 sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0);
151 /* assign the initial values */
152 sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right;
153 sp->cy = (float) (5000.0 - NRAND(2000));
154 sp->radius = (float) (NRAND(200) + 200);
156 sp->dx = (float) (10 - NRAND(20)) * SPEED;
157 sp->dy = (float) (10 - NRAND(20)) * SPEED;
158 sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2));
159 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
160 if (MI_NPIXELS(mi) > 2)
161 sp->colors = (float) NRAND(MI_NPIXELS(mi));
164 sp->traildots[sp->inc].hx = sp->cx;
165 sp->traildots[sp->inc].hy = sp->cy;
166 sp->traildots[sp->inc].ha = sp->angle;
167 sp->traildots[sp->inc].hr = sp->radius;
170 sp->dots = MI_BATCHCOUNT(mi);
171 if (sp->dots < -MINDOTS)
172 sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS;
173 /* Absolute minimum */
174 if (sp->dots < MINDOTS)
179 draw_spiral(ModeInfo * mi)
181 Display *display = MI_DISPLAY(mi);
183 spiralstruct *sp = &spirals[MI_SCREEN(mi)];
186 if (sp->erase == 1) {
187 XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
188 draw_dots(mi, sp->inc);
191 sp->traildots[sp->inc].hx = sp->cx;
193 if ((sp->cx > 9000.0) || (sp->cx < 1000.0))
197 sp->traildots[sp->inc].hy = sp->cy;
199 if ((sp->cy > 9000.0) || (sp->cy < 1000.0))
202 sp->radius += sp->dr;
203 sp->traildots[sp->inc].hr = sp->radius;
205 if ((sp->radius > 2500.0) && (sp->dr > 0.0))
207 else if ((sp->radius < 50.0) && (sp->radius < 0.0))
210 /* Randomly give some variations to: */
212 /* spiral direction (if it is within the boundaries) */
213 if ((NRAND(3000) < 1 * JAGGINESS) &&
214 (((sp->cx > 2000.0) && (sp->cx < 8000.0)) &&
215 ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) {
216 sp->dx = (float) (10 - NRAND(20)) * SPEED;
217 sp->dy = (float) (10 - NRAND(20)) * SPEED;
219 /* The speed of the change in size of the spiral */
220 if (NRAND(3000) < 1 * JAGGINESS) {
222 sp->dr += (float) (NRAND(3) + 1);
224 sp->dr -= (float) (NRAND(3) + 1);
226 /* don't let it get too wild */
229 else if (sp->dr < 4.0)
232 /* The speed of rotation */
233 if (NRAND(3000) < 1 * JAGGINESS)
234 sp->da = (float) NRAND(360) / 7200.0 + 0.01;
236 /* Reverse rotation */
237 if (NRAND(3000) < 1 * JAGGINESS)
241 sp->traildots[sp->inc].ha = sp->angle;
243 if (sp->angle > TWOPI)
245 else if (sp->angle < 0.0)
248 sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength));
249 if (sp->colors >= (float) MI_NPIXELS(mi))
252 if (MI_NPIXELS(mi) > 2)
253 XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors));
255 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
256 draw_dots(mi, sp->inc);
259 if (sp->inc > sp->nlength - 1) {
260 sp->inc -= sp->nlength;
264 for (i = 0; i < REDRAWSTEP; i++) {
265 j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength;
268 if (++(sp->redrawpos) >= sp->nlength) {
277 release_spiral(ModeInfo * mi)
279 if (spirals != NULL) {
282 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
283 spiralstruct *sp = &spirals[screen];
286 (void) free((void *) sp->traildots);
288 (void) free((void *) spirals);
294 refresh_spiral(ModeInfo * mi)
296 spiralstruct *sp = &spirals[MI_SCREEN(mi)];