http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / xflame.c
index 360ef379fc1d2515073e1335d37dc8870d8b79d8..b492561a7e55afb7d0c1404c657ec92394cf4016 100755 (executable)
@@ -1,4 +1,4 @@
-/* xflame, Copyright (c) 1996-1999 Carsten Haitzler <raster@redhat.com>
+/* xflame, Copyright (c) 1996-2002 Carsten Haitzler <raster@redhat.com>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
          behavioral constants.
 
        - General cleanup and portability tweaks.
+
+   * 4-Oct-99, jwz: added support for packed-24bpp (versus 32bpp.)
+   * 16-Jan-2002, jwz: added gdk_pixbuf support.
+
  */
 
 
 
 
 #include "screenhack.h"
+#include "xpm-pixmap.h"
 #include <X11/Xutil.h>
 #include <limits.h>
 
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
 #ifdef HAVE_XSHM_EXTENSION
 # include "xshm.h"
 #endif /* HAVE_XSHM_EXTENSION */
 
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-#  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
+#include "images/bob.xbm"
 
-#ifdef HAVE_XMU
-# ifndef VMS
-#  include <X11/Xmu/Drawing.h>
-# else  /* VMS */
-#  include <Xmu/Drawing.h>
-# endif /* VMS */
-#endif /* HAVE_XMU */
-
-#define MAX             255
+#define MAX_VAL             255
 
 static Display         *display;
 static Window          window;
@@ -76,7 +71,9 @@ static int             width;
 static int             height;
 static Colormap        colormap;
 static Visual          *visual;
+static Screen          *screen;
 static Bool            shared;
+static Bool            bloom;
 static XImage          *xim;
 #ifdef HAVE_XSHM_EXTENSION
 static XShmSegmentInfo shminfo;
@@ -111,6 +108,7 @@ GetXInfo(Display *disp, Window win)
   colormap = xwa.colormap;
   depth    = xwa.depth;
   visual   = xwa.visual;
+  screen   = xwa.screen;
   width    = xwa.width;
   height   = xwa.height;
 
@@ -125,9 +123,14 @@ MakeImage(void)
 {
   XGCValues gcv;
 
+#ifdef HAVE_XSHM_EXTENSION
   shared = True;
   xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
                            &shminfo, width, height);
+#else  /* !HAVE_XSHM_EXTENSION */
+  xim = 0;
+#endif /* !HAVE_XSHM_EXTENSION */
+
   if (!xim)
     {
       shared = False;
@@ -150,13 +153,27 @@ MakeImage(void)
 static void
 InitColors(void)
 {
-  int i = 0, j = 0;
+  int i = 0, j = 0, red = 0, green = 0, blue = 0;
+  XColor fg;
+
+  /* Make it possible to set the color of the flames, 
+     by Raymond Medeiros <ray@stommel.marine.usf.edu> and jwz.
+  */
+  fg.pixel = get_pixel_resource ("foreground", "Foreground",
+                                 display, colormap);
+  XQueryColor (display, colormap, &fg);
+
+  red   = 255 - (fg.red   >> 8);
+  green = 255 - (fg.green >> 8);
+  blue  = 255 - (fg.blue  >> 8);
+
+
   for (i = 0; i < 256 * 2; i += 2)
     {
       XColor xcl;
-      int r = (i -   0) * 3;
-      int g = (i -  80) * 3;
-      int b = (i - 160) * 3;
+      int r = (i - red)   * 3;
+      int g = (i - green) * 3;
+      int b = (i - blue)  * 3;
     
       if (r < 0)   r = 0;
       if (r > 255) r = 255;
@@ -180,10 +197,12 @@ InitColors(void)
 static void
 DisplayImage(void)
 {
+#ifdef HAVE_XSHM_EXTENSION
   if (shared)
     XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
                  (top - 1) << 1, width, height - ((top - 1) << 1), False);
   else
+#endif /* HAVE_XSHM_EXTENSION */
     XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
               (top - 1) << 1, width, height - ((top - 1) << 1));
 }
@@ -209,6 +228,7 @@ InitFlame(void)
   iresidual = get_integer_resource("residual", "Integer");
   variance  = get_integer_resource("variance", "Integer");
   vartrend  = get_integer_resource("vartrend", "Integer");
+  bloom     = get_boolean_resource("bloom",    "Boolean");
 
 # define THROTTLE(VAR,NAME) \
   if (VAR < 0 || VAR > 255) { \
@@ -296,6 +316,55 @@ Flame2Image32(void)
     }
 }
 
