http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / deluxe.c
index aced3efc966f335bec2f363a95b713cb0e7c92ad..75b9832900956d7d6369d2fbbe3bb87e997e3840 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999, 2001, 2002 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
 #include <math.h>
 #include "screenhack.h"
+#include "alpha.h"
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+# include "xdbe.h"
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 
 #define countof(x) (sizeof(x)/sizeof(*(x)))
 #define ABS(x) ((x)<0?-(x):(x))
 
+static Bool transparent_p;
+static int nplanes;
+static unsigned long base_pixel, *plane_masks;
+
 struct throbber {
   int x, y;
   int size;
@@ -116,6 +125,7 @@ static struct throbber *
 make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel)
 {
   XGCValues gcv;
+  unsigned long flags;
   struct throbber *t = (struct throbber *) malloc (sizeof (*t));
   t->x = w / 2;
   t->y = h / 2;
@@ -133,15 +143,25 @@ make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel)
   else
     t->size = t->thickness, t->speed = -t->speed;
 
-  gcv.foreground = pixel;
+  flags = GCForeground;
+  if (transparent_p)
+    {
+      gcv.foreground = ~0L;
+      gcv.plane_mask = base_pixel | plane_masks[random() % nplanes];
+      flags |= GCPlaneMask;
+    }
+  else
+    {
+      gcv.foreground = pixel;
+    }
+
   gcv.line_width = t->thickness;
   gcv.line_style = LineSolid;
   gcv.cap_style = CapProjecting;
   gcv.join_style = JoinMiter;
-  t->gc = XCreateGC (dpy, d,
-                     (GCForeground|GCLineWidth|GCLineStyle|
-                      GCCapStyle|GCJoinStyle),
-                     &gcv);
+
+  flags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
+  t->gc = XCreateGC (dpy, d, flags, &gcv);
 
   switch (random() % 11) {
   case 0: case 1: case 2: case 3: t->draw = draw_star; break;
@@ -197,7 +217,13 @@ char *defaults [] = {
   "*thickness:         50",
   "*speed:             15",
   "*ncolors:           20",
+  "*nlayers:           0",
+  "*transparent:       False",
   "*doubleBuffer:      True",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  "*useDBE:            True",
+  "*useDBEClear:       True",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
   0
 };
 
@@ -207,6 +233,10 @@ XrmOptionDescRec options [] = {
   { "-count",          ".count",       XrmoptionSepArg, 0 },
   { "-ncolors",                ".ncolors",     XrmoptionSepArg, 0 },
   { "-speed",          ".speed",       XrmoptionSepArg, 0 },
+  { "-transparent",    ".transparent",  XrmoptionNoArg,  "True" },
+  { "-opaque",         ".transparent",  XrmoptionNoArg,  "False" },
+  { "-db",             ".doubleBuffer", XrmoptionNoArg,  "True" },
+  { "-no-db",          ".doubleBuffer", XrmoptionNoArg,  "False" },
   { 0, 0, 0, 0 }
 };
 
@@ -217,23 +247,74 @@ screenhack (Display *dpy, Window window)
   int delay = get_integer_resource ("delay", "Integer");
   int ncolors = get_integer_resource ("ncolors", "Integer");
   Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
-  XColor colors[255];
+  Bool dbeclear_p = get_boolean_resource ("useDBEClear", "Boolean");
+  XColor *colors = 0;
   XGCValues gcv;
   GC erase_gc = 0;
   int i;
   struct throbber **throbbers;
   XWindowAttributes xgwa;
   Pixmap b=0, ba=0, bb=0;      /* double-buffer to reduce flicker */
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  XdbeBackBuffer backb = 0;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
 
   XGetWindowAttributes (dpy, window, &xgwa);
-  make_random_colormap (dpy, xgwa.visual, xgwa.colormap,
-                        colors, &ncolors, True, True, 0, True);
+
+  transparent_p = get_boolean_resource("transparent", "Transparent");
+
+  colors = (XColor *) calloc (sizeof(*colors), ncolors);
+
+  if (get_boolean_resource("mono", "Boolean"))
+    {
+    MONO:
+      ncolors = 1;
+      colors[0].pixel = get_pixel_resource("foreground", "Foreground",
+                                           dpy, xgwa.colormap);
+    }
+  else if (transparent_p)
+    {
+      nplanes = get_integer_resource ("planes", "Planes");
+      if (nplanes <= 0)
+        nplanes = (random() % (xgwa.depth-2)) + 2;
+
+      allocate_alpha_colors (xgwa.screen, xgwa.visual, xgwa.colormap,
+                             &nplanes, True, &plane_masks,
+                            &base_pixel);
+      if (nplanes <= 1)
+       {
+         fprintf (stderr,
+         "%s: couldn't allocate any color planes; turning transparency off.\n",
+                  progname);
+          transparent_p = False;
+         goto COLOR;
+       }
+    }
+  else
+    {
+    COLOR:
+      make_random_colormap (dpy, xgwa.visual, xgwa.colormap,
+                            colors, &ncolors, True, True, 0, True);
+      if (ncolors < 2)
+        goto MONO;
+    }
 
   if (dbuf)
     {
-      ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
-      bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
-      b = ba;
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+      if (dbeclear_p)
+        b = xdbe_get_backbuffer (dpy, window, XdbeBackground);
+      else
+        b = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
+      backb = b;
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+
+      if (!b)
+        {
+          ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
+          bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
+          b = ba;
+        }
     }
   else
     {
@@ -245,26 +326,37 @@ screenhack (Display *dpy, Window window)
     throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
                                   colors[random() % ncolors].pixel);
 
-  if (dbuf)
-    {
-      gcv.foreground = get_pixel_resource ("background", "Background",
-                                           dpy, xgwa.colormap);
-      erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
-      XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height);
-      XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height);
-    }
+  gcv.foreground = get_pixel_resource ("background", "Background",
+                                       dpy, xgwa.colormap);
+  erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
+
+  if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height);
+  if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height);
 
   while (1)
     {
-      if (dbuf)
+      if (!dbeclear_p
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+          || !backb
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+          )
         XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
-      else
-        XClearWindow (dpy, b);
 
       for (i = 0; i < count; i++)
         if (throb (dpy, b, throbbers[i]) < 0)
           throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
                                         colors[random() % ncolors].pixel);
+
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+      if (backb)
+        {
+          XdbeSwapInfo info[1];
+          info[0].swap_window = window;
+          info[0].swap_action = (dbeclear_p ? XdbeBackground : XdbeUndefined);
+          XdbeSwapBuffers (dpy, info, 1);
+        }
+      else
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
       if (dbuf)
         {
           XCopyArea (dpy, b, window, erase_gc, 0, 0,