]> code.delx.au - gnu-emacs/blobdiff - src/image.c
Merge branch 'master' into cairo
[gnu-emacs] / src / image.c
index a73a7251753b4b378c8078c760925806d98f6aaf..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);
        }
 
@@ -1859,19 +1888,6 @@ mark_image_cache (struct image_cache *c)
                          X / NS / W32 support code
  ***********************************************************************/
 
-#ifdef WINDOWSNT
-
-/* Macro for defining functions that will be loaded from image DLLs.  */
-#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
-
-/* Macro for loading those image functions from the library.  */
-#define LOAD_IMGLIB_FN(lib,func) {                                     \
-    fn_##func = (void *) GetProcAddress (lib, #func);                  \
-    if (!fn_##func) return 0;                                          \
-  }
-
-#endif /* WINDOWSNT */
-
 /* Return true if XIMG's size WIDTH x HEIGHT doesn't break the
    windowing system.
    WIDTH and HEIGHT must both be positive.
@@ -2375,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,
@@ -2690,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 =
@@ -3134,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.  */
 
@@ -3184,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,
@@ -3199,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
@@ -3377,12 +3392,14 @@ xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *
 
 /* XPM library details.  */
 
-DEF_IMGLIB_FN (void, XpmFreeAttributes, (XpmAttributes *));
-DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer, (Display *, char *, xpm_XImage **,
-                                         xpm_XImage **, XpmAttributes *));
-DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
-                                   xpm_XImage **, XpmAttributes *));
-DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
+DEF_DLL_FN (void, XpmFreeAttributes, (XpmAttributes *));
+DEF_DLL_FN (int, XpmCreateImageFromBuffer,
+           (Display *, char *, xpm_XImage **,
+            xpm_XImage **, XpmAttributes *));
+DEF_DLL_FN (int, XpmReadFileToImage,
+           (Display *, char *, xpm_XImage **,
+            xpm_XImage **, XpmAttributes *));
+DEF_DLL_FN (void, XImageFree, (xpm_XImage *));
 
 static bool
 init_xpm_functions (void)
@@ -3392,22 +3409,24 @@ init_xpm_functions (void)
   if (!(library = w32_delayed_load (Qxpm)))
     return 0;
 
-  LOAD_IMGLIB_FN (library, XpmFreeAttributes);
-  LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
-  LOAD_IMGLIB_FN (library, XpmReadFileToImage);
-  LOAD_IMGLIB_FN (library, XImageFree);
+  LOAD_DLL_FN (library, XpmFreeAttributes);
+  LOAD_DLL_FN (library, XpmCreateImageFromBuffer);
+  LOAD_DLL_FN (library, XpmReadFileToImage);
+  LOAD_DLL_FN (library, XImageFree);
   return 1;
 }
 
-#endif /* WINDOWSNT */
+# undef XImageFree
+# undef XpmCreateImageFromBuffer
+# undef XpmFreeAttributes
+# undef XpmReadFileToImage
 
-#if defined HAVE_NTGUI && !defined WINDOWSNT
-/* Glue for code below */
-#define fn_XpmReadFileToImage XpmReadFileToImage
-#define fn_XpmCreateImageFromBuffer XpmCreateImageFromBuffer
-#define fn_XImageFree XImageFree
-#define fn_XpmFreeAttributes XpmFreeAttributes
-#endif /* HAVE_NTGUI && !WINDOWSNT */
+# define XImageFree fn_XImageFree
+# define XpmCreateImageFromBuffer fn_XpmCreateImageFromBuffer
+# define XpmFreeAttributes fn_XpmFreeAttributes
+# define XpmReadFileToImage fn_XpmReadFileToImage
+
+#endif /* WINDOWSNT */
 
 /* Value is true if COLOR_SYMBOLS is a valid color symbols list
    for XPM images.  Such a list must consist of conses whose car and
@@ -3624,9 +3643,9 @@ xpm_load (struct frame *f, struct image *img)
 #endif
       /* XpmReadFileToPixmap is not available in the Windows port of
         libxpm.  But XpmReadFileToImage almost does what we want.  */
-      rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
-                                 &xpm_image, &xpm_mask,
-                                 &attrs);
+      rc = XpmReadFileToImage (&hdc, SDATA (file),
+                              &xpm_image, &xpm_mask,
+                              &attrs);
 #else
       rc = XpmReadFileToImage (FRAME_X_DISPLAY (f), SSDATA (file),
                               &img->ximg, &img->mask_img,
@@ -3648,9 +3667,9 @@ xpm_load (struct frame *f, struct image *img)
 #ifdef HAVE_NTGUI
       /* XpmCreatePixmapFromBuffer is not available in the Windows port
         of libxpm.  But XpmCreateImageFromBuffer almost does what we want.  */
-      rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
-                                       &xpm_image, &xpm_mask,
-                                       &attrs);
+      rc = XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
+                                    &xpm_image, &xpm_mask,
+                                    &attrs);
 #else
       rc = XpmCreateImageFromBuffer (FRAME_X_DISPLAY (f), SSDATA (buffer),
                                     &img->ximg, &img->mask_img,
@@ -3658,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)
     {
@@ -3683,6 +3740,7 @@ xpm_load (struct frame *f, struct image *img)
        }
     }
 #endif
+#endif /* ! USE_CAIRO */
 
   if (rc == XpmSuccess)
     {
@@ -3699,7 +3757,7 @@ xpm_load (struct frame *f, struct image *img)
          img->pixmap = xpm_image->bitmap;
          /* XImageFree in libXpm frees XImage struct without destroying
             the bitmap, which is what we want.  */
-         fn_XImageFree (xpm_image);
+         XImageFree (xpm_image);
        }
       if (xpm_mask && xpm_mask->bitmap)
        {
@@ -3713,7 +3771,7 @@ xpm_load (struct frame *f, struct image *img)
          SelectObject (hdc, old_obj);
 
          img->mask = xpm_mask->bitmap;
-         fn_XImageFree (xpm_mask);
+         XImageFree (xpm_mask);
          DeleteDC (hdc);
        }
 
@@ -3737,11 +3795,7 @@ xpm_load (struct frame *f, struct image *img)
       eassert (img->width > 0 && img->height > 0);
 
       /* The call to XpmFreeAttributes below frees attrs.alloc_pixels.  */
-#ifdef HAVE_NTGUI
-      fn_XpmFreeAttributes (&attrs);
-#else
       XpmFreeAttributes (&attrs);
-#endif /* HAVE_NTGUI */
 
 #ifdef HAVE_X_WINDOWS
       /* Maybe fill in the background field while we have ximg handy.  */
@@ -4468,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
@@ -4599,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);
 
@@ -4740,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);
 
@@ -5009,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.  */
@@ -5072,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
@@ -5116,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,
@@ -5196,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);
 
@@ -5283,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);
@@ -5299,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 ();
@@ -5311,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);
@@ -5327,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)
@@ -5337,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);
@@ -5351,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
@@ -5364,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);
@@ -5405,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
          }
     }
 
@@ -5432,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;
@@ -5452,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
@@ -5507,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,
@@ -5530,44 +5639,47 @@ 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
 
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
 /* PNG library details.  */
 
-DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
-DEF_IMGLIB_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
-DEF_IMGLIB_FN (png_structp, png_create_read_struct, (png_const_charp, png_voidp,
-                                                    png_error_ptr, png_error_ptr));
-DEF_IMGLIB_FN (png_infop, png_create_info_struct, (png_structp));
-DEF_IMGLIB_FN (void, png_destroy_read_struct, (png_structpp, png_infopp, png_infopp));
-DEF_IMGLIB_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
-DEF_IMGLIB_FN (void, png_set_sig_bytes, (png_structp, int));
-DEF_IMGLIB_FN (void, png_read_info, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_uint_32, png_get_IHDR, (png_structp, png_infop,
-                             png_uint_32 *, png_uint_32 *,
-                             int *, int *, int *, int *, int *));
-DEF_IMGLIB_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
-DEF_IMGLIB_FN (void, png_set_strip_16, (png_structp));
-DEF_IMGLIB_FN (void, png_set_expand, (png_structp));
-DEF_IMGLIB_FN (void, png_set_gray_to_rgb, (png_structp));
-DEF_IMGLIB_FN (void, png_set_background, (png_structp, png_color_16p,
-                                   int, int, double));
-DEF_IMGLIB_FN (png_uint_32, png_get_bKGD, (png_structp, png_infop, png_color_16p *));
-DEF_IMGLIB_FN (void, png_read_update_info, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_byte, png_get_channels, (png_structp, png_infop));
-DEF_IMGLIB_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
-DEF_IMGLIB_FN (void, png_read_image, (png_structp, png_bytepp));
-DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop));
-DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp));
-
-#if (PNG_LIBPNG_VER >= 10500)
-DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int)) PNG_NORETURN;
-DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
-#endif /* libpng version >= 1.5 */
+DEF_DLL_FN (png_voidp, png_get_io_ptr, (png_structp));
+DEF_DLL_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
+DEF_DLL_FN (png_structp, png_create_read_struct,
+           (png_const_charp, png_voidp, png_error_ptr, png_error_ptr));
+DEF_DLL_FN (png_infop, png_create_info_struct, (png_structp));
+DEF_DLL_FN (void, png_destroy_read_struct,
+           (png_structpp, png_infopp, png_infopp));
+DEF_DLL_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
+DEF_DLL_FN (void, png_set_sig_bytes, (png_structp, int));
+DEF_DLL_FN (void, png_read_info, (png_structp, png_infop));
+DEF_DLL_FN (png_uint_32, png_get_IHDR,
+           (png_structp, png_infop, png_uint_32 *, png_uint_32 *,
+            int *, int *, int *, int *, int *));
+DEF_DLL_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
+DEF_DLL_FN (void, png_set_strip_16, (png_structp));
+DEF_DLL_FN (void, png_set_expand, (png_structp));
+DEF_DLL_FN (void, png_set_gray_to_rgb, (png_structp));
+DEF_DLL_FN (void, png_set_background,
+           (png_structp, png_color_16p, int, int, double));
+DEF_DLL_FN (png_uint_32, png_get_bKGD,
+           (png_structp, png_infop, png_color_16p *));
+DEF_DLL_FN (void, png_read_update_info, (png_structp, png_infop));
+DEF_DLL_FN (png_byte, png_get_channels, (png_structp, png_infop));
+DEF_DLL_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
+DEF_DLL_FN (void, png_read_image, (png_structp, png_bytepp));
+DEF_DLL_FN (void, png_read_end, (png_structp, png_infop));
+DEF_DLL_FN (void, png_error, (png_structp, png_const_charp));
+
+#  if (PNG_LIBPNG_VER >= 10500)
+DEF_DLL_FN (void, png_longjmp, (png_structp, int)) PNG_NORETURN;
+DEF_DLL_FN (jmp_buf *, png_set_longjmp_fn,
+           (png_structp, png_longjmp_ptr, size_t));
+#  endif /* libpng version >= 1.5 */
 
 static bool
 init_png_functions (void)
@@ -5577,87 +5689,107 @@ init_png_functions (void)
   if (!(library = w32_delayed_load (Qpng)))
     return 0;
 
-  LOAD_IMGLIB_FN (library, png_get_io_ptr);
-  LOAD_IMGLIB_FN (library, png_sig_cmp);
-  LOAD_IMGLIB_FN (library, png_create_read_struct);
-  LOAD_IMGLIB_FN (library, png_create_info_struct);
-  LOAD_IMGLIB_FN (library, png_destroy_read_struct);
-  LOAD_IMGLIB_FN (library, png_set_read_fn);
-  LOAD_IMGLIB_FN (library, png_set_sig_bytes);
-  LOAD_IMGLIB_FN (library, png_read_info);
-  LOAD_IMGLIB_FN (library, png_get_IHDR);
-  LOAD_IMGLIB_FN (library, png_get_valid);
-  LOAD_IMGLIB_FN (library, png_set_strip_16);
-  LOAD_IMGLIB_FN (library, png_set_expand);
-  LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
-  LOAD_IMGLIB_FN (library, png_set_background);
-  LOAD_IMGLIB_FN (library, png_get_bKGD);
-  LOAD_IMGLIB_FN (library, png_read_update_info);
-  LOAD_IMGLIB_FN (library, png_get_channels);
-  LOAD_IMGLIB_FN (library, png_get_rowbytes);
-  LOAD_IMGLIB_FN (library, png_read_image);
-  LOAD_IMGLIB_FN (library, png_read_end);
-  LOAD_IMGLIB_FN (library, png_error);
-
-#if (PNG_LIBPNG_VER >= 10500)
-  LOAD_IMGLIB_FN (library, png_longjmp);
-  LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
-#endif /* libpng version >= 1.5 */
+  LOAD_DLL_FN (library, png_get_io_ptr);
+  LOAD_DLL_FN (library, png_sig_cmp);
+  LOAD_DLL_FN (library, png_create_read_struct);
+  LOAD_DLL_FN (library, png_create_info_struct);
+  LOAD_DLL_FN (library, png_destroy_read_struct);
+  LOAD_DLL_FN (library, png_set_read_fn);
+  LOAD_DLL_FN (library, png_set_sig_bytes);
+  LOAD_DLL_FN (library, png_read_info);
+  LOAD_DLL_FN (library, png_get_IHDR);
+  LOAD_DLL_FN (library, png_get_valid);
+  LOAD_DLL_FN (library, png_set_strip_16);
+  LOAD_DLL_FN (library, png_set_expand);
+  LOAD_DLL_FN (library, png_set_gray_to_rgb);
+  LOAD_DLL_FN (library, png_set_background);
+  LOAD_DLL_FN (library, png_get_bKGD);
+  LOAD_DLL_FN (library, png_read_update_info);
+  LOAD_DLL_FN (library, png_get_channels);
+  LOAD_DLL_FN (library, png_get_rowbytes);
+  LOAD_DLL_FN (library, png_read_image);
+  LOAD_DLL_FN (library, png_read_end);
+  LOAD_DLL_FN (library, png_error);
+
+#  if (PNG_LIBPNG_VER >= 10500)
+  LOAD_DLL_FN (library, png_longjmp);
+  LOAD_DLL_FN (library, png_set_longjmp_fn);
+#  endif /* libpng version >= 1.5 */
 
   return 1;
 }
-#else
-
-#define fn_png_get_io_ptr              png_get_io_ptr
-#define fn_png_sig_cmp                 png_sig_cmp
-#define fn_png_create_read_struct      png_create_read_struct
-#define fn_png_create_info_struct      png_create_info_struct
-#define fn_png_destroy_read_struct     png_destroy_read_struct
-#define fn_png_set_read_fn             png_set_read_fn
-#define fn_png_set_sig_bytes           png_set_sig_bytes
-#define fn_png_read_info               png_read_info
-#define fn_png_get_IHDR                        png_get_IHDR
-#define fn_png_get_valid               png_get_valid
-#define fn_png_set_strip_16            png_set_strip_16
-#define fn_png_set_expand              png_set_expand
-#define fn_png_set_gray_to_rgb         png_set_gray_to_rgb
-#define fn_png_set_background          png_set_background
-#define fn_png_get_bKGD                        png_get_bKGD
-#define fn_png_read_update_info                png_read_update_info
-#define fn_png_get_channels            png_get_channels
-#define fn_png_get_rowbytes            png_get_rowbytes
-#define fn_png_read_image              png_read_image
-#define fn_png_read_end                        png_read_end
-#define fn_png_error                   png_error
-
-#if (PNG_LIBPNG_VER >= 10500)
-#define fn_png_longjmp                 png_longjmp
-#define fn_png_set_longjmp_fn          png_set_longjmp_fn
-#endif /* libpng version >= 1.5 */
 
