1 /* xpm-pixmap.c --- converts XPM data to a Pixmap.
2 * xscreensaver, Copyright (c) 1998-2006 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
23 # include <X11/Xlib.h>
24 # include <X11/Xutil.h>
25 # include "visual.h" /* for screen_number() */
28 #include "xpm-pixmap.h"
30 extern char *progname;
32 #if defined(HAVE_GDK_PIXBUF)
34 # include <gdk-pixbuf/gdk-pixbuf.h>
37 # include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
38 # else /* !HAVE_GTK2 */
39 # include <gdk-pixbuf/gdk-pixbuf-xlib.h>
40 # endif /* !HAVE_GTK2 */
43 /* Returns a Pixmap structure containing the bits of the given XPM image.
44 This is the gdk_pixbuf version of this function.
47 xpm_to_pixmap_1 (Display *dpy, Window window,
48 int *width_ret, int *height_ret,
51 /*const*/ char * const *xpm_data)
54 static int initted = 0;
55 XWindowAttributes xgwa;
58 #endif /* HAVE_GTK2 */
59 XGetWindowAttributes (dpy, window, &xgwa);
65 #endif /* HAVE_GTK2 */
66 gdk_pixbuf_xlib_init (dpy, screen_number (xgwa.screen));
67 xlib_rgb_init (dpy, xgwa.screen);
73 ? gdk_pixbuf_new_from_file (filename, &gerr)
74 #else /* !HAVE_GTK2 */
75 ? gdk_pixbuf_new_from_file (filename)
76 #endif /* !HAVE_GTK2 */
77 : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data));
80 int w = gdk_pixbuf_get_width (pb);
81 int h = gdk_pixbuf_get_height (pb);
84 /* #### Note that this always uses the default colormap! Morons!
85 Owen says that in Gnome 2.0, I should try using
86 gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead.
87 But I don't have Gnome 2.0 yet.
89 gdk_pixbuf_xlib_render_pixmap_and_mask (pb, &pixmap, mask_ret, 128);
93 fprintf (stderr, "%s: out of memory (%d x %d)\n", progname, w, h);
96 /* gdk_pixbuf_unref (pb); -- #### does doing this free colors? */
98 if (width_ret) *width_ret = w;
99 if (height_ret) *height_ret = h;
106 fprintf (stderr, "%s: %s\n", progname, gerr->message);
108 #else /* !HAVE_GTK2 */
109 fprintf (stderr, "%s: unable to load %s\n", progname, filename);
110 #endif /* !HAVE_GTK2 */
115 fprintf (stderr, "%s: unable to initialize built-in images\n", progname);
121 #elif defined(HAVE_XPM)
123 #include <X11/Intrinsic.h>
128 # include <X11/Xmu/Drawing.h>
130 # include <Xmu/Drawing.h>
135 #define countof(x) (sizeof((x))/sizeof((*x)))
139 handle_xpm_error (const char *filename, int status)
141 if (!filename) filename = "builtin";
148 fprintf (stderr, "%s: %s: warning: color substitution performed\n",
156 fprintf (stderr, "%s: %s: no such file\n", progname, filename);
159 fprintf (stderr, "%s: %s: out of memory\n", progname, filename);
162 fprintf (stderr, "%s: %s: color allocation failed\n",
166 fprintf (stderr, "%s: %s: unknown XPM error %d\n", progname,
174 /* The libxpm version of this function...
177 xpm_to_pixmap_1 (Display *dpy, Window window,
178 int *width_ret, int *height_ret,
180 const char *filename,
181 /*const*/ char * const *xpm_data)
184 XpmAttributes xpmattrs;
188 XWindowAttributes xgwa;
189 XGetWindowAttributes (dpy, window, &xgwa);
191 memset (&xpm_image, 0, sizeof(xpm_image));
192 memset (&xpm_info, 0, sizeof(xpm_info));
197 status = XpmReadFileToData ((char *) filename, &xpm_data);
198 if (handle_xpm_error (filename, status))
202 xpmattrs.valuemask = 0;
205 xpmattrs.valuemask |= XpmCloseness;
206 xpmattrs.closeness = 40000;
209 xpmattrs.valuemask |= XpmVisual;
210 xpmattrs.visual = xgwa.visual;
213 xpmattrs.valuemask |= XpmDepth;
214 xpmattrs.depth = xgwa.depth;
217 xpmattrs.valuemask |= XpmColormap;
218 xpmattrs.colormap = xgwa.colormap;
221 status = XpmCreatePixmapFromData (dpy, window, xpm_data,
222 &pixmap, mask_ret, &xpmattrs);
223 if (handle_xpm_error (filename, status))
227 if (width_ret) *width_ret = xpmattrs.width;
228 if (height_ret) *height_ret = xpmattrs.height;
236 unsigned long fg = BlackPixelOfScreen (xgwa.screen);
237 unsigned long bg = WhitePixelOfScreen (xgwa.screen);
240 pixmap = XmuLocateBitmapFile (xgwa.screen, filename,
241 0, 0, width_ret, height_ret, &xh, &yh);
244 fprintf (stderr, "%s: couldn't find XBM %s\n", progname,
248 b2 = XmuCreatePixmapFromBitmap (dpy, window, pixmap,
249 *width_ret, *height_ret,
251 XFreePixmap (dpy, pixmap);
256 fprintf (stderr, "%s: couldn't load XBM %s\n", progname, filename);
263 "%s: your vendor doesn't ship the standard Xmu library.\n",
265 fprintf (stderr, "\tWe can't load XBM files without it.\n");
273 #else /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
275 /* If we don't have libXPM or Pixbuf, then use "minixpm".
276 This can read XPM data from memory, but can't read files.
282 xpm_to_pixmap_1 (Display *dpy, Window window,
283 int *width_ret, int *height_ret,
285 const char *filename,
286 /*const*/ char * const *xpm_data)
288 XWindowAttributes xgwa;
290 Pixmap pixmap, p2 = 0;
292 unsigned long *pixels = 0;
293 unsigned char *mask = 0;
300 "%s: no files: not compiled with XPM or Pixbuf support.\n",
305 if (! xpm_data) abort();
307 XGetWindowAttributes (dpy, window, &xgwa);
308 ximage = minixpm_to_ximage (dpy, xgwa.visual, xgwa.colormap, xgwa.depth,
309 BlackPixelOfScreen (xgwa.screen),
310 (const char * const *)
311 xpm_data, &iw, &ih, &pixels, &npixels,
312 (mask_ret ? &mask : 0));
313 if (pixels) free (pixels);
315 pixmap = XCreatePixmap (dpy, window, iw, ih, xgwa.depth);
316 gc = XCreateGC (dpy, pixmap, 0, &gcv);
317 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, iw, ih);
319 XDestroyImage (ximage);
323 p2 = XCreatePixmap (dpy, window, iw, ih, 1);
326 gc = XCreateGC (dpy, p2, GCForeground|GCBackground, &gcv);
327 ximage = XCreateImage (dpy, xgwa.visual, 1, XYBitmap, 0, (char *) mask,
329 ximage->byte_order = ximage->bitmap_bit_order = LSBFirst;
330 if (!ximage) abort();
331 XPutImage (dpy, p2, gc, ximage, 0, 0, 0, 0, iw, ih);
333 XDestroyImage (ximage);
336 if (width_ret) *width_ret = iw;
337 if (height_ret) *height_ret = ih;
338 if (mask_ret) *mask_ret = p2;
346 xpm_data_to_pixmap (Display *dpy, Window window,
347 /*const*/ char * const *xpm_data,
348 int *width_ret, int *height_ret,
351 return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,
357 xpm_file_to_pixmap (Display *dpy, Window window, const char *filename,
358 int *width_ret, int *height_ret,
361 return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,