]> code.delx.au - gnu-emacs/blobdiff - src/image.c
(erc-match-syntax-table): Replace `legal' with `valid'.
[gnu-emacs] / src / image.c
index fb3cdecaa54d409f45d92fbc1bd0344fb65dd304..71a8c4b4995d4dce5fdc0f30776092927abbd5d7 100644 (file)
@@ -1,12 +1,13 @@
 /* Functions for image support on window system.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -39,6 +40,8 @@ Boston, MA 02110-1301, USA.  */
 #include "blockinput.h"
 #include "systime.h"
 #include <epaths.h>
+#include "charset.h"
+#include "coding.h"
 
 
 #ifdef HAVE_X_WINDOWS
@@ -120,8 +123,6 @@ typedef struct mac_bitmap_record Bitmap_Record;
 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
 #define x_defined_color mac_defined_color
 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
-#define XDrawLine(display, w, gc, x1, y1, x2, y2) \
-       mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
 
 #endif /* MAC_OS */
 
@@ -189,14 +190,17 @@ XPutPixel (ximage, x, y, pixel)
   PixMapHandle pixmap = GetGWorldPixMap (ximage);
   short depth = GetPixDepth (pixmap);
 
+#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
   if (depth == 32)
     {
       char *base_addr = GetPixBaseAddr (pixmap);
       short row_bytes = GetPixRowBytes (pixmap);
 
-      ((unsigned long *) (base_addr + y * row_bytes))[x] = pixel;
+      ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
     }
-  else if (depth == 1)
+  else
+#endif
+  if (depth == 1)
     {
       char *base_addr = GetPixBaseAddr (pixmap);
       short row_bytes = GetPixRowBytes (pixmap);
@@ -233,14 +237,17 @@ XGetPixel (ximage, x, y)
   PixMapHandle pixmap = GetGWorldPixMap (ximage);
   short depth = GetPixDepth (pixmap);
 
+#if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
   if (depth == 32)
     {
       char *base_addr = GetPixBaseAddr (pixmap);
       short row_bytes = GetPixRowBytes (pixmap);
 
-      return ((unsigned long *) (base_addr + y * row_bytes))[x];
+      return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
     }
-  else if (depth == 1)
+  else
+#endif
+  if (depth == 1)
     {
       char *base_addr = GetPixBaseAddr (pixmap);
       short row_bytes = GetPixRowBytes (pixmap);
@@ -272,6 +279,49 @@ XDestroyImage (ximg)
 {
   UnlockPixels (GetGWorldPixMap (ximg));
 }
+
+#if USE_CG_DRAWING
+static CGImageRef
+mac_create_cg_image_from_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  Pixmap mask;
+  CGImageRef result = NULL;
+
+  BLOCK_INPUT;
+  if (img->mask)
+    mask = img->mask;
+  else
+    {
+      mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                           img->width, img->height, 1);
+      if (mask)
+       {
+         CGrafPtr old_port;
+         GDHandle old_gdh;
+         Rect r;
+
+         GetGWorld (&old_port, &old_gdh);
+         SetGWorld (mask, NULL);
+         BackColor (blackColor); /* Don't mask.  */
+         SetRect (&r, 0, 0, img->width, img->height);
+         EraseRect (&r);
+         SetGWorld (old_port, old_gdh);
+       }
+    }
+  if (mask)
+    {
+      CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
+                               GetGWorldPixMap (mask), &result);
+      if (mask != img->mask)
+       XFreePixmap (FRAME_X_DISPLAY (f), mask);
+    }
+  UNBLOCK_INPUT;
+
+  return result;
+}
+#endif /* USE_CG_DRAWING */
 #endif /* MAC_OS */
 
 
@@ -393,8 +443,6 @@ x_create_bitmap_from_data (f, bits, width, height)
   id = x_allocate_bitmap_record (f);
 #ifdef MAC_OS
   dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
-  if (! dpyinfo->bitmaps[id - 1].bitmap_data)
-    return -1;
   bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
 #endif  /* MAC_OS */
 
@@ -554,7 +602,9 @@ x_destroy_all_bitmaps (dpyinfo)
 /* Useful functions defined in the section
    `Image type independent image structures' below. */
 
-static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
+static unsigned long four_corners_best P_ ((XImagePtr ximg,
+                                           int *corners,
+                                           unsigned long width,
                                            unsigned long height));
 
 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
@@ -608,7 +658,7 @@ x_create_bitmap_mask (f, id)
       return -1;
     }
 
-  bg = four_corners_best (ximg, width, height);
+  bg = four_corners_best (ximg, NULL, width, height);
 
   for (y = 0; y < ximg->height; ++y)
     {
@@ -683,7 +733,7 @@ Lisp_Object Qxbm;
 /* Keywords.  */
 
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata, QCtype;
+extern Lisp_Object QCdata, QCtype, Qcount;
 extern Lisp_Object Qcenter;
 Lisp_Object QCascent, QCmargin, QCrelief;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
@@ -1092,6 +1142,27 @@ or omitted means use the selected frame.  */)
   return mask;
 }
 
+DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
+       doc: /* Return extension data for image SPEC.
+FRAME is the frame on which the image will be displayed.  FRAME nil
+or omitted means use the selected frame.  */)
+     (spec, frame)
+     Lisp_Object spec, frame;
+{
+  Lisp_Object ext;
+
+  ext = Qnil;
+  if (valid_image_p (spec))
+    {
+      struct frame *f = check_x_frame (frame);
+      int id = lookup_image (f, spec);
+      struct image *img = IMAGE_FROM_ID (f, id);
+      ext = img->data.lisp_val;
+    }
+
+  return ext;
+}
+
 \f
 /***********************************************************************
                 Image type independent image structures
@@ -1122,6 +1193,7 @@ make_image (spec, hash)
   img->data.lisp_val = Qnil;
   img->ascent = DEFAULT_IMAGE_ASCENT;
   img->hash = hash;
+  img->corners[BOT_CORNER] = -1;  /* Full image */
   return img;
 }
 
@@ -1206,6 +1278,18 @@ prepare_image_for_display (f, img)
      type dependent loader function.  */
   if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
     img->load_failed_p = img->type->load (f, img) == 0;
+
+#if defined (MAC_OS) && USE_CG_DRAWING
+  if (!img->load_failed_p && img->data.ptr_val == NULL)
+    {
+      img->data.ptr_val = mac_create_cg_image_from_image (f, img);
+      if (img->data.ptr_val == NULL)
+       {
+         img->load_failed_p = 1;
+         img->type->free (f, img);
+       }
+    }
+#endif
 }
 
 
@@ -1261,30 +1345,41 @@ image_ascent (img, face, slice)
    On W32, XIMG is assumed to a device context with the bitmap selected.  */
 
 static RGB_PIXEL_COLOR
-four_corners_best (ximg, width, height)
+four_corners_best (ximg, corners, width, height)
      XImagePtr_or_DC ximg;
+     int *corners;
      unsigned long width, height;
 {
-  RGB_PIXEL_COLOR corners[4], best;
+  RGB_PIXEL_COLOR corner_pixels[4], best;
   int i, best_count;
 
-  /* Get the colors at the corners of ximg.  */
-  corners[0] = GET_PIXEL (ximg, 0, 0);
-  corners[1] = GET_PIXEL (ximg, width - 1, 0);
-  corners[2] = GET_PIXEL (ximg, width - 1, height - 1);
-  corners[3] = GET_PIXEL (ximg, 0, height - 1);
-
+  if (corners && corners[BOT_CORNER] >= 0)
+    {
+      /* Get the colors at the corner_pixels of ximg.  */
+      corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
+      corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
+      corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
+      corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
+    }
+  else
+    {
+      /* Get the colors at the corner_pixels of ximg.  */
+      corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
+      corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
+      corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
+      corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
+    }
   /* Choose the most frequently found color as background.  */
   for (i = best_count = 0; i < 4; ++i)
     {
       int j, n;
 
       for (j = n = 0; j < 4; ++j)
-       if (corners[i] == corners[j])
+       if (corner_pixels[i] == corner_pixels[j])
          ++n;
 
       if (n > best_count)
-       best = corners[i], best_count = n;
+       best = corner_pixels[i], best_count = n;
     }
 
   return best;
@@ -1343,7 +1438,7 @@ image_background (img, f, ximg)
 #endif /* !HAVE_NTGUI */
        }
 
-      img->background = four_corners_best (ximg, img->width, img->height);
+      img->background = four_corners_best (ximg, img->corners, img->width, img->height);
 
       if (free_ximg)
        Destroy_Image (ximg, prev);
@@ -1388,7 +1483,7 @@ image_background_transparent (img, f, mask)
            }
 
          img->background_transparent
-           = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN);
+           = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
 
          if (free_mask)
            Destroy_Image (mask, prev);
@@ -1452,6 +1547,14 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
       img->colors = NULL;
       img->ncolors = 0;
     }
+
+#if defined (MAC_OS) && USE_CG_DRAWING
+  if (img->data.ptr_val)
+    {
+      CGImageRelease (img->data.ptr_val);
+      img->data.ptr_val = NULL;
+    }
+#endif
 }
 
 /* Free X resources of image IMG which is used on frame F.  */
@@ -1507,6 +1610,7 @@ x_alloc_image_color (f, img, color_name, dflt)
                             Image Cache
  ***********************************************************************/
 
+static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
 static void cache_image P_ ((struct frame *f, struct image *img));
 static void postprocess_image P_ ((struct frame *, struct image *));
 
@@ -1529,6 +1633,55 @@ make_image_cache ()
 }
 
 