-#endif /* WINDOWSNT */
+#  undef png_create_info_struct
+#  undef png_create_read_struct
+#  undef png_destroy_read_struct
+#  undef png_error
+#  undef png_get_bKGD
+#  undef png_get_channels
+#  undef png_get_IHDR
+#  undef png_get_io_ptr
+#  undef png_get_rowbytes
+#  undef png_get_valid
+#  undef png_longjmp
+#  undef png_read_end
+#  undef png_read_image
+#  undef png_read_info
+#  undef png_read_update_info
+#  undef png_set_background
+#  undef png_set_expand
+#  undef png_set_gray_to_rgb
+#  undef png_set_longjmp_fn
+#  undef png_set_read_fn
+#  undef png_set_sig_bytes
+#  undef png_set_strip_16
+#  undef png_sig_cmp
+
+#  define png_create_info_struct fn_png_create_info_struct
+#  define png_create_read_struct fn_png_create_read_struct
+#  define png_destroy_read_struct fn_png_destroy_read_struct
+#  define png_error fn_png_error
+#  define png_get_bKGD fn_png_get_bKGD
+#  define png_get_channels fn_png_get_channels
+#  define png_get_IHDR fn_png_get_IHDR
+#  define png_get_io_ptr fn_png_get_io_ptr
+#  define png_get_rowbytes fn_png_get_rowbytes
+#  define png_get_valid fn_png_get_valid
+#  define png_longjmp fn_png_longjmp
+#  define png_read_end fn_png_read_end
+#  define png_read_image fn_png_read_image
+#  define png_read_info fn_png_read_info
+#  define png_read_update_info fn_png_read_update_info
+#  define png_set_background fn_png_set_background
+#  define png_set_expand fn_png_set_expand
+#  define png_set_gray_to_rgb fn_png_set_gray_to_rgb
+#  define png_set_longjmp_fn fn_png_set_longjmp_fn
+#  define png_set_read_fn fn_png_set_read_fn
+#  define png_set_sig_bytes fn_png_set_sig_bytes
+#  define png_set_strip_16 fn_png_set_strip_16
+#  define png_sig_cmp fn_png_sig_cmp
+
+# endif /* WINDOWSNT */
 
 /* Fast implementations of setjmp and longjmp.  Although setjmp and longjmp
    will do, POSIX _setjmp and _longjmp (if available) are often faster.
    Do not use sys_setjmp, as PNG supports only jmp_buf.
    It's OK if the longjmp substitute restores the signal mask.  */
-#ifdef HAVE__SETJMP
-# define FAST_SETJMP(j) _setjmp (j)
-# define FAST_LONGJMP _longjmp
-#else
-# define FAST_SETJMP(j) setjmp (j)
-# define FAST_LONGJMP longjmp
-#endif
-
-#if PNG_LIBPNG_VER < 10500
-#define PNG_LONGJMP(ptr) FAST_LONGJMP ((ptr)->jmpbuf, 1)
-#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
-#else
+# ifdef HAVE__SETJMP
+#  define FAST_SETJMP(j) _setjmp (j)
+#  define FAST_LONGJMP _longjmp
+# else
+#  define FAST_SETJMP(j) setjmp (j)
+#  define FAST_LONGJMP longjmp
+# endif
+
+# if PNG_LIBPNG_VER < 10500
+#  define PNG_LONGJMP(ptr) FAST_LONGJMP ((ptr)->jmpbuf, 1)
+#  define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
+# else
 /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908)  */
-#define PNG_LONGJMP(ptr) fn_png_longjmp (ptr, 1)
-#define PNG_JMPBUF(ptr) \
-  (*fn_png_set_longjmp_fn (ptr, FAST_LONGJMP, sizeof (jmp_buf)))
-#endif
+#  define PNG_LONGJMP(ptr) png_longjmp (ptr, 1)
+#  define PNG_JMPBUF(ptr) \
+     (*png_set_longjmp_fn (ptr, FAST_LONGJMP, sizeof (jmp_buf)))
+# endif
 
 /* Error and warning handlers installed when the PNG library
    is initialized.  */
@@ -5697,10 +5829,10 @@ struct png_memory_storage
 static void
 png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
 {
-  struct png_memory_storage *tbr = fn_png_get_io_ptr (png_ptr);
+  struct png_memory_storage *tbr = png_get_io_ptr (png_ptr);
 
   if (length > tbr->len - tbr->index)
-    fn_png_error (png_ptr, "Read error");
+    png_error (png_ptr, "Read error");
 
   memcpy (data, tbr->bytes + tbr->index, length);
   tbr->index = tbr->index + length;
@@ -5714,10 +5846,10 @@ png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
 static void
 png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
 {
-  FILE *fp = fn_png_get_io_ptr (png_ptr);
+  FILE *fp = png_get_io_ptr (png_ptr);
 
   if (fread (data, 1, length, fp) < length)
-    fn_png_error (png_ptr, "Read error");
+    png_error (png_ptr, "Read error");
 }
 
 
@@ -5742,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;
@@ -5756,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))
     {
@@ -5779,7 +5918,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-         || fn_png_sig_cmp (sig, 0, sizeof sig))
+         || png_sig_cmp (sig, 0, sizeof sig))
        {
          fclose (fp);
          image_error ("Not a PNG file: `%s'", file, Qnil);
@@ -5801,7 +5940,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
       /* Check PNG signature.  */
       if (tbr.len < sizeof sig
-         || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
+         || png_sig_cmp (tbr.bytes, 0, sizeof sig))
        {
          image_error ("Not a PNG image: `%s'", img->spec, Qnil);
          return 0;
@@ -5812,13 +5951,13 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
     }
 
   /* Initialize read and info structs for PNG lib.  */
-  png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
+  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                       NULL, my_png_error,
                                       my_png_warning);
   if (png_ptr)
     {
-      info_ptr = fn_png_create_info_struct (png_ptr);
-      end_info = fn_png_create_info_struct (png_ptr);
+      info_ptr = png_create_info_struct (png_ptr);
+      end_info = png_create_info_struct (png_ptr);
     }
 
   c->png_ptr = png_ptr;
@@ -5830,7 +5969,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
   if (! (info_ptr && end_info))
     {
-      fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+      png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
       png_ptr = 0;
     }
   if (! png_ptr)
@@ -5845,7 +5984,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
     {
     error:
       if (c->png_ptr)
-       fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+       png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
       xfree (c->pixels);
       xfree (c->rows);
       if (c->fp)
@@ -5855,17 +5994,18 @@ 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))
-    fn_png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
+    png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
   else
-    fn_png_set_read_fn (png_ptr, fp, png_read_from_file);
+    png_set_read_fn (png_ptr, fp, png_read_from_file);
 
-  fn_png_set_sig_bytes (png_ptr, sizeof sig);
-  fn_png_read_info (png_ptr, info_ptr);
-  fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-                  &interlace_type, NULL, NULL);
+  png_set_sig_bytes (png_ptr, sizeof sig);
+  png_read_info (png_ptr, info_ptr);
+  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+               &interlace_type, NULL, NULL);
 
   if (! (width <= INT_MAX && height <= INT_MAX
         && check_image_size (f, width, height)))
@@ -5874,14 +6014,16 @@ 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.  */
-  if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
     transparent_p = 1;
   else
     transparent_p = 0;
@@ -5892,16 +6034,16 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 
   /* Strip more than 8 bits per channel.  */
   if (bit_depth == 16)
-    fn_png_set_strip_16 (png_ptr);
+    png_set_strip_16 (png_ptr);
 
   /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
      if available.  */
