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 "*fpsSolid: true \n" \
43 # define SMOOTH_COLORS
44 # define reshape_rotor 0
45 # define rotor_handle_event 0
46 # include "xlockmore.h" /* in xscreensaver distribution */
47 #else /* STANDALONE */
48 # include "xlock.h" /* in xlockmore distribution */
49 #endif /* STANDALONE */
53 ENTRYPOINT ModeSpecOpt rotor_opts =
54 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
57 ModStruct rotor_description =
58 {"rotor", "init_rotor", "draw_rotor", "release_rotor",
59 "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
60 100, 4, 100, -6, 64, 0.3, "",
61 "Shows Tom's Roto-Rooter", 0, NULL};
66 * A 'batchcount' of 3 or 4 works best!
69 #define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */
71 /* How many segments to draw per cycle when redrawing */
79 float radius_drift_max;
80 float radius_drift_now;
85 float ratio_drift_max;
86 float ratio_drift_now;
96 int prevcenterx, prevcentery;
97 unsigned char firsttime;
98 unsigned char iconifiedscreen; /* for iconified view */
99 unsigned char forward;
100 unsigned char unused;
103 int redrawing, redrawpos;
107 static rotorstruct *rotors = (rotorstruct *) NULL;
110 free_rotor(rotorstruct *rp)
112 if (rp->elements != NULL) {
113 (void) free((void *) rp->elements);
114 rp->elements = (elem *) NULL;
116 if (rp->save != NULL) {
117 (void) free((void *) rp->save);
118 rp->save = (XPoint *) NULL;
123 init_rotor (ModeInfo * mi)
127 unsigned char wasiconified;
130 MI_INIT (mi, rotors, 0);
131 rp = &rotors[MI_SCREEN(mi)];
134 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
137 rp->prevcenterx = rp->centerx;
138 rp->prevcentery = rp->centery;
140 rp->centerx = MI_WIDTH(mi) / 2;
141 rp->centery = MI_HEIGHT(mi) / 2;
145 * sometimes, you go into iconified view, only to see a really whizzy pattern
146 * that you would like to look more closely at. Normally, clicking in the
147 * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
148 * HENCE, the wasiconified stuff you see here.
151 wasiconified = rp->iconifiedscreen;
152 rp->iconifiedscreen = MI_IS_ICONIC(mi);
154 if (wasiconified && !rp->iconifiedscreen)
155 rp->firsttime = True;
158 /* This is a fudge is needed since prevcenter may not be set when it comes
159 from the the random mode and return is pressed (and its not the first
160 mode that was running). This assumes that the size of the lock screen
161 window / size of the icon window = 12 */
162 if (!rp->prevcenterx)
163 rp->prevcenterx = rp->centerx * 12;
164 if (!rp->prevcentery)
165 rp->prevcentery = rp->centery * 12;
167 rp->num = MI_COUNT(mi);
169 rp->num = NRAND(-rp->num) + 1;
170 if (rp->elements != NULL) {
171 (void) free((void *) rp->elements);
172 rp->elements = (elem *) NULL;
175 if (rp->elements == NULL)
176 if ((rp->elements = (elem *) calloc(rp->num,
177 sizeof (elem))) == NULL) {
181 rp->nsave = MI_CYCLES(mi);
184 if (rp->save == NULL)
185 if ((rp->save = (XPoint *) malloc(rp->nsave *
186 sizeof (XPoint))) == NULL) {
190 for (x = 0; x < rp->nsave; x++) {
191 rp->save[x].x = rp->centerx;
192 rp->save[x].y = rp->centery;
195 pelem = rp->elements;
197 for (x = rp->num; --x >= 0; pelem++) {
198 pelem->radius_drift_max = 1.0;
199 pelem->radius_drift_now = 1.0;
201 pelem->end_radius = 100.0;
203 pelem->ratio_drift_max = 1.0;
204 pelem->ratio_drift_now = 1.0;
205 pelem->end_ratio = 10.0;
207 if (MI_NPIXELS(mi) > 2)
208 rp->pix = NRAND(MI_NPIXELS(mi));
212 rp->lastx = rp->centerx;
213 rp->lasty = rp->centery;
214 rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
215 rp->forward = rp->firsttime = True;
217 rp->linewidth = MI_SIZE(mi);
219 if (rp->linewidth == 0)
221 if (rp->linewidth < 0)
222 rp->linewidth = NRAND(-rp->linewidth) + 1;
228 draw_rotor (ModeInfo * mi)
230 Display *display = MI_DISPLAY(mi);
232 register elem *pelem;
235 int x_1, y_1, x_2, y_2;
240 rp = &rotors[MI_SCREEN(mi)];
241 if (rp->elements == NULL)
244 MI_IS_DRAWN(mi) = True;
245 if (!rp->iconifiedscreen) {
249 thisx = rp->prevcenterx;
250 thisy = rp->prevcentery;
252 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
253 LineSolid, CapButt, JoinMiter);
254 for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
255 if (pelem->radius_drift_max <= pelem->radius_drift_now) {
256 pelem->start_radius = pelem->end_radius;
257 pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
258 pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
259 pelem->radius_drift_now = 0.0;
261 if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
262 pelem->start_ratio = pelem->end_ratio;
263 pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
264 pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
265 pelem->ratio_drift_now = 0.0;
267 pelem->ratio = pelem->start_ratio +
268 (pelem->end_ratio - pelem->start_ratio) /
269 pelem->ratio_drift_max * pelem->ratio_drift_now;
270 pelem->angle = rp->angle * pelem->ratio;
271 pelem->radius = pelem->start_radius +
272 (pelem->end_radius - pelem->start_radius) /
273 pelem->radius_drift_max * pelem->radius_drift_now;
275 thisx += (int) (COSF(pelem->angle) * pelem->radius);
276 thisy += (int) (SINF(pelem->angle) * pelem->radius);
278 pelem->ratio_drift_now += 1.0;
279 pelem->radius_drift_now += 1.0;
282 rp->firsttime = False;
284 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
286 x_1 = (int) rp->save[rp->rotor].x;
287 y_1 = (int) rp->save[rp->rotor].y;
288 x_2 = (int) rp->save[rp->prev].x;
289 y_2 = (int) rp->save[rp->prev].y;
291 if (rp->iconifiedscreen) {
292 x_1 = x_1 * rp->centerx / rp->prevcenterx;
293 x_2 = x_2 * rp->centerx / rp->prevcenterx;
294 y_1 = y_1 * rp->centery / rp->prevcentery;
295 y_2 = y_2 * rp->centery / rp->prevcentery;
297 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
299 if (MI_NPIXELS(mi) > 2) {
300 XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
301 if (++rp->pix >= MI_NPIXELS(mi))
304 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
311 if (rp->iconifiedscreen) {
312 x_1 = x_1 * rp->centerx / rp->prevcenterx;
313 x_2 = x_2 * rp->centerx / rp->prevcenterx;
314 y_1 = y_1 * rp->centery / rp->prevcentery;
315 y_2 = y_2 * rp->centery / rp->prevcentery;
317 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
319 rp->save[rp->rotor].x = rp->lastx = thisx;
320 rp->save[rp->rotor].y = rp->lasty = thisy;
323 rp->rotor %= rp->nsave;
325 rp->prev %= rp->nsave;
328 if (rp->angle >= MAXANGLE) {
329 rp->angle = MAXANGLE;
334 if (rp->angle <= 0) {
342 for (i = 0; i < REDRAWSTEP; i++) {
343 j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
345 x_1 = (int) rp->save[j].x;
346 y_1 = (int) rp->save[j].y;
347 x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
348 y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
350 if (rp->iconifiedscreen) {
351 x_1 = x_1 * rp->centerx / rp->prevcenterx;
352 x_2 = x_2 * rp->centerx / rp->prevcenterx;
353 y_1 = y_1 * rp->centery / rp->prevcentery;
354 y_2 = y_2 * rp->centery / rp->prevcentery;
356 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
358 if (++(rp->redrawpos) >= rp->nsave) {
364 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
365 LineSolid, CapButt, JoinMiter);
369 release_rotor (ModeInfo * mi)
371 if (rotors != NULL) {
374 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
375 free_rotor(&rotors[screen]);
376 (void) free((void *) rotors);
377 rotors = (rotorstruct *) NULL;
382 refresh_rotor (ModeInfo * mi)
388 rp = &rotors[MI_SCREEN(mi)];
395 XSCREENSAVER_MODULE ("Rotor", rotor)
397 #endif /* MODE_rotor */