+/* Find an image matching SPEC in the cache, and return it.  If no
+   image is found, return NULL.  */
+static struct image *
+search_image_cache (f, spec, hash)
+     struct frame *f;
+     Lisp_Object spec;
+     unsigned hash;
+{
+  struct image *img;
+  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
+
+  if (!c) return NULL;
+
+  /* If the image spec does not specify a background color, the cached
+     image must have the same background color as the current frame.
+     The foreground color must also match, for the sake of monochrome
+     images.
+
+     In fact, we could ignore the foreground color matching condition
+     for color images, or if the image spec specifies :foreground;
+     similarly we could ignore the background color matching condition
+     for formats that don't use transparency (such as jpeg), or if the
+     image spec specifies :background.  However, the extra memory
+     usage is probably negligible in practice, so we don't bother.  */
+
+  for (img = c->buckets[i]; img; img = img->next)
+    if (img->hash == hash
+       && !NILP (Fequal (img->spec, spec))
+       && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
+       && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
+      break;
+  return img;
+}
+
+
+/* Search frame F for an image with spec SPEC, and free it.  */
+
+static void
+uncache_image (f, spec)
+     struct frame *f;
+     Lisp_Object spec;
+{
+  struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
+  if (img)
+    free_image (f, img);
+}
+
+
 /* Free image cache of frame F.  Be aware that X frames share images
    caches.  */
 
@@ -1557,9 +1710,9 @@ free_image_cache (f)
 /* Clear image cache of frame F.  FORCE_P non-zero means free all
    images.  FORCE_P zero means clear only images that haven't been
    displayed for some time.  Should be called from time to time to
-   reduce the number of loaded images.  If image-eviction-seconds is
-   non-nil, this frees images in the cache which weren't displayed for
-   at least that many seconds.  */
+   reduce the number of loaded images.  If image-cache-eviction-delay
+   is non-nil, this frees images in the cache which weren't displayed
+   for at least that many seconds.  */
 
 void
 clear_image_cache (f, force_p)
@@ -1639,6 +1792,36 @@ FRAME t means clear the image caches of all frames.  */)
 }
 
 
+DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
+       1, 2, 0,
+       doc: /* Refresh the image with specification SPEC on frame FRAME.
+If SPEC specifies an image file, the displayed image is updated with
+the current contents of that file.
+FRAME nil or omitted means use the selected frame.
+FRAME t means refresh the image on all frames.  */)
+     (spec, frame)
+     Lisp_Object spec, frame;
+{
+  if (!valid_image_p (spec))
+    error ("Invalid image specification");
+
+  if (EQ (frame, Qt))
+    {
+      Lisp_Object tail;
+      FOR_EACH_FRAME (tail, frame)
+       {
+         struct frame *f = XFRAME (frame);
+         if (FRAME_WINDOW_P (f))
+           uncache_image (f, spec);
+       }
+    }
+  else
+    uncache_image (check_x_frame (frame), spec);
+
+  return Qnil;
+}
+
+
 /* Compute masks and transform image IMG on frame F, as specified
    by the image's specification,  */
 
@@ -1722,9 +1905,7 @@ lookup_image (f, spec)
      struct frame *f;
      Lisp_Object spec;
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
   struct image *img;
-  int i;
   unsigned hash;
   struct gcpro gcpro1;
   EMACS_TIME now;
@@ -1738,12 +1919,7 @@ lookup_image (f, spec)
 
   /* Look up SPEC in the hash table of the image cache.  */
   hash = sxhash (spec, 0);
-  i = hash % IMAGE_CACHE_BUCKETS_SIZE;
-
-  for (img = c->buckets[i]; img; img = img->next)
-    if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
-      break;
-
+  img = search_image_cache (f, spec, hash);
   if (img && img->load_failed_p)
     {
       free_image (f, img);
@@ -1759,6 +1935,8 @@ lookup_image (f, spec)
       img = make_image (spec, hash);
       cache_image (f, img);
       img->load_failed_p = img->type->load (f, img) == 0;
+      img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
+      img->frame_background = FRAME_BACKGROUND_PIXEL (f);
 
       /* If we can't load the image, and we don't have a width and
         height, use some arbitrary width and height so that we can
@@ -2177,8 +2355,8 @@ static unsigned char *slurp_file P_ ((char *, int *));
 
 
 /* Find image file FILE.  Look in data-directory, then
-   x-bitmap-file-path.  Value is the full name of the file found, or
-   nil if not found.  */
+   x-bitmap-file-path.  Value is the encoded full name of the file
+   found, or nil if not found.  */
 
 Lisp_Object
 x_find_image_file (file)
@@ -2198,7 +2376,10 @@ x_find_image_file (file)
   if (fd == -1)
     file_found = Qnil;
   else
-    close (fd);
+    {
+      file_found = ENCODE_FILE (file_found);
+      close (fd);
+    }
 
   UNGCPRO;
   return file_found;
@@ -2259,23 +2440,25 @@ find_image_fsspec (specified_file, file, fss)
      Lisp_Object specified_file, *file;
      FSSpec *fss;
 {
-#if MAC_OSX
-  FSRef fsr;
-#endif
   OSErr err;
+  AEDesc desc;
 
   *file = x_find_image_file (specified_file);
   if (!STRINGP (*file))
     return fnfErr;             /* file or directory not found;
                                   incomplete pathname */
   /* Try to open the image file.  */
-#if MAC_OSX
-  err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
+  err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
+                    SBYTES (*file), typeFSS, &desc);
   if (err == noErr)
-    err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
+    {
+#if TARGET_API_MAC_CARBON
+      err = AEGetDescData (&desc, fss, sizeof (FSSpec));
 #else
-  err = posix_pathname_to_fsspec (SDATA (*file), fss);
+      *fss = *(FSSpec *)(*(desc.dataHandle));
 #endif
+      AEDisposeDesc (&desc);
+    }
   return err;
 }
 
@@ -2284,10 +2467,10 @@ image_load_qt_1 (f, img, type, fss, dh)
      struct frame *f;
      struct image *img;
      OSType type;
