1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* deluxe --- */
3
4 #if 0
5 static const char sccsid[] = "@(#)deluxe.c 5.22 2006/03/07 xlockmore";
6 #endif
7
8 /* xscreensaver, Copyright (c) 1999, 2001, 2002 Jamie Zawinski <jwz AT jwz.org>
9 *
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
16 * implied warranty.
17 *
18 * adapted for xlockmore : March 2006
19 */
20
21 #ifdef STANDALONE
22 # define MODE_deluxe
23
24 # define DEFAULTS "*delay: 5000 \n" \
25 "*count: 5 \n" \
26 "*ncolors: 64 \n" \
27 "*fullrandom: True \n" \
28 "*verbose: False \n" \
29
30 #if 0
31 # define DEFAULTS "*delay: 10000 \n" \
32 "*count: 5 \n", \
33 "*ncolors: 20 \n", \
34 "*nlayers: 0 \n", \
35 "*doubleBuffer: True\n"
36 ".background: black\n", \
37 "foreground: white\n", \
38
39 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
40 , "*useDBE: True\n", \
41
42 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
43 #endif
44 # define free_deluxe 0
45 # define reshape_deluxe 0
46 # define deluxe_handle_event 0
47 # include "xlockmore.h" /* in xscreensaver distribution */
48 extern Bool allocate_alpha_colors (Screen *screen, Visual *visual,
49 Colormap cmap,
50 int *nplanesP, Bool additive_p,
51 unsigned long **plane_masks,
52 unsigned long *base_pixelP ,
53 ModeInfo* mi );
54 #else /* STANDALONE */
55 # include "xlock.h" /* in xlockmore distribution */
56 # include "color.h"
57 #endif /* STANDALONE */
58
59 #ifdef MODE_deluxe
60
61 #include <math.h>
62
63 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
64 # include "xdbe.h"
65 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
66
67 #ifndef countof
68 #define countof(x) (sizeof(x)/sizeof(*(x)))
69 #endif
70
71 #define DEF_THICKNESS "50"
72 #define DEF_SPEED "15"
73 #define DEF_TRANSPARENT "False"
74 #ifdef WIN32
75 #define DEF_DB "False"
76 #else
77 #define DEF_DB "True"
78 #endif
79 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
80 #define DEF_USEDBECLEAR "True"
81 #endif
82 #define DEF_MONO "False"
83 #define DEF_PLANES "0"
84
85 static int st_thickness;
86 static int st_speed;
87 static Bool st_transparent;
88 static Bool st_db;
89 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
90 static Bool st_dbeclear_p;
91 #endif
92 static Bool st_mono;
93 static int st_planes;
94
95 struct throbber {
96 int x, y;
97 int size;
98 int max_size;
99 int thickness;
100 int speed;
101 int fuse;
102 GC gc;
103 void (*draw) (Display *, Drawable, struct throbber *);
104 };
105
106 typedef struct {
107 Bool transparent_p;
108 int nplanes;
109 unsigned long base_pixel, *plane_masks;
110 int count;
111 int ncolors;
112 Bool dbuf;
113 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
114 Bool dbeclear_p;
115 XdbeBackBuffer backb;
116 #endif
117 XColor *colors;
118 GC erase_gc;
119 struct throbber **throbbers;
120 XWindowAttributes xgwa;
121 Pixmap b, ba, bb; /* double-buffer to reduce flicker */
122 } deluxestruct;
123
124 static deluxestruct *deluxes = (deluxestruct *) NULL;
125
126 static XrmOptionDescRec opts [] = {
127 { "-thickness", "deluxe.thickness", XrmoptionSepArg, (caddr_t) NULL },
128 { "-speed", "deluxe.speed", XrmoptionSepArg, (caddr_t) NULL },
129 { "-planes", "deluxe.planes", XrmoptionSepArg, (caddr_t) NULL },
130 { "-transparent", "deluxe.transparent", XrmoptionNoArg, (caddr_t) "on" },
131 { "+transparent", "deluxe.transparent", XrmoptionNoArg, (caddr_t) "off" },
132 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
133 { "-useDBEClear", "deluxe.useDBEClear", XrmoptionNoArg, (caddr_t) "on" },
134 { "+useDBEClear", "deluxe.useDBEClear", XrmoptionNoArg, (caddr_t) "off" },
135 #endif
136 { "-mono", "deluxe.mono", XrmoptionNoArg, (caddr_t) "on" },
137 { "+mono", "deluxe.mono", XrmoptionNoArg, (caddr_t) "off" },
138 { "-db", "deluxe.doubleBuffer", XrmoptionNoArg, (caddr_t) "on" },
139 { "+db", "deluxe.doubleBuffer", XrmoptionNoArg, (caddr_t) "off" }
140 };
141
142 static argtype vars[] =
143 {
144 {(void *) & st_thickness, (char *) "thickness", (char *) "thickness",
145 (char *) DEF_THICKNESS, t_Int},
146 {(void *) & st_speed, (char *) "speed", (char *) "speed",
147 (char *) DEF_SPEED, t_Int},
148 {(void *) & st_planes, (char *) "planes", (char *) "Planes",
149 (char *) DEF_PLANES, t_Int},
150 {(void *) & st_transparent, (char *) "transparent",
151 (char *) "Transparent", (char *) DEF_TRANSPARENT, t_Bool},
152 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
153 {(void *) & st_dbeclear_p, (char *) "useDBEClear",
154 (char *) "useDBEClear",
155 (char *) DEF_USEDBECLEAR, t_Bool},
156 #endif
157 {(void *) & st_mono, (char *) "mono", (char *) "mono",
158 (char *) DEF_MONO, t_Bool},
159 {(void *) & st_db, (char *) "db", (char *) "db",
160 (char *) DEF_DB, t_Bool}
161
162 };
163 static OptionStruct desc[] =
164 {
165 {(char *) "-thickness num", (char *) "Figure thickness"},
166 {(char *) "-speed num", (char *) "Animation speed"},
167 {(char *) "-planes num", (char *) "Number of planes"},
168 {(char *) "-/+transparent", (char *) "turn on/off transparency"},
169 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
170 {(char *) "-/+useDBEClear", (char *) "turn on/off useDBEClear"},
171 #endif
172 {(char *) "-/+mono", (char *) "turn on/off monochromatic mode"},
173 {(char *) "-/+db", (char *) "turn on/off double buffering"}
174 };
175
176 ENTRYPOINT ModeSpecOpt deluxe_opts =
177 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
178
179 #ifdef USE_MODULES
180 ModStruct deluxe_description =
181 {"deluxe", "init_deluxe", "draw_deluxe", "release_deluxe",
182 "(char *) NULL", "init_deluxe", (char *) NULL, &deluxe_opts,
183 5000, 5, 1, 1, 64, 1.0, "",
184 "Shows pulsing sequence of stars, circles, and lines.", 0, NULL};
185
186 #endif
187
188
189 static void
free_deluxe_screen(Display * dpy,deluxestruct * dlp)190 free_deluxe_screen(Display *dpy, deluxestruct *dlp)
191 {
192 int i;
193
194 if (dlp == NULL) {
195 return;
196 }
197 for (i = 0; i < dlp->count; i++)
198 if ( dlp->throbbers[i] )
199 {
200 if (dlp->throbbers[i]->gc != None)
201 XFreeGC (dpy, dlp->throbbers[i]->gc);
202 free( dlp->throbbers[i] );
203 }
204 if ( dlp->throbbers )
205 {
206 free( dlp->throbbers );
207 dlp->throbbers = ( struct throbber** ) NULL;
208 }
209 if ( dlp->colors )
210 {
211 free( dlp->colors );
212 dlp->colors = (XColor *) NULL;
213 }
214 if ( dlp->plane_masks )
215 {
216 free( dlp->plane_masks );
217 dlp->plane_masks = (unsigned long*) NULL;
218 }
219 if (dlp->erase_gc != None)
220 {
221 XFreeGC (dpy, dlp->erase_gc);
222 dlp->erase_gc = None;
223 }
224 dlp = NULL;
225 }
226
227 /* http://mathworld.wolfram.com/Pentagram.html
228 * R / p
229 * R=sqrt((25-11*sqrt(5))/10)
230 * p=sqrt((5-sqrt(5))/10)
231 * sqrt(14-6*sqrt(5))/2
232 */
233 static void
deluxe_draw_star(Display * dpy,Drawable w,struct throbber * t)234 deluxe_draw_star (Display *dpy, Drawable w, struct throbber *t)
235 {
236 XPoint points[11];
237 int x = t->x;
238 int y = t->y;
239 int s = (int) (t->size / 0.381966);
240 int s2 = t->size;
241 double c = M_PI * 2.0;
242 double o = -M_PI / 2.0;
243
244 points[0].x = (short) (x + s * cos(o + 0.0*c));
245 points[0].y = (short) (y + s * sin(o + 0.0*c));
246 points[1].x = (short) (x + s2 * cos(o + 0.1*c));
247 points[1].y = (short) (y + s2 * sin(o + 0.1*c));
248 points[2].x = (short) (x + s * cos(o + 0.2*c));
249 points[2].y = (short) (y + s * sin(o + 0.2*c));
250 points[3].x = (short) (x + s2 * cos(o + 0.3*c));
251 points[3].y = (short) (y + s2 * sin(o + 0.3*c));
252 points[4].x = (short) (x + s * cos(o + 0.4*c));
253 points[4].y = (short) (y + s * sin(o + 0.4*c));
254 points[5].x = (short) (x + s2 * cos(o + 0.5*c));
255 points[5].y = (short) (y + s2 * sin(o + 0.5*c));
256 points[6].x = (short) (x + s * cos(o + 0.6*c));
257 points[6].y = (short) (y + s * sin(o + 0.6*c));
258 points[7].x = (short) (x + s2 * cos(o + 0.7*c));
259 points[7].y = (short) (y + s2 * sin(o + 0.7*c));
260 points[8].x = (short) (x + s * cos(o + 0.8*c));
261 points[8].y = (short) (y + s * sin(o + 0.8*c));
262 points[9].x = (short) (x + s2 * cos(o + 0.9*c));
263 points[9].y = (short) (y + s2 * sin(o + 0.9*c));
264 points[10] = points[0];
265
266 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
267 }
268
269 static void
draw_circle(Display * dpy,Drawable w,struct throbber * t)270 draw_circle (Display *dpy, Drawable w, struct throbber *t)
271 {
272 XDrawArc (dpy, w, t->gc,
273 t->x - t->size / 2,
274 t->y - t->size / 2,
275 t->size, t->size,
276 0, 360*64);
277 }
278
279 static void
draw_hlines(Display * dpy,Drawable w,struct throbber * t)280 draw_hlines (Display *dpy, Drawable w, struct throbber *t)
281 {
282 XDrawLine (dpy, w, t->gc, 0,
283 t->y - t->size, t->max_size,
284 t->y - t->size);
285 XDrawLine (dpy, w, t->gc, 0,
286 t->y + t->size, t->max_size,
287 t->y + t->size);
288 }
289
290 static void
draw_vlines(Display * dpy,Drawable w,struct throbber * t)291 draw_vlines (Display *dpy, Drawable w, struct throbber *t)
292 {
293 XDrawLine (dpy, w, t->gc,
294 t->x - t->size, 0,
295 t->x - t->size, t->max_size);
296 XDrawLine (dpy, w, t->gc,
297 t->x + t->size, 0,
298 t->x + t->size, t->max_size);
299 }
300
301 static void
draw_corners(Display * dpy,Drawable w,struct throbber * t)302 draw_corners (Display *dpy, Drawable w, struct throbber *t)
303 {
304 int s = (t->size + t->thickness) / 2;
305 XPoint points[3];
306
307 points[0].x = 0; points[0].y = t->y - s;
308 points[1].x = t->x - s; points[1].y = t->y - s;
309 points[2].x = t->x - s; points[2].y = 0;
310 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
311
312 points[0].x = 0; points[0].y = t->y + s;
313 points[1].x = t->x - s; points[1].y = t->y + s;
314 points[2].x = t->x - s; points[2].y = t->max_size;
315 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
316
317 points[0].x = t->x + s; points[0].y = 0;
318 points[1].x = t->x + s; points[1].y = t->y - s;
319 points[2].x = t->max_size; points[2].y = t->y - s;
320 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
321
322 points[0].x = t->x + s; points[0].y = t->max_size;
323 points[1].x = t->x + s; points[1].y = t->y + s;
324 points[2].x = t->max_size; points[2].y = t->y + s;
325 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
326 }
327
328
329 static struct throbber *
make_throbber(Display * dpy,Drawable d,int w,int h,unsigned long pixel,deluxestruct * dlp,ModeInfo * mi)330 make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel ,
331 deluxestruct *dlp, ModeInfo * mi)
332 {
333 XGCValues gcv;
334 unsigned long flags;
335 struct throbber *t = (struct throbber *) malloc (sizeof (*t));
336 t->x = w / 2;
337 t->y = h / 2;
338 t->max_size = w;
339 t->speed = st_speed;
340 t->fuse = 1 + (NRAND(4));
341 t->thickness = st_thickness;
342
343 if (t->speed < 0) t->speed = -t->speed;
344 t->speed += (((NRAND(t->speed)) / 2) - (t->speed / 2));
345 if (t->speed > 0) t->speed = -t->speed;
346
347 if (NRAND(4))
348 t->size = t->max_size;
349 else
350 t->size = t->thickness, t->speed = -t->speed;
351
352 flags = GCForeground;
353 if (dlp->transparent_p)
354 {
355 gcv.foreground = (unsigned long) ~0L;
356 gcv.plane_mask = dlp->base_pixel |
357 dlp->plane_masks[NRAND(dlp->nplanes)];
358 flags |= GCPlaneMask;
359 }
360 else
361 {
362 #ifdef WIN32
363 gcv.foreground = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
364 #else
365 gcv.foreground = pixel;
366 #endif
367 }
368
369 gcv.line_width = t->thickness;
370 gcv.line_style = LineSolid;
371 gcv.cap_style = CapProjecting;
372 gcv.join_style = JoinMiter;
373
374 flags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
375 t->gc = XCreateGC (dpy, d, flags, &gcv);
376 switch (NRAND(11)) {
377 case 0: case 1: case 2: case 3: t->draw = deluxe_draw_star; break;
378 case 4: case 5: case 6: case 7: t->draw = draw_circle; break;
379 case 8: t->draw = draw_hlines; break;
380 case 9: t->draw = draw_vlines; break;
381 case 10: t->draw = draw_corners; break;
382 default: abort(); break;
383 }
384
385 return t;
386 }
387
388 static int
throb(Display * dpy,Drawable window,struct throbber * t)389 throb (Display *dpy, Drawable window, struct throbber *t)
390 {
391 t->size += t->speed;
392 if (t->size <= (t->thickness / 2))
393 {
394 t->speed = -t->speed;
395 t->size += (t->speed * 2);
396 }
397 else if (t->size > t->max_size)
398 {
399 t->speed = -t->speed;
400 t->size += (t->speed * 2);
401 t->fuse--;
402 }
403
404 if (t->fuse <= 0)
405 {
406 XFreeGC (dpy, t->gc);
407 memset (t, 0, sizeof(*t));
408 free (t);
409 return -1;
410 }
411 else
412 {
413 t->draw (dpy, window, t);
414 return 0;
415 }
416 }
417
418 ENTRYPOINT void
init_deluxe(ModeInfo * mi)419 init_deluxe(ModeInfo * mi)
420 {
421 deluxestruct *dlp;
422 Display *dpy = MI_DISPLAY(mi);
423 Window window = MI_WINDOW(mi);
424 XGCValues gcv;
425 Bool writeable = (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2);
426 int i;
427
428 /* initialize */
429 MI_INIT(mi, deluxes);
430 dlp = &deluxes[MI_SCREEN(mi)];
431
432 dlp->count = MI_COUNT(mi);
433 dlp->ncolors = MI_NCOLORS(mi);
434 dlp->dbuf = st_db;
435 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
436 dlp->dbeclear_p = st_dbeclear_p;
437 #endif
438 dlp->colors = 0;
439 dlp->erase_gc = 0;
440 dlp->b=0;
441 dlp->ba=0;
442 dlp->bb=0; /* double-buffer to reduce flicker */
443 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
444 dlp->backb =0;
445 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
446
447 XGetWindowAttributes (dpy, window, &dlp->xgwa);
448
449 dlp->transparent_p = st_transparent;
450
451 dlp->colors = (XColor *) calloc (sizeof(XColor), dlp->ncolors);
452
453 if ( st_mono )
454 {
455 MONO:
456 dlp->ncolors = 1;
457 dlp->colors[0].pixel = MI_WHITE_PIXEL(mi);
458 }
459 else if (dlp->transparent_p)
460 {
461 dlp->nplanes = st_planes;
462 if (dlp->nplanes <= 0)
463 dlp->nplanes = NRAND(dlp->xgwa.depth-2) + 2;
464
465 allocate_alpha_colors (dlp->xgwa.screen, dlp->xgwa.visual,
466 dlp->xgwa.colormap,
467 &dlp->nplanes, True, &dlp->plane_masks,
468 &dlp->base_pixel , mi );
469 if (dlp->nplanes <= 1)
470 {
471 fprintf (stderr,
472 "deluxe: couldn't allocate any color planes; turning transparency off.\n"
473 );
474 dlp->transparent_p = False;
475 goto COLOR;
476 }
477 }
478 else
479 {
480 COLOR:
481 make_random_colormap (
482 #ifdef STANDALONE
483 dlp->xgwa.screen, dlp->xgwa.visual,
484 dlp->xgwa.colormap, dlp->colors, &dlp->ncolors,
485 True, True, &writeable, True
486 #else
487 mi,
488 dlp->xgwa.colormap, dlp->colors, &dlp->ncolors,
489 True, True, &writeable
490 #endif
491 );
492 if (dlp->ncolors < 2)
493 goto MONO;
494 }
495
496 if (dlp->dbuf)
497 {
498 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
499 if (dlp->dbeclear_p)
500 dlp->b = xdbe_get_backbuffer (dpy, window, XdbeBackground);
501 else
502 dlp->b = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
503 dlp->backb = dlp->b;
504 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
505
506 if (!dlp->b)
507 {
508 dlp->ba = XCreatePixmap (dpy, window, dlp->xgwa.width,
509 dlp->xgwa.height, dlp->xgwa.depth);
510 dlp->bb = XCreatePixmap (dpy, window, dlp->xgwa.width,
511 dlp->xgwa.height, dlp->xgwa.depth);
512 dlp->b = dlp->ba;
513 }
514 }
515 else
516 {
517 dlp->b = window;
518 }
519
520 dlp->throbbers = (struct throbber **) calloc ( dlp->count, sizeof(struct throbber *));
521 for (i = 0; i < dlp->count; i++)
522 dlp->throbbers[i] = make_throbber (dpy, dlp->b, dlp->xgwa.width,
523 dlp->xgwa.height,
524 dlp->colors[ NRAND( dlp->ncolors )].pixel ,
525 dlp, mi);
526
527 gcv.foreground = MI_BLACK_PIXEL(mi);
528 dlp->erase_gc = XCreateGC (dpy, dlp->b, GCForeground, &gcv);
529
530 if ( dlp->ba) XFillRectangle (dpy, dlp->ba, dlp->erase_gc, 0, 0,
531 dlp->xgwa.width, dlp->xgwa.height);
532 if ( dlp->bb) XFillRectangle (dpy, dlp->bb, dlp->erase_gc, 0, 0,
533 dlp->xgwa.width, dlp->xgwa.height);
534 }
535
536 ENTRYPOINT void
draw_deluxe(ModeInfo * mi)537 draw_deluxe(ModeInfo * mi)
538 {
539 deluxestruct *dlp = &deluxes[MI_SCREEN(mi)];
540 Display *dpy = MI_DISPLAY(mi);
541 Window window = MI_WINDOW(mi);
542 int i;
543
544 if (deluxes == NULL)
545 return;
546 MI_IS_DRAWN(mi) = True;
547
548
549 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
550 if (!dlp->dbeclear_p || !dlp->backb )
551 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
552 XFillRectangle (dpy, dlp->b, dlp->erase_gc, 0, 0, dlp->xgwa.width,
553 dlp->xgwa.height);
554
555 for (i = 0; i < dlp->count; i++)
556 if (throb (dpy, dlp->b, dlp->throbbers[i]) < 0)
557 dlp->throbbers[i] = make_throbber (dpy, dlp->b, dlp->xgwa.width,
558 dlp->xgwa.height,
559 dlp->colors[ NRAND( dlp->ncolors )].pixel ,
560 dlp, mi);
561
562 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
563 if (dlp->backb)
564 {
565 XdbeSwapInfo info[1];
566 info[0].swap_window = window;
567 info[0].swap_action = (dlp->dbeclear_p ? XdbeBackground : XdbeUndefined);
568 XdbeSwapBuffers (dpy, info, 1);
569 }
570 else
571 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
572 if (dlp->dbuf)
573 {
574 XCopyArea (dpy, dlp->b, window, dlp->erase_gc, 0, 0,
575 dlp->xgwa.width, dlp->xgwa.height, 0, 0);
576 dlp->b = (dlp->b == dlp->ba ? dlp->bb : dlp->ba);
577 }
578 XSync (dpy, False);
579 }
580
581 ENTRYPOINT void
release_deluxe(ModeInfo * mi)582 release_deluxe(ModeInfo * mi)
583 {
584 if (deluxes != NULL) {
585 int screen;
586
587 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
588 free_deluxe_screen(MI_DISPLAY(mi), &deluxes[screen]);
589 free(deluxes);
590 deluxes = (deluxestruct *) NULL;
591 }
592 }
593
594 XSCREENSAVER_MODULE ("Deluxe", deluxe)
595
596 #endif /* MODE_deluxe */
597