]> code.delx.au - gnu-emacs/blobdiff - src/image.c
Merge branch 'master' into cairo
[gnu-emacs] / src / image.c
index 4cba8863b888fb7a7b870cdf9ddf1c6aeb31ca3c..87029bfa1b0ea9c3ef751c7945927611093f5450 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for image support on window system.
 
-Copyright (C) 1989, 1992-2014 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -86,14 +86,12 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define x_defined_color w32_defined_color
 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
 
-/* Versions of libpng, libgif, and libjpeg that we were compiled with,
-   or -1 if no PNG/GIF support was compiled in.  This is tested by
-   w32-win.el to correctly set up the alist used to search for the
-   respective image libraries.  */
-Lisp_Object Qlibpng_version, Qlibgif_version, Qlibjpeg_version;
-
 #endif /* HAVE_NTGUI */
 
+#ifdef USE_CAIRO
+#undef COLOR_TABLE_SUPPORT
+#endif
+
 #ifdef HAVE_NS
 #undef COLOR_TABLE_SUPPORT
 
@@ -110,11 +108,6 @@ typedef struct ns_bitmap_record Bitmap_Record;
 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
 #endif /* HAVE_NS */
 
-
-/* The symbol `postscript' identifying images of this type.  */
-
-static Lisp_Object Qpostscript;
-
 static void x_disable_image (struct frame *, struct image *);
 static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
                               Lisp_Object);
@@ -126,8 +119,6 @@ static void free_color_table (void);
 static unsigned long *colors_in_color_table (int *n);
 #endif
 
-static Lisp_Object QCmax_width, QCmax_height;
-
 /* Code to deal with bitmaps.  Bitmaps are referenced by their bitmap
    id, which is just an int that this section returns.  Bitmaps are
    reference counted so they can be shared among frames.
@@ -246,7 +237,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
 #endif /* HAVE_NTGUI */
 
 #ifdef HAVE_NS
-  void *bitmap = ns_image_from_XBM (bits, width, height);
+  void *bitmap = ns_image_from_XBM (bits, width, height, 0, 0);
   if (!bitmap)
       return -1;
 #endif
@@ -527,7 +518,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
 
 #endif /* HAVE_X_WINDOWS */
 
-
 /***********************************************************************
                            Image types
  ***********************************************************************/
@@ -537,24 +527,6 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
 
 static struct image_type *image_types;
 
-/* The symbol `xbm' which is used as the type symbol for XBM images.  */
-
-static Lisp_Object Qxbm;
-
-/* Keywords.  */
-
-Lisp_Object QCascent, QCmargin, QCrelief;
-Lisp_Object QCconversion;
-static Lisp_Object QCheuristic_mask;
-static Lisp_Object QCcolor_symbols;
-static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
-static Lisp_Object QCcrop, QCrotation;
-
-/* Other symbols.  */
-
-static Lisp_Object Qcount, Qextension_data, Qdelay;
-static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
-
 /* Forward function prototypes.  */
 
 static struct image_type *lookup_image_type (Lisp_Object);
@@ -579,27 +551,29 @@ static struct image_type *
 define_image_type (struct image_type *type)
 {
   struct image_type *p = NULL;
-  Lisp_Object target_type = *type->type;
-  bool type_valid = 1;
+  int new_type = type->type;
+  bool type_valid = true;
 
   block_input ();
 
   for (p = image_types; p; p = p->next)
-    if (EQ (*p->type, target_type))
+    if (p->type == new_type)
       goto done;
 
   if (type->init)
     {
 #if defined HAVE_NTGUI && defined WINDOWSNT
       /* If we failed to load the library before, don't try again.  */
-      Lisp_Object tested = Fassq (target_type, Vlibrary_cache);
+      Lisp_Object tested = Fassq (builtin_lisp_symbol (new_type),
+                                 Vlibrary_cache);
       if (CONSP (tested) && NILP (XCDR (tested)))
-       type_valid = 0;
+       type_valid = false;
       else
 #endif
        {
          type_valid = type->init ();
-         CACHE_IMAGE_TYPE (target_type, type_valid ? Qt : Qnil);
+         CACHE_IMAGE_TYPE (builtin_lisp_symbol (new_type),
+                           type_valid ? Qt : Qnil);
        }
     }
 
@@ -1048,6 +1022,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
   /* We're about to display IMG, so set its timestamp to `now'.  */
   img->timestamp = current_timespec ();
 
+#ifndef USE_CAIRO
   /* If IMG doesn't have a pixmap yet, load it now, using the image
      type dependent loader function.  */
   if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
@@ -1061,6 +1036,7 @@ prepare_image_for_display (struct frame *f, struct image *img)
       unblock_input ();
     }
 #endif
+#endif
 }
 
 
@@ -1107,6 +1083,54 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
   return ascent;
 }
 
