http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.04.2.tar.gz
[xscreensaver] / hacks / xpm-pixmap.c
1 /* xpm-pixmap.c --- converts XPM data to a Pixmap.
2  * xscreensaver, Copyright (c) 1998, 2001, 2002 Jamie Zawinski <jwz@jwz.org>
3  *
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 
10  * implied warranty.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <X11/Xlib.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20
21 #include "visual.h"  /* for screen_number() */
22
23 extern char *progname;
24
25
26 #if defined(HAVE_GDK_PIXBUF)
27
28 # include <gdk-pixbuf/gdk-pixbuf.h>
29
30 # ifdef HAVE_GTK2
31 #  include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
32 # else  /* !HAVE_GTK2 */
33 #  include <gdk-pixbuf/gdk-pixbuf-xlib.h>
34 # endif /* !HAVE_GTK2 */
35
36
37 /* Returns a Pixmap structure containing the bits of the given XPM image.
38    This is the gdk_pixbuf version of this function.
39  */
40 static Pixmap
41 xpm_to_pixmap_1 (Display *dpy, Window window,
42                  int *width_ret, int *height_ret,
43                  Pixmap *mask_ret,
44                  const char *filename,
45                  char **xpm_data)
46 {
47   GdkPixbuf *pb;
48   static int initted = 0;
49   XWindowAttributes xgwa;
50 #ifdef HAVE_GTK2
51   GError *gerr = NULL;
52 #endif /* HAVE_GTK2 */
53   XGetWindowAttributes (dpy, window, &xgwa);
54
55   if (!initted)
56     {
57 #ifdef HAVE_GTK2
58       g_type_init ();
59 #endif /* HAVE_GTK2 */
60       gdk_pixbuf_xlib_init (dpy, screen_number (xgwa.screen));
61       xlib_rgb_init (dpy, xgwa.screen);
62       initted = 1;
63     }
64
65   pb = (filename
66 #ifdef HAVE_GTK2
67         ? gdk_pixbuf_new_from_file (filename, &gerr)
68 #else  /* !HAVE_GTK2 */
69         ? gdk_pixbuf_new_from_file (filename)
70 #endif /* !HAVE_GTK2 */
71         : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data));
72   if (pb)
73     {
74       int w = gdk_pixbuf_get_width (pb);
75       int h = gdk_pixbuf_get_height (pb);
76       Pixmap pixmap = 0;
77
78       /* #### Note that this always uses the default colormap!  Morons!
79               Owen says that in Gnome 2.0, I should try using
80               gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead.
81               But I don't have Gnome 2.0 yet.
82        */
83       gdk_pixbuf_xlib_render_pixmap_and_mask (pb, &pixmap, mask_ret, 128);
84
85       if (!pixmap)
86         {
87           fprintf (stderr, "%s: out of memory (%d x %d)\n", progname, w, h);
88           exit (-1);
89         }
90       /* gdk_pixbuf_unref (pb);  -- #### does doing this free colors? */
91
92       if (width_ret)  *width_ret  = w;
93       if (height_ret) *height_ret = h;
94
95       return pixmap;
96     }
97   else if (filename)
98     {
99 #ifdef HAVE_GTK2
100       fprintf (stderr, "%s: %s\n", progname, gerr->message);
101       g_error_free (gerr);
102 #else /* !HAVE_GTK2 */
103       fprintf (stderr, "%s: unable to load %s\n", progname, filename);
104 #endif /* !HAVE_GTK2 */
105       exit (-1);
106     }
107   else
108     {
109       fprintf (stderr, "%s: unable to initialize built-in images\n", progname);
110       exit (-1);
111     }
112 }
113
114
115 #elif defined(HAVE_XPM)
116
117 #include <X11/Intrinsic.h>
118 #include <X11/Xutil.h>
119 #include <X11/xpm.h>
120
121 #ifdef HAVE_XMU
122 # ifndef VMS
123 #  include <X11/Xmu/Drawing.h>
124 #else  /* VMS */
125 #  include <Xmu/Drawing.h>
126 # endif /* VMS */
127 #endif
128
129 #undef countof
130 #define countof(x) (sizeof((x))/sizeof((*x)))
131
132
133 static int
134 handle_xpm_error (const char *filename, int status)
135 {
136   if (!filename) filename = "builtin";
137   switch (status)
138     {
139     case XpmSuccess:
140       return 0;
141       break;
142     case XpmColorError:
143       fprintf (stderr, "%s: %s: warning: color substitution performed\n",
144                progname, filename);
145       return 0;
146       break;
147     case XpmFileInvalid:
148       return 1;
149       break;
150     case XpmOpenFailed:
151       fprintf (stderr, "%s: %s: no such file\n", progname, filename);
152       break;
153     case XpmNoMemory:
154       fprintf (stderr, "%s: %s: out of memory\n", progname, filename);
155       break;
156     case XpmColorFailed:
157       fprintf (stderr, "%s: %s: color allocation failed\n",
158                progname, filename);
159       break;
160     default:
161       fprintf (stderr, "%s: %s: unknown XPM error %d\n", progname,
162                filename, status);
163       break;
164     }
165   exit (-1);
166 }
167
168
169 /* The libxpm version of this function...
170  */
171 static Pixmap
172 xpm_to_pixmap_1 (Display *dpy, Window window,
173                  int *width_ret, int *height_ret,
174                  Pixmap *mask_ret,
175                  const char *filename,
176                  char **xpm_data)
177 {
178   Pixmap pixmap = 0;
179   XpmAttributes xpmattrs;
180   XpmImage xpm_image;
181   XpmInfo xpm_info;
182   int status;
183   XWindowAttributes xgwa;
184   XGetWindowAttributes (dpy, window, &xgwa);
185
186   memset (&xpm_image, 0, sizeof(xpm_image));
187   memset (&xpm_info, 0, sizeof(xpm_info));
188
189   if (filename)
190     {
191       xpm_data = 0;
192       status = XpmReadFileToData ((char *) filename, &xpm_data);
193       if (handle_xpm_error (filename, status))
194         goto TRY_XBM;
195     }
196
197   xpmattrs.valuemask = 0;
198
199 # ifdef XpmCloseness
200   xpmattrs.valuemask |= XpmCloseness;
201   xpmattrs.closeness = 40000;
202 # endif
203 # ifdef XpmVisual
204   xpmattrs.valuemask |= XpmVisual;
205   xpmattrs.visual = xgwa.visual;
206 # endif
207 # ifdef XpmDepth
208   xpmattrs.valuemask |= XpmDepth;
209   xpmattrs.depth = xgwa.depth;
210 # endif
211 # ifdef XpmColormap
212   xpmattrs.valuemask |= XpmColormap;
213   xpmattrs.colormap = xgwa.colormap;
214 # endif
215
216   status = XpmCreatePixmapFromData (dpy, window, xpm_data,
217                                     &pixmap, mask_ret, &xpmattrs);
218   if (handle_xpm_error (filename, status))
219     pixmap = 0;
220   else
221     {
222       if (width_ret)  *width_ret  = xpmattrs.width;
223       if (height_ret) *height_ret = xpmattrs.height;
224     }
225
226  TRY_XBM:
227
228 #ifdef HAVE_XMU
229   if (! pixmap)
230     {
231       unsigned long fg = BlackPixelOfScreen (xgwa.screen);
232       unsigned long bg = WhitePixelOfScreen (xgwa.screen);
233       int xh, yh;
234       Pixmap b2;
235       pixmap = XmuLocateBitmapFile (xgwa.screen, filename,
236                                     0, 0, width_ret, height_ret, &xh, &yh);
237       if (! pixmap)
238         {
239           fprintf (stderr, "%s: couldn't find XBM %s\n", progname,
240                    filename);
241           exit (-1);
242         }
243       b2 = XmuCreatePixmapFromBitmap (dpy, window, pixmap,
244                                       *width_ret, *height_ret,
245                                       xgwa.depth, fg, bg);
246       XFreePixmap (dpy, pixmap);
247       pixmap = b2;
248
249       if (!pixmap)
250         {
251           fprintf (stderr, "%s: couldn't load XBM %s\n", progname, filename);
252           exit (-1);
253         }
254     }
255 #else  /* !XMU */
256     {
257       fprintf (stderr,
258                "%s: your vendor doesn't ship the standard Xmu library.\n",
259                progname);
260       fprintf (stderr, "\tWe can't load XBM files without it.\n");
261       exit (-1);
262     }
263 #endif /* !XMU */
264
265   return pixmap;
266 }
267
268 #else  /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
269
270 static Pixmap
271 xpm_to_pixmap_1 (Display *dpy, Window window,
272                  int *width_ret, int *height_ret,
273                  Pixmap *mask_ret,
274                  const char *filename,
275                  char **xpm_data)
276 {
277   fprintf(stderr, "%s: not compiled with XPM or Pixbuf support.\n", progname);
278   exit (-1);
279 }
280
281 #endif /* !HAVE_XPM */
282
283
284 Pixmap
285 xpm_data_to_pixmap (Display *dpy, Window window, char **xpm_data,
286                     int *width_ret, int *height_ret,
287                     Pixmap *mask_ret)
288 {
289   return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,
290                           0, xpm_data);
291 }
292
293
294 Pixmap
295 xpm_file_to_pixmap (Display *dpy, Window window, const char *filename,
296                     int *width_ret, int *height_ret,
297                     Pixmap *mask_ret)
298 {
299   return xpm_to_pixmap_1 (dpy, window, width_ret, height_ret, mask_ret,
300                           filename, 0);
301 }