1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* laser --- spinning lasers */
5 static const char sccsid[] = "@(#)laser.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
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.
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.
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
31 # define DEFAULTS "*delay: 40000 \n" \
35 "*fpsSolid: true \n" \
37 # define BRIGHT_COLORS
38 # define reshape_laser 0
39 # define laser_handle_event 0
40 # include "xlockmore.h" /* in xscreensaver distribution */
41 #else /* STANDALONE */
42 # include "xlock.h" /* in xlockmore distribution */
43 #endif /* STANDALONE */
47 ENTRYPOINT ModeSpecOpt laser_opts =
48 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
51 ModStruct 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};
59 #define MINREDRAW 3 /* Number of redrawn on each frame */
62 #define MINLASER 1 /* Laser number */
64 #define MINWIDTH 2 /* Laser ray width range */
67 #define MINSPEED 2 /* Speed range */
70 #define MINDIST 10 /* Minimal distance from edges */
72 #define COLORSTEP 2 /* Laser color step */
74 #define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min)))
77 TOP, RIGHT, BOTTOM, LEFT
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 */
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 */
103 XGCValues gcv_black; /* for black color */
107 static lasersstruct *lasers = (lasersstruct *) NULL;
110 free_laser(Display *display, lasersstruct *lp)
112 if (lp->laser != NULL) {
113 (void) free((void *) lp->laser);
114 lp->laser = (laserstruct *) NULL;
116 if (lp->stippledGC != None) {
117 XFreeGC(display, lp->stippledGC);
118 lp->stippledGC = None;
123 init_laser(ModeInfo * mi)
125 Display *display = MI_DISPLAY(mi);
129 if (lasers == NULL) {
130 if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
131 sizeof (lasersstruct))) == NULL)
134 lp = &lasers[MI_SCREEN(mi)];
136 lp->width = MI_WIDTH(mi);
137 lp->height = MI_HEIGHT(mi);
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;
147 lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
148 } else if (lp->ln < MINLASER)
151 if (lp->laser == NULL) {
152 if ((lp->laser = (laserstruct *) malloc(lp->ln *
153 sizeof (laserstruct))) == NULL) {
154 free_laser(display, lp);
158 if (lp->stippledGC == None) {
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);
170 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), lp->stippledGC, False);
175 if (MINDIST < lp->width - MINDIST)
176 lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
178 lp->cx = RANGE_RAND(0, lp->width);
179 if (MINDIST < lp->height - MINDIST)
180 lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
182 lp->cy = RANGE_RAND(0, lp->height);
183 lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
184 lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
188 if (MI_NPIXELS(mi) > 2)
189 c = NRAND(MI_NPIXELS(mi));
191 for (i = 0; i < lp->ln; i++) {
192 laserstruct *l = &lp->laser[i];
194 l->bn = (border) NRAND(4);
198 l->bx = NRAND(lp->width);
203 l->by = NRAND(lp->height);
206 l->bx = NRAND(lp->width);
211 l->by = NRAND(lp->height);
214 l->dir = (int) (LRAND() & 1);
215 l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
216 if (MI_NPIXELS(mi) > 2) {
217 l->gcv.foreground = MI_PIXEL(mi, c);
218 c = (c + COLORSTEP) % MI_NPIXELS(mi);
220 l->gcv.foreground = MI_WHITE_PIXEL(mi);
225 draw_laser_once(ModeInfo * mi)
227 Display *display = MI_DISPLAY(mi);
228 lasersstruct *lp = &lasers[MI_SCREEN(mi)];
231 for (i = 0; i < lp->ln; i++) {
232 laserstruct *l = &lp->laser[i];
234 if (lp->sw >= lp->lw) {
235 XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
236 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
238 l->sx[lp->so], l->sy[lp->so]);
253 l->bx = lp->width + l->by;
260 if (l->bx >= lp->width) {
261 l->by = lp->height - l->bx % lp->width;
268 if (l->by >= lp->height) {
269 l->bx = l->by % lp->height;
278 if (l->bx >= lp->width) {
279 l->by = l->bx % lp->width;
286 if (l->by >= lp->height) {
287 l->bx = lp->width - l->by % lp->height;
295 l->by = lp->height + l->bx;
310 XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
311 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
312 lp->cx, lp->cy, l->bx, l->by);
314 l->sx[lp->so] = l->bx;
315 l->sy[lp->so] = l->by;
322 lp->so = (lp->so + 1) % lp->lw;
326 draw_laser(ModeInfo * mi)
333 lp = &lasers[MI_SCREEN(mi)];
334 if (lp->laser == NULL)
337 MI_IS_DRAWN(mi) = True;
338 for (i = 0; i < lp->lr; i++)
341 if (++lp->time > MI_CYCLES(mi))
346 release_laser(ModeInfo * mi)
348 if (lasers != NULL) {
351 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
352 free_laser(MI_DISPLAY(mi), &lasers[screen]);
353 (void) free((void *) lasers);
354 lasers = (lasersstruct *) NULL;
359 refresh_laser(ModeInfo * mi)
364 XSCREENSAVER_MODULE ("Laser", laser)
366 #endif /* MODE_laser */