+ GdkPixbuf *pb;
+ Display *dpy = DisplayOfScreen (screen);
+ unsigned int win_width, win_height;
+# ifdef HAVE_GTK2
+ GError *gerr = 0;
+# endif /* HAVE_GTK2 */
+
+ {
+ Window root;
+ int x, y;
+ unsigned int bw, d;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ screen = xgwa.screen;
+ XGetGeometry (dpy, drawable,
+ &root, &x, &y, &win_width, &win_height, &bw, &d);
+ }
+
+ gdk_pixbuf_xlib_init (dpy, screen_number (screen));
+# ifdef HAVE_GTK2
+ g_type_init();
+# else /* !HAVE_GTK2 */
+ xlib_rgb_init (dpy, screen);
+# endif /* !HAVE_GTK2 */
+
+ pb = gdk_pixbuf_new_from_file (filename
+# ifdef HAVE_GTK2
+ , &gerr
+# endif /* HAVE_GTK2 */
+ );
+
+ if (!pb)
+ {
+ fprintf (stderr, "%s: unable to load \"%s\"\n", progname, filename);
+# ifdef HAVE_GTK2
+ if (gerr && gerr->message && *gerr->message)
+ fprintf (stderr, "%s: reason: %s\n", progname, gerr->message);
+# endif /* HAVE_GTK2 */
+ return False;
+ }
+ else
+ {
+ int w = gdk_pixbuf_get_width (pb);
+ int h = gdk_pixbuf_get_height (pb);
+ int srcx, srcy, destx, desty, w2, h2;
+
+ compute_image_scaling (w, h, win_width, win_height, verbose_p,
+ &srcx, &srcy, &destx, &desty, &w2, &h2);
+ if (w != w2 || h != h2)
+ {
+ GdkPixbuf *pb2 = gdk_pixbuf_scale_simple (pb, w2, h2,
+ GDK_INTERP_BILINEAR);
+ if (pb2)
+ {
+ gdk_pixbuf_unref (pb);
+ pb = pb2;
+ w = w2;
+ h = h2;
+ }
+ else
+ fprintf (stderr, "%s: out of memory when scaling?\n", progname);
+ }
+
+ clear_drawable (screen, drawable);
+
+ /* #### Note that this always uses the default colormap! Morons!
+ Owen says that in Gnome 2.0, I should try using
+ gdk_pixbuf_render_pixmap_and_mask_for_colormap() instead.
+ But I haven't tried.
+ */
+ gdk_pixbuf_xlib_render_to_drawable_alpha (pb, drawable,
+ srcx, srcy, destx, desty,
+ w, h,
+ GDK_PIXBUF_ALPHA_FULL, 127,
+ XLIB_RGB_DITHER_NORMAL,
+ 0, 0);
+ XSync (dpy, False);
+ }
+
+ return True;
+}
+
+#endif /* HAVE_GDK_PIXBUF */
+
+
+
+#ifdef HAVE_JPEGLIB
+
+/* Allocates a colormap that makes a PseudoColor or DirectColor
+ visual behave like a TrueColor visual of the same depth.
+ */
+static void
+allocate_cubic_colormap (Screen *screen, Visual *visual, Colormap cmap,
+ Bool verbose_p)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ int nr, ng, nb, cells;
+ int r, g, b;
+ int depth;
+ XColor colors[4097];
+ int i;
+
+ depth = visual_depth (screen, visual);
+
+ switch (depth)
+ {
+ case 8: nr = 3; ng = 3; nb = 2; cells = 256; break;
+ case 12: nr = 4; ng = 4; nb = 4; cells = 4096; break;
+ default: abort(); break;
+ }
+
+ memset(colors, 0, sizeof(colors));
+ for (r = 0; r < (1 << nr); r++)
+ for (g = 0; g < (1 << ng); g++)
+ for (b = 0; b < (1 << nb); b++)
+ {
+ i = (r | (g << nr) | (b << (nr + ng)));
+ colors[i].pixel = i;
+ colors[i].flags = DoRed|DoGreen|DoBlue;
+ if (depth == 8)
+ {
+ colors[i].red = ((r << 13) | (r << 10) | (r << 7) |
+ (r << 4) | (r << 1));
+ colors[i].green = ((g << 13) | (g << 10) | (g << 7) |
+ (g << 4) | (g << 1));
+ colors[i].blue = ((b << 14) | (b << 12) | (b << 10) |
+ (b << 8) | (b << 6) | (b << 4) |
+ (b << 2) | b);
+ }
+ else
+ {
+ colors[i].red = (r << 12) | (r << 8) | (r << 4) | r;
+ colors[i].green = (g << 12) | (g << 8) | (g << 4) | g;
+ colors[i].blue = (b << 12) | (b << 8) | (b << 4) | b;
+ }
+ }
+
+ {
+ int j;
+ int allocated = 0;
+ int interleave = cells / 8; /* skip around, rather than allocating in
+ order, so that we get better coverage if
+ we can't allocated all of them. */
+ for (j = 0; j < interleave; j++)
+ for (i = 0; i < cells; i += interleave)
+ if (XAllocColor (dpy, cmap, &colors[i + j]))
+ allocated++;
+
+ if (verbose_p)
+ fprintf (stderr, "%s: allocated %d of %d colors for cubic map\n",
+ progname, allocated, cells);
+ }