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 # define BRIGHT_COLORS
36 # define reshape_laser 0
37 # define laser_handle_event 0
38 # include "xlockmore.h" /* in xscreensaver distribution */
39 #else /* STANDALONE */
40 # include "xlock.h" /* in xlockmore distribution */
41 #endif /* STANDALONE */
45 ENTRYPOINT ModeSpecOpt laser_opts =
46 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
49 ModStruct laser_description =
50 {"laser", "init_laser", "draw_laser", "release_laser",
51 "refresh_laser", "init_laser", (char *) NULL, &laser_opts,
52 20000, -10, 200, 1, 64, 1.0, "",
53 "Shows spinning lasers", 0, NULL};
57 #define MINREDRAW 3 /* Number of redrawn on each frame */
60 #define MINLASER 1 /* Laser number */
62 #define MINWIDTH 2 /* Laser ray width range */
65 #define MINSPEED 2 /* Speed range */
68 #define MINDIST 10 /* Minimal distance from edges */
70 #define COLORSTEP 2 /* Laser color step */
72 #define RANGE_RAND(min,max) (int) ((min) + LRAND() % ((max) - (min)))
75 TOP, RIGHT, BOTTOM, LEFT
79 int bx; /* border x */
80 int by; /* border y */
81 border bn; /* active border */
82 int dir; /* direction */
83 int speed; /* laser velocity from MINSPEED to MAXSPEED */
84 int sx[MAXWIDTH]; /* x stack */
85 int sy[MAXWIDTH]; /* x stack */
86 XGCValues gcv; /* for color */
92 int cx; /* center x */
93 int cy; /* center y */
94 int lw; /* laser width */
95 int ln; /* laser number */
96 int lr; /* laser redraw */
97 int sw; /* stack width */
98 int so; /* stack offset */
99 int time; /* up time */
101 XGCValues gcv_black; /* for black color */
105 static lasersstruct *lasers = (lasersstruct *) NULL;
108 free_laser(Display *display, lasersstruct *lp)
110 if (lp->laser != NULL) {
111 (void) free((void *) lp->laser);
112 lp->laser = (laserstruct *) NULL;
114 if (lp->stippledGC != None) {
115 XFreeGC(display, lp->stippledGC);
116 lp->stippledGC = None;
121 init_laser(ModeInfo * mi)
123 Display *display = MI_DISPLAY(mi);
127 if (lasers == NULL) {
128 if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
129 sizeof (lasersstruct))) == NULL)
132 lp = &lasers[MI_SCREEN(mi)];
134 lp->width = MI_WIDTH(mi);
135 lp->height = MI_HEIGHT(mi);
138 lp->ln = MI_COUNT(mi);
139 if (lp->ln < -MINLASER) {
140 /* if lp->ln is random ... the size can change */
141 if (lp->laser != NULL) {
142 (void) free((void *) lp->laser);
143 lp->laser = (laserstruct *) NULL;
145 lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
146 } else if (lp->ln < MINLASER)
149 if (lp->laser == NULL) {
150 if ((lp->laser = (laserstruct *) malloc(lp->ln *
151 sizeof (laserstruct))) == NULL) {
152 free_laser(display, lp);
156 if (lp->stippledGC == None) {
159 gcv.foreground = MI_WHITE_PIXEL(mi);
160 gcv.background = MI_BLACK_PIXEL(mi);
161 lp->gcv_black.foreground = MI_BLACK_PIXEL(mi);
162 if ((lp->stippledGC = XCreateGC(display, MI_WINDOW(mi),
163 GCForeground | GCBackground, &gcv)) == None) {
164 free_laser(display, lp);
168 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), lp->stippledGC, False);
173 if (MINDIST < lp->width - MINDIST)
174 lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
176 lp->cx = RANGE_RAND(0, lp->width);
177 if (MINDIST < lp->height - MINDIST)
178 lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
180 lp->cy = RANGE_RAND(0, lp->height);
181 lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
182 lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
186 if (MI_NPIXELS(mi) > 2)
187 c = NRAND(MI_NPIXELS(mi));
189 for (i = 0; i < lp->ln; i++) {
190 laserstruct *l = &lp->laser[i];
192 l->bn = (border) NRAND(4);
196 l->bx = NRAND(lp->width);
201 l->by = NRAND(lp->height);
204 l->bx = NRAND(lp->width);
209 l->by = NRAND(lp->height);
212 l->dir = (int) (LRAND() & 1);
213 l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
214 if (MI_NPIXELS(mi) > 2) {
215 l->gcv.foreground = MI_PIXEL(mi, c);
216 c = (c + COLORSTEP) % MI_NPIXELS(mi);
218 l->gcv.foreground = MI_WHITE_PIXEL(mi);
223 draw_laser_once(ModeInfo * mi)
225 Display *display = MI_DISPLAY(mi);
226 lasersstruct *lp = &lasers[MI_SCREEN(mi)];
229 for (i = 0; i < lp->ln; i++) {
230 laserstruct *l = &lp->laser[i];
232 if (lp->sw >= lp->lw) {
233 XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
234 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
236 l->sx[lp->so], l->sy[lp->so]);
251 l->bx = lp->width + l->by;
258 if (l->bx >= lp->width) {
259 l->by = lp->height - l->bx % lp->width;
266 if (l->by >= lp->height) {
267 l->bx = l->by % lp->height;
276 if (l->bx >= lp->width) {
277 l->by = l->bx % lp->width;
284 if (l->by >= lp->height) {
285 l->bx = lp->width - l->by % lp->height;
293 l->by = lp->height + l->bx;
308 XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
309 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
310 lp->cx, lp->cy, l->bx, l->by);
312 l->sx[lp->so] = l->bx;
313 l->sy[lp->so] = l->by;
320 lp->so = (lp->so + 1) % lp->lw;
324 draw_laser(ModeInfo * mi)
331 lp = &lasers[MI_SCREEN(mi)];
332 if (lp->laser == NULL)
335 MI_IS_DRAWN(mi) = True;
336 for (i = 0; i < lp->lr; i++)
339 if (++lp->time > MI_CYCLES(mi))
344 release_laser(ModeInfo * mi)
346 if (lasers != NULL) {
349 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
350 free_laser(MI_DISPLAY(mi), &lasers[screen]);
351 (void) free((void *) lasers);
352 lasers = (lasersstruct *) NULL;
357 refresh_laser(ModeInfo * mi)
362 XSCREENSAVER_MODULE ("Laser", laser)
364 #endif /* MODE_laser */