+ float rw = (float) dest_w / src_w;
+ float rh = (float) dest_h / src_h;
+ float r = (rw < rh ? rw : rh);
+ int tw, th, pct;
+
+ /* If the window is a goofy aspect ratio, take a middle slice of
+ the image instead. */
+ if (dest_w > dest_h * 5 || dest_h > dest_w * 5)
+ {
+ double r2 = (dest_w > dest_h
+ ? dest_w / (double) dest_h
+ : dest_h / (double) dest_w);
+ r *= r2;
+ if (verbose_p)
+ fprintf (stderr, "%s: weird aspect: scaling by %.1f\n",
+ progname, r2);
+ }
+
+ tw = src_w * r;
+ th = src_h * r;
+ pct = (r * 100);
+
+#if 0
+ /* this optimization breaks things */
+ if (pct < 95 || pct > 105) /* don't scale if it's close */
+#endif
+ {
+ if (verbose_p)
+ fprintf (stderr, "%s: scaling image by %d%% (%dx%d -> %dx%d)\n",
+ progname, pct, src_w, src_h, tw, th);
+ src_w = tw;
+ src_h = th;
+ }
+ }
+
+ /* Center the image on the window/pixmap. */
+ srcx = 0;
+ srcy = 0;
+ destx = (dest_w - src_w) / 2;
+ desty = (dest_h - src_h) / 2;
+ if (destx < 0) srcx = -destx, destx = 0;
+ if (desty < 0) srcy = -desty, desty = 0;
+
+ /* if (dest_w < src_w) src_w = dest_w;
+ if (dest_h < src_h) src_h = dest_h; */
+
+ *scaled_w_ret = src_w;
+ *scaled_h_ret = src_h;
+ *scaled_from_x_ret = srcx;
+ *scaled_from_y_ret = srcy;
+ *scaled_to_x_ret = destx;
+ *scaled_to_y_ret = desty;
+
+ if (verbose_p)
+ fprintf (stderr, "%s: displaying %dx%d+%d+%d image at %d,%d in %dx%d.\n",
+ progname, src_w, src_h, srcx, srcy, destx, desty, dest_w, dest_h);
+}
+
+
+static void
+colorbars (Screen *screen, Visual *visual, Drawable drawable, Colormap cmap)
+{
+ Pixmap mask = 0;
+ unsigned long *pixels; /* ignored - unfreed */
+ int npixels;
+ Pixmap logo = xscreensaver_logo (screen, visual, drawable, cmap,
+ BlackPixelOfScreen (screen),
+ &pixels, &npixels, &mask, True);
+ draw_colorbars (screen, visual, drawable, cmap, 0, 0, 0, 0, logo, mask);
+ XFreePixmap (DisplayOfScreen (screen), logo);
+ XFreePixmap (DisplayOfScreen (screen), mask);
+}
+
+
+/* Scales an XImage, modifying it in place.
+ This doesn't do dithering or smoothing, so it might have artifacts.
+ If out of memory, returns False, and the XImage will have been
+ destroyed and freed.
+ */
+#if !defined(USE_EXTERNAL_SCREEN_GRABBER) || defined(HAVE_JPEGLIB)
+static Bool
+scale_ximage (Screen *screen, Visual *visual,
+ XImage *ximage, int new_width, int new_height)
+{
+ Display *dpy = DisplayOfScreen (screen);
+ int depth = visual_depth (screen, visual);
+ int x, y;
+ double xscale, yscale;
+
+ XImage *ximage2 = XCreateImage (dpy, visual, depth,
+ ZPixmap, 0, 0,
+ new_width, new_height, 8, 0);
+ ximage2->data = (char *) calloc (ximage2->height, ximage2->bytes_per_line);
+
+ if (!ximage2->data)
+ {
+ fprintf (stderr, "%s: out of memory scaling %dx%d image to %dx%d\n",
+ progname,
+ ximage->width, ximage->height,
+ ximage2->width, ximage2->height);
+ if (ximage->data) free (ximage->data);
+ if (ximage2->data) free (ximage2->data);
+ ximage->data = 0;
+ ximage2->data = 0;
+ XDestroyImage (ximage);
+ XDestroyImage (ximage2);
+ return False;
+ }
+
+ /* Brute force scaling... */
+ xscale = (double) ximage->width / ximage2->width;
+ yscale = (double) ximage->height / ximage2->height;
+ for (y = 0; y < ximage2->height; y++)
+ for (x = 0; x < ximage2->width; x++)
+ XPutPixel (ximage2, x, y,
+ XGetPixel (ximage, x * xscale, y * yscale));
+
+ free (ximage->data);
+ ximage->data = 0;
+
+ (*ximage) = (*ximage2);
+
+ ximage2->data = 0;
+ XDestroyImage (ximage2);
+
+ return True;
+}
+#endif /* !USE_EXTERNAL_SCREEN_GRABBER || HAVE_JPEGLIB */
+
+
+#ifdef HAVE_GDK_PIXBUF
+
+/* Reads the given image file and renders it on the Drawable, using GDK.
+ Returns False if it fails.
+ */
+static Bool
+read_file_gdk (Screen *screen, Window window, Drawable drawable,
+ const char *filename, Bool verbose_p,
+ XRectangle *geom_ret)
+{
+ GdkPixbuf *pb;
+ Display *dpy = DisplayOfScreen (screen);
+ unsigned int win_width, win_height, win_depth;
+# ifdef HAVE_GTK2
+ GError *gerr = 0;
+# endif /* HAVE_GTK2 */
+
+ /* Find the size of the Drawable. */
+ {
+ Window root;
+ int x, y;
+ unsigned int bw;
+ XGetGeometry (dpy, drawable,
+ &root, &x, &y, &win_width, &win_height, &bw, &win_depth);
+ }
+
+ gdk_pixbuf_xlib_init_with_depth (dpy, screen_number (screen), win_depth);
+# ifdef HAVE_GTK2
+# if !GLIB_CHECK_VERSION(2, 36 ,0)
+ g_type_init();