-     FSSpec *fss;
+     const FSSpec *fss;
      Handle dh;
 {
-  OSErr err;
+  ComponentResult err;
   GraphicsImportComponent gi;
   Rect rect;
   int width, height;
@@ -2298,8 +2481,7 @@ image_load_qt_1 (f, img, type, fss, dh)
   XImagePtr ximg;
   RGBColor bg_color;
 
-  err = OpenADefaultComponent (GraphicsImporterComponentType,
-                              type, &gi);
+  err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
   if (err != noErr)
     {
       image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
@@ -2519,7 +2701,7 @@ image_load_quartz2d (f, img, png_p)
          UNGCPRO;
          return 0;
        }
-      path = cfstring_create_with_string (file);
+      path = cfstring_create_with_utf8_cstring (SDATA (file));
       url = CFURLCreateWithFileSystemPath (NULL, path,
                                           kCFURLPOSIXPathStyle, 0);
       CFRelease (path);
@@ -2549,6 +2731,7 @@ image_load_quartz2d (f, img, png_p)
 
   if (!check_image_size (f, width, height))
     {
+      CGImageRelease (image);
       UNGCPRO;
       image_error ("Invalid image size", Qnil, Qnil);
       return 0;
@@ -2696,7 +2879,7 @@ enum xbm_token
    3. a vector of strings or bool-vectors, one for each line of the
    bitmap.
 
-   4. A string containing an in-memory XBM file.  WIDTH and HEIGHT
+   4. a string containing an in-memory XBM file.  WIDTH and HEIGHT
    may not be specified in this case because they are defined in the
    XBM file.
 
@@ -2921,7 +3104,8 @@ w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
   return bmp;
 }
 
-static void convert_mono_to_color_image (f, img, foreground, background)
+static void
+convert_mono_to_color_image (f, img, foreground, background)
      struct frame *f;
      struct image *img;
      COLORREF foreground, background;
@@ -2937,8 +3121,10 @@ static void convert_mono_to_color_image (f, img, foreground, background)
   release_frame_dc (f, hdc);
   old_prev = SelectObject (old_img_dc, img->pixmap);
   new_prev = SelectObject (new_img_dc, new_pixmap);
-  SetTextColor (new_img_dc, foreground);
-  SetBkColor (new_img_dc, background);
+  /* Windows convention for mono bitmaps is black = background,
+     white = foreground.  */
+  SetTextColor (new_img_dc, background);
+  SetBkColor (new_img_dc, foreground);
 
   BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
          0, 0, SRCCOPY);
@@ -3041,7 +3227,7 @@ xbm_read_bitmap_data (f, contents, end, width, height, data)
       expect_ident ("define");
       expect (XBM_TK_IDENT);
 
-      if (LA1 == XBM_TK_NUMBER);
+      if (LA1 == XBM_TK_NUMBER)
        {
           char *p = strrchr (buffer, '_');
          p = p ? p + 1 : buffer;
@@ -3332,6 +3518,19 @@ xbm_load (f, img)
          else
            bits = XBOOL_VECTOR (data)->data;
 
+#ifdef WINDOWSNT
+          {
+            char *invertedBits;
+            int nbytes, i;
+            /* Windows mono bitmaps are reversed compared with X.  */
+            invertedBits = bits;
+            nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR 
+              * img->height;
+            bits = (char *) alloca(nbytes);
+            for (i = 0; i < nbytes; i++)
+              bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
+          }
+#endif
          /* Create the pixmap.  */
 
          Create_Pixmap_From_Bitmap_Data (f, img, bits,
@@ -3715,6 +3914,47 @@ xpm_image_p (object)
 
 #endif /* HAVE_XPM || MAC_OS */
 
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+int
+x_create_bitmap_from_xpm_data (f, bits)
+     struct frame *f;
+     char **bits;
+{
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+  int id, rc;
+  XpmAttributes attrs;
+  Pixmap bitmap, mask;
+
+  bzero (&attrs, sizeof attrs);
+
+  attrs.visual = FRAME_X_VISUAL (f);
+  attrs.colormap = FRAME_X_COLORMAP (f);
+  attrs.valuemask |= XpmVisual;
+  attrs.valuemask |= XpmColormap;
+
+  rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                               bits, &bitmap, &mask, &attrs);
+  if (rc != XpmSuccess)
+    {
+      XpmFreeAttributes (&attrs);
+      return -1;
+    }
+
+  id = x_allocate_bitmap_record (f);
+  dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+  dpyinfo->bitmaps[id - 1].have_mask = 1;
+  dpyinfo->bitmaps[id - 1].mask = mask;
+  dpyinfo->bitmaps[id - 1].file = NULL;
+  dpyinfo->bitmaps[id - 1].height = attrs.height;
+  dpyinfo->bitmaps[id - 1].width = attrs.width;
+  dpyinfo->bitmaps[id - 1].depth = attrs.depth;
+  dpyinfo->bitmaps[id - 1].refcount = 1;
+
+  XpmFreeAttributes (&attrs);
+  return id;
+}
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
 /* Load image IMG which will be displayed on frame F.  Value is
    non-zero if successful.  */
 
@@ -3956,25 +4196,25 @@ xpm_load (f, img)
 /* XPM support functions for Mac OS where libxpm is not available.
    Only XPM version 3 (without any extensions) is supported.  */
 
-static int xpm_scan P_ ((unsigned char **, unsigned char *,
-                        unsigned char **, int *));
+static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
+                        const unsigned char **, int *));
 static Lisp_Object xpm_make_color_table_v