-  fn_png_set_expand (png_ptr);
+  png_set_expand (png_ptr);
 
   /* Convert grayscale images to RGB.  */
   if (color_type == PNG_COLOR_TYPE_GRAY
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-    fn_png_set_gray_to_rgb (png_ptr);
+    png_set_gray_to_rgb (png_ptr);
 
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
@@ -5927,28 +6069,28 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
          bg.green = color.green >> shift;
          bg.blue = color.blue >> shift;
 
-         fn_png_set_background (png_ptr, &bg,
-                                PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+         png_set_background (png_ptr, &bg,
+                             PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }
     }
 
   /* Update info structure.  */
-  fn_png_read_update_info (png_ptr, info_ptr);
+  png_read_update_info (png_ptr, info_ptr);
 
   /* Get number of channels.  Valid values are 1 for grayscale images
      and images with a palette, 2 for grayscale images with transparency
      information (alpha channel), 3 for RGB images, and 4 for RGB
      images with alpha channel, i.e. RGBA.  If conversions above were
      sufficient we should only have 3 or 4 channels here.  */
-  channels = fn_png_get_channels (png_ptr, info_ptr);
+  channels = png_get_channels (png_ptr, info_ptr);
   eassert (channels == 3 || channels == 4);
 
   /* Number of bytes needed for one row of the image.  */
-  row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
+  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);
@@ -5956,14 +6098,18 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
     rows[i] = pixels + i * row_bytes;
 
   /* Read the entire image.  */
-  fn_png_read_image (png_ptr, rows);
-  fn_png_read_end (png_ptr, info_ptr);
+  png_read_image (png_ptr, rows);
+  png_read_end (png_ptr, info_ptr);
   if (fp)
     {
       fclose (fp);
       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
@@ -5975,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 ();
@@ -5987,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;
@@ -6013,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
        }
     }
 
@@ -6021,27 +6177,30 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
        overrode it.  */
     {
       png_color_16 *bg;
-      if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
+      if (png_get_bKGD (png_ptr, info_ptr, &bg))
        {
          img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
          img->background_valid = 1;
        }
     }
 
-#ifdef COLOR_TABLE_SUPPORT
+# ifdef COLOR_TABLE_SUPPORT
   /* Remember colors allocated for this image.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
+# endif /* COLOR_TABLE_SUPPORT */
 
   /* Clean up.  */
-  fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
+  png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
   xfree (rows);
   xfree (pixels);
 
   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);
@@ -6058,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;
 }
@@ -6079,6 +6239,7 @@ png_load (struct frame *f, struct image *img)
                         image_spec_value (img->spec, QCdata, NULL));
 }
 
+
 #endif /* HAVE_NS */
 
 
@@ -6092,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
@@ -6140,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,
@@ -6170,15 +6327,15 @@ jpeg_image_p (Lisp_Object object)
 
 /* Work around a warning about HAVE_STDLIB_H being redefined in
    jconfig.h.  */
-#ifdef HAVE_STDLIB_H
-#undef HAVE_STDLIB_H
-#endif /* HAVE_STLIB_H */
+# ifdef HAVE_STDLIB_H
+#  undef HAVE_STDLIB_H
+# endif
 
-#if defined (HAVE_NTGUI) && !defined (__WIN32__)
+# if defined (HAVE_NTGUI) && !defined (__WIN32__)
 /* In older releases of the jpeg library, jpeglib.h will define boolean
    differently depending on __WIN32__, so make sure it is defined.  */
-#define __WIN32__ 1
-#endif
+#  define __WIN32__ 1
+# endif
 
 /* rpcndr.h (via windows.h) and jpeglib.h both define boolean types.
    Some versions of jpeglib try to detect whether rpcndr.h is loaded,
@@ -6194,23 +6351,25 @@ jpeg_image_p (Lisp_Object object)
    different name.  This name, jpeg_boolean, remains in effect through
    the rest of image.c.
 */
-#if defined CYGWIN && defined HAVE_NTGUI
-#define boolean jpeg_boolean
-#endif
-#include <jpeglib.h>
-#include <jerror.h>
+# if defined CYGWIN && defined HAVE_NTGUI
+#  define boolean jpeg_boolean
+# endif
+# include <jpeglib.h>
+# include <jerror.h>
 
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
 
 /* JPEG library details.  */
-DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
-DEF_IMGLIB_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
-DEF_IMGLIB_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
-DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
-DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr *));
-DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
+DEF_DLL_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
+DEF_DLL_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
+DEF_DLL_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
+DEF_DLL_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
+DEF_DLL_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
+DEF_DLL_FN (JDIMENSION, jpeg_read_scanlines,
+           (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
+DEF_DLL_FN (struct jpeg_error_mgr *, jpeg_std_error,
+           (struct jpeg_error_mgr *));
+DEF_DLL_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
 
 static bool
 init_jpeg_functions (void)
@@ -6220,37 +6379,46 @@ init_jpeg_functions (void)
   if (!(library = w32_delayed_load (Qjpeg)))
     return 0;
 
-  LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
-  LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
-  LOAD_IMGLIB_FN (library, jpeg_start_decompress);
-  LOAD_IMGLIB_FN (library, jpeg_read_header);
-  LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
-  LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
-  LOAD_IMGLIB_FN (library, jpeg_std_error);
-  LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
+  LOAD_DLL_FN (library, jpeg_finish_decompress);
+  LOAD_DLL_FN (library, jpeg_read_scanlines);
+  LOAD_DLL_FN (library, jpeg_start_decompress);
+  LOAD_DLL_FN (library, jpeg_read_header);
+  LOAD_DLL_FN (library, jpeg_CreateDecompress);
+  LOAD_DLL_FN (library, jpeg_destroy_decompress);
+  LOAD_DLL_FN (library, jpeg_std_error);
+  LOAD_DLL_FN (library, jpeg_resync_to_restart);
   return 1;
 }
 
+#  undef jpeg_CreateDecompress
+#  undef jpeg_destroy_decompress
+#  undef jpeg_finish_decompress
+#  undef jpeg_read_header
+#  undef jpeg_read_scanlines
+#  undef jpeg_resync_to_restart
+#  undef jpeg_start_decompress
+#  undef jpeg_std_error
+
+#  define jpeg_CreateDecompress fn_jpeg_CreateDecompress
+#  define jpeg_destroy_decompress fn_jpeg_destroy_decompress
+#  define jpeg_finish_decompress fn_jpeg_finish_decompress
+#  define jpeg_read_header fn_jpeg_read_header
+#  define jpeg_read_scanlines fn_jpeg_read_scanlines
+#  define jpeg_resync_to_restart fn_jpeg_resync_to_restart
+#  define jpeg_start_decompress fn_jpeg_start_decompress
+#  define jpeg_std_error fn_jpeg_std_error
+
 /* Wrapper since we can't directly assign the function pointer
    to another function pointer that was declared more completely easily.  */
 static boolean
 jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
 {
-  return fn_jpeg_resync_to_restart (cinfo, desired);
+  return jpeg_resync_to_restart (cinfo, desired);
 }
+#  undef jpeg_resync_to_restart
+#  define jpeg_resync_to_restart jpeg_resync_to_restart_wrapper
 
-#else
-
-#define fn_jpeg_CreateDecompress(a,b,c)        jpeg_create_decompress (a)
-#define fn_jpeg_start_decompress       jpeg_start_decompress
-#define fn_jpeg_finish_decompress      jpeg_finish_decompress
-#define fn_jpeg_destroy_decompress     jpeg_destroy_decompress
-#define fn_jpeg_read_header            jpeg_read_header
-#define fn_jpeg_read_scanlines         jpeg_read_scanlines
-#define fn_jpeg_std_error              jpeg_std_error
-#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
-
-#endif /* WINDOWSNT */
+# endif /* WINDOWSNT */
 
 struct my_jpeg_error_mgr
 {
@@ -6358,7 +6526,7 @@ jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
   src->init_source = our_common_init_source;
   src->fill_input_buffer = our_memory_fill_input_buffer;
   src->skip_input_data = our_memory_skip_input_data;
-  src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method.  */
+  src->resync_to_restart = jpeg_resync_to_restart; /* Use default method.  */
   src->term_source = our_common_term_source;
   src->bytes_in_buffer = len;
   src->next_input_byte = data;
@@ -6464,7 +6632,7 @@ jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
   src->mgr.init_source = our_common_init_source;
   src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
   src->mgr.skip_input_data = our_stdio_skip_input_data;
-  src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method.  */
+  src->mgr.resync_to_restart = jpeg_resync_to_restart; /* Use default.  */
   src->mgr.term_source = our_common_term_source;
   src->mgr.bytes_in_buffer = 0;
   src->mgr.next_input_byte = NULL;
@@ -6483,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))
     {
@@ -6515,7 +6687,7 @@ jpeg_load_body (struct frame *f, struct image *img,
 
   /* Customize libjpeg's error handling to call my_error_exit when an
      error is detected.  This function will perform a longjmp.  */
-  mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
+  mgr->cinfo.err = jpeg_std_error (&mgr->pub);
   mgr->pub.error_exit = my_error_exit;
   if (sys_setjmp (mgr->setjmp_buffer))
     {
@@ -6541,19 +6713,23 @@ jpeg_load_body (struct frame *f, struct image *img,
       /* Close the input file and destroy the JPEG object.  */
       if (fp)
        fclose (fp);
-      fn_jpeg_destroy_decompress (&mgr->cinfo);
+      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.  */
-  fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
+  jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
 
   if (NILP (specified_data))
     jpeg_file_src (&mgr->cinfo, fp);
@@ -6561,12 +6737,12 @@ jpeg_load_body (struct frame *f, struct image *img,
     jpeg_memory_src (&mgr->cinfo, SDATA (specified_data),
                     SBYTES (specified_data));
 
-  fn_jpeg_read_header (&mgr->cinfo, 1);
+  jpeg_read_header (&mgr->cinfo, 1);
 
   /* Customize decompression so that color quantization will be used.
         Start decompression.  */
   mgr->cinfo.quantize_colors = 1;
-  fn_jpeg_start_decompress (&mgr->cinfo);
+  jpeg_start_decompress (&mgr->cinfo);
   width = img->width = mgr->cinfo.output_width;
   height = img->height = mgr->cinfo.output_height;
 
@@ -6576,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
@@ -6590,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)
@@ -6599,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
@@ -6615,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.  */
@@ -6627,19 +6805,44 @@ 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)
     {
-      fn_jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
+      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.  */
-  fn_jpeg_finish_decompress (&mgr->cinfo);
-  fn_jpeg_destroy_decompress (&mgr->cinfo);
+  jpeg_finish_decompress (&mgr->cinfo);
+  jpeg_destroy_decompress (&mgr->cinfo);
   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.  */
@@ -6647,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;
 }
@@ -6683,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
@@ -6733,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,
@@ -6760,22 +6960,22 @@ tiff_image_p (Lisp_Object object)
 
 #ifdef HAVE_TIFF
 
-#include <tiffio.h>
+# include <tiffio.h>
 
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
 
 /* TIFF library details.  */
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
-DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
-DEF_IMGLIB_FN (TIFF *, TIFFOpen, (const char *, const char *));
-DEF_IMGLIB_FN (TIFF *, TIFFClientOpen, (const char *, const char *, thandle_t,
-                               TIFFReadWriteProc, TIFFReadWriteProc,
-                               TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
-                               TIFFMapFileProc, TIFFUnmapFileProc));
-DEF_IMGLIB_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
-DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
-DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
-DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
+DEF_DLL_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
+DEF_DLL_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
+DEF_DLL_FN (TIFF *, TIFFOpen, (const char *, const char *));
+DEF_DLL_FN (TIFF *, TIFFClientOpen,
+           (const char *, const char *, thandle_t, TIFFReadWriteProc,
+            TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
+            TIFFMapFileProc, TIFFUnmapFileProc));
+DEF_DLL_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
+DEF_DLL_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
+DEF_DLL_FN (void, TIFFClose, (TIFF *));
+DEF_DLL_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
 
 static bool
 init_tiff_functions (void)
@@ -6785,28 +6985,36 @@ init_tiff_functions (void)
   if (!(library = w32_delayed_load (Qtiff)))
     return 0;
 
-  LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
-  LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
-  LOAD_IMGLIB_FN (library, TIFFOpen);
-  LOAD_IMGLIB_FN (library, TIFFClientOpen);
-  LOAD_IMGLIB_FN (library, TIFFGetField);
-  LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
-  LOAD_IMGLIB_FN (library, TIFFClose);
-  LOAD_IMGLIB_FN (library, TIFFSetDirectory);
+  LOAD_DLL_FN (library, TIFFSetErrorHandler);
+  LOAD_DLL_FN (library, TIFFSetWarningHandler);
+  LOAD_DLL_FN (library, TIFFOpen);
+  LOAD_DLL_FN (library, TIFFClientOpen);
+  LOAD_DLL_FN (library, TIFFGetField);
+  LOAD_DLL_FN (library, TIFFReadRGBAImage);
+  LOAD_DLL_FN (library, TIFFClose);
+  LOAD_DLL_FN (library, TIFFSetDirectory);
   return 1;
 }
 
-#else
+#  undef TIFFClientOpen
+#  undef TIFFClose
+#  undef TIFFGetField
+#  undef TIFFOpen
+#  undef TIFFReadRGBAImage
+#  undef TIFFSetDirectory
+#  undef TIFFSetErrorHandler
+#  undef TIFFSetWarningHandler
 
-#define fn_TIFFSetErrorHandler         TIFFSetErrorHandler
-#define fn_TIFFSetWarningHandler       TIFFSetWarningHandler
-#define fn_TIFFOpen                    TIFFOpen
-#define fn_TIFFClientOpen              TIFFClientOpen
-#define fn_TIFFGetField                        TIFFGetField
-#define fn_TIFFReadRGBAImage           TIFFReadRGBAImage
-#define fn_TIFFClose                   TIFFClose
-#define fn_TIFFSetDirectory            TIFFSetDirectory
-#endif /* WINDOWSNT */
+#  define TIFFClientOpen fn_TIFFClientOpen
+#  define TIFFClose fn_TIFFClose
+#  define TIFFGetField fn_TIFFGetField
+#  define TIFFOpen fn_TIFFOpen
+#  define TIFFReadRGBAImage fn_TIFFReadRGBAImage
+#  define TIFFSetDirectory fn_TIFFSetDirectory
+#  define TIFFSetErrorHandler fn_TIFFSetErrorHandler
+#  define TIFFSetWarningHandler fn_TIFFSetWarningHandler
+
+# endif /* WINDOWSNT */
 
 
 /* Reading from a memory buffer for TIFF images Based on the PNG
@@ -6904,11 +7112,11 @@ tiff_size_of_memory (thandle_t data)
    compiler error compiling tiff_handler, see Bugzilla bug #17406
    (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406).  Declaring
    this function as external works around that problem.  */
-#if defined (__MINGW32__) && __GNUC__ == 3
-# define MINGW_STATIC
-#else
-# define MINGW_STATIC static
-#endif
+# if defined (__MINGW32__) && __GNUC__ == 3
+#  define MINGW_STATIC
+# else
+#  define MINGW_STATIC static
+# endif
 
 MINGW_STATIC void
 tiff_handler (const char *, const char *, const char *, va_list)
@@ -6927,7 +7135,7 @@ tiff_handler (const char *log_format, const char *title,
   add_to_log (log_format, build_string (title),
              make_string (buf, max (0, min (len, sizeof buf - 1))));
 }
-#undef MINGW_STATIC
+# undef MINGW_STATIC
 
 static void tiff_error_handler (const char *, const char *, va_list)
   ATTRIBUTE_FORMAT_PRINTF (2, 0);
@@ -6966,8 +7174,8 @@ tiff_load (struct frame *f, struct image *img)
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
 
-  fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
-  fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
+  TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
+  TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
 
   if (NILP (specified_data))
     {
@@ -6978,12 +7186,12 @@ tiff_load (struct frame *f, struct image *img)
          image_error ("Cannot find image file `%s'", specified_file, Qnil);
          return 0;
        }
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
       file = ansi_encode_filename (file);
-#endif
+# endif
 
       /* Try to open the image file.  */
-      tiff = fn_TIFFOpen (SSDATA (file), "r");
+      tiff = TIFFOpen (SSDATA (file), "r");
       if (tiff == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
@@ -7003,14 +7211,14 @@ tiff_load (struct frame *f, struct image *img)
       memsrc.len = SBYTES (specified_data);
       memsrc.index = 0;
 
-      tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
-                               tiff_read_from_memory,
-                               tiff_write_from_memory,
-                               tiff_seek_in_memory,
-                               tiff_close_memory,
-                               tiff_size_of_memory,
-                               tiff_mmap_memory,
-                               tiff_unmap_memory);
+      tiff = TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
+                            tiff_read_from_memory,
+                            tiff_write_from_memory,
+                            tiff_seek_in_memory,
+                            tiff_close_memory,
+                            tiff_size_of_memory,
+                            tiff_mmap_memory,
+                            tiff_unmap_memory);
 
       if (!tiff)
        {
@@ -7024,24 +7232,24 @@ tiff_load (struct frame *f, struct image *img)
     {
       EMACS_INT ino = XFASTINT (image);
       if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
-            && fn_TIFFSetDirectory (tiff, ino)))
+            && TIFFSetDirectory (tiff, ino)))
        {
          image_error ("Invalid image number `%s' in image `%s'",
                       image, img->spec);
-         fn_TIFFClose (tiff);
+         TIFFClose (tiff);
          return 0;
        }
     }
 
   /* Get width and height of the image, and allocate a raster buffer
      of width x height 32-bit values.  */
