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);
64 #if !GLIB_CHECK_VERSION(2, 36 ,0)
67 #endif /* HAVE_GTK2 */
68 gdk_pixbuf_xlib_init (dpy, screen_number (xgwa.screen));
69 xlib_rgb_init (dpy, xgwa.screen);
75 ? gdk_pixbuf_new_from_file (filename, &gerr)
76 #else /* !HAVE_GTK2 */
77 ? gdk_pixbuf_new_from_file (filename)
78 #endif /* !HAVE_GTK2 */
79 : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data));
82 int w = gdk_pixbuf_get_width (pb);
83 int h = gdk_pixbuf_get_height (pb);
86 /* #### Note that this always uses the default colormap! Morons!
87 Owen says that in Gnome 2.0, I should try using
88 gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead.
89 But I don't have Gnome 2.0 yet.
91 gdk_pixbuf_xlib_render_pixmap_and_mask (pb, &pixmap, mask_ret, 128);
95 fprintf (stderr, "%s: out of memory (%d x %d)\n", progname, w, h);
98 /* gdk_pixbuf_unref (pb); -- #### does doing this free colors? */
100 if (width_ret) *width_ret = w;
101 if (height_ret) *height_ret = h;
108 fprintf (stderr, "%s: %s\n", progname, gerr->message);
110 #else /* !HAVE_GTK2 */
111 fprintf (stderr, "%s: unable to load %s\n", progname, filename);
112 #endif /* !HAVE_GTK2 */
117 fprintf (stderr, "%s: unable to initialize built-in images\n", progname);
123 #elif defined(HAVE_XPM)
125 #include <X11/Intrinsic.h>
130 # include <X11/Xmu/Drawing.h>
132 # include <Xmu/Drawing.h>
137 #define countof(x) (sizeof((x))/sizeof((*x)))
141 handle_xpm_error (const char *filename, int status)
143 if (!filename) filename = "builtin";
150 fprintf (stderr, "%s: %s: warning: color substitution performed\n",
158 fprintf (stderr, "%s: %s: no such file\n", progname, filename);
161 fprintf (stderr, "%s: %s: out of memory\n", progname, filename);
164 fprintf (stderr, "%s: %s: color allocation failed\n",
168 fprintf (stderr, "%s: %s: unknown XPM error %d\n", progname,
176 /* The libxpm version of this function...
179 xpm_to_pixmap_1 (Display *dpy, Window window,
180 int *width_ret, int *height_ret,
182 const char *filename,
183 /*const*/ char * const *xpm_data)
186 XpmAttributes xpmattrs;
190 XWindowAttributes xgwa;
191 XGetWindowAttributes (dpy, window, &xgwa);
193 memset (&xpm_image, 0, sizeof(xpm_image));
194 memset (&xpm_info, 0, sizeof(xpm_info));
199 status = XpmReadFileToData ((char *) filename, &xpm_data);
200 if (handle_xpm_error (filename, status))
204 xpmattrs.valuemask = 0;
207 xpmattrs.valuemask |= XpmCloseness;
208 xpmattrs.closeness = 40000;
211 xpmattrs.valuemask |= XpmVisual;
212 xpmattrs.visual = xgwa.visual;
215 xpmattrs.valuemask |= XpmDepth;
216 xpmattrs.depth = xgwa.depth;
219 xpmattrs.valuemask |= XpmColormap;
220 xpmattrs.colormap = xgwa.colormap;
223 status = XpmCreatePixmapFromData (dpy, window, xpm_data,
224 &pixmap, mask_ret, &xpmattrs);
225 if (handle_xpm_error (filename, status))
229 if (width_ret) *width_ret = xpmattrs.width;
230 if (height_ret) *height_ret = xpmattrs.height;
238 unsigned long fg = BlackPixelOfScreen (xgwa.screen);
239 unsigned long bg = WhitePixelOfScreen (xgwa.screen);
242 pixmap = XmuLocateBitmapFile (xgwa.screen, filename,
243 0, 0, width_ret, height_ret, &xh, &yh);
246 fprintf (stderr, "%s: couldn't find XBM %s\n", progname,
250 b2 = XmuCreatePixmapFromBitmap (dpy, window, pixmap,
251 *width_ret, *height_ret,
253 XFreePixmap (dpy, pixmap);
258 fprintf (stderr, "%s: couldn't load XBM %s\n", progname, filename);
265 "%s: your vendor doesn't ship the standard Xmu library.\n",
267 fprintf (stderr, "\tWe can't load XBM files without it.\n");
275 #else /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
277 /* If we don't have libXPM or Pixbuf, then use "minixpm".
278 This can read XPM data from memory, but can't read files.
284 xpm_to_pixmap_1 (Display *dpy, Window window,
285 int *width_ret, int *height_ret,
287 const char *filename,
288 /*const*/ char * const *xpm_data)
290 XWindowAttributes xgwa;
292 Pixmap pixmap, p2 = 0;
294 unsigned long *pixels = 0;
295 unsigned char *mask = 0;
302 "%s: no files: not compiled with XPM or Pixbuf support.\n",
307 if (! xpm_data) abort();
309 XGetWindowAttributes (dpy, window, &xgwa);
310 ximage = minixpm_to_ximage (dpy, xgwa.visual, xgwa.colormap, xgwa.depth,
311 BlackPixelOfScreen (xgwa.screen),
312 (const char * const *)
313 xpm_data, &iw, &ih, &pixels, &npixels,
314 (mask_ret ? &mask : 0));
315 if (pixels) free (pixels);
317 pixmap = XCreatePixmap (dpy, window, iw, ih, xgwa.depth);
318 gc = XCreateGC (dpy, pixmap, 0, &gcv);
319 XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, iw, ih);
321 XDestroyImage (ximage);
325 p2 = XCreatePixmap (dpy, window, iw, ih, 1);
328 gc = XCreateGC (dpy, p2, GCForeground|GCBackground, &gcv);
329 ximage = XCreateImage (dpy, xgwa.visual, 1, XYBitmap, 0, (char *) mask,
331 ximage->byte_order = ximage->bitmap_bit_order = LSBFirst;
332 if (!ximage) abort();
333 XPutImage (dpy, p2, gc, ximage, 0, 0, 0, 0, iw, ih);
335 XDestroyImage (ximage);
338 if (width_ret) *width_ret = iw;
339 if (height_ret) *height_ret = ih;
340 if (mask_ret) *mask_ret = p2;
348 xpm_data_to_pixmap (Display *dpy, Window window,
349 /*const*/ char * const *xpm_data,
350 int *width_ret, int *height_ret,
353 return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,
359 xpm_file_to_pixmap (Display *dpy, Window window, const char *filename,
360 int *width_ret, int *height_ret,
363 return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,