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

Revision 20148, 8.2 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/* laser --- spinning lasers */
3
4#if 0
5static const char sccsid[] = "@(#)laser.c       5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
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 * 1995: Written.
27 */
28
29#ifdef STANDALONE
30#define MODE_laser
31#define PROGCLASS "Laser"
32#define HACK_INIT init_laser
33#define HACK_DRAW draw_laser
34#define laser_opts xlockmore_opts
35#define DEFAULTS "*delay: 40000 \n" \
36 "*count: 10 \n" \
37 "*cycles: 200 \n" \
38 "*ncolors: 64 \n"
39#define BRIGHT_COLORS
40#include "xlockmore.h"          /* in xscreensaver distribution */
41#else /* STANDALONE */
42#include "xlock.h"              /* in xlockmore distribution */
43#endif /* STANDALONE */
44
45#ifdef MODE_laser
46
47ModeSpecOpt laser_opts =
48{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
49
50#ifdef USE_MODULES
51ModStruct   laser_description =
52{"laser", "init_laser", "draw_laser", "release_laser",
53 "refresh_laser", "init_laser", (char *) NULL, &laser_opts,
54 20000, -10, 200, 1, 64, 1.0, "",
55 "Shows spinning lasers", 0, NULL};
56
57#endif
58
59#define MINREDRAW 3             /* Number of redrawn on each frame */
60#define MAXREDRAW 8
61
62#define MINLASER  1             /* Laser number */
63
64#define MINWIDTH  2             /* Laser ray width range */
65#define MAXWIDTH 40
66
67#define MINSPEED  2             /* Speed range */
68#define MAXSPEED 17
69
70#define MINDIST  10             /* Minimal distance from edges */
71
72#define COLORSTEP 2             /* Laser color step */
73
74#define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min)))
75
76typedef enum {
77        TOP, RIGHT, BOTTOM, LEFT
78} border;
79
80typedef struct {
81        int         bx;         /* border x */
82        int         by;         /* border y */
83        border      bn;         /* active border */
84        int         dir;        /* direction */
85        int         speed;      /* laser velocity from MINSPEED to MAXSPEED */
86        int         sx[MAXWIDTH];       /* x stack */
87        int         sy[MAXWIDTH];       /* x stack */
88        XGCValues   gcv;        /* for color */
89} laserstruct;
90
91typedef struct {
92        int         width;
93        int         height;
94        int         cx;         /* center x */
95        int         cy;         /* center y */
96        int         lw;         /* laser width */
97        int         ln;         /* laser number */
98        int         lr;         /* laser redraw */
99        int         sw;         /* stack width */
100        int         so;         /* stack offset */
101        int         time;       /* up time */
102        GC          stippledGC;
103        XGCValues   gcv_black;  /* for black color */
104        laserstruct *laser;
105} lasersstruct;
106
107static lasersstruct *lasers = (lasersstruct *) NULL;
108
109static void
110free_laser(Display *display, lasersstruct *lp)
111{
112        if (lp->laser != NULL) {
113                (void) free((void *) lp->laser);
114                lp->laser = (laserstruct *) NULL;
115        }
116        if (lp->stippledGC != None) {
117                XFreeGC(display, lp->stippledGC);
118                lp->stippledGC = None;
119        }
120}
121
122void
123init_laser(ModeInfo * mi)
124{
125        Display *display = MI_DISPLAY(mi);
126        int         i, c = 0;
127        lasersstruct *lp;
128
129        if (lasers == NULL) {
130                if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
131                                             sizeof (lasersstruct))) == NULL)
132                        return;
133        }
134        lp = &lasers[MI_SCREEN(mi)];
135
136        lp->width = MI_WIDTH(mi);
137        lp->height = MI_HEIGHT(mi);
138        lp->time = 0;
139
140        lp->ln = MI_COUNT(mi);
141        if (lp->ln < -MINLASER) {
142                /* if lp->ln is random ... the size can change */
143                if (lp->laser != NULL) {
144                        (void) free((void *) lp->laser);
145                        lp->laser = (laserstruct *) NULL;
146                }
147                lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
148        } else if (lp->ln < MINLASER)
149                lp->ln = MINLASER;
150
151        if (lp->laser == NULL) {
152                if ((lp->laser = (laserstruct *) malloc(lp->ln *
153                                sizeof (laserstruct))) == NULL) {
154                        free_laser(display, lp);
155                        return;
156                }
157        }
158        if (lp->stippledGC == None) {
159                XGCValues   gcv;
160
161                gcv.foreground = MI_WHITE_PIXEL(mi);
162                gcv.background = MI_BLACK_PIXEL(mi);
163                lp->gcv_black.foreground = MI_BLACK_PIXEL(mi);
164                if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi),
165                                GCForeground | GCBackground, &gcv)) == None) {
166                        free_laser(display, lp);
167                        return;
168                }
169        }
170        MI_CLEARWINDOW(mi);
171
172        if (MINDIST < lp->width - MINDIST)
173                lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
174        else
175                lp->cx = RANGE_RAND(0, lp->width);
176        if (MINDIST < lp->height - MINDIST)
177                lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
178        else
179                lp->cy = RANGE_RAND(0, lp->height);
180        lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
181        lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
182        lp->sw = 0;
183        lp->so = 0;
184
185        if (MI_NPIXELS(mi) > 2)
186                c = NRAND(MI_NPIXELS(mi));
187
188        for (i = 0; i < lp->ln; i++) {
189                laserstruct *l = &lp->laser[i];
190
191                l->bn = (border) NRAND(4);
192
193                switch (l->bn) {
194                        case TOP:
195                                l->bx = NRAND(lp->width);
196                                l->by = 0;
197                                break;
198                        case RIGHT:
199                                l->bx = lp->width;
200                                l->by = NRAND(lp->height);
201                                break;
202                        case BOTTOM:
203                                l->bx = NRAND(lp->width);
204                                l->by = lp->height;
205                                break;
206                        case LEFT:
207                                l->bx = 0;
208                                l->by = NRAND(lp->height);
209                }
210
211                l->dir = (int) (LRAND() & 1);
212                l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
213                if (MI_NPIXELS(mi) > 2) {
214                        l->gcv.foreground = MI_PIXEL(mi, c);
215                        c = (c + COLORSTEP) % MI_NPIXELS(mi);
216                } else
217                        l->gcv.foreground = MI_WHITE_PIXEL(mi);
218        }
219}
220
221static void
222draw_laser_once(ModeInfo * mi)
223{
224        Display    *display = MI_DISPLAY(mi);
225        lasersstruct *lp = &lasers[MI_SCREEN(mi)];
226        int         i;
227
228        for (i = 0; i < lp->ln; i++) {
229                laserstruct *l = &lp->laser[i];
230
231                if (lp->sw >= lp->lw) {
232                        XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
233                        XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
234                                  lp->cx, lp->cy,
235                                  l->sx[lp->so], l->sy[lp->so]);
236                }
237                if (l->dir) {
238                        switch (l->bn) {
239                                case TOP:
240                                        l->bx -= l->speed;
241                                        if (l->bx < 0) {
242                                                l->by = -l->bx;
243                                                l->bx = 0;
244                                                l->bn = LEFT;
245                                        }
246                                        break;
247                                case RIGHT:
248                                        l->by -= l->speed;
249                                        if (l->by < 0) {
250                                                l->bx = lp->width + l->by;
251                                                l->by = 0;
252                                                l->bn = TOP;
253                                        }
254                                        break;
255                                case BOTTOM:
256                                        l->bx += l->speed;
257                                        if (l->bx >= lp->width) {
258                                                l->by = lp->height - l->bx % lp->width;
259                                                l->bx = lp->width;
260                                                l->bn = RIGHT;
261                                        }
262                                        break;
263                                case LEFT:
264                                        l->by += l->speed;
265                                        if (l->by >= lp->height) {
266                                                l->bx = l->by % lp->height;
267                                                l->by = lp->height;
268                                                l->bn = BOTTOM;
269                                        }
270                        }
271                } else {
272                        switch (l->bn) {
273                                case TOP:
274                                        l->bx += l->speed;
275                                        if (l->bx >= lp->width) {
276                                                l->by = l->bx % lp->width;
277                                                l->bx = lp->width;
278                                                l->bn = RIGHT;
279                                        }
280                                        break;
281                                case RIGHT:
282                                        l->by += l->speed;
283                                        if (l->by >= lp->height) {
284                                                l->bx = lp->width - l->by % lp->height;
285                                                l->by = lp->height;
286                                                l->bn = BOTTOM;
287                                        }
288                                        break;
289                                case BOTTOM:
290                                        l->bx -= l->speed;
291                                        if (l->bx < 0) {
292                                                l->by = lp->height + l->bx;
293                                                l->bx = 0;
294                                                l->bn = LEFT;
295                                        }
296                                        break;
297                                case LEFT:
298                                        l->by -= l->speed;
299                                        if (l->by < 0) {
300                                                l->bx = -l->bx;
301                                                l->by = 0;
302                                                l->bn = TOP;
303                                        }
304                        }
305                }
306
307                XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
308                XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
309                          lp->cx, lp->cy, l->bx, l->by);
310
311                l->sx[lp->so] = l->bx;
312                l->sy[lp->so] = l->by;
313
314        }
315
316        if (lp->sw < lp->lw)
317                ++lp->sw;
318
319        lp->so = (lp->so + 1) % lp->lw;
320}
321
322void
323draw_laser(ModeInfo * mi)
324{
325        int         i;
326        lasersstruct *lp;
327
328        if (lasers == NULL)
329                return;
330        lp = &lasers[MI_SCREEN(mi)];
331        if (lp->laser == NULL)
332                return;
333
334        MI_IS_DRAWN(mi) = True;
335        for (i = 0; i < lp->lr; i++)
336                draw_laser_once(mi);
337
338        if (++lp->time > MI_CYCLES(mi))
339                init_laser(mi);
340}
341
342void
343release_laser(ModeInfo * mi)
344{
345        if (lasers != NULL) {
346                int         screen;
347
348                for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
349                        free_laser(MI_DISPLAY(mi), &lasers[screen]);
350                (void) free((void *) lasers);
351                lasers = (lasersstruct *) NULL;
352        }
353}
354
355void
356refresh_laser(ModeInfo * mi)
357{
358        MI_CLEARWINDOW(mi);
359}
360
361#endif /* MODE_laser */
Note: See TracBrowser for help on using the repository browser.