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