+#ifdef USE_CAIRO
+static uint32_t
+xcolor_to_argb32 (XColor xc)
+{
+  return (0xff << 24) | ((xc.red / 256) << 16)
+      | ((xc.green / 256) << 8) | (xc.blue / 256);
+}
+
+static uint32_t
+get_spec_bg_or_alpha_as_argb (struct image *img,
+                              struct frame *f)
+{
+  uint32_t bgcolor = 0;
+  XColor xbgcolor;
+  Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL);
+
+  if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f),
+                                   FRAME_X_COLORMAP (f),
+                                   SSDATA (bg),
+                                   &xbgcolor))
+    bgcolor = xcolor_to_argb32 (xbgcolor);
+
+  return bgcolor;
+}
+
+static void
+create_cairo_image_surface (struct image *img,
+                            unsigned char *data,
+                            int width,
+                            int height)
+{
+  cairo_surface_t *surface;
+  cairo_format_t format = CAIRO_FORMAT_ARGB32;
+  int stride = cairo_format_stride_for_width (format, width);
+  surface = cairo_image_surface_create_for_data (data,
+                                                 format,
+                                                 width,
+                                                 height,
+                                                 stride);
+  img->width = width;
+  img->height = height;
+  img->cr_data = surface;
+  img->cr_data2 = data;
+  img->pixmap = 0;
+}
+#endif
+
+
 \f
 /* Image background colors.  */
 
@@ -1328,6 +1352,11 @@ static void
 x_clear_image (struct frame *f, struct image *img)
 {
   block_input ();
+#ifdef USE_CAIRO
+  if (img->cr_data)
+    cairo_surface_destroy ((cairo_surface_t *)img->cr_data);
+  if (img->cr_data2) xfree (img->cr_data2);
+#endif
   x_clear_image_1 (f, img,
                   CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
   unblock_input ();
@@ -1777,7 +1806,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
 
          /* Do image transformations and compute masks, unless we
             don't have the image yet.  */
-         if (!EQ (*img->type->type, Qpostscript))
+         if (!EQ (builtin_lisp_symbol (img->type->type), Qpostscript))
            postprocess_image (f, img);
        }
 
@@ -2362,7 +2391,7 @@ static const struct image_keyword xbm_format[XBM_LAST] =
 
 static struct image_type xbm_type =
 {
-  &Qxbm,
+  SYMBOL_INDEX (Qxbm),
   xbm_image_p,
   xbm_load,
   x_clear_image,
@@ -2677,7 +2706,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
     convert_mono_to_color_image (f, img, fg, bg);
 
 #elif defined (HAVE_NS)
-  img->pixmap = ns_image_from_XBM (data, img->width, img->height);
+  img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg);
 
 #else
   img->pixmap =
@@ -3121,9 +3150,6 @@ static bool xpm_load (struct frame *f, struct image *img);
 #endif /* HAVE_XPM */
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
-/* The symbol `xpm' identifying XPM-format images.  */
-
-static Lisp_Object Qxpm;
 
 /* Indices of image specification fields in xpm_format, below.  */
 
@@ -3171,7 +3197,7 @@ static bool init_xpm_functions (void);
 
 static struct image_type xpm_type =
 {
-  &Qxpm,
+  SYMBOL_INDEX (Qxpm),
   xpm_image_p,
   xpm_load,
   x_clear_image,
@@ -3186,9 +3212,11 @@ static struct image_type xpm_type =
    color allocation failures more gracefully than the ones on the XPM
    lib.  */
 
+#ifndef USE_CAIRO
 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
 #define ALLOC_XPM_COLORS
 #endif
+#endif /* USE_CAIRO */
 #endif /* HAVE_X_WINDOWS */
 
 #ifdef ALLOC_XPM_COLORS
@@ -3649,6 +3677,44 @@ xpm_load (struct frame *f, struct image *img)
 #endif /* HAVE_NTGUI */
     }
 
+#ifdef USE_CAIRO
+  // Load very specific Xpm:s.
+  if (rc == XpmSuccess
+      && img->ximg->format == ZPixmap
+      && img->ximg->bits_per_pixel == 32
+      && (! img->mask_img || img->mask_img->bits_per_pixel == 1))
+    {
+      int width = img->ximg->width;
+      int height = img->ximg->height;
+      unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+      int i;
+      uint32_t *od = (uint32_t *)data;
+      uint32_t *id = (uint32_t *)img->ximg->data;
+      unsigned char *mid = img->mask_img ? img->mask_img->data : 0;
+      uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
+
+      for (i = 0; i < height; ++i)
+        {
+          int k;
+          for (k = 0; k < width; ++k)
+            {
+              int idx = i * img->ximg->bytes_per_line/4 + k;
+              int maskidx = mid ? i * img->mask_img->bytes_per_line + k/8 : 0;
+              int mask = mid ? mid[maskidx] & (1 << (k % 8)) : 1;
+
+              if (mask) od[idx] = id[idx] + 0xff000000; // ff => full alpha
+              else od[idx] = bgcolor;
+            }
+        }
+
+      create_cairo_image_surface (img, data, width, height);
+    }
+  else
+    {
+      rc = XpmFileInvalid;
+      x_clear_image (f, img);
+    }
+#else
 #ifdef HAVE_X_WINDOWS
   if (rc == XpmSuccess)
     {
@@ -3674,6 +3740,7 @@ xpm_load (struct frame *f, struct image *img)
        }
     }
 #endif
