source: trunk/third/xscreensaver/hacks/spiral.c @ 20148

Revision 20148, 8.1 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 4 -*- */
2/* spiral --- spiraling dots */
3
4#if 0
5static const char sccsid[] = "@(#)spiral.c      5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1994 by Darrick Brown.
10 *
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.
16 *
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.
22 *
23 * Revision History:
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.
31 *
32 * Low CPU usage mode.
33 * Idea based on a graphics demo I saw a *LONG* time ago.
34 */
35
36#ifdef STANDALONE
37#define MODE_spiral
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 "*delay: 50000 \n" \
43 "*count: 40 \n" \
44 "*cycles: 350 \n" \
45 "*ncolors: 64 \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 */
51
52#ifdef MODE_spiral
53
54ModeSpecOpt spiral_opts =
55{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
56
57#ifdef USE_MODULES
58ModStruct   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};
63
64#endif
65
66#define MAXTRAIL 512            /* The length of the trail */
67#define MAXDOTS 40
68#define MINDOTS 1
69#define TWOPI (2.0*M_PI)        /* for convienence */
70#define JAGGINESS 4             /* This sets the "Craziness" of the spiral (I like 4) */
71#define SPEED 2.0
72
73/* How many segments to draw per cycle when redrawing */
74#define REDRAWSTEP 3
75
76
77typedef struct {
78        float       hx, hy, ha, hr;
79} Traildots;
80
81typedef struct {
82        Traildots  *traildots;
83        float       cx, cy;
84        float       angle;
85        float       radius;
86        float       dr, da;
87        float       dx, dy;
88        int         erase;
89        int         inc;
90        float       colors;
91        int         width, height;
92        float       top, bottom, left, right;
93        int         dots, nlength;
94        int         redrawing, redrawpos;
95} spiralstruct;
96
97static spiralstruct *spirals = (spiralstruct *) NULL;
98
99static void draw_dots(ModeInfo * mi, int in);
100
101#define TFX(sp,x) ((int)((x/sp->right)*(float)sp->width))
102#define TFY(sp,y) ((int)((y/sp->top)*(float)sp->height))
103
104static void
105draw_dots(ModeInfo * mi, int in)
106{
107
108        float       i, inc;
109        float       x, y;
110
111        spiralstruct *sp = &spirals[MI_SCREEN(mi)];
112
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));
121        }
122}
123
124void
125init_spiral(ModeInfo * mi)
126{
127        spiralstruct *sp;
128        int         i;
129
130        if (spirals == NULL) {
131                if ((spirals = (spiralstruct *) calloc(MI_NUM_SCREENS(mi),
132                                             sizeof (spiralstruct))) == NULL)
133                        return;
134        }
135        sp = &spirals[MI_SCREEN(mi)];
136
137        sp->width = MI_WIDTH(mi);
138        sp->height = MI_HEIGHT(mi);
139
140        MI_CLEARWINDOW(mi);
141
142        /* Init */
143        sp->nlength = MI_CYCLES(mi);
144
145        if (!sp->traildots)
146                if ((sp->traildots = (Traildots *) malloc(sp->nlength *
147                                sizeof (Traildots))) == NULL) {
148                        return;
149                }
150
151        /* initialize the allocated array */
152        for (i = 0; i < sp->nlength; i++) {
153                sp->traildots[i].hx = 0.0;
154                sp->traildots[i].hy = 0.0;
155                sp->traildots[i].ha = 0.0;
156                sp->traildots[i].hr = 0.0;
157        }
158        sp->redrawing = 0;
159
160        /* keep the window parameters proportional */
161        sp->top = 10000.0;
162        sp->bottom = 0;
163        sp->right = (float) (sp->width) / (float) (sp->height) * (10000.0);
164        sp->left = 0;
165
166        /* assign the initial values */
167        sp->cx = (float) (5000.0 - NRAND(2000)) / 10000.0 * sp->right;
168        sp->cy = (float) (5000.0 - NRAND(2000));
169        sp->radius = (float) (NRAND(200) + 200);
170        sp->angle = 0.0;
171        sp->dx = (float) (10 - NRAND(20)) * SPEED;
172        sp->dy = (float) (10 - NRAND(20)) * SPEED;
173        sp->dr = (float) ((NRAND(10) + 4) * (1 - (LRAND() & 1) * 2));
174        sp->da = (float) NRAND(360) / 7200.0 + 0.01;
175        if (MI_NPIXELS(mi) > 2)
176                sp->colors = (float) NRAND(MI_NPIXELS(mi));
177        sp->erase = 0;
178        sp->inc = 0;
179        sp->traildots[sp->inc].hx = sp->cx;
180        sp->traildots[sp->inc].hy = sp->cy;
181        sp->traildots[sp->inc].ha = sp->angle;
182        sp->traildots[sp->inc].hr = sp->radius;
183        sp->inc++;
184
185        sp->dots = MI_COUNT(mi);
186        if (sp->dots < -MINDOTS)
187                sp->dots = NRAND(sp->dots - MINDOTS + 1) + MINDOTS;
188        /* Absolute minimum */
189        if (sp->dots < MINDOTS)
190                sp->dots = MINDOTS;
191}
192
193void
194draw_spiral(ModeInfo * mi)
195{
196        Display    *display = MI_DISPLAY(mi);
197        GC          gc = MI_GC(mi);
198        int         i, j;
199        spiralstruct *sp;
200
201        if (spirals == NULL)
202                return;
203        sp = &spirals[MI_SCREEN(mi)];
204        if (sp->traildots == NULL)
205                return;
206
207        MI_IS_DRAWN(mi) = True;
208        if (sp->erase == 1) {
209                XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
210                draw_dots(mi, sp->inc);
211        }
212        sp->cx += sp->dx;
213        sp->traildots[sp->inc].hx = sp->cx;
214
215        if ((sp->cx > 9000.0) || (sp->cx < 1000.0))
216                sp->dx *= -1.0;
217
218        sp->cy += sp->dy;
219        sp->traildots[sp->inc].hy = sp->cy;
220
221        if ((sp->cy > 9000.0) || (sp->cy < 1000.0))
222                sp->dy *= -1.0;
223
224        sp->radius += sp->dr;
225        sp->traildots[sp->inc].hr = sp->radius;
226
227        if ((sp->radius > 2500.0) && (sp->dr > 0.0))
228                sp->dr *= -1.0;
229        else if ((sp->radius < 50.0) && (sp->radius < 0.0))
230                sp->dr *= -1.0;
231
232        /* Randomly give some variations to:  */
233
234        /* spiral direction (if it is within the boundaries) */
235        if ((NRAND(3000) < 1 * JAGGINESS) &&
236            (((sp->cx > 2000.0) && (sp->cx < 8000.0)) &&
237             ((sp->cy > 2000.0) && (sp->cy < 8000.0)))) {
238                sp->dx = (float) (10 - NRAND(20)) * SPEED;
239                sp->dy = (float) (10 - NRAND(20)) * SPEED;
240        }
241        /* The speed of the change in size of the spiral */
242        if (NRAND(3000) < 1 * JAGGINESS) {
243                if (LRAND() & 1)
244                        sp->dr += (float) (NRAND(3) + 1);
245                else
246                        sp->dr -= (float) (NRAND(3) + 1);
247
248                /* don't let it get too wild */
249                if (sp->dr > 18.0)
250                        sp->dr = 18.0;
251                else if (sp->dr < 4.0)
252                        sp->dr = 4.0;
253        }
254        /* The speed of rotation */
255        if (NRAND(3000) < 1 * JAGGINESS)
256                sp->da = (float) NRAND(360) / 7200.0 + 0.01;
257
258        /* Reverse rotation */
259        if (NRAND(3000) < 1 * JAGGINESS)
260                sp->da *= -1.0;
261
262        sp->angle += sp->da;
263        sp->traildots[sp->inc].ha = sp->angle;
264
265        if (sp->angle > TWOPI)
266                sp->angle -= TWOPI;
267        else if (sp->angle < 0.0)
268                sp->angle += TWOPI;
269
270        sp->colors += (float) MI_NPIXELS(mi) / ((float) (2 * sp->nlength));
271        if (sp->colors >= (float) MI_NPIXELS(mi))
272                sp->colors = 0.0;
273
274        if (MI_NPIXELS(mi) > 2)
275                XSetForeground(display, gc, MI_PIXEL(mi, (int) sp->colors));
276        else
277                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
278        draw_dots(mi, sp->inc);
279        sp->inc++;
280
281        if (sp->inc > sp->nlength - 1) {
282                sp->inc -= sp->nlength;
283                sp->erase = 1;
284        }
285        if (sp->redrawing) {
286                for (i = 0; i < REDRAWSTEP; i++) {
287                        j = (sp->inc - sp->redrawpos + sp->nlength) % sp->nlength;
288                        draw_dots(mi, j);
289
290                        if (++(sp->redrawpos) >= sp->nlength) {
291                                sp->redrawing = 0;
292                                break;
293                        }
294                }
295        }
296}
297
298void
299release_spiral(ModeInfo * mi)
300{
301        if (spirals != NULL) {
302                int         screen;
303
304                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
305                        spiralstruct *sp = &spirals[screen];
306
307                        if (sp->traildots)
308                                (void) free((void *) sp->traildots);
309                }
310                (void) free((void *) spirals);
311                spirals = (spiralstruct *) NULL;
312        }
313}
314
315void
316refresh_spiral(ModeInfo * mi)
317{
318        spiralstruct *sp;
319
320        if (spirals == NULL)
321                return;
322        sp = &spirals[MI_SCREEN(mi)];
323
324        MI_CLEARWINDOW(mi);
325        sp->redrawing = 1;
326        sp->redrawpos = 0;
327}
328
329#endif /* MODE_spiral */
Note: See TracBrowser for help on using the repository browser.