-  P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
-       Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
-static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
+  P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
+       Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
+static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
                                       int, Lisp_Object));
 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
-                                             unsigned char *, int));
+                                             const unsigned char *, int));
 static Lisp_Object xpm_make_color_table_h
-  P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
-       Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
-static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
+  P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
+       Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
+static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
                                       int, Lisp_Object));
 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
-                                             unsigned char *, int));
-static int xpm_str_to_color_key P_ ((char *));
+                                             const unsigned char *, int));
+static int xpm_str_to_color_key P_ ((const char *));
 static int xpm_load_image P_ ((struct frame *, struct image *,
-                              unsigned char *, unsigned char *));
+                              const unsigned char *, const unsigned char *));
 
 /* Tokens returned from xpm_scan.  */
 
@@ -3994,7 +4234,7 @@ enum xpm_token
 
 static int
 xpm_scan (s, end, beg, len)
-     unsigned char **s, *end, **beg;
+     const unsigned char **s, *end, **beg;
      int *len;
 {
   int c;
@@ -4051,7 +4291,7 @@ xpm_scan (s, end, beg, len)
   return XPM_TK_EOF;
 }
 
-/* Functions for color table lookup in XPM data.  A Key is a string
+/* Functions for color table lookup in XPM data.  A key is a string
    specifying the color of each pixel in XPM data.  A value is either
    an integer that specifies a pixel color, Qt that specifies
    transparency, or Qnil for the unspecified color.  If the length of
@@ -4060,8 +4300,8 @@ xpm_scan (s, end, beg, len)
 
 static Lisp_Object
 xpm_make_color_table_v (put_func, get_func)
-     void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
-     Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
+     void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+     Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
 {
   *put_func = xpm_put_color_table_v;
   *get_func = xpm_get_color_table_v;
@@ -4071,7 +4311,7 @@ xpm_make_color_table_v (put_func, get_func)
 static void
 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
      Lisp_Object color_table;
-     unsigned char *chars_start;
+     const unsigned char *chars_start;
      int chars_len;
      Lisp_Object color;
 {
@@ -4081,7 +4321,7 @@ xpm_put_color_table_v (color_table, chars_start, chars_len, color)
 static Lisp_Object
 xpm_get_color_table_v (color_table, chars_start, chars_len)
      Lisp_Object color_table;
-     unsigned char *chars_start;
+     const unsigned char *chars_start;
      int chars_len;
 {
   return XVECTOR (color_table)->contents[*chars_start];
@@ -4089,8 +4329,8 @@ xpm_get_color_table_v (color_table, chars_start, chars_len)
 
 static Lisp_Object
 xpm_make_color_table_h (put_func, get_func)
-     void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
-     Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
+     void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+     Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
 {
   *put_func = xpm_put_color_table_h;
   *get_func = xpm_get_color_table_h;
@@ -4103,7 +4343,7 @@ xpm_make_color_table_h (put_func, get_func)
 static void
 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
      Lisp_Object color_table;
-     unsigned char *chars_start;
+     const unsigned char *chars_start;
      int chars_len;
      Lisp_Object color;
 {
@@ -4118,7 +4358,7 @@ xpm_put_color_table_h (color_table, chars_start, chars_len, color)
 static Lisp_Object
 xpm_get_color_table_h (color_table, chars_start, chars_len)
      Lisp_Object color_table;
-     unsigned char *chars_start;
+     const unsigned char *chars_start;
      int chars_len;
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
@@ -4136,11 +4376,11 @@ enum xpm_color_key {
   XPM_COLOR_KEY_C
 };
 
-static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
+static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
 
 static int
 xpm_str_to_color_key (s)
-     char *s;
+     const char *s;
 {
   int i;
 
@@ -4156,15 +4396,15 @@ static int
 xpm_load_image (f, img, contents, end)
      struct frame *f;
      struct image *img;
-     unsigned char *contents, *end;
+     const unsigned char *contents, *end;
 {
-  unsigned char *s = contents, *beg, *str;
+  const unsigned char *s = contents, *beg, *str;
   unsigned char buffer[BUFSIZ];
   int width, height, x, y;
   int num_colors, chars_per_pixel;
   int len, LA1;
-  void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
-  Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
+  void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
+  Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
   Lisp_Object frame, color_symbols, color_table;
   int best_key, have_mask = 0;
   XImagePtr ximg = NULL, mask_img = NULL;
@@ -4258,7 +4498,7 @@ xpm_load_image (f, img, contents, end)
          if (color == NULL)
            goto failure;
 
-         while (str = strtok (NULL, " \t"))
+         while ((str = strtok (NULL, " \t")) != NULL)
            {
              next_key = xpm_str_to_color_key (str);
              if (next_key >= 0)
@@ -4286,17 +4526,21 @@ xpm_load_image (f, img, contents, end)
          Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
 
          if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
-           if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
-             color_val = Qt;
-           else if (x_defined_color (f, SDATA (XCDR (specified_color)),
-                                     &cdef, 0))
-             color_val = make_number (cdef.pixel);
+           {
+             if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
+               color_val = Qt;
+             else if (x_defined_color (f, SDATA (XCDR (specified_color)),
+                                       &cdef, 0))
+               color_val = make_number (cdef.pixel);
+           }
        }
       if (NILP (color_val) && max_key > 0)
-       if (xstricmp (max_color, "None") == 0)
-         color_val = Qt;
-       else if (x_defined_color (f, max_color, &cdef, 0))
-         color_val = make_number (cdef.pixel);
+       {
+         if (xstricmp (max_color, "None") == 0)
+           color_val = Qt;
+         else if (x_defined_color (f, max_color, &cdef, 0))
+           color_val = make_number (cdef.pixel);
+       }
       if (!NILP (color_val))
        (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
 
@@ -4337,6 +4581,10 @@ xpm_load_image (f, img, contents, end)
   img->width = width;
   img->height = height;
 
+  /* Maybe fill in the background field while we have ximg handy. */
+  if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
+    IMAGE_BACKGROUND (img, f, ximg);
+
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
   if (have_mask)
