source: trunk/third/xscreensaver/hacks/deluxe.c @ 20148

Revision 20148, 10.7 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* xscreensaver, Copyright (c) 1999, 2001, 2002 Jamie Zawinski <jwz@jwz.org>
2 *
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation.  No representations are made about the suitability of this
8 * software for any purpose.  It is provided "as is" without express or
9 * implied warranty.
10 */
11
12#include <math.h>
13#include "screenhack.h"
14#include "alpha.h"
15
16#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
17# include "xdbe.h"
18#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
19
20#define countof(x) (sizeof(x)/sizeof(*(x)))
21#define ABS(x) ((x)<0?-(x):(x))
22
23static Bool transparent_p;
24static int nplanes;
25static unsigned long base_pixel, *plane_masks;
26
27struct throbber {
28  int x, y;
29  int size;
30  int max_size;
31  int thickness;
32  int speed;
33  int fuse;
34  GC gc;
35  void (*draw) (Display *, Drawable, struct throbber *);
36};
37
38static void
39draw_star (Display *dpy, Drawable w, struct throbber *t)
40{
41  XPoint points[11];
42  int x = t->x;
43  int y = t->y;
44  int s = t->size / 0.383;  /* trial and error, I forget how to derive this */
45  int s2 = t->size;
46  double c = M_PI * 2;
47  double o = -M_PI / 2;
48
49  points[0].x = x + s  * cos(o + 0.0*c); points[0].y = y + s  * sin(o + 0.0*c);
50  points[1].x = x + s2 * cos(o + 0.1*c); points[1].y = y + s2 * sin(o + 0.1*c);
51  points[2].x = x + s  * cos(o + 0.2*c); points[2].y = y + s  * sin(o + 0.2*c);
52  points[3].x = x + s2 * cos(o + 0.3*c); points[3].y = y + s2 * sin(o + 0.3*c);
53  points[4].x = x + s  * cos(o + 0.4*c); points[4].y = y + s  * sin(o + 0.4*c);
54  points[5].x = x + s2 * cos(o + 0.5*c); points[5].y = y + s2 * sin(o + 0.5*c);
55  points[6].x = x + s  * cos(o + 0.6*c); points[6].y = y + s  * sin(o + 0.6*c);
56  points[7].x = x + s2 * cos(o + 0.7*c); points[7].y = y + s2 * sin(o + 0.7*c);
57  points[8].x = x + s  * cos(o + 0.8*c); points[8].y = y + s  * sin(o + 0.8*c);
58  points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c);
59  points[10] = points[0];
60
61  XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
62}
63
64static void
65draw_circle (Display *dpy, Drawable w, struct throbber *t)
66{
67  XDrawArc (dpy, w, t->gc,
68            t->x - t->size / 2,
69            t->y - t->size / 2,
70            t->size, t->size,
71            0, 360*64);
72}
73
74static void
75draw_hlines (Display *dpy, Drawable w, struct throbber *t)
76{
77  XDrawLine (dpy, w, t->gc, 0,
78             t->y - t->size, t->max_size,
79             t->y - t->size);
80  XDrawLine (dpy, w, t->gc, 0,
81             t->y + t->size, t->max_size,
82             t->y + t->size);
83}
84
85static void
86draw_vlines (Display *dpy, Drawable w, struct throbber *t)
87{
88  XDrawLine (dpy, w, t->gc,
89             t->x - t->size, 0,
90             t->x - t->size, t->max_size);
91  XDrawLine (dpy, w, t->gc,
92             t->x + t->size, 0,
93             t->x + t->size, t->max_size);
94}
95
96static void
97draw_corners (Display *dpy, Drawable w, struct throbber *t)
98{
99  int s = (t->size + t->thickness) / 2;
100  XPoint points[3];
101
102  points[0].x = 0;        points[0].y = t->y - s;
103  points[1].x = t->x - s; points[1].y = t->y - s;
104  points[2].x = t->x - s; points[2].y = 0;
105  XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
106
107  points[0].x = 0;        points[0].y = t->y + s;
108  points[1].x = t->x - s; points[1].y = t->y + s;
109  points[2].x = t->x - s; points[2].y = t->max_size;
110  XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
111
112  points[0].x = t->x + s;    points[0].y = 0;
113  points[1].x = t->x + s;    points[1].y = t->y - s;
114  points[2].x = t->max_size; points[2].y = t->y - s;
115  XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
116
117  points[0].x = t->x + s;    points[0].y = t->max_size;
118  points[1].x = t->x + s;    points[1].y = t->y + s;
119  points[2].x = t->max_size; points[2].y = t->y + s;
120  XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
121}
122
123
124static struct throbber *
125make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel)
126{
127  XGCValues gcv;
128  unsigned long flags;
129  struct throbber *t = (struct throbber *) malloc (sizeof (*t));
130  t->x = w / 2;
131  t->y = h / 2;
132  t->max_size = w;
133  t->speed = get_integer_resource ("speed", "Speed");
134  t->fuse = 1 + (random() % 4);
135  t->thickness = get_integer_resource ("thickness", "Thickness");
136
137  if (t->speed < 0) t->speed = -t->speed;
138  t->speed += (((random() % t->speed) / 2) - (t->speed / 2));
139  if (t->speed > 0) t->speed = -t->speed;
140
141  if (random() % 4)
142    t->size = t->max_size;
143  else
144    t->size = t->thickness, t->speed = -t->speed;
145
146  flags = GCForeground;
147  if (transparent_p)
148    {
149      gcv.foreground = ~0L;
150      gcv.plane_mask = base_pixel | plane_masks[random() % nplanes];
151      flags |= GCPlaneMask;
152    }
153  else
154    {
155      gcv.foreground = pixel;
156    }
157
158  gcv.line_width = t->thickness;
159  gcv.line_style = LineSolid;
160  gcv.cap_style = CapProjecting;
161  gcv.join_style = JoinMiter;
162
163  flags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
164  t->gc = XCreateGC (dpy, d, flags, &gcv);
165
166  switch (random() % 11) {
167  case 0: case 1: case 2: case 3: t->draw = draw_star; break;
168  case 4: case 5: case 6: case 7: t->draw = draw_circle; break;
169  case 8: t->draw = draw_hlines; break;
170  case 9: t->draw = draw_vlines; break;
171  case 10: t->draw = draw_corners; break;
172  default: abort(); break;
173  }
174
175  return t;
176}
177
178static int
179throb (Display *dpy, Drawable window, struct throbber *t)
180{
181  t->size += t->speed;
182  if (t->size <= (t->thickness / 2))
183    {
184      t->speed = -t->speed;
185      t->size += (t->speed * 2);
186    }
187  else if (t->size > t->max_size)
188    {
189      t->speed = -t->speed;
190      t->size += (t->speed * 2);
191      t->fuse--;
192    }
193
194  if (t->fuse <= 0)
195    {
196      XFreeGC (dpy, t->gc);
197      memset (t, 0, sizeof(*t));
198      free (t);
199      return -1;
200    }
201  else
202    {
203      t->draw (dpy, window, t);
204      return 0;
205    }
206}
207
208
209
210char *progclass = "Deluxe";
211
212char *defaults [] = {
213  ".background:         black",
214  ".foreground:         white",
215  "*delay:              5000",
216  "*count:              5",
217  "*thickness:          50",
218  "*speed:              15",
219  "*ncolors:            20",
220  "*nlayers:            0",
221  "*transparent:        False",
222  "*doubleBuffer:       True",
223#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
224  "*useDBE:             True",
225  "*useDBEClear:        True",
226#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
227  0
228};
229
230XrmOptionDescRec options [] = {
231  { "-delay",           ".delay",       XrmoptionSepArg, 0 },
232  { "-thickness",       ".thickness",   XrmoptionSepArg, 0 },
233  { "-count",           ".count",       XrmoptionSepArg, 0 },
234  { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
235  { "-speed",           ".speed",       XrmoptionSepArg, 0 },
236  { "-transparent",     ".transparent",  XrmoptionNoArg,  "True" },
237  { "-opaque",          ".transparent",  XrmoptionNoArg,  "False" },
238  { "-db",              ".doubleBuffer", XrmoptionNoArg,  "True" },
239  { "-no-db",           ".doubleBuffer", XrmoptionNoArg,  "False" },
240  { 0, 0, 0, 0 }
241};
242
243void
244screenhack (Display *dpy, Window window)
245{
246  int count = get_integer_resource ("count", "Integer");
247  int delay = get_integer_resource ("delay", "Integer");
248  int ncolors = get_integer_resource ("ncolors", "Integer");
249  Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
250  Bool dbeclear_p = get_boolean_resource ("useDBEClear", "Boolean");
251  XColor *colors = 0;
252  XGCValues gcv;
253  GC erase_gc = 0;
254  int i;
255  struct throbber **throbbers;
256  XWindowAttributes xgwa;
257  Pixmap b=0, ba=0, bb=0;       /* double-buffer to reduce flicker */
258#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
259  XdbeBackBuffer backb = 0;
260#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
261
262  XGetWindowAttributes (dpy, window, &xgwa);
263
264  transparent_p = get_boolean_resource("transparent", "Transparent");
265
266  colors = (XColor *) calloc (sizeof(*colors), ncolors);
267
268  if (get_boolean_resource("mono", "Boolean"))
269    {
270    MONO:
271      ncolors = 1;
272      colors[0].pixel = get_pixel_resource("foreground", "Foreground",
273                                           dpy, xgwa.colormap);
274    }
275  else if (transparent_p)
276    {
277      nplanes = get_integer_resource ("planes", "Planes");
278      if (nplanes <= 0)
279        nplanes = (random() % (xgwa.depth-2)) + 2;
280
281      allocate_alpha_colors (xgwa.screen, xgwa.visual, xgwa.colormap,
282                             &nplanes, True, &plane_masks,
283                             &base_pixel);
284      if (nplanes <= 1)
285        {
286          fprintf (stderr,
287         "%s: couldn't allocate any color planes; turning transparency off.\n",
288                   progname);
289          transparent_p = False;
290          goto COLOR;
291        }
292    }
293  else
294    {
295    COLOR:
296      make_random_colormap (dpy, xgwa.visual, xgwa.colormap,
297                            colors, &ncolors, True, True, 0, True);
298      if (ncolors < 2)
299        goto MONO;
300    }
301
302  if (dbuf)
303    {
304#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
305      if (dbeclear_p)
306        b = xdbe_get_backbuffer (dpy, window, XdbeBackground);
307      else
308        b = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
309      backb = b;
310#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
311
312      if (!b)
313        {
314          ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
315          bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
316          b = ba;
317        }
318    }
319  else
320    {
321      b = window;
322    }
323
324  throbbers = (struct throbber **) calloc (count, sizeof(struct throbber *));
325  for (i = 0; i < count; i++)
326    throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
327                                  colors[random() % ncolors].pixel);
328
329  gcv.foreground = get_pixel_resource ("background", "Background",
330                                       dpy, xgwa.colormap);
331  erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
332
333  if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height);
334  if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height);
335
336  while (1)
337    {
338      if (!dbeclear_p
339#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
340          || !backb
341#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
342          )
343        XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
344
345      for (i = 0; i < count; i++)
346        if (throb (dpy, b, throbbers[i]) < 0)
347          throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
348                                        colors[random() % ncolors].pixel);
349
350#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
351      if (backb)
352        {
353          XdbeSwapInfo info[1];
354          info[0].swap_window = window;
355          info[0].swap_action = (dbeclear_p ? XdbeBackground : XdbeUndefined);
356          XdbeSwapBuffers (dpy, info, 1);
357        }
358      else
359#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
360      if (dbuf)
361        {
362          XCopyArea (dpy, b, window, erase_gc, 0, 0,
363                     xgwa.width, xgwa.height, 0, 0);
364          b = (b == ba ? bb : ba);
365        }
366
367      XSync (dpy, False);
368      screenhack_handle_events (dpy);
369      if (delay)
370        usleep (delay);
371    }
372}
Note: See TracBrowser for help on using the repository browser.