+#endif /* ! USE_CAIRO */
 
   if (rc == XpmSuccess)
     {
@@ -4455,7 +4522,7 @@ lookup_pixel_color (struct frame *f, unsigned long pixel)
       Colormap cmap;
       bool rc;
 
-      if (ct_colors_allocated_max <= ct_colors_allocated)
+      if (ct_colors_allocated >= ct_colors_allocated_max)
        return FRAME_FOREGROUND_PIXEL (f);
 
 #ifdef HAVE_X_WINDOWS
@@ -4586,7 +4653,7 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
   HGDIOBJ prev;
 #endif /* HAVE_NTGUI */
 
-  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+  if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width)
     memory_full (SIZE_MAX);
   colors = xmalloc (sizeof *colors * img->width * img->height);
 
@@ -4727,7 +4794,7 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus
 
 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
-  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+  if (img->height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width)
     memory_full (SIZE_MAX);
   new = xmalloc (sizeof *new * img->width * img->height);
 
@@ -4996,7 +5063,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
       if (i == 3 && NILP (how))
        {
          char color_name[30];
-         sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
+         sprintf (color_name, "#%04x%04x%04x",
+                  rgb[0] + 0u, rgb[1] + 0u, rgb[2] + 0u);
          bg = (
 #ifdef HAVE_NTGUI
                0x00ffffff & /* Filter out palette info.  */
@@ -5059,10 +5127,6 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
 static bool pbm_image_p (Lisp_Object object);
 static bool pbm_load (struct frame *f, struct image *img);
 
-/* The symbol `pbm' identifying images of this type.  */
-
-static Lisp_Object Qpbm;
-
 /* Indices of image specification fields in gs_format, below.  */
 
 enum pbm_keyword_index
@@ -5103,7 +5167,7 @@ static const struct image_keyword pbm_format[PBM_LAST] =
 
 static struct image_type pbm_type =
 {
-  &Qpbm,
+  SYMBOL_INDEX (Qpbm),
   pbm_image_p,
   pbm_load,
   x_clear_image,
@@ -5183,12 +5247,17 @@ pbm_load (struct frame *f, struct image *img)
   bool raw_p;
   int x, y;
   int width, height, max_color_idx = 0;
-  XImagePtr ximg;
   Lisp_Object file, specified_file;
   enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
   unsigned char *contents = NULL;
   unsigned char *end, *p;
   ptrdiff_t size;
+#ifdef USE_CAIRO
+  unsigned char *data = 0;
+  uint32_t *dataptr;
+#else
+  XImagePtr ximg;
+#endif
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
 
@@ -5270,6 +5339,11 @@ pbm_load (struct frame *f, struct image *img)
   width = pbm_scan_number (&p, end);
   height = pbm_scan_number (&p, end);
 
+#ifdef USE_CAIRO
+  data = (unsigned char *) xmalloc (width * height * 4);
+  dataptr = (uint32_t *) data;
+#endif
+
   if (type != PBM_MONO)
     {
       max_color_idx = pbm_scan_number (&p, end);
@@ -5286,8 +5360,10 @@ pbm_load (struct frame *f, struct image *img)
       goto error;
     }
 
+#ifndef USE_CAIRO
   if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
     goto error;
+#endif
 
   /* Initialize the color hash table.  */
   init_color_table ();
@@ -5298,12 +5374,34 @@ pbm_load (struct frame *f, struct image *img)
       struct image_keyword fmt[PBM_LAST];
       unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
       unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
-
+#ifdef USE_CAIRO
+      XColor xfg, xbg;
+      int fga32, bga32;
+#endif
       /* Parse the image specification.  */
       memcpy (fmt, pbm_format, sizeof fmt);
       parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
 
       /* Get foreground and background colors, maybe allocate colors.  */
+#ifdef USE_CAIRO
+      if (! fmt[PBM_FOREGROUND].count
+          || ! STRINGP (fmt[PBM_FOREGROUND].value)
+          || ! x_defined_color (f, SSDATA (fmt[PBM_FOREGROUND].value), &xfg, 0))
+        {
+          xfg.pixel = fg;
+          x_query_color (f, &xfg);
+        }
+      fga32 = xcolor_to_argb32 (xfg);
+
+      if (! fmt[PBM_BACKGROUND].count
+          || ! STRINGP (fmt[PBM_BACKGROUND].value)
+          || ! x_defined_color (f, SSDATA (fmt[PBM_BACKGROUND].value), &xbg, 0))
+       {
+          xbg.pixel = bg;
+          x_query_color (f, &xbg);
+       }
+      bga32 = xcolor_to_argb32 (xbg);
+#else
       if (fmt[PBM_FOREGROUND].count
          && STRINGP (fmt[PBM_FOREGROUND].value))
        fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
@@ -5314,6 +5412,7 @@ pbm_load (struct frame *f, struct image *img)
          img->background = bg;
          img->background_valid = 1;
        }
+#endif
 
       for (y = 0; y < height; ++y)
        for (x = 0; x < width; ++x)
@@ -5324,7 +5423,11 @@ pbm_load (struct frame *f, struct image *img)
                  {
                    if (p >= end)
                      {
+#ifdef USE_CAIRO
+                        xfree (data);
+#else
                        x_destroy_x_image (ximg);
+#endif
                        x_clear_image (f, img);
                        image_error ("Invalid image size in image `%s'",
                                     img->spec, Qnil);
@@ -5338,7 +5441,11 @@ pbm_load (struct frame *f, struct image *img)
            else
              g = pbm_scan_number (&p, end);
 
+#ifdef USE_CAIRO
+            *dataptr++ = g ? fga32 : bga32;
+#else
            XPutPixel (ximg, x, y, g ? fg : bg);
+#endif
          }
     }
   else
@@ -5351,7 +5458,11 @@ pbm_load (struct frame *f, struct image *img)
 
       if (raw_p && p + expected_size > end)
        {
+#ifdef USE_CAIRO
+          xfree (data);
+#else
          x_destroy_x_image (ximg);
+#endif
          x_clear_image (f, img);
          image_error ("Invalid image size in image `%s'",
                       img->spec, Qnil);
@@ -5392,18 +5503,29 @@ pbm_load (struct frame *f, struct image *img)
 
            if (r < 0 || g < 0 || b < 0)
              {
+#ifdef USE_CAIRO
+                xfree (data);
+#else
                x_destroy_x_image (ximg);
+#endif
                image_error ("Invalid pixel value in image `%s'",
                             img->spec, Qnil);
                goto error;
              }
 
+#ifdef USE_CAIRO
+           r = (double) r * 255 / max_color_idx;
+           g = (double) g * 255 / max_color_idx;
+           b = (double) b * 255 / max_color_idx;
+            *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
            /* RGB values are now in the range 0..max_color_idx.
               Scale this to the range 0..0xffff supported by X.  */
            r = (double) r * 65535 / max_color_idx;
            g = (double) g * 65535 / max_color_idx;
            b = (double) b * 65535 / max_color_idx;
            XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+#endif
          }
     }
 
@@ -5419,12 +5541,16 @@ pbm_load (struct frame *f, struct image *img)
 
   /* Maybe fill in the background field while we have ximg handy.  */
 
+#ifdef USE_CAIRO
+  create_cairo_image_surface (img, data, width, height);
+#else
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     /* Casting avoids a GCC warning.  */
     IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
+#endif
 
   /* X and W32 versions did it here, MAC version above.  ++kfs
      img->width = width;
@@ -5439,17 +5565,13 @@ pbm_load (struct frame *f, struct image *img)
                                 PNG
  ***********************************************************************/
 
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
 
 /* Function prototypes.  */
 
 static bool png_image_p (Lisp_Object object);
 static bool png_load (struct frame *f, struct image *img);
 
-/* The symbol `png' identifying images of this type.  */
-
-static Lisp_Object Qpng;
-
 /* Indices of image specification fields in png_format, below.  */
 
 enum png_keyword_index
@@ -5494,7 +5616,7 @@ static bool init_png_functions (void);
 
 static struct image_type png_type =
 {
-  &Qpng,
+  SYMBOL_INDEX (Qpng),
   png_image_p,
   png_load,
   x_clear_image,
@@ -5517,7 +5639,7 @@ png_image_p (Lisp_Object object)
   return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
 }
 
-#endif /* HAVE_PNG || HAVE_NS */
+#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
 
 
 #if defined HAVE_PNG && !defined HAVE_NS
@@ -5752,7 +5874,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   Lisp_Object specified_data;
   int x, y;
   ptrdiff_t i;
-  XImagePtr ximg, mask_img = NULL;
   png_struct *png_ptr;
   png_info *info_ptr = NULL, *end_info = NULL;
   FILE *fp = NULL;
@@ -5766,9 +5887,17 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   bool transparent_p;
   struct png_memory_storage tbr;  /* Data to be read */
 
+#ifdef USE_CAIRO
+  unsigned char *data = 0;
+  uint32_t *dataptr;
+#else
+  XImagePtr ximg, mask_img = NULL;
+#endif
+
   /* Find out what file to load.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
+  IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
 
   if (NILP (specified_data))
     {
@@ -5865,6 +5994,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
   /* Silence a bogus diagnostic; see GCC bug 54561.  */
   IF_LINT (fp = c->fp);
+  IF_LINT (specified_data = specified_data_volatile);
 
   /* Read image info.  */
   if (!NILP (specified_data))
@@ -5884,10 +6014,12 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       goto error;
     }
 
