From http://www.jwz.org/xscreensaver/xscreensaver-5.35.tar.gz
[xscreensaver] / hacks / xpm-pixmap.c
index a4b3e2afcd96b33eba34a110b83ec4fcb512df5e..635a5018d0ea686bd115aaf1257700cf856dac3e 100644 (file)
@@ -1,5 +1,5 @@
 /* xpm-pixmap.c --- converts XPM data to a Pixmap.
- * xscreensaver, Copyright (c) 1998, 2001, 2002 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1998-2006 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 "config.h"
 #endif
 
-#include <X11/Xlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 
-#include "visual.h"  /* for screen_number() */
+#ifdef HAVE_JWXYZ
+# include "jwxyz.h"
+#else
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
+# include "visual.h"  /* for screen_number() */
+#endif
 
-extern char *progname;
+#include "xpm-pixmap.h"
 
+extern char *progname;
 
 #if defined(HAVE_GDK_PIXBUF)
 
 # include <gdk-pixbuf/gdk-pixbuf.h>
-# include <gdk-pixbuf/gdk-pixbuf-xlib.h>
+
+# ifdef HAVE_GTK2
+#  include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
+# else  /* !HAVE_GTK2 */
+#  include <gdk-pixbuf/gdk-pixbuf-xlib.h>
+# endif /* !HAVE_GTK2 */
 
 
 /* Returns a Pixmap structure containing the bits of the given XPM image.
@@ -37,22 +48,34 @@ xpm_to_pixmap_1 (Display *dpy, Window window,
                  int *width_ret, int *height_ret,
                  Pixmap *mask_ret,
                  const char *filename,
-                 char **xpm_data)
+                 /*const*/ char * const *xpm_data)
 {
   GdkPixbuf *pb;
   static int initted = 0;
   XWindowAttributes xgwa;
+#ifdef HAVE_GTK2
+  GError *gerr = NULL;
+#endif /* HAVE_GTK2 */
   XGetWindowAttributes (dpy, window, &xgwa);
 
   if (!initted)
     {
+#ifdef HAVE_GTK2
+#if !GLIB_CHECK_VERSION(2, 36 ,0)
+      g_type_init ();
+#endif
+#endif /* HAVE_GTK2 */
       gdk_pixbuf_xlib_init (dpy, screen_number (xgwa.screen));
       xlib_rgb_init (dpy, xgwa.screen);
       initted = 1;
     }
 
   pb = (filename
-        ? gdk_pixbuf_new_from_file (filename)
+#ifdef HAVE_GTK2
+        ? gdk_pixbuf_new_from_file (filename, &gerr)
+#else  /* !HAVE_GTK2 */
+       ? gdk_pixbuf_new_from_file (filename)
+#endif /* !HAVE_GTK2 */
         : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data));
   if (pb)
     {
@@ -81,7 +104,12 @@ xpm_to_pixmap_1 (Display *dpy, Window window,
     }
   else if (filename)
     {
+#ifdef HAVE_GTK2
+      fprintf (stderr, "%s: %s\n", progname, gerr->message);
+      g_error_free (gerr);
+#else /* !HAVE_GTK2 */
       fprintf (stderr, "%s: unable to load %s\n", progname, filename);
+#endif /* !HAVE_GTK2 */
       exit (-1);
     }
   else
@@ -95,7 +123,6 @@ xpm_to_pixmap_1 (Display *dpy, Window window,
 #elif defined(HAVE_XPM)
 
 #include <X11/Intrinsic.h>
-#include <X11/Xutil.h>
 #include <X11/xpm.h>
 
 #ifdef HAVE_XMU
@@ -153,7 +180,7 @@ xpm_to_pixmap_1 (Display *dpy, Window window,
                  int *width_ret, int *height_ret,
                  Pixmap *mask_ret,
                  const char *filename,
-                 char **xpm_data)
+                 /*const*/ char * const *xpm_data)
 {
   Pixmap pixmap = 0;
   XpmAttributes xpmattrs;
@@ -247,22 +274,79 @@ xpm_to_pixmap_1 (Display *dpy, Window window,
 
 #else  /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
 
+/* If we don't have libXPM or Pixbuf, then use "minixpm".
+   This can read XPM data from memory, but can't read files.
+ */
+
+#include "minixpm.h"
+
 static Pixmap
 xpm_to_pixmap_1 (Display *dpy, Window window,
                  int *width_ret, int *height_ret,
                  Pixmap *mask_ret,
                  const char *filename,
-                 char **xpm_data)
+                 /*const*/ char * const *xpm_data)
 {
-  fprintf(stderr, "%s: not compiled with XPM or Pixbuf support.\n", progname);
-  exit (-1);
+  XWindowAttributes xgwa;
+  XImage *ximage;
+  Pixmap pixmap, p2 = 0;
+  int iw, ih, npixels;
+  unsigned long *pixels = 0;
+  unsigned char *mask = 0;
+  XGCValues gcv;
+  GC gc;
+
+  if (filename)
+    {
+      fprintf(stderr, 
+              "%s: no files: not compiled with XPM or Pixbuf support.\n", 
+              progname);
+      exit (1);
+    }
+
+  if (! xpm_data) abort();
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  ximage = minixpm_to_ximage (dpy, xgwa.visual, xgwa.colormap, xgwa.depth, 
+                              BlackPixelOfScreen (xgwa.screen),
+                              (const char * const *)
+                              xpm_data, &iw, &ih, &pixels, &npixels, 
+                              (mask_ret ? &mask : 0));
+  if (pixels) free (pixels);
+
+  pixmap = XCreatePixmap (dpy, window, iw, ih, xgwa.depth);
+  gc = XCreateGC (dpy, pixmap, 0, &gcv);
+  XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, iw, ih);
+  XFreeGC (dpy, gc);
+  XDestroyImage (ximage);
+
+  if (mask)
+    {
+      p2 = XCreatePixmap (dpy, window, iw, ih, 1);
+      gcv.foreground = 1;
+      gcv.background = 0;
+      gc = XCreateGC (dpy, p2, GCForeground|GCBackground, &gcv);
+      ximage = XCreateImage (dpy, xgwa.visual, 1, XYBitmap, 0, (char *) mask,
+                             iw, ih, 8, 0);
+      ximage->byte_order = ximage->bitmap_bit_order = LSBFirst;
+      if (!ximage) abort();
+      XPutImage (dpy, p2, gc, ximage, 0, 0, 0, 0, iw, ih);
+      XFreeGC (dpy, gc);
+      XDestroyImage (ximage);
+    }
+
+  if (width_ret)  *width_ret  = iw;
+  if (height_ret) *height_ret = ih;
+  if (mask_ret)   *mask_ret   = p2;
+  return pixmap;
 }
 
-#endif /* !HAVE_XPM */
+#endif /* minixpm */
 
 
 Pixmap
-xpm_data_to_pixmap (Display *dpy, Window window, char **xpm_data,
+xpm_data_to_pixmap (Display *dpy, Window window, 
+                    /*const*/ char * const *xpm_data,
                     int *width_ret, int *height_ret,
                     Pixmap *mask_ret)
 {