ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-1.27.tar.Z
[xscreensaver] / hacks / blitspin.c
index a532e2967fe71b68208239fa165202d7f439c45e..9a72b302d7ccba7d496877a921f85cd3a291a8b9 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+/* xscreensaver, Copyright (c) 1992-1996 Jamie Zawinski <jwz@netscape.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
    The input bitmap may be non-square, it is padded and centered
    with the background color.  Another way would be to subdivide
-   the bitmap into square components and rotate them independently,
-   but I don't think that would be as interesting looking.
+   the bitmap into square components and rotate them independently
+   (and preferably in parallel), but I don't think that would be as
+   interesting looking.
 
    It's too bad almost nothing uses blitter hardware these days,
    or this might actually win.
  */
 
 #include "screenhack.h"
-#include <X11/Xmu/Drawing.h>
 #include <stdio.h>
 
+#ifdef HAVE_XPM
+# include <X11/xpm.h>
+# ifndef PIXEL_ALREADY_TYPEDEFED
+#  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
+# endif
+#endif
+
+#include <X11/Xmu/Drawing.h>
+
+#include "default.xbm"
+
 static Display *dpy;
 static Window window;
 static unsigned int size;
@@ -35,6 +46,8 @@ static GC SET, CLR, CPY, IOR, AND, XOR;
 static GC gc;
 static int delay, delay2;
 static Pixmap bitmap;
+static int depth;
+static unsigned int fg, bg;
 
 static void rotate(), init (), display ();
 
@@ -74,35 +87,103 @@ rotate ()
     }
 }
 
+static void
+read_bitmap (bitmap_name, widthP, heightP)
+     char *bitmap_name;
+     int *widthP, *heightP;
+{
+#ifdef HAVE_XPM
+  XpmAttributes xpmattrs;
+  int result;
+  xpmattrs.valuemask = 0;
+  bitmap = 0;
+
+#ifdef XpmCloseness
+  xpmattrs.valuemask |= XpmCloseness;
+  xpmattrs.closeness = 40000;
+#endif
+
+  result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0,
+                               &xpmattrs);
+  switch (result)
+    {
+    case XpmColorError:
+      fprintf (stderr, "%s: warning: xpm color substitution performed\n",
+              progname);
+      /* fall through */
+    case XpmSuccess:
+      *widthP = xpmattrs.width;
+      *heightP = xpmattrs.height;
+      break;
+    case XpmFileInvalid:
+    case XpmOpenFailed:
+      bitmap = 0;
+      break;
+    case XpmColorFailed:
+      fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
+      exit (-1);
+    case XpmNoMemory:
+      fprintf (stderr, "%s: xpm: out of memory\n", progname);
+      exit (-1);
+    default:
+      fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
+      exit (-1);
+    }
+  if (! bitmap)
+#endif
+    {
+      int xh, yh;
+      Pixmap b2;
+      bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
+                                   0, 0, widthP, heightP, &xh, &yh);
+      if (! bitmap)
+       {
+         fprintf (stderr, "%s: couldn't find bitmap %s\n", progname,
+                  bitmap_name);
+         exit (1);
+       }
+      b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP,
+                                     depth, fg, bg);
+      XFreePixmap (dpy, bitmap);
+      bitmap = b2;
+    }
+}
+
 static void
 init ()
 {
   XWindowAttributes xgwa;
   Colormap cmap;
   XGCValues gcv;
-  int width, height, xh, yh;
+  int width, height;
   unsigned int real_size;
   char *bitmap_name;
   int i;
+
   XGetWindowAttributes (dpy, window, &xgwa);
   cmap = xgwa.colormap;
+  depth = xgwa.depth;
 
+  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  bg = get_pixel_resource ("background", "Background", dpy, cmap);
   delay = get_integer_resource ("delay", "Integer");
   delay2 = get_integer_resource ("delay2", "Integer");
   if (delay < 0) delay = 0;
   if (delay2 < 0) delay2 = 0;
   bitmap_name = get_string_resource ("bitmap", "Bitmap");
-  if (! bitmap_name)
+  if (! bitmap_name || !*bitmap_name)
+    bitmap_name = "(default)";
+
+  if (!strcmp (bitmap_name, "(default)"))
     {
-      fprintf (stderr, "%s: no bitmap specified\n", progname);
-      exit (1);
+      width = logo_width;
+      height = logo_height;
+      bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits,
+                                           width, height, fg, bg, depth);
     }
-  bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
-                               0, 0, &width, &height, &xh, &yh);
-  if (! bitmap)
+  else
     {
-      fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, bitmap_name);
-      exit (1);
+      read_bitmap (bitmap_name, &width, &height);
     }
 
   real_size = (width > height) ? width : height;
@@ -113,10 +194,10 @@ init ()
     if (size & (1<<i)) break;
   if (size & (~(1<<i)))
     size = (size>>i)<<(i+1);
-  self = XCreatePixmap (dpy, window, size, size, 1);
-  temp = XCreatePixmap (dpy, window, size, size, 1);
-  mask = XCreatePixmap (dpy, window, size, size, 1);
-  gcv.foreground = 1;
+  self = XCreatePixmap (dpy, window, size, size, depth);
+  temp = XCreatePixmap (dpy, window, size, size, depth);
+  mask = XCreatePixmap (dpy, window, size, size, depth);
+  gcv.foreground = (depth == 1 ? 1 : (~0));
   gcv.function=GXset;  SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
   gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
   gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
@@ -124,13 +205,14 @@ init ()
   gcv.function=GXand;  AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
   gcv.function=GXxor;  XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
 
-  XFillRectangle (dpy, self, CLR, 0, 0, size, size);
+  gcv.foreground = gcv.background = bg;
+  gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+  /* Clear self to the background color (not to 0, which CLR does.) */
+  XFillRectangle (dpy, self, gc, 0, 0, size, size);
+  XSetForeground (dpy, gc, fg);
+
   XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
             (size - width)>>1, (size - height)>>1);
-
-  gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
-  gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
-  gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
 }
 
 static void
@@ -146,8 +228,14 @@ display (pixmap)
       last_w = xgwa.width;
       last_h = xgwa.height;
     }
-  XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
-             (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
+#ifdef HAVE_XPM
+  if (depth != 1)
+    XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
+              (xgwa.width-size)>>1, (xgwa.height-size)>>1);
+  else
+#endif
+    XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
+               (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
 /*
   XDrawRectangle (dpy, window, gc,
                  ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
@@ -160,11 +248,11 @@ display (pixmap)
 char *progclass = "BlitSpin";
 
 char *defaults [] = {
-  "*background:        black",
-  "*foreground:        white",
+  "BlitSpin.background:        black",         /* to placate SGI */
+  "BlitSpin.foreground:        white",
   "*delay:     500000",
   "*delay2:    500000",
-  "*bitmap:    xlogo64",       /* hey, pick something better! */
+  "*bitmap:    (default)",
   0
 };