+#ifndef USE_CAIRO
   /* Create the X image and pixmap now, so that the work below can be
      omitted if the image is too large for X.  */
   if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
     goto error;
+#endif
 
   /* If image contains simply transparency data, we prefer to
      construct a clipping mask.  */
@@ -5957,8 +6089,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   row_bytes = png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
-  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
-      || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
+  if (height > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows
+      || row_bytes > min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height)
     memory_full (SIZE_MAX);
   c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
   c->rows = rows = xmalloc (height * sizeof *rows);
@@ -5974,6 +6106,10 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       c->fp = NULL;
     }
 
+#ifdef USE_CAIRO
+  data = (unsigned char *) xmalloc (width * height * 4);
+  dataptr = (uint32_t *) data;
+#else
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -5985,6 +6121,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
       goto error;
     }
+#endif
 
   /* Fill the X image and mask from PNG data.  */
   init_color_table ();
@@ -5997,6 +6134,14 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
        {
          int r, g, b;
 
+#ifdef USE_CAIRO
+          int a = 0xff;
+         r = *p++;
+         g = *p++;
+         b = *p++;
+          if (channels == 4) a = *p++;
+          *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
+#else
          r = *p++ << 8;
          g = *p++ << 8;
          b = *p++ << 8;
@@ -6023,6 +6168,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
                XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
              ++p;
            }