@@ -4821,7 +5069,8 @@ x_to_xcolors (f, img, rgb_p)
    created with CreateDIBSection, with the pointer to the bit values
    stored in ximg->data.  */
 
-static void XPutPixel (ximg, x, y, color)
+static void
+XPutPixel (ximg, x, y, color)
      XImagePtr  ximg;
      int x, y;
      COLORREF color;
@@ -5090,14 +5339,12 @@ x_disable_image (f, img)
       GC gc;
 
 #ifdef MAC_OS
-#define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
 #define MaskForeground(f)  PIX_MASK_DRAW
 #else
-#define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
 #define MaskForeground(f)  WHITE_PIX_DEFAULT (f)
 #endif
 
-      gc = XCreateGC_pixmap (dpy, img->pixmap);
+      gc = XCreateGC (dpy, img->pixmap, 0, NULL);
       XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
       XDrawLine (dpy, img->pixmap, gc, 0, 0,
                 img->width - 1, img->height - 1);
@@ -5107,7 +5354,7 @@ x_disable_image (f, img)
 
       if (img->mask)
        {
-         gc = XCreateGC_pixmap (dpy, img->mask);
+         gc = XCreateGC (dpy, img->mask, 0, NULL);
          XSetForeground (dpy, gc, MaskForeground (f));
          XDrawLine (dpy, img->mask, gc, 0, 0,
                     img->width - 1, img->height - 1);
@@ -5231,7 +5478,7 @@ x_build_heuristic_mask (f, img, how)
     }
 
   if (use_img_background)
-    bg = four_corners_best (ximg, img->width, img->height);
+    bg = four_corners_best (ximg, img->corners, img->width, img->height);
 
   /* Set all bits in mask_img to 1 whose color in ximg is different
      from the background color bg.  */
@@ -5573,7 +5820,17 @@ pbm_load (f, img)
            if (raw_p)
              {
                if ((x & 7) == 0)
-                 c = *p++;
+                 {
+                   if (p >= end)
+                     {
+                       x_destroy_x_image (ximg);
+                       x_clear_image (f, img);
+                       image_error ("Invalid image size in image `%s'",
+                                    img->spec, Qnil);
+                       goto error;
+                     }
+                   c = *p++;
+                 }
                g = c & 0x80;
                c <<= 1;
              }
@@ -5585,6 +5842,18 @@ pbm_load (f, img)
     }
   else
     {
+      if (raw_p
+         && ((type == PBM_GRAY)
+             ? (p + height * width > end)
+             : (p + 3 * height * width > end)))
+       {
+         x_destroy_x_image (ximg);
+         x_clear_image (f, img);
+         image_error ("Invalid image size in image `%s'",
+                      img->spec, Qnil);
+         goto error;
+       }
+
       for (y = 0; y < height; ++y)
        for (x = 0; x < width; ++x)
          {
@@ -5942,7 +6211,6 @@ png_load (f, img)
        {
          image_error ("Cannot open image file `%s'", file, Qnil);
          UNGCPRO;
-         fclose (fp);
          return 0;
        }
 
@@ -6108,11 +6376,14 @@ png_load (f, img)
                                     PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
            }
        }