-  fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
-  fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+  TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
+  TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
 
   if (!check_image_size (f, width, height))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
-      fn_TIFFClose (tiff);
+      TIFFClose (tiff);
       return 0;
     }
 
@@ -7050,16 +7258,16 @@ tiff_load (struct frame *f, struct image *img)
         && image_create_x_image_and_pixmap (f, img, width, height, 0,
                                             &ximg, 0)))
     {
-      fn_TIFFClose (tiff);
+      TIFFClose (tiff);
       return 0;
     }
 
   buf = xmalloc (sizeof *buf * width * height);
 
-  rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+  rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
 
   /* Count the number of images in the file.  */
-  for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
+  for (count = 1; TIFFSetDirectory (tiff, count); count++)
     continue;
 
   if (count > 1)
@@ -7067,7 +7275,7 @@ tiff_load (struct frame *f, struct image *img)
                            Fcons (make_number (count),
                                   img->lisp_data));
 
-  fn_TIFFClose (tiff);
+  TIFFClose (tiff);
   if (!rc)
     {
       image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
@@ -7075,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 ();
 
@@ -7093,11 +7324,11 @@ tiff_load (struct frame *f, struct image *img)
        }
     }
 
-#ifdef COLOR_TABLE_SUPPORT
+# ifdef COLOR_TABLE_SUPPORT
   /* Remember the colors allocated for the image.  Free the color table.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
-#endif /* COLOR_TABLE_SUPPORT */
+# endif /* COLOR_TABLE_SUPPORT */
 
   img->width = width;
   img->height = height;
@@ -7109,14 +7340,15 @@ 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;
 }
 
-#else /* HAVE_TIFF */
+#elif defined HAVE_NS
 
-#ifdef HAVE_NS
 static bool
 tiff_load (struct frame *f, struct image *img)
 {
@@ -7124,9 +7356,8 @@ tiff_load (struct frame *f, struct image *img)
                         image_spec_value (img->spec, QCfile, NULL),
                         image_spec_value (img->spec, QCdata, NULL));
 }
-#endif  /* HAVE_NS */
 
-#endif /* !HAVE_TIFF */
+#endif
 
 
 \f
@@ -7140,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
@@ -7190,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,
@@ -7226,54 +7453,54 @@ gif_image_p (Lisp_Object object)
 
 #ifdef HAVE_GIF
 
-#if defined (HAVE_NTGUI)
+# ifdef HAVE_NTGUI
 
 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
    Undefine before redefining to avoid a preprocessor warning.  */
-#ifdef DrawText
-#undef DrawText
-#endif
+#  ifdef DrawText
+#   undef DrawText
+#  endif
 /* avoid conflict with QuickdrawText.h */
-#define DrawText gif_DrawText
-#include <gif_lib.h>
-#undef DrawText
+#  define DrawText gif_DrawText
+#  include <gif_lib.h>
+#  undef DrawText
 
 /* Giflib before 5.0 didn't define these macros (used only if HAVE_NTGUI).  */
-#ifndef GIFLIB_MINOR
-#define GIFLIB_MINOR 0
-#endif
-#ifndef GIFLIB_RELEASE
-#define GIFLIB_RELEASE 0
-#endif
+#  ifndef GIFLIB_MINOR
+#   define GIFLIB_MINOR 0
+#  endif
+#  ifndef GIFLIB_RELEASE
+#   define GIFLIB_RELEASE 0
+#  endif
 
-#else /* HAVE_NTGUI */
+# else /* HAVE_NTGUI */
 
-#include <gif_lib.h>
+#  include <gif_lib.h>
 
-#endif /* HAVE_NTGUI */
+# endif /* HAVE_NTGUI */
 
 /* Giflib before 5.0 didn't define these macros.  */
-#ifndef GIFLIB_MAJOR
-#define GIFLIB_MAJOR 4
-#endif
+# ifndef GIFLIB_MAJOR
+#  define GIFLIB_MAJOR 4
+# endif
 
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
 
 /* GIF library details.  */
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
-DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *, int *));
-#else
-DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
-#endif
-DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
-#if GIFLIB_MAJOR < 5
-DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
-DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
-#else
-DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc, int *));
-DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *, int *));
-DEF_IMGLIB_FN (char *, GifErrorString, (int));
-#endif
+#  if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
+DEF_DLL_FN (int, DGifCloseFile, (GifFileType *, int *));
+#   else
+DEF_DLL_FN (int, DGifCloseFile, (GifFileType *));
+#  endif
+DEF_DLL_FN (int, DGifSlurp, (GifFileType *));
+#  if GIFLIB_MAJOR < 5
+DEF_DLL_FN (GifFileType *, DGifOpen, (void *, InputFunc));
+DEF_DLL_FN (GifFileType *, DGifOpenFileName, (const char *));
+#  else
+DEF_DLL_FN (GifFileType *, DGifOpen, (void *, InputFunc, int *));
+DEF_DLL_FN (GifFileType *, DGifOpenFileName, (const char *, int *));
+DEF_DLL_FN (char *, GifErrorString, (int));
+#  endif
 
 static bool
 init_gif_functions (void)
@@ -7283,27 +7510,29 @@ init_gif_functions (void)
   if (!(library = w32_delayed_load (Qgif)))
     return 0;
 
-  LOAD_IMGLIB_FN (library, DGifCloseFile);
-  LOAD_IMGLIB_FN (library, DGifSlurp);
-  LOAD_IMGLIB_FN (library, DGifOpen);
-  LOAD_IMGLIB_FN (library, DGifOpenFileName);
-#if GIFLIB_MAJOR >= 5
-  LOAD_IMGLIB_FN (library, GifErrorString);
-#endif
+  LOAD_DLL_FN (library, DGifCloseFile);
+  LOAD_DLL_FN (library, DGifSlurp);
+  LOAD_DLL_FN (library, DGifOpen);
+  LOAD_DLL_FN (library, DGifOpenFileName);
+#  if GIFLIB_MAJOR >= 5
+  LOAD_DLL_FN (library, GifErrorString);
+#  endif
   return 1;
 }
 
-#else
+#  undef DGifCloseFile
+#  undef DGifOpen
+#  undef DGifOpenFileName
+#  undef DGifSlurp
+#  undef GifErrorString
 