+#endif
        }
     }
 
@@ -6052,6 +6198,9 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   img->width = width;
   img->height = height;
 
+#ifdef USE_CAIRO
+  create_cairo_image_surface (img, data, width, height);
+#else
   /* Maybe fill in the background field while we have ximg handy.
      Casting avoids a GCC warning.  */
   IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
@@ -6068,6 +6217,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
       image_put_x_image (f, img, mask_img, 1);
     }
+#endif
 
   return 1;
 }
@@ -6089,6 +6239,7 @@ png_load (struct frame *f, struct image *img)
                         image_spec_value (img->spec, QCdata, NULL));
 }
 
+
 #endif /* HAVE_NS */
 
 
@@ -6102,10 +6253,6 @@ png_load (struct frame *f, struct image *img)
 static bool jpeg_image_p (Lisp_Object object);
 static bool jpeg_load (struct frame *f, struct image *img);
 
-/* The symbol `jpeg' identifying images of this type.  */
-
-static Lisp_Object Qjpeg;
-
 /* Indices of image specification fields in gs_format, below.  */
 
 enum jpeg_keyword_index
@@ -6150,7 +6297,7 @@ static bool init_jpeg_functions (void);
 
 static struct image_type jpeg_type =
 {
-  &Qjpeg,
+  SYMBOL_INDEX (Qjpeg),
   jpeg_image_p,
   jpeg_load,
   x_clear_image,
@@ -6504,13 +6651,17 @@ jpeg_load_body (struct frame *f, struct image *img,
   FILE * IF_LINT (volatile) fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
-  XImagePtr ximg = NULL;
   unsigned long *colors;
   int width, height;
+  int i, ir, ig, ib;
+#ifndef USE_CAIRO
+  XImagePtr ximg = NULL;
+#endif
 
   /* Open the JPEG file.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
+  IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
 
   if (NILP (specified_data))
     {
@@ -6565,13 +6716,17 @@ jpeg_load_body (struct frame *f, struct image *img,
       jpeg_destroy_decompress (&mgr->cinfo);
 
       /* If we already have an XImage, free that.  */
+#ifndef USE_CAIRO
       x_destroy_x_image (ximg);
-
+#endif
       /* Free pixmap and colors.  */
       x_clear_image (f, img);
       return 0;
     }
 
+  /* Silence a bogus diagnostic; see GCC bug 54561.  */
+  IF_LINT (specified_data = specified_data_volatile);
+
   /* Create the JPEG decompression object.  Let it read from fp.
         Read the JPEG image header.  */
   jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
@@ -6597,12 +6752,14 @@ jpeg_load_body (struct frame *f, struct image *img,
       sys_longjmp (mgr->setjmp_buffer, 1);
     }
 
+#ifndef USE_CAIRO
   /* Create X image and pixmap.  */
   if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
     {
       mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
       sys_longjmp (mgr->setjmp_buffer, 1);
     }
+#endif
 
   /* Allocate colors.  When color quantization is used,
      mgr->cinfo.actual_number_of_colors has been set with the number of
@@ -6611,8 +6768,6 @@ jpeg_load_body (struct frame *f, struct image *img,
      No more than 255 colors will be generated.  */
   USE_SAFE_ALLOCA;
   {
-    int i, ir, ig, ib;
-
     if (mgr->cinfo.out_color_components > 2)
       ir = 0, ig = 1, ib = 2;
     else if (mgr->cinfo.out_color_components > 1)
@@ -6620,6 +6775,7 @@ jpeg_load_body (struct frame *f, struct image *img,
     else
       ir = 0, ig = 0, ib = 0;
 
+#ifndef CAIRO
     /* Use the color table mechanism because it handles colors that
        cannot be allocated nicely.  Such colors will be replaced with
        a default color, and we don't have to care about which colors
@@ -6636,6 +6792,7 @@ jpeg_load_body (struct frame *f, struct image *img,
        int b = mgr->cinfo.colormap[ib][i] << 8;
        colors[i] = lookup_rgb_color (f, r, g, b);
       }
+#endif
 
 #ifdef COLOR_TABLE_SUPPORT
     /* Remember those colors actually allocated.  */
@@ -6648,12 +6805,36 @@ jpeg_load_body (struct frame *f, struct image *img,
   row_stride = width * mgr->cinfo.output_components;
   buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
                                         JPOOL_IMAGE, row_stride, 1);
+#ifdef USE_CAIRO
+  {
+    unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+    uint32_t *dataptr = (uint32_t *) data;
+    int r, g, b;
+
+    for (y = 0; y < height; ++y)
+      {
+        jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
+
+        for (x = 0; x < width; ++x)
+          {
+            i = buffer[0][x];
+            r = mgr->cinfo.colormap[ir][i];
+            g = mgr->cinfo.colormap[ig][i];
+            b = mgr->cinfo.colormap[ib][i];
+            *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+          }
+      }
+
+    create_cairo_image_surface (img, data, width, height);
+  }
+#else
   for (y = 0; y < height; ++y)
     {
       jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
       for (x = 0; x < mgr->cinfo.output_width; ++x)
        XPutPixel (ximg, x, y, colors[buffer[0][x]]);
     }
+#endif
 
   /* Clean up.  */
   jpeg_finish_decompress (&mgr->cinfo);
@@ -6661,6 +6842,7 @@ jpeg_load_body (struct frame *f, struct image *img,
   if (fp)
     fclose (fp);
 
+#ifndef USE_CAIRO
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     /* Casting avoids a GCC warning.  */
@@ -6668,6 +6850,7 @@ jpeg_load_body (struct frame *f, struct image *img,
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
+#endif
   SAFE_FREE ();
   return 1;
 }
@@ -6704,10 +6887,6 @@ jpeg_load (struct frame *f, struct image *img)
 static bool tiff_image_p (Lisp_Object object);
 static bool tiff_load (struct frame *f, struct image *img);
 
-/* The symbol `tiff' identifying images of this type.  */
-
-static Lisp_Object Qtiff;
-
 /* Indices of image specification fields in tiff_format, below.  */
 
 enum tiff_keyword_index
@@ -6754,7 +6933,7 @@ static bool init_tiff_functions (void);
 
 static struct image_type tiff_type =
 {
-  &Qtiff,
+  SYMBOL_INDEX (Qtiff),
   tiff_image_p,
   tiff_load,
   x_clear_image,
@@ -7104,6 +7283,29 @@ tiff_load (struct frame *f, struct image *img)
       return 0;
     }
 
+#ifdef USE_CAIRO
+  {
+    unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+    uint32_t *dataptr = (uint32_t *) data;
+    int r, g, b, a;
+
+    for (y = 0; y < height; ++y)
+      {
+        uint32 *row = buf + (height - 1 - y) * width;
+        for (x = 0; x < width; ++x)
+          {
+            uint32 abgr = row[x];
+            int r = TIFFGetR (abgr);
+            int g = TIFFGetG (abgr);
+            int b = TIFFGetB (abgr);
+            int a = TIFFGetA (abgr);
+            *dataptr++ = (a << 24) | (r << 16) | (g << 8) | b;
+          }
+      }
+
+    create_cairo_image_surface (img, data, width, height);
+  }
+#else
   /* Initialize the color table.  */
   init_color_table ();
 
@@ -7138,8 +7340,10 @@ tiff_load (struct frame *f, struct image *img)
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
-  xfree (buf);
 
+#endif /* ! USE_CAIRO */
+
+  xfree (buf);
   return 1;
 }
 
@@ -7167,10 +7371,6 @@ static bool gif_image_p (Lisp_Object object);
 static bool gif_load (struct frame *f, struct image *img);
 static void gif_clear_image (struct frame *f, struct image *img);
 
-/* The symbol `gif' identifying images of this type.  */
-
-static Lisp_Object Qgif;
-
 /* Indices of image specification fields in gif_format, below.  */
 
 enum gif_keyword_index
@@ -7217,7 +7417,7 @@ static bool init_gif_functions (void);
 
 static struct image_type gif_type =
 {
-  &Qgif,
+  SYMBOL_INDEX (Qgif),
   gif_image_p,
   gif_load,
   gif_clear_image,
@@ -7287,7 +7487,7 @@ gif_image_p (Lisp_Object object)
 # ifdef WINDOWSNT
 
 /* GIF library details.  */
-#  if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
+#  if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
 DEF_DLL_FN (int, DGifCloseFile, (GifFileType *, int *));
 #   else
 DEF_DLL_FN (int, DGifCloseFile, (GifFileType *));
@@ -7368,7 +7568,7 @@ gif_close (GifFileType *gif, int *err)
 {
   int retval;
 
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
+#if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
   retval = DGifCloseFile (gif, err);
 #else
   retval = DGifCloseFile (gif);
@@ -7393,7 +7593,6 @@ gif_load (struct frame *f, struct image *img)
 {
   Lisp_Object file;
   int rc, width, height, x, y, i, j;
-  XImagePtr ximg;
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
@@ -7405,6 +7604,12 @@ gif_load (struct frame *f, struct image *img)
   EMACS_INT idx;
   int gif_err;
 
+#ifdef USE_CAIRO
+  unsigned char *data = 0;
+#else
+  XImagePtr ximg;
+#endif
+
   if (NILP (specified_data))
     {
       file = x_find_image_file (specified_file);
@@ -7523,7 +7728,7 @@ gif_load (struct frame *f, struct image *img)
       int subimg_height = subimage->ImageDesc.Height;
       int subimg_top = subimage->ImageDesc.Top;
       int subimg_left = subimage->ImageDesc.Left;
-      if (! (0 <= subimg_width && 0 <= subimg_height
+      if (! (subimg_width >= 0 && subimg_height >= 0
             && 0 <= subimg_top && subimg_top <= height - subimg_height
             && 0 <= subimg_left && subimg_left <= width - subimg_width))
        {
@@ -7533,6 +7738,25 @@ gif_load (struct frame *f, struct image *img)
        }
     }
 
+#ifdef USE_CAIRO
+  /* xzalloc so data is zero => transparent */
+  data = (unsigned char *) xzalloc (width * height * 4);
+  if (STRINGP (specified_bg))
+    {
+      XColor color;
+      if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
+        {
+          uint32_t *dataptr = (uint32_t *)data;
+          int r = color.red/256;
+          int g = color.green/256;
+          int b = color.blue/256;
+
+          for (y = 0; y < height; ++y)
+            for (x = 0; x < width; ++x)
+              *dataptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
+        }
+    }
+#else
   /* Create the X image and pixmap.  */
   if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
     {
@@ -7559,6 +7783,7 @@ gif_load (struct frame *f, struct image *img)
       for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
+#endif
 
   /* Read the GIF image into the X image.   */
 
@@ -7613,12 +7838,14 @@ gif_load (struct frame *f, struct image *img)
       if (disposal == 0)
        disposal = 1;
 
-      /* Allocate subimage colors.  */
-      memset (pixel_colors, 0, sizeof pixel_colors);
       gif_color_map = subimage->ImageDesc.ColorMap;
       if (!gif_color_map)
        gif_color_map = gif->SColorMap;
 
+#ifndef USE_CAIRO
+      /* Allocate subimage colors.  */
+      memset (pixel_colors, 0, sizeof pixel_colors);
+
       if (gif_color_map)
        for (i = 0; i < gif_color_map->ColorCount; ++i)
          {
@@ -7633,6 +7860,7 @@ gif_load (struct frame *f, struct image *img)
                pixel_colors[i] = lookup_rgb_color (f, r, g, b);
              }
          }
+#endif
 
       /* Apply the pixel values.  */
       if (GIFLIB_MAJOR < 5 && gif->SavedImages[j].ImageDesc.Interlace)
@@ -7650,20 +7878,47 @@ gif_load (struct frame *f, struct image *img)
                {
                  int c = raster[y * subimg_width + x];
                  if (transparency_color_index != c || disposal != 1)
-                   XPutPixel (ximg, x + subimg_left, row + subimg_top,
-                              pixel_colors[c]);
+                    {
+#ifdef USE_CAIRO
+                      uint32_t *dataptr =
+                        ((uint32_t*)data + ((row + subimg_top) * subimg_width
+                                            + x + subimg_left));
+                      int r = gif_color_map->Colors[c].Red;
+                      int g = gif_color_map->Colors[c].Green;
+                      int b = gif_color_map->Colors[c].Blue;
+
+                      if (transparency_color_index != c)
+                        *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
+                      XPutPixel (ximg, x + subimg_left, row + subimg_top,
+                                 pixel_colors[c]);
+#endif
+                    }
                }
            }
        }
       else
        {
-         for (y = 0; y < subimg_height; ++y)
+          for (y = 0; y < subimg_height; ++y)
            for (x = 0; x < subimg_width; ++x)
              {
                int c = raster[y * subimg_width + x];
                if (transparency_color_index != c || disposal != 1)
-                 XPutPixel (ximg, x + subimg_left, y + subimg_top,
-                            pixel_colors[c]);
+                  {
+#ifdef USE_CAIRO
+                    uint32_t *dataptr =
+                      ((uint32_t*)data + ((y + subimg_top) * subimg_width
+                                          + x + subimg_left));
+                    int r = gif_color_map->Colors[c].Red;
+                    int g = gif_color_map->Colors[c].Green;
+                    int b = gif_color_map->Colors[c].Blue;
+                    if (transparency_color_index != c)
+                      *dataptr = (0xff << 24) | (r << 16) | (g << 8) | b;
+#else
+                    XPutPixel (ximg, x + subimg_left, y + subimg_top,
+                               pixel_colors[c]);
+#endif
+                  }
              }
        }
     }
@@ -7720,6 +7975,9 @@ gif_load (struct frame *f, struct image *img)
 #endif
     }
 
+#ifdef USE_CAIRO
+  create_cairo_image_surface (img, data, width, height);
+#else
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     /* Casting avoids a GCC warning.  */
@@ -7727,6 +7985,7 @@ gif_load (struct frame *f, struct image *img)
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
+#endif
 
   return 1;
 }
@@ -7841,8 +8100,6 @@ compute_image_size (size_t width, size_t height,
   *d_height = desired_height;
 }
 
-static Lisp_Object Qimagemagick;
-
 static bool imagemagick_image_p (Lisp_Object);
 static bool imagemagick_load (struct frame *, struct image *);
 static void imagemagick_clear_image (struct frame *, struct image *);
@@ -7906,7 +8163,7 @@ static bool init_imagemagick_functions (void);
 
 static struct image_type imagemagick_type =
   {
-    &Qimagemagick,
+    SYMBOL_INDEX (Qimagemagick),
     imagemagick_image_p,
     imagemagick_load,
     imagemagick_clear_image,
@@ -8632,10 +8889,6 @@ static bool svg_load (struct frame *f, struct image *img);
 static bool svg_load_image (struct frame *, struct image *,
                            unsigned char *, ptrdiff_t, char *);
 
-/* The symbol `svg' identifying images of this type. */
-
-static Lisp_Object Qsvg;
-
 /* Indices of image specification fields in svg_format, below.  */
 
 enum svg_keyword_index
@@ -8682,7 +8935,7 @@ static bool init_svg_functions (void);
 
 static struct image_type svg_type =
 {
-  &Qsvg,
+  SYMBOL_INDEX (Qsvg),
   svg_image_p,
   svg_load,
   x_clear_image,
@@ -8737,8 +8990,6 @@ DEF_DLL_FN (void, g_type_init, (void));
 DEF_DLL_FN (void, g_object_unref, (gpointer));
 DEF_DLL_FN (void, g_error_free, (GError *));
 
-Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
-
 static bool
 init_svg_functions (void)
 {
@@ -8954,6 +9205,37 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   eassert (gdk_pixbuf_get_has_alpha (pixbuf));
   eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
 
+#ifdef USE_CAIRO
+  {
+    unsigned char *data = (unsigned char *) xmalloc (width*height*4);
+    int y;
+    uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
+
+    for (y = 0; y < height; ++y)
+      {
+        const guchar *iconptr = pixels + y * rowstride;
+        uint32_t *dataptr = (uint32_t *) (data + y * rowstride);
+        int x;
+
+        for (x = 0; x < width; ++x)
+          {
+            if (iconptr[3] == 0)
+              *dataptr = bgcolor;
+            else
+              *dataptr = (iconptr[0] << 16)
+                | (iconptr[1] << 8)
+                | iconptr[2]
+                | (iconptr[3] << 24);
+
+            iconptr += 4;
+            ++dataptr;
+          }
+      }
+
+    create_cairo_image_surface (img, data, width, height);
+    g_object_unref (pixbuf);
+  }
+#else
   /* Try to create a x pixmap to hold the svg pixmap.  */
   if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
     {
@@ -9025,6 +9307,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
 
   /* Put ximg into the image.  */
   image_put_x_image (f, img, ximg, 0);
+#endif /* ! USE_CAIRO */
 
   return 1;
 
@@ -9056,10 +9339,6 @@ static bool gs_image_p (Lisp_Object object);
 static bool gs_load (struct frame *f, struct image *img);
 static void gs_clear_image (struct frame *f, struct image *img);
 
-/* Keyword symbols.  */
-
-static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
-
 /* Indices of image specification fields in gs_format, below.  */
 
 enum gs_keyword_index
@@ -9104,7 +9383,7 @@ static const struct image_keyword gs_format[GS_LAST] =
 
 static struct image_type gs_type =
 {
-  &Qpostscript,
+  SYMBOL_INDEX (Qpostscript),
   gs_image_p,
   gs_load,
   gs_clear_image,
@@ -9296,15 +9575,16 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
          /* For each pixel of the image, look its color up in the
             color table.  After having done so, the color table will
             contain an entry for each color used by the image.  */
+#ifdef COLOR_TABLE_SUPPORT
          for (y = 0; y < img->height; ++y)
            for (x = 0; x < img->width; ++x)
              {
                unsigned long pixel = XGetPixel (ximg, x, y);
+
                lookup_pixel_color (f, pixel);
              }
 
          /* Record colors in the image.  Free color table and XImage.  */
-#ifdef COLOR_TABLE_SUPPORT
          img->colors = colors_in_color_table (&img->ncolors);
          free_color_table ();
 #endif
@@ -9352,7 +9632,8 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
 }
 
 
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
+DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0,
+       doc: /* */)
   (Lisp_Object spec)
 {
   ptrdiff_t id = -1;
@@ -9416,7 +9697,7 @@ lookup_image_type (Lisp_Object type)
     return define_image_type (&gif_type);
 #endif
 
-#if defined (HAVE_PNG) || defined (HAVE_NS)
+#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
   if (EQ (type, Qpng))
     return define_image_type (&png_type);
 #endif
@@ -9479,10 +9760,12 @@ as a ratio to the frame height and width.  If the value is
 non-numeric, there is no explicit limit on the size of images.  */);
   Vmax_image_size = make_float (MAX_IMAGE_SIZE);
 
+  /* Other symbols.  */
   DEFSYM (Qcount, "count");
   DEFSYM (Qextension_data, "extension-data");
   DEFSYM (Qdelay, "delay");
 
+  /* Keywords.  */
   DEFSYM (QCascent, ":ascent");
   DEFSYM (QCmargin, ":margin");
   DEFSYM (QCrelief, ":relief");
@@ -9497,6 +9780,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   DEFSYM (QCcolor_adjustment, ":color-adjustment");
   DEFSYM (QCmask, ":mask");
 
+  /* Other symbols.  */
   DEFSYM (Qlaplace, "laplace");
   DEFSYM (Qemboss, "emboss");
   DEFSYM (Qedge_detection, "edge-detection");
@@ -9514,6 +9798,10 @@ non-numeric, there is no explicit limit on the size of images.  */);
 #endif /* HAVE_GHOSTSCRIPT */
 
 #ifdef HAVE_NTGUI
+  /* Versions of libpng, libgif, and libjpeg that we were compiled with,
+     or -1 if no PNG/GIF support was compiled in.  This is tested by
+     w32-win.el to correctly set up the alist used to search for the
+     respective image libraries.  */
   DEFSYM (Qlibpng_version, "libpng-version");
   Fset (Qlibpng_version,
 #if HAVE_PNG