+static void
+Flame2Image24(void)
+{
+  int x,y;
+  unsigned char *ptr;
+  unsigned char *ptr1;
+  int v1,v2,v3,v4;
+
+  ptr  = (unsigned char *)xim->data;
+  ptr += (top << 1) * xim->bytes_per_line;
+  ptr1 = flame + 1 + (top * (fwidth + 2));
+
+  for( y = top; y < fheight; y++)
+    {
+      unsigned char *last_ptr = ptr;
+      for( x = 0; x < fwidth; x++)
+        {
+          v1 = (int)*ptr1;
+          v2 = (int)*(ptr1 + 1);
+          v3 = (int)*(ptr1 + fwidth + 2);
+          v4 = (int)*(ptr1 + fwidth + 2 + 1);
+          ptr1++;
+
+          ptr[2] = ((unsigned int)ctab[v1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[v1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[v1] & 0x000000FF);
+          ptr += 3;
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x000000FF);
+          ptr += ((width - 1) * 3);
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x000000FF);
+          ptr += 3;
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x000000FF);
+          ptr -= ((width - 1) * 3);
+        }
+
+      ptr = last_ptr + (xim->bytes_per_line << 1);
+      ptr1 += 2;
+    }
+}
+
 static void
 Flame2Image8(void)
 {
@@ -358,14 +427,22 @@ Flame2Image1234567(void)
 static void
 Flame2Image(void)
 {
-  if (depth >= 24)      Flame2Image32();
-  else if (depth == 16) Flame2Image16();
-  else if (depth == 8)  Flame2Image8();
-  else if (depth == 15) Flame2Image16(); 
-  else if (depth <  8)  Flame2Image1234567();
-  else if (depth == 12) Flame2Image16();
+  switch (xim->bits_per_pixel)
+    {
+    case 32: Flame2Image32(); break;
+    case 24: Flame2Image24(); break;
+    case 16: Flame2Image16(); break;
+    case 8:  Flame2Image8();  break;
+    default:
+      if (xim->bits_per_pixel <= 7)
+        Flame2Image1234567();
+      else
+        abort();
+      break;
+    }
 }
 
+
 static void
 FlameActive(void)
 {
@@ -381,13 +458,16 @@ FlameActive(void)
       *ptr1++ = v1 % 255;
     }
 
-  v1= (random() % 100);
-  if (v1 == 10)
-    residual += (random()%10);
-  else if (v1 == 20)
-    hspread += (random()%15);
-  else if (v1 == 30)
-    vspread += (random()%20);
+  if (bloom)
+    {
+      v1= (random() % 100);
+      if (v1 == 10)
+       residual += (random()%10);
+      else if (v1 == 20)
+       hspread += (random()%15);
+      else if (v1 == 30)
+       vspread += (random()%20);
+    }
 
   residual = ((iresidual* 10) + (residual *90)) / 100;
   hspread  = ((ihspread * 10) + (hspread  *90)) / 100;
@@ -417,21 +497,21 @@ FlameAdvance(void)
               v3   = (v1 * vspread) >> 8;
               v2   = (int)*(ptr2);
               v2  += v3;
-              if (v2 > MAX) 
-                v2 = MAX;
+              if (v2 > MAX_VAL
+                v2 = MAX_VAL;
 
               *(ptr2) = (unsigned char)v2;
               v3  = (v1 * hspread) >> 8;
               v2  = (int)*(ptr2 + 1);
               v2 += v3;
-              if (v2 > MAX) 
-                v2 = MAX;
+              if (v2 > MAX_VAL
+                v2 = MAX_VAL;
           
               *(ptr2 + 1) = (unsigned char)v2;
               v2          = (int)*(ptr2 - 1);
               v2         += v3;
-              if (v2 > MAX) 
-                v2 = MAX;
+              if (v2 > MAX_VAL
+                v2 = MAX_VAL;
           
               *(ptr2 - 1) = (unsigned char)v2;
         
@@ -445,6 +525,13 @@ FlameAdvance(void)
           if (used) 
             newtop = y - 1;
         }
+      /* clean up the right gutter */
+      {
+        int v1 = (int)*ptr1;
+        v1 = (v1 * residual) >> 8;
+        *ptr1 = (unsigned char)v1;
+      }
     }
 
   top = newtop - 1;
@@ -517,117 +604,88 @@ loadBitmap(int *w, int *h)
 {
   char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
 
-  if (bitmap_name &&
-      *bitmap_name &&
-      !!strcmp(bitmap_name, "none"))
+  if (!bitmap_name ||
+      !*bitmap_name ||
+      !strcmp(bitmap_name, "none"))
+    ;
+  else if (!strcmp(bitmap_name, "(default)"))   /* use the builtin */
+    {
+      XImage *ximage;
+      unsigned char *result, *o;
+      char *bits = (char *) malloc (sizeof(bob_bits));
+      int x, y;
+      int scale = ((width > bob_width * 11) ? 2 : 1);
+      memcpy (bits, bob_bits, sizeof(bob_bits));
+      ximage = XCreateImage (display, visual, 1, XYBitmap, 0, bits,
+                             bob_width, bob_height, 8, 0);
+      ximage->byte_order = LSBFirst;
+      ximage->bitmap_bit_order = LSBFirst;
+      *w = ximage->width * scale;
+      *h = ximage->height * scale;
+      o = result = (unsigned char *) malloc ((*w * scale) * (*h * scale));
+      for (y = 0; y < *h; y++)
+        for (x = 0; x < *w; x++)
+          *o++ = (XGetPixel(ximage, x/scale, y/scale) ? 255 : 0);
+       
+      return result;
+    }
+  else  /* load a bitmap file */
     {
-      XpmInfo xpm_info = { 0, };
-      XpmImage xpm_image = { 0, };
+      Pixmap pixmap =
+        xpm_file_to_pixmap (display, window, bitmap_name, &width, &height, 0);
+      XImage *image;
+      int x, y;
+      unsigned char *result, *o;
+      XColor colors[256];
+      Bool cmap_p = has_writable_cells (screen, visual);
 
-      int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
-      if (result == XpmSuccess)
+      if (cmap_p)
         {
-          int x, y;
-          unsigned char *result, *o;
-          unsigned char *grays;
-          XWindowAttributes xgwa;
-
-          *w = xpm_image.width;
-          *h = xpm_image.height;
-          result = (unsigned char *) malloc ((*w) * (*h));
-          if (!result)
-            {
-              fprintf(stderr, "%s: out of memory loading %s\n",
-                      progname, bitmap_name);
-              exit (1);
-            }
-
-          XGetWindowAttributes (display, window, &xgwa);
-
-          grays = (unsigned char *) calloc (xpm_image.ncolors+1, 1);
-          for (x = 0; x < xpm_image.ncolors; x++)
-            {
-              XColor xc;
-              XpmColor *xpmc = &xpm_image.colorTable[x];
-              char *cstring = 0;
-              if (xpmc->g_color && *xpmc->g_color)
-                cstring = xpmc->g_color;
-              else if (xpmc->g4_color && *xpmc->g4_color)
-                cstring = xpmc->g4_color;
-              else if (xpmc->c_color && *xpmc->c_color)
-                cstring = xpmc->c_color;
-              else
-                cstring = xpmc->m_color;
-
-              memset (&xc, 0, sizeof(xc));
-              if (!cstring ||
-                  !*cstring ||
-                  !XParseColor (display, xgwa.colormap, cstring, &xc))
-                grays[x] = 0;
-              else
-                grays[x] = (int) (((xc.red   * 0.299) +
-                                   (xc.green * 0.587) +
-                                   (xc.blue  * 0.114))
-                                  / 255);
-            }
-
-          o = result;
-          for (y = 0; y < *h; y++)
-            for (x = 0; x < *w; x++)
-              {
-                int color = xpm_image.data[(y * (*w)) + x];
-                if (color < 0 || color > xpm_image.ncolors) abort();
-                *o++ = grays[color];
-              }
-          return result;
+          int i;
+          for (i = 0; i < countof (colors); i++)
+            colors[i].pixel = i;
+          XQueryColors (display, colormap, colors, countof (colors));
         }
-      else      /* failed to read XPM -- fall through and try XBM */
-        {
-#ifdef HAVE_XMU
-          XImage *ximage = 0;
-          int width, height, xh, yh;
-          int x, y;
-          unsigned char *result, *o;
-          Pixmap bitmap =
-            XmuLocateBitmapFile (DefaultScreenOfDisplay (display),
-                                 bitmap_name, 0, 0, &width, &height, &xh, &yh);
-          if (!bitmap)
-            {
-              fprintf(stderr, "%s: unable to load bitmap file %s\n",
-                      progname, bitmap_name);
-              exit (1);
-            }
-          ximage = XGetImage (display, bitmap, 0, 0, width, height,
-                              1L, XYPixmap);
-          XFreePixmap (display, bitmap);
-
-          if (ximage->depth != 1) abort();
-
-          *w = ximage->width;
-          *h = ximage->height;
-          result = (unsigned char *) malloc ((*w) * (*h));
-          if (!result)
-            {
-              fprintf(stderr, "%s: out of memory loading %s\n",
-                      progname, bitmap_name);
-              exit (1);
-            }
-
-          o = result;
-          for (y = 0; y < *h; y++)
-            for (x = 0; x < *w; x++)
-              *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
 
-          return result;
-
-#else  /* !XMU */
-          fprintf (stderr,
-                   "%s: your vendor doesn't ship the standard Xmu library.\n",
-                   progname);
-          fprintf (stderr, "\tWe can't load XBM files without it.\n");
-          exit (1);
-#endif /* !XMU */
-        }
+      image = XGetImage (display, pixmap, 0, 0, width, height, ~0L, ZPixmap);
+      XFreePixmap(display, pixmap);
+
+      result = (unsigned char *) malloc (width * height);
+      o = result;
+      for (y = 0; y < height; y++)
+        for (x = 0; x < width; x++)
+          {
+            int rgba = XGetPixel (image, x, y);
+            int gray;
+            if (cmap_p)
+              gray = ((200 - ((((colors[rgba].red   >> 8) & 0xFF) +
+                              ((colors[rgba].green >> 8) & 0xFF) +
+                              ((colors[rgba].blue  >> 8) & 0xFF))
+                             >> 1))
+                      & 0xFF);
+            else
+              /* This is *so* not handling all the cases... */
+              gray = (image->depth > 16
+                      ? ((((rgba >> 24) & 0xFF) +
+                          ((rgba >> 16) & 0xFF) +
+                          ((rgba >>  8) & 0xFF) +
+                          ((rgba      ) & 0xFF)) >> 2)
+                      : ((((rgba >> 12) & 0x0F) +
+                          ((rgba >>  8) & 0x0F) +
+                          ((rgba >>  4) & 0x0F) +
+                          ((rgba      ) & 0x0F)) >> 1));
+
+            *o++ = 255 - gray;
+          }
+
+      XFree (image->data);
+      image->data = 0;
+      XDestroyImage (image);
+
+      *w = width;
+      *h = height;
+      return result;
     }
 
   *w = 0;
@@ -642,8 +700,8 @@ char *progclass = "XFlame";
 
 char *defaults [] = {
   ".background:     black",
-  ".foreground:     red",
-  "*bitmap:         none",
+  ".foreground:     #FFAF5F",
+  "*bitmap:         (default)",
   "*bitmapBaseline: 20",
   "*delay:          10000",
   "*hspread:        30",
@@ -651,6 +709,7 @@ char *defaults [] = {
   "*residual:       99",
   "*variance:       50",
   "*vartrend:       20",
+  "*bloom:          True",   
 
 #ifdef HAVE_XSHM_EXTENSION
   "*useSHM: False",   /* xshm turns out not to help. */
@@ -659,6 +718,8 @@ char *defaults [] = {
 };
 
 XrmOptionDescRec options [] = {
+  { "-foreground",".foreground",     XrmoptionSepArg, 0 },
+  { "-fg",        ".foreground",     XrmoptionSepArg, 0 },
   { "-delay",     ".delay",          XrmoptionSepArg, 0 },
   { "-bitmap",    ".bitmap",         XrmoptionSepArg, 0 },
   { "-baseline",  ".bitmapBaseline", XrmoptionSepArg, 0 },
@@ -667,6 +728,8 @@ XrmOptionDescRec options [] = {
   { "-residual",  ".residual",       XrmoptionSepArg, 0 },
   { "-variance",  ".variance",       XrmoptionSepArg, 0 },
   { "-vartrend",  ".vartrend",       XrmoptionSepArg, 0 },
+  { "-bloom",     ".bloom",          XrmoptionNoArg, "True" },
+  { "-no-bloom",  ".bloom",          XrmoptionNoArg, "False" },
 #ifdef HAVE_XSHM_EXTENSION
   { "-shm",       ".useSHM",         XrmoptionNoArg, "True" },
   { "-no-shm",    ".useSHM",         XrmoptionNoArg, "False" },