+      /* The commented-out code checked if the png specifies a default
+        background color, and uses that.  Since we use the current
+        frame background, it is OK for us to ignore this.
+
       else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
-       /* Image contains a background color with which to
-          combine the image.  */
        fn_png_set_background (png_ptr, image_bg,
                               PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+       */
       else
        {
          /* Image does not contain a background color with which
@@ -6514,18 +6785,19 @@ our_common_term_source (cinfo)
    whenever more data is needed.  We read the whole image in one step,
    so this only adds a fake end of input marker at the end.  */
 
+static JOCTET our_memory_buffer[2];
+
 static boolean
 our_memory_fill_input_buffer (cinfo)
      j_decompress_ptr cinfo;
 {
   /* Insert a fake EOI marker.  */
   struct jpeg_source_mgr *src = cinfo->src;
-  static JOCTET buffer[2];
 
-  buffer[0] = (JOCTET) 0xFF;
-  buffer[1] = (JOCTET) JPEG_EOI;
+  our_memory_buffer[0] = (JOCTET) 0xFF;
+  our_memory_buffer[1] = (JOCTET) JPEG_EOI;
 
-  src->next_input_byte = buffer;
+  src->next_input_byte = our_memory_buffer;
   src->bytes_in_buffer = 2;
   return 1;
 }
@@ -7324,6 +7596,7 @@ tiff_load (f, img)
 
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
+static void gif_clear_image P_ ((struct frame *f, struct image *img));
 
 /* The symbol `gif' identifying images of this type.  */
 
@@ -7372,10 +7645,22 @@ static struct image_type gif_type =
   &Qgif,
   gif_image_p,
   gif_load,
-  x_clear_image,
+  gif_clear_image,
   NULL
 };
 
+/* Free X resources of GIF image IMG which is used on frame F.  */
+
+static void
+gif_clear_image (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  /* IMG->data.ptr_val may contain extension data.  */
+  img->data.lisp_val = Qnil;
+  x_clear_image (f, img);
+}
+
 /* Return non-zero if OBJECT is a valid GIF image specification.  */
 
 static int
@@ -7482,6 +7767,9 @@ gif_read_from_memory (file, buf, len)
 /* Load GIF image IMG for use on frame F.  Value is non-zero if
    successful.  */
 
+static int interlace_start[] = {0, 4, 2, 1};
+static int interlace_increment[] = {8, 8, 4, 2};
+
 static int
 gif_load (f, img)
      struct frame *f;
@@ -7496,7 +7784,7 @@ gif_load (f, img)
   GifFileType *gif;
   struct gcpro gcpro1;
   Lisp_Object image;
-  int ino, image_left, image_top, image_width, image_height;
+  int ino, image_height, image_width;
   gif_memory_source memsrc;
   unsigned char *raster;
 
@@ -7573,17 +7861,19 @@ gif_load (f, img)
       return 0;
     }
 
-  image_top = gif->SavedImages[ino].ImageDesc.Top;
-  image_left = gif->SavedImages[ino].ImageDesc.Left;
-  image_width = gif->SavedImages[ino].ImageDesc.Width;
+  img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
   image_height = gif->SavedImages[ino].ImageDesc.Height;
+  img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
+  image_width = gif->SavedImages[ino].ImageDesc.Width;
+  img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
 
   width = img->width = max (gif->SWidth,
                            max (gif->Image.Left + gif->Image.Width,
-                                image_left + image_width));
+                                img->corners[RIGHT_CORNER]));
   height = img->height = max (gif->SHeight,
                              max (gif->Image.Top + gif->Image.Height,
-                                  image_top + image_height));
+                                  img->corners[BOT_CORNER]));
 
   if (!check_image_size (f, width, height))
     {
@@ -7608,13 +7898,14 @@ gif_load (f, img)
   init_color_table ();
   bzero (pixel_colors, sizeof pixel_colors);
 
-  for (i = 0; i < gif_color_map->ColorCount; ++i)
-    {
-      int r = gif_color_map->Colors[i].Red << 8;
-      int g = gif_color_map->Colors[i].Green << 8;
-      int b = gif_color_map->Colors[i].Blue << 8;
-      pixel_colors[i] = lookup_rgb_color (f, r, g, b);
-    }
+  if (gif_color_map)
+    for (i = 0; i < gif_color_map->ColorCount; ++i)
+      {
+        int r = gif_color_map->Colors[i].Red << 8;
+        int g = gif_color_map->Colors[i].Green << 8;
+        int b = gif_color_map->Colors[i].Blue << 8;
+        pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+      }
 
 #ifdef COLOR_TABLE_SUPPORT
   img->colors = colors_in_color_table (&img->ncolors);
@@ -7626,19 +7917,19 @@ gif_load (f, img)
      requires more than can be done here (see the gif89 spec,
      disposal methods).  Let's simply assume that the part
      not covered by a sub-image is in the frame's background color.  */
-  for (y = 0; y < image_top; ++y)
+  for (y = 0; y < img->corners[TOP_CORNER]; ++y)
     for (x = 0; x < width; ++x)
       XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
 
-  for (y = image_top + image_height; y < height; ++y)
+  for (y = img->corners[BOT_CORNER]; y < height; ++y)
     for (x = 0; x < width; ++x)
       XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
 
-  for (y = image_top; y < image_top + image_height; ++y)
+  for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
     {
-      for (x = 0; x < image_left; ++x)
+      for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
-      for (x = image_left + image_width; x < width; ++x)
+      for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
        XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
     }
 
@@ -7649,8 +7940,6 @@ gif_load (f, img)
 
   if (gif->SavedImages[ino].ImageDesc.Interlace)
     {
-      static int interlace_start[] = {0, 4, 2, 1};
-      static int interlace_increment[] = {8, 8, 4, 2};
       int pass;
       int row = interlace_start[0];
 
@@ -7668,8 +7957,8 @@ gif_load (f, img)
          for (x = 0; x < image_width; x++)
            {
              int i = raster[(y * image_width) + x];
-             XPutPixel (ximg, x + image_left, row + image_top,
-                        pixel_colors[i]);
+             XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                        row + img->corners[TOP_CORNER], pixel_colors[i]);
            }
 
          row += interlace_increment[pass];
@@ -7681,10 +7970,29 @@ gif_load (f, img)
        for (x = 0; x < image_width; ++x)
          {
            int i = raster[y * image_width + x];
-           XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
+           XPutPixel (ximg, x + img->corners[LEFT_CORNER],
+                      y + img->corners[TOP_CORNER], pixel_colors[i]);
          }
     }
 