-#define fn_DGifCloseFile       DGifCloseFile
-#define fn_DGifSlurp           DGifSlurp
-#define fn_DGifOpen            DGifOpen
-#define fn_DGifOpenFileName    DGifOpenFileName
-#if 5 <= GIFLIB_MAJOR
-# define fn_GifErrorString     GifErrorString
-#endif
+#  define DGifCloseFile fn_DGifCloseFile
+#  define DGifOpen fn_DGifOpen
+#  define DGifOpenFileName fn_DGifOpenFileName
+#  define DGifSlurp fn_DGifSlurp
+#  define GifErrorString fn_GifErrorString
 
-#endif /* WINDOWSNT */
+# endif /* WINDOWSNT */
 
 /* Reading a GIF image from memory
    Based on the PNG memory stuff to a certain extent. */
@@ -7339,10 +7568,10 @@ gif_close (GifFileType *gif, int *err)
 {
   int retval;
 
-#if 5 < GIFLIB_MAJOR + (1 <= GIFLIB_MINOR)
-  retval = fn_DGifCloseFile (gif, err);
+#if GIFLIB_MAJOR + (GIFLIB_MINOR >= 1) > 5
+  retval = DGifCloseFile (gif, err);
 #else
-  retval = fn_DGifCloseFile (gif);
+  retval = DGifCloseFile (gif);
 #if GIFLIB_MAJOR >= 5
   if (err)
     *err = gif->Error;
@@ -7364,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;
@@ -7376,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);
@@ -7390,18 +7624,18 @@ gif_load (struct frame *f, struct image *img)
 
       /* Open the GIF file.  */
 #if GIFLIB_MAJOR < 5
-      gif = fn_DGifOpenFileName (SSDATA (file));
+      gif = DGifOpenFileName (SSDATA (file));
       if (gif == NULL)
        {
          image_error ("Cannot open `%s'", file, Qnil);
          return 0;
        }
 #else
-      gif = fn_DGifOpenFileName (SSDATA (file), &gif_err);
+      gif = DGifOpenFileName (SSDATA (file), &gif_err);
       if (gif == NULL)
        {
          image_error ("Cannot open `%s': %s",
-                      file, build_string (fn_GifErrorString (gif_err)));
+                      file, build_string (GifErrorString (gif_err)));
          return 0;
        }
 #endif
@@ -7421,18 +7655,18 @@ gif_load (struct frame *f, struct image *img)
       memsrc.index = 0;
 
 #if GIFLIB_MAJOR < 5
-      gif = fn_DGifOpen (&memsrc, gif_read_from_memory);
+      gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
          return 0;
        }
 #else
-      gif = fn_DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
+      gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s': %s",
-                      img->spec, build_string (fn_GifErrorString (gif_err)));
+                      img->spec, build_string (GifErrorString (gif_err)));
          return 0;
        }
 #endif
@@ -7447,7 +7681,7 @@ gif_load (struct frame *f, struct image *img)
     }
 
   /* Read entire contents.  */
-  rc = fn_DGifSlurp (gif);
+  rc = DGifSlurp (gif);
   if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
       image_error ("Error reading `%s'", img->spec, Qnil);
@@ -7494,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))
        {
@@ -7504,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))
     {
@@ -7530,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.   */
 
@@ -7584,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)
          {
@@ -7604,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)
@@ -7621,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
+                  }
              }
        }
     }
@@ -7681,7 +7965,7 @@ gif_load (struct frame *f, struct image *img)
   if (gif_close (gif, &gif_err) == GIF_ERROR)
     {
 #if 5 <= GIFLIB_MAJOR
-      char *error_text = fn_GifErrorString (gif_err);
+      char *error_text = GifErrorString (gif_err);
 
       if (error_text)
        image_error ("Error closing `%s': %s",
@@ -7691,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.  */
@@ -7698,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;
 }
@@ -7812,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 *);
@@ -7877,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,
@@ -8593,7 +8879,7 @@ and `imagemagick-types-inhibit'.  */)
                                 SVG
  ***********************************************************************/
 
-#if defined (HAVE_RSVG)
+#ifdef HAVE_RSVG
 
 /* Function prototypes.  */
 
@@ -8603,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
@@ -8641,11 +8923,11 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
-#if defined HAVE_NTGUI && defined WINDOWSNT
+# if defined HAVE_NTGUI && defined WINDOWSNT
 static bool init_svg_functions (void);
-#else
+# else
 #define init_svg_functions NULL
-#endif
+# endif
 
 /* Structure describing the image type `svg'.  Its the same type of
    structure defined for all image formats, handled by emacs image
@@ -8653,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,
@@ -8679,34 +8961,34 @@ svg_image_p (Lisp_Object object)
   return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
 }
 
-#include <librsvg/rsvg.h>
+# include <librsvg/rsvg.h>
 
-#ifdef WINDOWSNT
+# ifdef WINDOWSNT
 
 /* SVG library functions.  */
-DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new, (void));
-DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions, (RsvgHandle *, RsvgDimensionData *));
-DEF_IMGLIB_FN (gboolean, rsvg_handle_write, (RsvgHandle *, const guchar *, gsize, GError **));
-DEF_IMGLIB_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **));
-DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *));
-DEF_IMGLIB_FN (void, rsvg_handle_set_base_uri, (RsvgHandle *, const char *));
-
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *));
-DEF_IMGLIB_FN (guchar *, gdk_pixbuf_get_pixels, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_rowstride, (const GdkPixbuf *));
-DEF_IMGLIB_FN (GdkColorspace, gdk_pixbuf_get_colorspace, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels, (const GdkPixbuf *));
-DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha, (const GdkPixbuf *));
-DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample, (const GdkPixbuf *));
-
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
-DEF_IMGLIB_FN (void, g_type_init, (void));
-#endif
-DEF_IMGLIB_FN (void, g_object_unref, (gpointer));
-DEF_IMGLIB_FN (void, g_error_free, (GError *));
-
-Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
+DEF_DLL_FN (RsvgHandle *, rsvg_handle_new, (void));
+DEF_DLL_FN (void, rsvg_handle_get_dimensions,
+           (RsvgHandle *, RsvgDimensionData *));
+DEF_DLL_FN (gboolean, rsvg_handle_write,
+           (RsvgHandle *, const guchar *, gsize, GError **));
+DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **));
+DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *));
+DEF_DLL_FN (void, rsvg_handle_set_base_uri, (RsvgHandle *, const char *));
+
+DEF_DLL_FN (int, gdk_pixbuf_get_width, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_height, (const GdkPixbuf *));
+DEF_DLL_FN (guchar *, gdk_pixbuf_get_pixels, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_rowstride, (const GdkPixbuf *));
+DEF_DLL_FN (GdkColorspace, gdk_pixbuf_get_colorspace, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_n_channels, (const GdkPixbuf *));
+DEF_DLL_FN (gboolean, gdk_pixbuf_get_has_alpha, (const GdkPixbuf *));
+DEF_DLL_FN (int, gdk_pixbuf_get_bits_per_sample, (const GdkPixbuf *));
+
+#  if ! GLIB_CHECK_VERSION (2, 36, 0)
+DEF_DLL_FN (void, g_type_init, (void));
+#  endif
+DEF_DLL_FN (void, g_object_unref, (gpointer));
+DEF_DLL_FN (void, g_error_free, (GError *));
 
 static bool
 init_svg_functions (void)
@@ -8724,56 +9006,71 @@ init_svg_functions (void)
       return 0;
     }
 
