1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* rotor --- a swirly rotor */
5 static const char sccsid[] = "@(#)rotor.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1991 by Patrick J. Naughton.
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
26 * 08-Mar-1995: CAT stuff for ## was tripping up some C compilers. Removed.
27 * 01-Dec-1993: added patch for AIXV3 from Tom McConnell
28 * <tmcconne@sedona.intel.com>
29 * 11-Nov-1990: put into xlock by Steve Zellers <zellers@sun.com>
30 * 16-Oct-1990: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight'
36 #define DEFAULTS "*delay: 10000 \n" \
41 # define SMOOTH_COLORS
42 # define reshape_rotor 0
43 # define rotor_handle_event 0
44 # include "xlockmore.h" /* in xscreensaver distribution */
45 #else /* STANDALONE */
46 # include "xlock.h" /* in xlockmore distribution */
47 #endif /* STANDALONE */
51 ENTRYPOINT ModeSpecOpt rotor_opts =
52 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
55 ModStruct rotor_description =
56 {"rotor", "init_rotor", "draw_rotor", "release_rotor",
57 "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
58 100, 4, 100, -6, 64, 0.3, "",
59 "Shows Tom's Roto-Rooter", 0, NULL};
64 * A 'batchcount' of 3 or 4 works best!
67 #define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */
69 /* How many segments to draw per cycle when redrawing */
77 float radius_drift_max;
78 float radius_drift_now;
83 float ratio_drift_max;
84 float ratio_drift_now;
94 int prevcenterx, prevcentery;
95 unsigned char firsttime;
96 unsigned char iconifiedscreen; /* for iconified view */
97 unsigned char forward;
101 int redrawing, redrawpos;
105 static rotorstruct *rotors = (rotorstruct *) NULL;
108 free_rotor(rotorstruct *rp)
110 if (rp->elements != NULL) {
111 (void) free((void *) rp->elements);
112 rp->elements = (elem *) NULL;
114 if (rp->save != NULL) {
115 (void) free((void *) rp->save);
116 rp->save = (XPoint *) NULL;
121 init_rotor (ModeInfo * mi)
125 unsigned char wasiconified;
128 if (rotors == NULL) {
129 if ((rotors = (rotorstruct *) calloc(MI_NUM_SCREENS(mi),
130 sizeof (rotorstruct))) == NULL)
133 rp = &rotors[MI_SCREEN(mi)];
136 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
139 rp->prevcenterx = rp->centerx;
140 rp->prevcentery = rp->centery;
142 rp->centerx = MI_WIDTH(mi) / 2;
143 rp->centery = MI_HEIGHT(mi) / 2;
147 * sometimes, you go into iconified view, only to see a really whizzy pattern
148 * that you would like to look more closely at. Normally, clicking in the
149 * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
150 * HENCE, the wasiconified stuff you see here.
153 wasiconified = rp->iconifiedscreen;
154 rp->iconifiedscreen = MI_IS_ICONIC(mi);
156 if (wasiconified && !rp->iconifiedscreen)
157 rp->firsttime = True;
160 /* This is a fudge is needed since prevcenter may not be set when it comes
161 from the the random mode and return is pressed (and its not the first
162 mode that was running). This assumes that the size of the lock screen
163 window / size of the icon window = 12 */
164 if (!rp->prevcenterx)
165 rp->prevcenterx = rp->centerx * 12;
166 if (!rp->prevcentery)
167 rp->prevcentery = rp->centery * 12;
169 rp->num = MI_COUNT(mi);
171 rp->num = NRAND(-rp->num) + 1;
172 if (rp->elements != NULL) {
173 (void) free((void *) rp->elements);
174 rp->elements = (elem *) NULL;
177 if (rp->elements == NULL)
178 if ((rp->elements = (elem *) calloc(rp->num,
179 sizeof (elem))) == NULL) {
183 rp->nsave = MI_CYCLES(mi);
186 if (rp->save == NULL)
187 if ((rp->save = (XPoint *) malloc(rp->nsave *
188 sizeof (XPoint))) == NULL) {
192 for (x = 0; x < rp->nsave; x++) {
193 rp->save[x].x = rp->centerx;
194 rp->save[x].y = rp->centery;
197 pelem = rp->elements;
199 for (x = rp->num; --x >= 0; pelem++) {
200 pelem->radius_drift_max = 1.0;
201 pelem->radius_drift_now = 1.0;
203 pelem->end_radius = 100.0;
205 pelem->ratio_drift_max = 1.0;
206 pelem->ratio_drift_now = 1.0;
207 pelem->end_ratio = 10.0;
209 if (MI_NPIXELS(mi) > 2)
210 rp->pix = NRAND(MI_NPIXELS(mi));
214 rp->lastx = rp->centerx;
215 rp->lasty = rp->centery;
216 rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
217 rp->forward = rp->firsttime = True;
219 rp->linewidth = MI_SIZE(mi);
221 if (rp->linewidth == 0)
223 if (rp->linewidth < 0)
224 rp->linewidth = NRAND(-rp->linewidth) + 1;
230 draw_rotor (ModeInfo * mi)
232 Display *display = MI_DISPLAY(mi);
234 register elem *pelem;
237 int x_1, y_1, x_2, y_2;
242 rp = &rotors[MI_SCREEN(mi)];
243 if (rp->elements == NULL)
246 MI_IS_DRAWN(mi) = True;
247 if (!rp->iconifiedscreen) {
251 thisx = rp->prevcenterx;
252 thisy = rp->prevcentery;
254 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
255 LineSolid, CapButt, JoinMiter);
256 for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
257 if (pelem->radius_drift_max <= pelem->radius_drift_now) {
258 pelem->start_radius = pelem->end_radius;
259 pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
260 pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
261 pelem->radius_drift_now = 0.0;
263 if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
264 pelem->start_ratio = pelem->end_ratio;
265 pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
266 pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
267 pelem->ratio_drift_now = 0.0;
269 pelem->ratio = pelem->start_ratio +
270 (pelem->end_ratio - pelem->start_ratio) /
271 pelem->ratio_drift_max * pelem->ratio_drift_now;
272 pelem->angle = rp->angle * pelem->ratio;
273 pelem->radius = pelem->start_radius +
274 (pelem->end_radius - pelem->start_radius) /
275 pelem->radius_drift_max * pelem->radius_drift_now;
277 thisx += (int) (COSF(pelem->angle) * pelem->radius);
278 thisy += (int) (SINF(pelem->angle) * pelem->radius);
280 pelem->ratio_drift_now += 1.0;
281 pelem->radius_drift_now += 1.0;
284 rp->firsttime = False;
286 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
288 x_1 = (int) rp->save[rp->rotor].x;
289 y_1 = (int) rp->save[rp->rotor].y;
290 x_2 = (int) rp->save[rp->prev].x;
291 y_2 = (int) rp->save[rp->prev].y;
293 if (rp->iconifiedscreen) {
294 x_1 = x_1 * rp->centerx / rp->prevcenterx;
295 x_2 = x_2 * rp->centerx / rp->prevcenterx;
296 y_1 = y_1 * rp->centery / rp->prevcentery;
297 y_2 = y_2 * rp->centery / rp->prevcentery;
299 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
301 if (MI_NPIXELS(mi) > 2) {
302 XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
303 if (++rp->pix >= MI_NPIXELS(mi))
306 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
313 if (rp->iconifiedscreen) {
314 x_1 = x_1 * rp->centerx / rp->prevcenterx;
315 x_2 = x_2 * rp->centerx / rp->prevcenterx;
316 y_1 = y_1 * rp->centery / rp->prevcentery;
317 y_2 = y_2 * rp->centery / rp->prevcentery;
319 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
321 rp->save[rp->rotor].x = rp->lastx = thisx;
322 rp->save[rp->rotor].y = rp->lasty = thisy;
325 rp->rotor %= rp->nsave;
327 rp->prev %= rp->nsave;
330 if (rp->angle >= MAXANGLE) {
331 rp->angle = MAXANGLE;
336 if (rp->angle <= 0) {
344 for (i = 0; i < REDRAWSTEP; i++) {
345 j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
347 x_1 = (int) rp->save[j].x;
348 y_1 = (int) rp->save[j].y;
349 x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
350 y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
352 if (rp->iconifiedscreen) {
353 x_1 = x_1 * rp->centerx / rp->prevcenterx;
354 x_2 = x_2 * rp->centerx / rp->prevcenterx;
355 y_1 = y_1 * rp->centery / rp->prevcentery;
356 y_2 = y_2 * rp->centery / rp->prevcentery;
358 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
360 if (++(rp->redrawpos) >= rp->nsave) {
366 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
367 LineSolid, CapButt, JoinMiter);
371 release_rotor (ModeInfo * mi)
373 if (rotors != NULL) {
376 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
377 free_rotor(&rotors[screen]);
378 (void) free((void *) rotors);
379 rotors = (rotorstruct *) NULL;
384 refresh_rotor (ModeInfo * mi)
390 rp = &rotors[MI_SCREEN(mi)];
397 XSCREENSAVER_MODULE ("Rotor", rotor)
399 #endif /* MODE_rotor */