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

Revision 20148, 8.0 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/* lissie --- the Lissajous worm */
3
4#if 0
5static const char sccsid[] = "@(#)lissie.c      5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * lissie.c - The Lissajous worm for xlock, the X Window System
10 *               lockscreen.
11 *
12 * Copyright (c) 1996 by Alexander Jolk <ub9x@rz.uni-karlsruhe.de>
13 *
14 * Permission to use, copy, modify, and distribute this software and its
15 * documentation for any purpose and without fee is hereby granted,
16 * provided that the above copyright notice appear in all copies and that
17 * both that copyright notice and this permission notice appear in
18 * supporting documentation.
19 *
20 * This file is provided AS IS with no warranties of any kind.  The author
21 * shall have no liability with respect to the infringement of copyrights,
22 * trade secrets or any patents by this file or any part thereof.  In no
23 * event will the author be liable for any lost revenue or profits or
24 * other special, indirect and consequential damages.
25 *
26 * Revision History:
27 * 01-Nov-2000: Allocation checks
28 * 10-May-1997: Compatible with xscreensaver
29 * 18-Aug-1996: added refresh-hook.
30 * 01-May-1996: written.
31 */
32
33#ifdef STANDALONE
34#define MODE_lissie
35#define PROGCLASS "Lissie"
36#define HACK_INIT init_lissie
37#define HACK_DRAW draw_lissie
38#define lissie_opts xlockmore_opts
39#define DEFAULTS "*delay: 10000 \n" \
40 "*count: 1 \n" \
41 "*cycles: 20000 \n" \
42 "*size: -200 \n" \
43 "*ncolors: 200 \n"
44#define SMOOTH_COLORS
45#include "xlockmore.h"          /* in xscreensaver distribution */
46#else /* STANDALONE */
47#include "xlock.h"              /* in xlockmore distribution */
48#endif /* STANDALONE */
49
50#ifdef MODE_lissie
51
52ModeSpecOpt lissie_opts =
53{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
54
55#ifdef USE_MODULES
56ModStruct   lissie_description =
57{"lissie", "init_lissie", "draw_lissie", "release_lissie",
58 "refresh_lissie", "init_lissie", (char *) NULL, &lissie_opts,
59 10000, 1, 2000, -200, 64, 0.6, "",
60 "Shows lissajous worms", 0, NULL};
61
62#endif
63
64#define MINSIZE 1
65
66#define Lissie(n)\
67        if (lissie->loc[(n)].x > 0 && lissie->loc[(n)].y > 0 &&\
68                lissie->loc[(n)].x <= lp->width && lissie->loc[(n)].y <= lp->height) {\
69                if (lissie->ri < 2)\
70                        XDrawPoint(display, MI_WINDOW(mi),\
71                                gc, lissie->loc[(n)].x, lissie->loc[(n)].y);\
72                else\
73                        XDrawArc(display, MI_WINDOW(mi), gc,\
74                                lissie->loc[(n)].x - lissie->ri / 2,\
75                                lissie->loc[(n)].y - lissie->ri / 2,\
76                                lissie->ri, lissie->ri, 0, 23040);\
77        }
78
79#define FLOATRAND(min,max)      ((min)+(LRAND()/MAXRAND)*((max)-(min)))
80#define INTRAND(min,max)     ((min)+NRAND((max)-(min)+1))
81
82#define MINDT  0.01
83#define MAXDT  0.15
84
85#define MAXLISSIELEN  100
86#define MINLISSIELEN  10
87#define MINLISSIES 1
88
89/* How many segments to draw per cycle when redrawing */
90#define REDRAWSTEP 3
91
92typedef struct {
93        double      tx, ty, dtx, dty;
94        int         xi, yi, ri, rx, ry, len, pos;
95        int         redrawing, redrawpos;
96        XPoint      loc[MAXLISSIELEN];
97        unsigned long color;
98} lissiestruct;
99
100typedef struct {
101        Bool        painted;
102        int         width, height;
103        int         nlissies;
104        lissiestruct *lissie;
105        int         loopcount;
106} lissstruct;
107
108static lissstruct *lisses = (lissstruct *) NULL;
109
110
111static void
112drawlissie(ModeInfo * mi, lissiestruct * lissie)
113{
114        Display    *display = MI_DISPLAY(mi);
115        GC          gc = MI_GC(mi);
116        lissstruct *lp = &lisses[MI_SCREEN(mi)];
117        int         p = (++lissie->pos) % MAXLISSIELEN;
118        int         oldp = (lissie->pos - lissie->len + MAXLISSIELEN) % MAXLISSIELEN;
119
120        /* Let time go by ... */
121        lissie->tx += lissie->dtx;
122        lissie->ty += lissie->dty;
123        if (lissie->tx > 2 * M_PI)
124                lissie->tx -= 2 * M_PI;
125        if (lissie->ty > 2 * M_PI)
126                lissie->ty -= 2 * M_PI;
127
128        /* vary both (x/y) speeds by max. 1% */
129        lissie->dtx *= FLOATRAND(0.99, 1.01);
130        lissie->dty *= FLOATRAND(0.99, 1.01);
131        if (lissie->dtx < MINDT)
132                lissie->dtx = MINDT;
133        else if (lissie->dtx > MAXDT)
134                lissie->dtx = MAXDT;
135        if (lissie->dty < MINDT)
136                lissie->dty = MINDT;
137        else if (lissie->dty > MAXDT)
138                lissie->dty = MAXDT;
139
140        lissie->loc[p].x = lissie->xi + (int) (sin(lissie->tx) * lissie->rx);
141        lissie->loc[p].y = lissie->yi + (int) (sin(lissie->ty) * lissie->ry);
142
143        /* Mask */
144        XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
145        Lissie(oldp);
146
147        /* Redraw */
148        if (MI_NPIXELS(mi) > 2) {
149                XSetForeground(display, gc, MI_PIXEL(mi, lissie->color));
150                if (++lissie->color >= (unsigned) MI_NPIXELS(mi))
151                        lissie->color = 0;
152        } else
153                XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
154        Lissie(p);
155        if (lissie->redrawing) {
156                int         i;
157
158                lissie->redrawpos++;
159                /* This compensates for the changed p
160                   since the last callback. */
161
162                for (i = 0; i < REDRAWSTEP; i++) {
163                        Lissie((p - lissie->redrawpos + MAXLISSIELEN) % MAXLISSIELEN);
164                        if (++(lissie->redrawpos) >= lissie->len) {
165                                lissie->redrawing = 0;
166                                break;
167                        }
168                }
169        }
170}
171
172static void
173initlissie(ModeInfo * mi, lissiestruct * lissie)
174{
175        lissstruct *lp = &lisses[MI_SCREEN(mi)];
176        int         size = MI_SIZE(mi);
177        int         i;
178
179        if (MI_NPIXELS(mi) > 2)
180                lissie->color = NRAND(MI_NPIXELS(mi));
181        else
182                lissie->color = MI_WHITE_PIXEL(mi);
183        /* Initialize parameters */
184        if (size < -MINSIZE)
185                lissie->ri = NRAND(MIN(-size, MAX(MINSIZE,
186                   MIN(lp->width, lp->height) / 4)) - MINSIZE + 1) + MINSIZE;
187        else if (size < MINSIZE) {
188                if (!size)
189                        lissie->ri = MAX(MINSIZE, MIN(lp->width, lp->height) / 4);
190                else
191                        lissie->ri = MINSIZE;
192        } else
193                lissie->ri = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / 4));
194        lissie->xi = INTRAND(lp->width / 4 + lissie->ri,
195                             lp->width * 3 / 4 - lissie->ri);
196        lissie->yi = INTRAND(lp->height / 4 + lissie->ri,
197                             lp->height * 3 / 4 - lissie->ri);
198        lissie->rx = INTRAND(lp->width / 4,
199                   MIN(lp->width - lissie->xi, lissie->xi)) - 2 * lissie->ri;
200        lissie->ry = INTRAND(lp->height / 4,
201                  MIN(lp->height - lissie->yi, lissie->yi)) - 2 * lissie->ri;
202        lissie->len = INTRAND(MINLISSIELEN, MAXLISSIELEN - 1);
203        lissie->pos = 0;
204
205        lissie->redrawing = 0;
206
207        lissie->tx = FLOATRAND(0, 2 * M_PI);
208        lissie->ty = FLOATRAND(0, 2 * M_PI);
209        lissie->dtx = FLOATRAND(MINDT, MAXDT);
210        lissie->dty = FLOATRAND(MINDT, MAXDT);
211
212        for (i = 0; i < MAXLISSIELEN; i++)
213                lissie->loc[i].x = lissie->loc[i].y = 0;
214        /* Draw lissie */
215        drawlissie(mi, lissie);
216}
217
218void
219init_lissie(ModeInfo * mi)
220{
221        lissstruct *lp;
222        unsigned char ball;
223
224        if (lisses == NULL) {
225                if ((lisses = (lissstruct *) calloc(MI_NUM_SCREENS(mi),
226                                               sizeof (lissstruct))) == NULL)
227                        return;
228        }
229        lp = &lisses[MI_SCREEN(mi)];
230
231        lp->width = MI_WIDTH(mi);
232        lp->height = MI_HEIGHT(mi);
233
234        lp->nlissies = MI_COUNT(mi);
235        if (lp->nlissies < -MINLISSIES) {
236                if (lp->lissie) {
237                        (void) free((void *) lp->lissie);
238                        lp->lissie = (lissiestruct *) NULL;
239                }
240                lp->nlissies = NRAND(-lp->nlissies - MINLISSIES + 1) + MINLISSIES;
241        } else if (lp->nlissies < MINLISSIES)
242                lp->nlissies = MINLISSIES;
243
244        lp->loopcount = 0;
245
246        if (lp->lissie == NULL)
247                if ((lp->lissie = (lissiestruct *) calloc(lp->nlissies,
248                                sizeof (lissiestruct))) == NULL)
249                        return;
250
251        MI_CLEARWINDOW(mi);
252        lp->painted = False;
253
254        for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
255                initlissie(mi, &lp->lissie[ball]);
256
257}
258
259void
260draw_lissie(ModeInfo * mi)
261{
262        register unsigned char ball;
263        lissstruct *lp;
264
265        if (lisses == NULL)
266                return;
267        lp = &lisses[MI_SCREEN(mi)];
268        if (lp->lissie == NULL)
269                return;
270
271        MI_IS_DRAWN(mi) = True;
272
273        if (++lp->loopcount > MI_CYCLES(mi)) {
274                init_lissie(mi);
275        } else {
276                lp->painted = True;
277                for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
278                        drawlissie(mi, &lp->lissie[ball]);
279        }
280}
281
282void
283release_lissie(ModeInfo * mi)
284{
285        if (lisses != NULL) {
286                int         screen;
287
288                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
289                        lissstruct *lp = &lisses[screen];
290
291                        if (lp->lissie != NULL) {
292                                (void) free((void *) lp->lissie);
293                                /* lp->lissie = NULL; */
294                        }
295                }
296                (void) free((void *) lisses);
297                lisses = (lissstruct *) NULL;
298        }
299}
300
301void
302refresh_lissie(ModeInfo * mi)
303{
304        int         i;
305        lissstruct *lp;
306
307        if (lisses == NULL)
308                return;
309        lp = &lisses[MI_SCREEN(mi)];
310        if (lp->lissie == NULL)
311                return;
312
313        if (lp->painted) {
314                MI_CLEARWINDOW(mi);
315                for (i = 0; i < lp->nlissies; i++) {
316                        lp->lissie[i].redrawing = 1;
317                        lp->lissie[i].redrawpos = 0;
318                }
319        }
320}
321
322#endif /* MODE_lissie */
Note: See TracBrowser for help on using the repository browser.