-  LOAD_IMGLIB_FN (library, rsvg_handle_new);
-  LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
-  LOAD_IMGLIB_FN (library, rsvg_handle_write);
-  LOAD_IMGLIB_FN (library, rsvg_handle_close);
-  LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
-  LOAD_IMGLIB_FN (library, rsvg_handle_set_base_uri);
-
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
-  LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
-
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
-  LOAD_IMGLIB_FN (gobject, g_type_init);
-#endif
-  LOAD_IMGLIB_FN (gobject, g_object_unref);
-  LOAD_IMGLIB_FN (glib, g_error_free);
+  LOAD_DLL_FN (library, rsvg_handle_new);
+  LOAD_DLL_FN (library, rsvg_handle_get_dimensions);
+  LOAD_DLL_FN (library, rsvg_handle_write);
+  LOAD_DLL_FN (library, rsvg_handle_close);
+  LOAD_DLL_FN (library, rsvg_handle_get_pixbuf);
+  LOAD_DLL_FN (library, rsvg_handle_set_base_uri);
+
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_width);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_height);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_pixels);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_rowstride);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_colorspace);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_n_channels);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_has_alpha);
+  LOAD_DLL_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
+
+#  if ! GLIB_CHECK_VERSION (2, 36, 0)
+  LOAD_DLL_FN (gobject, g_type_init);
+#  endif
+  LOAD_DLL_FN (gobject, g_object_unref);
+  LOAD_DLL_FN (glib, g_error_free);
 
   return 1;
 }
 
-#else
 /* The following aliases for library functions allow dynamic loading
    to be used on some platforms.  */
-#define fn_rsvg_handle_new             rsvg_handle_new
-#define fn_rsvg_handle_get_dimensions   rsvg_handle_get_dimensions
-#define fn_rsvg_handle_write           rsvg_handle_write
-#define fn_rsvg_handle_close           rsvg_handle_close
-#define fn_rsvg_handle_get_pixbuf      rsvg_handle_get_pixbuf
-#define fn_rsvg_handle_set_base_uri    rsvg_handle_set_base_uri
-
-#define fn_gdk_pixbuf_get_width                  gdk_pixbuf_get_width
-#define fn_gdk_pixbuf_get_height         gdk_pixbuf_get_height
-#define fn_gdk_pixbuf_get_pixels         gdk_pixbuf_get_pixels
-#define fn_gdk_pixbuf_get_rowstride      gdk_pixbuf_get_rowstride
-#define fn_gdk_pixbuf_get_colorspace     gdk_pixbuf_get_colorspace
-#define fn_gdk_pixbuf_get_n_channels     gdk_pixbuf_get_n_channels
-#define fn_gdk_pixbuf_get_has_alpha      gdk_pixbuf_get_has_alpha
-#define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
 
-#if ! GLIB_CHECK_VERSION (2, 36, 0)
-#define fn_g_type_init                    g_type_init
-#endif
-#define fn_g_object_unref                 g_object_unref
-#define fn_g_error_free                   g_error_free
-#endif /* !WINDOWSNT  */
+#  undef gdk_pixbuf_get_bits_per_sample
+#  undef gdk_pixbuf_get_colorspace
+#  undef gdk_pixbuf_get_has_alpha
+#  undef gdk_pixbuf_get_height
+#  undef gdk_pixbuf_get_n_channels
+#  undef gdk_pixbuf_get_pixels
+#  undef gdk_pixbuf_get_rowstride
+#  undef gdk_pixbuf_get_width
+#  undef g_error_free
+#  undef g_object_unref
+#  undef g_type_init
+#  undef rsvg_handle_close
+#  undef rsvg_handle_get_dimensions
+#  undef rsvg_handle_get_pixbuf
+#  undef rsvg_handle_new
+#  undef rsvg_handle_set_base_uri
+#  undef rsvg_handle_write
+
+#  define gdk_pixbuf_get_bits_per_sample fn_gdk_pixbuf_get_bits_per_sample
+#  define gdk_pixbuf_get_colorspace fn_gdk_pixbuf_get_colorspace
+#  define gdk_pixbuf_get_has_alpha fn_gdk_pixbuf_get_has_alpha
+#  define gdk_pixbuf_get_height fn_gdk_pixbuf_get_height
+#  define gdk_pixbuf_get_n_channels fn_gdk_pixbuf_get_n_channels
+#  define gdk_pixbuf_get_pixels fn_gdk_pixbuf_get_pixels
+#  define gdk_pixbuf_get_rowstride fn_gdk_pixbuf_get_rowstride
+#  define gdk_pixbuf_get_width fn_gdk_pixbuf_get_width
+#  define g_error_free fn_g_error_free
+#  define g_object_unref fn_g_object_unref
+#  define g_type_init fn_g_type_init
+#  define rsvg_handle_close fn_rsvg_handle_close
+#  define rsvg_handle_get_dimensions fn_rsvg_handle_get_dimensions
+#  define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf
+#  define rsvg_handle_new fn_rsvg_handle_new
+#  define rsvg_handle_set_base_uri fn_rsvg_handle_set_base_uri
+#  define rsvg_handle_write fn_rsvg_handle_write
+
+# endif /* !WINDOWSNT  */
 
 /* Load SVG image IMG for use on frame F.  Value is true if
    successful.  */
@@ -8862,28 +9159,28 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
 #if ! GLIB_CHECK_VERSION (2, 36, 0)
   /* g_type_init is a glib function that must be called prior to
      using gnome type library functions (obsolete since 2.36.0).  */
-  fn_g_type_init ();
+  g_type_init ();
 #endif
 
   /* Make a handle to a new rsvg object.  */
-  rsvg_handle = fn_rsvg_handle_new ();
+  rsvg_handle = rsvg_handle_new ();
 
   /* Set base_uri for properly handling referenced images (via 'href').
      See rsvg bug 596114 - "image refs are relative to curdir, not .svg file"
      (https://bugzilla.gnome.org/show_bug.cgi?id=596114). */
   if (filename)
-    fn_rsvg_handle_set_base_uri(rsvg_handle, filename);
+    rsvg_handle_set_base_uri(rsvg_handle, filename);
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
-  fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
+  rsvg_handle_write (rsvg_handle, contents, size, &err);
   if (err) goto rsvg_error;
 
   /* The parsing is complete, rsvg_handle is ready to used, close it
      for further writes.  */
-  fn_rsvg_handle_close (rsvg_handle, &err);
+  rsvg_handle_close (rsvg_handle, &err);
   if (err) goto rsvg_error;
 
-  fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
+  rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
@@ -8892,26 +9189,57 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
 
   /* We can now get a valid pixel buffer from the svg file, if all
      went ok.  */
-  pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
+  pixbuf = rsvg_handle_get_pixbuf (rsvg_handle);
   if (!pixbuf) goto rsvg_error;
-  fn_g_object_unref (rsvg_handle);
+  g_object_unref (rsvg_handle);
 
   /* Extract some meta data from the svg handle.  */
-  width     = fn_gdk_pixbuf_get_width (pixbuf);
-  height    = fn_gdk_pixbuf_get_height (pixbuf);
-  pixels    = fn_gdk_pixbuf_get_pixels (pixbuf);
-  rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
+  width     = gdk_pixbuf_get_width (pixbuf);
+  height    = gdk_pixbuf_get_height (pixbuf);
+  pixels    = gdk_pixbuf_get_pixels (pixbuf);
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
 
   /* Validate the svg meta data.  */
-  eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
-  eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
-  eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
-  eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
+  eassert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
+  eassert (gdk_pixbuf_get_n_channels (pixbuf) == 4);
+  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))
     {
-      fn_g_object_unref (pixbuf);
+      g_object_unref (pixbuf);
       return 0;
     }
 
@@ -8968,7 +9296,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   free_color_table ();
 #endif /* COLOR_TABLE_SUPPORT */
 
-  fn_g_object_unref (pixbuf);
+  g_object_unref (pixbuf);
 
   img->width  = width;
   img->height = height;
@@ -8979,15 +9307,16 @@ 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;
 
  rsvg_error:
-  fn_g_object_unref (rsvg_handle);
+  g_object_unref (rsvg_handle);
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
   image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
-  fn_g_error_free (err);
+  g_error_free (err);
   return 0;
 }
 
@@ -9010,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
@@ -9058,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,
@@ -9250,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
@@ -9306,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;
@@ -9370,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
@@ -9433,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");
@@ -9451,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");
@@ -9468,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