1 /* -*- Mode: C; tab-width: 4 -*-
2 * laser --- draws swinging laser beams.
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)laser.c 4.00 97/01/01 xlockmore";
8 /* Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
10 * Permission to use, copy, modify, distribute, and sell this software and its
11 * documentation for any purpose is hereby granted without fee, provided that
12 * the above copyright notice appear in all copies and that both that
13 * copyright notice and this permission notice appear in supporting
14 * documentation. No representations are made about the suitability of this
15 * software for any purpose. It is provided "as is" without express or
19 * 10-May-97: jwz@jwz.org: turned into a standalone program.
23 # define PROGCLASS "Laser"
24 # define HACK_INIT init_laser
25 # define HACK_DRAW draw_laser
26 # define laser_opts xlockmore_opts
27 # define DEFAULTS "*count: 10 \n" \
31 # define SMOOTH_COLORS
32 # include "xlockmore.h" /* from the xscreensaver distribution */
33 #else /* !STANDALONE */
34 # include "xlock.h" /* from the xlockmore distribution */
35 #endif /* !STANDALONE */
37 ModeSpecOpt laser_opts = {
38 0, NULL, 0, NULL, NULL };
40 #define MINREDRAW 3 /* Number of redrawn on each frame */
43 #define MINLASER 1 /* Laser number */
45 #define MINWIDTH 2 /* Laser ray width range */
48 #define MINSPEED 2 /* Speed range */
51 #define MINDIST 10 /* Minimal distance from edges */
53 #define COLORSTEP 2 /* Laser color step */
55 #define RANGE_RAND(min,max) ((min) + LRAND() % ((max) - (min)))
58 TOP, RIGHT, BOTTOM, LEFT
62 int bx; /* border x */
63 int by; /* border y */
64 border bn; /* active border */
65 int dir; /* direction */
66 int speed; /* laser velocity from MINSPEED to MAXSPEED */
67 int sx[MAXWIDTH]; /* x stack */
68 int sy[MAXWIDTH]; /* x stack */
69 XGCValues gcv; /* for color */
75 int cx; /* center x */
76 int cy; /* center y */
77 int lw; /* laser width */
78 int ln; /* laser number */
79 int lr; /* laser redraw */
80 int sw; /* stack width */
81 int so; /* stack offset */
82 int time; /* up time */
84 XGCValues gcv_black; /* for black color */
88 static lasersstruct *lasers = NULL;
92 init_laser(ModeInfo * mi)
98 if ((lasers = (lasersstruct *) calloc(MI_NUM_SCREENS(mi),
99 sizeof (lasersstruct))) == NULL)
102 lp = &lasers[MI_SCREEN(mi)];
104 lp->width = MI_WIN_WIDTH(mi);
105 lp->height = MI_WIN_HEIGHT(mi);
108 lp->ln = MI_BATCHCOUNT(mi);
109 if (lp->ln < -MINLASER) {
110 /* if lp->ln is random ... the size can change */
111 if (lp->laser != NULL) {
112 (void) free((void *) lp->laser);
115 lp->ln = NRAND(-lp->ln - MINLASER + 1) + MINLASER;
116 } else if (lp->ln < MINLASER)
120 lp->laser = (laserstruct *) malloc(lp->ln * sizeof (laserstruct));
122 if (lp->stippledGC == NULL) {
125 gcv.foreground = MI_WIN_WHITE_PIXEL(mi);
126 gcv.background = MI_WIN_BLACK_PIXEL(mi);
127 lp->gcv_black.foreground = MI_WIN_BLACK_PIXEL(mi);
128 lp->stippledGC = XCreateGC(MI_DISPLAY(mi), MI_WINDOW(mi),
129 GCForeground | GCBackground, &gcv);
131 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
133 if (MINDIST < lp->width - MINDIST)
134 lp->cx = RANGE_RAND(MINDIST, lp->width - MINDIST);
136 lp->cx = RANGE_RAND(0, lp->width);
137 if (MINDIST < lp->height - MINDIST)
138 lp->cy = RANGE_RAND(MINDIST, lp->height - MINDIST);
140 lp->cy = RANGE_RAND(0, lp->height);
141 lp->lw = RANGE_RAND(MINWIDTH, MAXWIDTH);
142 lp->lr = RANGE_RAND(MINREDRAW, MAXREDRAW);
146 if (MI_NPIXELS(mi) > 2)
147 c = NRAND(MI_NPIXELS(mi));
149 for (i = 0; i < lp->ln; i++) {
150 laserstruct *l = &lp->laser[i];
152 l->bn = (border) NRAND(4);
156 l->bx = NRAND(lp->width);
161 l->by = NRAND(lp->height);
164 l->bx = NRAND(lp->width);
169 l->by = NRAND(lp->height);
172 l->dir = LRAND() & 1;
173 l->speed = ((RANGE_RAND(MINSPEED, MAXSPEED) * lp->width) / 1000) + 1;
174 if (MI_NPIXELS(mi) > 2) {
175 l->gcv.foreground = MI_PIXEL(mi, c);
176 c = (c + COLORSTEP) % MI_NPIXELS(mi);
178 l->gcv.foreground = MI_WIN_WHITE_PIXEL(mi);
183 draw_laser_once(ModeInfo * mi)
185 Display *display = MI_DISPLAY(mi);
186 lasersstruct *lp = &lasers[MI_SCREEN(mi)];
189 for (i = 0; i < lp->ln; i++) {
190 laserstruct *l = &lp->laser[i];
192 if (lp->sw >= lp->lw) {
193 XChangeGC(display, lp->stippledGC, GCForeground, &(lp->gcv_black));
194 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
196 l->sx[lp->so], l->sy[lp->so]);
211 l->bx = lp->width + l->by;
218 if (l->bx >= lp->width) {
219 l->by = lp->height - l->bx % lp->width;
226 if (l->by >= lp->height) {
227 l->bx = l->by % lp->height;
236 if (l->bx >= lp->width) {
237 l->by = l->bx % lp->width;
244 if (l->by >= lp->height) {
245 l->bx = lp->width - l->by % lp->height;
253 l->by = lp->height + l->bx;
268 XChangeGC(display, lp->stippledGC, GCForeground, &l->gcv);
269 XDrawLine(display, MI_WINDOW(mi), lp->stippledGC,
270 lp->cx, lp->cy, l->bx, l->by);
272 l->sx[lp->so] = l->bx;
273 l->sy[lp->so] = l->by;
280 lp->so = (lp->so + 1) % lp->lw;
284 draw_laser(ModeInfo * mi)
286 lasersstruct *lp = &lasers[MI_SCREEN(mi)];
289 for (i = 0; i < lp->lr; i++)
292 if (++lp->time > MI_CYCLES(mi))
297 release_laser(ModeInfo * mi)
299 if (lasers != NULL) {
302 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
303 lasersstruct *lp = &lasers[screen];
305 if (lp->laser != NULL)
306 (void) free((void *) lp->laser);
307 if (lp->stippledGC != NULL)
308 XFreeGC(MI_DISPLAY(mi), lp->stippledGC);
310 (void) free((void *) lasers);
316 refresh_laser(ModeInfo * mi)
318 /* Do nothing, it will refresh by itself */