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

Revision 20148, 10.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/* rotor --- a swirly rotor */
3
4#if 0
5static const char sccsid[] = "@(#)rotor.c       5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1991 by Patrick J. Naughton.
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: Compatible with xscreensaver
26 * 08-Mar-1995: CAT stuff for ## was tripping up some C compilers.  Removed.
27 * 01-Dec-1993: added patch for AIXV3 from Tom McConnell
28 *              <tmcconne@sedona.intel.com>
29 * 11-Nov-1990: put into xlock by Steve Zellers <zellers@sun.com>
30 * 16-Oct-1990: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight'
31 *               simulator)
32 */
33
34#ifdef STANDALONE
35#define MODE_rotor
36#define PROGCLASS "Rotor"
37#define HACK_INIT init_rotor
38#define HACK_DRAW draw_rotor
39#define rotor_opts xlockmore_opts
40#define DEFAULTS "*delay: 10000 \n" \
41 "*count: 4 \n" \
42 "*cycles: 20 \n" \
43 "*size: -6 \n" \
44 "*ncolors: 200 \n"
45#define SMOOTH_COLORS
46#include "xlockmore.h"          /* in xscreensaver distribution */
47#else /* STANDALONE */
48#include "xlock.h"              /* in xlockmore distribution */
49#endif /* STANDALONE */
50
51#ifdef MODE_rotor
52
53ModeSpecOpt rotor_opts =
54{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
55
56#ifdef USE_MODULES
57ModStruct   rotor_description =
58{"rotor", "init_rotor", "draw_rotor", "release_rotor",
59 "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
60 100, 4, 100, -6, 64, 0.3, "",
61 "Shows Tom's Roto-Rooter", 0, NULL};
62
63#endif
64
65/*-
66 * A 'batchcount' of 3 or 4 works best!
67 */
68
69#define MAXANGLE        3000.0  /* irrectangular  (was 10000.0) */
70
71/* How many segments to draw per cycle when redrawing */
72#define REDRAWSTEP 3
73
74typedef struct {
75        float       angle;
76        float       radius;
77        float       start_radius;
78        float       end_radius;
79        float       radius_drift_max;
80        float       radius_drift_now;
81
82        float       ratio;
83        float       start_ratio;
84        float       end_ratio;
85        float       ratio_drift_max;
86        float       ratio_drift_now;
87} elem;
88
89typedef struct {
90        int         pix;
91        int         lastx, lasty;
92        int         num, rotor, prev;
93        int         nsave;
94        float       angle;
95        int         centerx, centery;
96        int         prevcenterx, prevcentery;
97        unsigned char firsttime;
98        unsigned char iconifiedscreen;  /* for iconified view */
99        unsigned char forward;
100        unsigned char unused;
101        elem       *elements;
102        XPoint     *save;
103        int         redrawing, redrawpos;
104        int         linewidth;
105} rotorstruct;
106
107static rotorstruct *rotors = (rotorstruct *) NULL;
108
109static void
110free_rotor(rotorstruct *rp)
111{
112        if (rp->elements != NULL) {
113                (void) free((void *) rp->elements);
114                rp->elements = (elem *) NULL;
115        }
116        if (rp->save != NULL) {
117                (void) free((void *) rp->save);
118                rp->save = (XPoint *) NULL;
119        }
120}
121
122void
123init_rotor(ModeInfo * mi)
124{
125        int         x;
126        elem       *pelem;
127        unsigned char wasiconified;
128        rotorstruct *rp;
129
130        if (rotors == NULL) {
131                if ((rotors = (rotorstruct *) calloc(MI_NUM_SCREENS(mi),
132                                              sizeof (rotorstruct))) == NULL)
133                        return;
134        }
135        rp = &rotors[MI_SCREEN(mi)];
136
137        rp->prevcenterx = rp->centerx;
138        rp->prevcentery = rp->centery;
139
140        rp->centerx = MI_WIDTH(mi) / 2;
141        rp->centery = MI_HEIGHT(mi) / 2;
142
143        rp->redrawing = 0;
144        /*
145         * sometimes, you go into iconified view, only to see a really whizzy pattern
146         * that you would like to look more closely at. Normally, clicking in the
147         * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
148         * HENCE, the wasiconified stuff you see here.
149         */
150
151        wasiconified = rp->iconifiedscreen;
152        rp->iconifiedscreen = MI_IS_ICONIC(mi);
153
154        if (wasiconified && !rp->iconifiedscreen)
155                rp->firsttime = True;
156        else {
157
158                /* This is a fudge is needed since prevcenter may not be set when it comes
159                   from the the random mode and return is pressed (and its not the first
160                   mode that was running). This assumes that the size of the lock screen
161                   window / size of the icon window = 12 */
162                if (!rp->prevcenterx)
163                        rp->prevcenterx = rp->centerx * 12;
164                if (!rp->prevcentery)
165                        rp->prevcentery = rp->centery * 12;
166
167                rp->num = MI_COUNT(mi);
168                if (rp->num < 0) {
169                        rp->num = NRAND(-rp->num) + 1;
170                        if (rp->elements != NULL) {
171                                (void) free((void *) rp->elements);
172                                rp->elements = (elem *) NULL;
173                        }
174                }
175                if (rp->elements == NULL)
176                        if ((rp->elements = (elem *) calloc(rp->num,
177                                        sizeof (elem))) == NULL) {
178                                free_rotor(rp);
179                                return;
180                        }
181                rp->nsave = MI_CYCLES(mi);
182                if (rp->nsave <= 1)
183                        rp->nsave = 2;
184                if (rp->save == NULL)
185                        if ((rp->save = (XPoint *) malloc(rp->nsave *
186                                        sizeof (XPoint))) == NULL) {
187                                free_rotor(rp);
188                                return;
189                        }
190                for (x = 0; x < rp->nsave; x++) {
191                        rp->save[x].x = rp->centerx;
192                        rp->save[x].y = rp->centery;
193                }
194
195                pelem = rp->elements;
196
197                for (x = rp->num; --x >= 0; pelem++) {
198                        pelem->radius_drift_max = 1.0;
199                        pelem->radius_drift_now = 1.0;
200
201                        pelem->end_radius = 100.0;
202
203                        pelem->ratio_drift_max = 1.0;
204                        pelem->ratio_drift_now = 1.0;
205                        pelem->end_ratio = 10.0;
206                }
207                if (MI_NPIXELS(mi) > 2)
208                        rp->pix = NRAND(MI_NPIXELS(mi));
209
210                rp->rotor = 0;
211                rp->prev = 1;
212                rp->lastx = rp->centerx;
213                rp->lasty = rp->centery;
214                rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
215                rp->forward = rp->firsttime = True;
216        }
217        rp->linewidth = MI_SIZE(mi);
218
219        if (rp->linewidth == 0)
220                rp->linewidth = 1;
221        if (rp->linewidth < 0)
222                rp->linewidth = NRAND(-rp->linewidth) + 1;
223
224        MI_CLEARWINDOW(mi);
225}
226
227void
228draw_rotor(ModeInfo * mi)
229{
230        Display    *display = MI_DISPLAY(mi);
231        GC          gc = MI_GC(mi);
232        register elem *pelem;
233        int         thisx, thisy;
234        int         i;
235        int         x_1, y_1, x_2, y_2;
236        rotorstruct *rp;
237
238        if (rotors == NULL)
239                return;
240        rp = &rotors[MI_SCREEN(mi)];
241        if (rp->elements == NULL)
242                return;
243
244        MI_IS_DRAWN(mi) = True;
245        if (!rp->iconifiedscreen) {
246                thisx = rp->centerx;
247                thisy = rp->centery;
248        } else {
249                thisx = rp->prevcenterx;
250                thisy = rp->prevcentery;
251        }
252        XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
253                           LineSolid, CapButt, JoinMiter);
254        for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
255                if (pelem->radius_drift_max <= pelem->radius_drift_now) {
256                        pelem->start_radius = pelem->end_radius;
257                        pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
258                        pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
259                        pelem->radius_drift_now = 0.0;
260                }
261                if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
262                        pelem->start_ratio = pelem->end_ratio;
263                        pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
264                        pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
265                        pelem->ratio_drift_now = 0.0;
266                }
267                pelem->ratio = pelem->start_ratio +
268                        (pelem->end_ratio - pelem->start_ratio) /
269                        pelem->ratio_drift_max * pelem->ratio_drift_now;
270                pelem->angle = rp->angle * pelem->ratio;
271                pelem->radius = pelem->start_radius +
272                        (pelem->end_radius - pelem->start_radius) /
273                        pelem->radius_drift_max * pelem->radius_drift_now;
274
275                thisx += (int) (COSF(pelem->angle) * pelem->radius);
276                thisy += (int) (SINF(pelem->angle) * pelem->radius);
277
278                pelem->ratio_drift_now += 1.0;
279                pelem->radius_drift_now += 1.0;
280        }
281        if (rp->firsttime)
282                rp->firsttime = False;
283        else {
284                XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
285
286                x_1 = (int) rp->save[rp->rotor].x;
287                y_1 = (int) rp->save[rp->rotor].y;
288                x_2 = (int) rp->save[rp->prev].x;
289                y_2 = (int) rp->save[rp->prev].y;
290
291                if (rp->iconifiedscreen) {
292                        x_1 = x_1 * rp->centerx / rp->prevcenterx;
293                        x_2 = x_2 * rp->centerx / rp->prevcenterx;
294                        y_1 = y_1 * rp->centery / rp->prevcentery;
295                        y_2 = y_2 * rp->centery / rp->prevcentery;
296                }
297                XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
298
299                if (MI_NPIXELS(mi) > 2) {
300                        XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
301                        if (++rp->pix >= MI_NPIXELS(mi))
302                                rp->pix = 0;
303                } else
304                        XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
305
306                x_1 = rp->lastx;
307                y_1 = rp->lasty;
308                x_2 = thisx;
309                y_2 = thisy;
310
311                if (rp->iconifiedscreen) {
312                        x_1 = x_1 * rp->centerx / rp->prevcenterx;
313                        x_2 = x_2 * rp->centerx / rp->prevcenterx;
314                        y_1 = y_1 * rp->centery / rp->prevcentery;
315                        y_2 = y_2 * rp->centery / rp->prevcentery;
316                }
317                XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
318        }
319        rp->save[rp->rotor].x = rp->lastx = thisx;
320        rp->save[rp->rotor].y = rp->lasty = thisy;
321
322        ++rp->rotor;
323        rp->rotor %= rp->nsave;
324        ++rp->prev;
325        rp->prev %= rp->nsave;
326        if (rp->forward) {
327                rp->angle += 0.01;
328                if (rp->angle >= MAXANGLE) {
329                        rp->angle = MAXANGLE;
330                        rp->forward = False;
331                }
332        } else {
333                rp->angle -= 0.1;
334                if (rp->angle <= 0) {
335                        rp->angle = 0.0;
336                        rp->forward = True;
337                }
338        }
339        if (rp->redrawing) {
340                int         j;
341
342                for (i = 0; i < REDRAWSTEP; i++) {
343                        j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
344
345                        x_1 = (int) rp->save[j].x;
346                        y_1 = (int) rp->save[j].y;
347                        x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
348                        y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
349
350                        if (rp->iconifiedscreen) {
351                                x_1 = x_1 * rp->centerx / rp->prevcenterx;
352                                x_2 = x_2 * rp->centerx / rp->prevcenterx;
353                                y_1 = y_1 * rp->centery / rp->prevcentery;
354                                y_2 = y_2 * rp->centery / rp->prevcentery;
355                        }
356                        XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
357
358                        if (++(rp->redrawpos) >= rp->nsave) {
359                                rp->redrawing = 0;
360                                break;
361                        }
362                }
363        }
364        XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
365                           LineSolid, CapButt, JoinMiter);
366}
367
368void
369release_rotor(ModeInfo * mi)
370{
371        if (rotors != NULL) {
372                int         screen;
373
374                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
375                        free_rotor(&rotors[screen]);
376                (void) free((void *) rotors);
377                rotors = (rotorstruct *) NULL;
378        }
379}
380
381void
382refresh_rotor(ModeInfo * mi)
383{
384        rotorstruct *rp;
385
386        if (rotors == NULL)
387                return;
388        rp = &rotors[MI_SCREEN(mi)];
389
390        MI_CLEARWINDOW(mi);
391        rp->redrawing = 1;
392        rp->redrawpos = 1;
393}
394
395#endif /* MODE_rotor */
Note: See TracBrowser for help on using the repository browser.