+  /* Save GIF image extension data for `image-extension-data'.
+     Format is (count IMAGES FUNCTION "BYTES" ...).  */
+  img->data.lisp_val = Qnil;
+  if (gif->SavedImages[ino].ExtensionBlockCount > 0)
+    {
+      ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
+      for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
+       /* Append (... FUNCTION "BYTES") */
+       img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+                                   Fcons (make_number (ext->Function),
+                                          img->data.lisp_val));
+      img->data.lisp_val = Fnreverse (img->data.lisp_val);
+    }
+  if (gif->ImageCount > 1)
+    img->data.lisp_val = Fcons (Qcount,
+                               Fcons (make_number (gif->ImageCount),
+                                      img->data.lisp_val));
+
   fn_DGifCloseFile (gif);
 
   /* Maybe fill in the background field while we have ximg handy. */
@@ -7724,8 +8032,8 @@ gif_load (f, img)
   RGBColor bg_color;
   int width, height;
   XImagePtr ximg;
-  TimeValue time;
-  struct gcpro gcpro1;
+  TimeScale time_scale;
+  TimeValue time, duration;
   int ino;
   CGrafPtr old_port;
   GDHandle old_gdh;
@@ -7733,6 +8041,9 @@ gif_load (f, img)
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
 
+  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it here. */
+  EnterMovies ();
+
   if (NILP (specified_data))
     {
       /* Read from a file */
@@ -7830,6 +8141,7 @@ gif_load (f, img)
                   image, img->spec);
       goto error;
     }
+  time_scale = GetMediaTimeScale (media);
 
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   if (!STRINGP (specified_bg) ||
@@ -7855,7 +8167,7 @@ gif_load (f, img)
   SetGWorld (old_port, old_gdh);
   SetMovieActive (movie, 1);
   SetMovieGWorld (movie, ximg, NULL);
-  SampleNumToMediaTime (media, ino + 1, &time, NULL);
+  SampleNumToMediaTime (media, ino + 1, &time, &duration);
   SetMovieTimeValue (movie, time);
   MoviesTask (movie, 0L);
   DisposeTrackMedia (media);
@@ -7863,6 +8175,24 @@ gif_load (f, img)
   DisposeMovie (movie);
   if (dh)
     DisposeHandle (dh);
+
+  /* Save GIF image extension data for `image-extension-data'.
+     Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK).  */
+  {
+    Lisp_Object gce = make_uninit_string (4);
+    int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
+
+    /* Fill the delay time field.  */
+    SSET (gce, 1, centisec & 0xff);
+    SSET (gce, 2, (centisec >> 8) & 0xff);
+    /* We don't know about other fields.  */
+    SSET (gce, 0, 0);
+    SSET (gce, 3, 0);
+
+    img->data.lisp_val = list4 (Qcount, make_number (nsamples),
+                               make_number (0xf9), gce);
+  }
+
   /* Maybe fill in the background field while we have ximg handy. */
   if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
     IMAGE_BACKGROUND (img, f, ximg);
@@ -8306,7 +8636,7 @@ syms_of_image ()
      defining the supported image types.  */
   DEFVAR_LISP ("image-types", &Vimage_types,
     doc: /* List of potentially supported image types.
-Each element of the list is a symbol for a image type, like 'jpeg or 'png.
+Each element of the list is a symbol for an image type, like 'jpeg or 'png.
 To check whether it is really supported, use `image-type-available-p'.  */);
   Vimage_types = Qnil;
 
@@ -8320,7 +8650,7 @@ alternate filenames for the corresponding external libraries.
 Emacs tries to load the libraries in the order they appear on the
 list; if none is loaded, the running session of Emacs won't
 support the image type.  Types 'pbm and 'xbm don't need to be
-listed; they're always supported.  */);
+listed; they are always supported.  */);
   Vimage_library_alist = Qnil;
   Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
 
@@ -8426,8 +8756,10 @@ non-numeric, there is no explicit limit on the size of images.  */);
 
   defsubr (&Sinit_image_library);
   defsubr (&Sclear_image_cache);
+  defsubr (&Simage_refresh);
   defsubr (&Simage_size);
   defsubr (&Simage_mask_p);
+  defsubr (&Simage_extension_data);
 
 #if GLYPH_DEBUG
   defsubr (&Simagep);
@@ -8436,7 +8768,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
 
   DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
     doc: /* Non-nil means always draw a cross over disabled images.
-Disabled images are those having an `:conversion disabled' property.
+Disabled images are those having a `:conversion disabled' property.
 A cross is always drawn on black & white displays.  */);
   cross_disabled_images = 0;
 
@@ -8455,13 +8787,9 @@ meaning don't clear the cache.  */);
 void
 init_image ()
 {
-#ifdef MAC_OS
-  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it here. */
-  EnterMovies ();
-#ifdef MAC_OSX
+#if defined (MAC_OSX) && TARGET_API_MAC_CARBON
   init_image_func_pointer ();
 #endif
-#endif
 }
 
 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9