(Qgobject): New symbol.
[bpt/emacs.git] / src / image.c
index d8b16d8..827e35d 100644 (file)
@@ -1,13 +1,14 @@
 /* Functions for image support on window system.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007 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
+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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include <stdio.h>
@@ -39,9 +38,10 @@ Boston, MA 02110-1301, USA.  */
 #include "blockinput.h"
 #include "systime.h"
 #include <epaths.h>
-#include "charset.h"
+#include "character.h"
 #include "coding.h"
-
+#include "termhooks.h"
+#include "font.h"
 
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
@@ -81,49 +81,30 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
 #endif /* HAVE_NTGUI */
 
-
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
+#include <sys/types.h>
 #include <sys/stat.h>
-#ifndef MAC_OSX
-#include <alloca.h>
-#include <sys/param.h>
-#endif
-#if TARGET_API_MAC_CARBON
-#ifdef MAC_OSX
-#include <QuickTime/QuickTime.h>
-#else  /* not MAC_OSX */
-#include <QuickTime.h>
-#endif /* not MAC_OSX */
-#else  /* not TARGET_API_MAC_CARBON */
-#include <Windows.h>
-#include <Gestalt.h>
-#include <TextUtils.h>
-#include <ImageCompression.h>
-#include <QuickTimeComponents.h>
-#endif /* not TARGET_API_MAC_CARBON */
-
-/* MAC_TODO : Color tables on Mac.  */
+
 #undef COLOR_TABLE_SUPPORT
 
-#define ZPixmap 0              /* arbitrary */
-typedef struct mac_bitmap_record Bitmap_Record;
+typedef struct ns_bitmap_record Bitmap_Record;
 
 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
 #define NO_PIXMAP 0
 
 #define RGB_PIXEL_COLOR unsigned long
+#define ZPixmap 0
 
-/* A black pixel in a mask bitmap/pixmap means ``draw a source
-   pixel''.  A white pixel means ``retain the current pixel''. */
-#define PIX_MASK_DRAW  RGB_TO_ULONG(0,0,0)
-#define PIX_MASK_RETAIN        RGB_TO_ULONG(255,255,255)
-
-#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 PIX_MASK_RETAIN        0
+#define PIX_MASK_DRAW  1
 
-#endif /* MAC_OS */
+#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
+#define x_defined_color(f, name, color_def, alloc) \
+  ns_defined_color (f, name, color_def, alloc, 0)
+#define FRAME_X_SCREEN(f) 0
+#define DefaultDepthOfScreen(screen) x_display_list->n_planes
+#endif /* HAVE_NS */
 
 
 /* Search path for bitmap files.  */
@@ -165,6 +146,7 @@ XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
      unsigned long plane_mask;         /* not used */
      int format;               /* not used */
 {
+#if !USE_MAC_IMAGE_IO
 #if GLYPH_DEBUG
   xassert (x == 0 && y == 0);
   {
@@ -176,6 +158,7 @@ XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
 #endif
 
   LockPixels (GetGWorldPixMap (pixmap));
+#endif
 
   return pixmap;
 }
@@ -186,6 +169,12 @@ XPutPixel (ximage, x, y, pixel)
      int x, y;
      unsigned long pixel;
 {
+#if USE_MAC_IMAGE_IO
+  if (ximage->bits_per_pixel == 32)
+    ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
+  else
+    ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
+#else
   PixMapHandle pixmap = GetGWorldPixMap (ximage);
   short depth = GetPixDepth (pixmap);
 
@@ -226,6 +215,7 @@ XPutPixel (ximage, x, y, pixel)
 
       SetGWorld (old_port, old_gdh);
     }
+#endif
 }
 
 static unsigned long
@@ -233,6 +223,12 @@ XGetPixel (ximage, x, y)
      XImagePtr ximage;
      int x, y;
 {
+#if USE_MAC_IMAGE_IO
+  if (ximage->bits_per_pixel == 32)
+    return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
+  else
+    return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
+#else
   PixMapHandle pixmap = GetGWorldPixMap (ximage);
   short depth = GetPixDepth (pixmap);
 
@@ -270,21 +266,78 @@ XGetPixel (ximage, x, y)
       SetGWorld (old_port, old_gdh);
       return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
     }
+#endif
 }
 
 static void
 XDestroyImage (ximg)
      XImagePtr ximg;
 {
+#if !USE_MAC_IMAGE_IO
   UnlockPixels (GetGWorldPixMap (ximg));
+#endif
 }
 
 #if USE_CG_DRAWING
+#if USE_MAC_IMAGE_IO
+void
+mac_data_provider_release_data (info, data, size)
+     void *info;
+     const void *data;
+     size_t size;
+{
+  xfree ((void *)data);
+}
+#endif
+
 static CGImageRef
 mac_create_cg_image_from_image (f, img)
      struct frame *f;
      struct image *img;
 {
+#if USE_MAC_IMAGE_IO
+  XImagePtr ximg = img->pixmap;
+  CGDataProviderRef provider;
+  CGImageRef result;
+
+  if (img->mask)
+    {
+      int x, y;
+      unsigned long color, alpha;
+
+      for (y = 0; y < ximg->height; y++)
+       for (x = 0; x < ximg->width; x++)
+         {
+           color = XGetPixel (ximg, x, y);
+           alpha = XGetPixel (img->mask, x, y);
+           XPutPixel (ximg, x, y,
+                      ARGB_TO_ULONG (alpha,
+                                     RED_FROM_ULONG (color)
+                                     * alpha / PIX_MASK_DRAW,
+                                     GREEN_FROM_ULONG (color)
+                                     * alpha / PIX_MASK_DRAW,
+                                     BLUE_FROM_ULONG (color)
+                                     * alpha / PIX_MASK_DRAW));
+         }
+      xfree (img->mask->data);
+      img->mask->data = NULL;
+    }
+  BLOCK_INPUT;
+  provider = CGDataProviderCreateWithData (NULL, ximg->data,
+                                          ximg->bytes_per_line * ximg->height,
+                                          mac_data_provider_release_data);
+  ximg->data = NULL;
+  result = CGImageCreate (ximg->width, ximg->height, 8, 32,
+                         ximg->bytes_per_line, mac_cg_color_space_rgb,
+                         ((img->mask ? kCGImageAlphaPremultipliedFirst
+                           : kCGImageAlphaNoneSkipFirst)
+                          | kCGBitmapByteOrder32Host),
+                         provider, NULL, 0, kCGRenderingIntentDefault);
+  CGDataProviderRelease (provider);
+  UNBLOCK_INPUT;
+
+  return result;
+#else
   Pixmap mask;
   CGImageRef result = NULL;
 
@@ -319,10 +372,38 @@ mac_create_cg_image_from_image (f, img)
   UNBLOCK_INPUT;
 
   return result;
+#endif
 }
 #endif /* USE_CG_DRAWING */
 #endif /* MAC_OS */
 
+#ifdef HAVE_NS
+XImagePtr
+XGetImage (Display *display, Pixmap pixmap, int x, int y,
+           unsigned int width, unsigned int height,
+           unsigned long plane_mask, int format)
+{
+  /* TODO: not sure what this function is supposed to do.. */
+  ns_retain_object(pixmap);
+  return pixmap;
+}
+
+/* use with imgs created by ns_image_for_XPM */
+unsigned long
+XGetPixel (XImagePtr ximage, int x, int y)
+{
+  return ns_get_pixel(ximage, x, y);
+}
+
+/* use with imgs created by ns_image_for_XPM; alpha set to 1;
+   pixel is assumed to be in form RGB */
+void
+XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
+{
+  ns_put_pixel(ximage, x, y, pixel);
+}
+#endif /* HAVE_NS */
+
 
 /* Functions to access the contents of a bitmap, given an id.  */
 
@@ -433,17 +514,18 @@ x_create_bitmap_from_data (f, bits, width, height)
     return -1;
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-  /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
-  if (width % 16 != 0)
-    return -1;
+#ifdef HAVE_NS
+  void *bitmap = ns_image_from_XBM(bits, width, height);
+  if (!bitmap)
+      return -1;
 #endif
 
   id = x_allocate_bitmap_record (f);
-#ifdef MAC_OS
-  dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
-  bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
-#endif  /* MAC_OS */
+
+#ifdef HAVE_NS
+  dpyinfo->bitmaps[id - 1].img = bitmap;
+  dpyinfo->bitmaps[id - 1].depth = 1;
+#endif
 
   dpyinfo->bitmaps[id - 1].file = NULL;
   dpyinfo->bitmaps[id - 1].height = height;
@@ -472,16 +554,32 @@ x_create_bitmap_from_file (f, file)
      struct frame *f;
      Lisp_Object file;
 {
-#ifdef MAC_OS
-  return -1;  /* MAC_TODO : bitmap support */
-#endif  /* MAC_OS */
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
 
 #ifdef HAVE_NTGUI
   return -1;  /* W32_TODO : bitmap support */
 #endif /* HAVE_NTGUI */
 
+#ifdef HAVE_NS
+  int id;
+  void *bitmap = ns_image_from_file(file);
+
+  if (!bitmap)
+      return -1;
+
+
+  id = x_allocate_bitmap_record (f);
+  dpyinfo->bitmaps[id - 1].img = bitmap;
+  dpyinfo->bitmaps[id - 1].refcount = 1;
+  dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
+  dpyinfo->bitmaps[id - 1].depth = 1;
+  dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
+  dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
+  strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
+  return id;
+#endif
+
 #ifdef HAVE_X_WINDOWS
-  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   unsigned int width, height;
   Pixmap bitmap;
   int xhot, yhot, result, id;
@@ -531,7 +629,7 @@ x_create_bitmap_from_file (f, file)
 /* Free bitmap B.  */
 
 static void
-Free_Bitmap_Record (dpyinfo, bm)
+free_bitmap_record (dpyinfo, bm)
      Display_Info *dpyinfo;
      Bitmap_Record *bm;
 {
@@ -545,10 +643,9 @@ Free_Bitmap_Record (dpyinfo, bm)
   DeleteObject (bm->pixmap);
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-  xfree (bm->bitmap_data);  /* Added ++kfs */
-  bm->bitmap_data = NULL;
-#endif  /* MAC_OS */
+#ifdef HAVE_NS
+  ns_release_object(bm->img);
+#endif
 
   if (bm->file)
     {
@@ -573,7 +670,7 @@ x_destroy_bitmap (f, id)
       if (--bm->refcount == 0)
        {
          BLOCK_INPUT;
-         Free_Bitmap_Record (dpyinfo, bm);
+         free_bitmap_record (dpyinfo, bm);
          UNBLOCK_INPUT;
        }
     }
@@ -590,7 +687,7 @@ x_destroy_all_bitmaps (dpyinfo)
 
   for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
     if (bm->refcount > 0)
-      Free_Bitmap_Record (dpyinfo, bm);
+      free_bitmap_record (dpyinfo, bm);
 
   dpyinfo->bitmaps_last = 0;
 }
@@ -732,9 +829,9 @@ Lisp_Object Qxbm;
 /* Keywords.  */
 
 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata, QCtype, Qcount;
+extern Lisp_Object QCdata, QCtype;
 extern Lisp_Object Qcenter;
-Lisp_Object QCascent, QCmargin, QCrelief;
+Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
@@ -1183,9 +1280,11 @@ make_image (spec, hash)
      unsigned hash;
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
+  Lisp_Object file = image_spec_value (spec, QCfile, NULL);
 
   xassert (valid_image_p (spec));
   bzero (img, sizeof *img);
+  img->dependencies = NILP (file) ? Qnil : list1 (file);
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
   xassert (img->type != NULL);
   img->spec = spec;
@@ -1206,7 +1305,7 @@ free_image (f, img)
 {
   if (img)
     {
-      struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+      struct image_cache *c = FRAME_IMAGE_CACHE (f);
 
       /* Remove IMG from the hash table of its cache.  */
       if (img->prev)
@@ -1278,17 +1377,6 @@ prepare_image_for_display (f, img)
   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
 }
 
 
@@ -1317,15 +1405,16 @@ image_ascent (img, face, slice)
        {
 #ifdef HAVE_NTGUI
          /* W32 specific version.  Why?. ++kfs  */
-         ascent = height / 2 - (FONT_DESCENT(face->font)
-                                - FONT_BASE(face->font)) / 2;
+         ascent = height / 2 - (FONT_DESCENT (face->font)
+                                - FONT_BASE (face->font)) / 2;
 #else
          /* This expression is arranged so that if the image can't be
             exactly centered, it will be moved slightly up.  This is
             because a typical font is `top-heavy' (due to the presence
             uppercase letters), so the image placement should err towards
             being top-heavy too.  It also just generally looks better.  */
-         ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
+         ascent = (height + FONT_BASE(face->font)
+                    - FONT_DESCENT(face->font) + 1) / 2;
 #endif /* HAVE_NTGUI */
        }
       else
@@ -1394,6 +1483,14 @@ four_corners_best (ximg, corners, width, height)
 #define Free_Pixmap(display, pixmap) \
   DeleteObject (pixmap)
 
+#elif defined (HAVE_NS)
+
+#define Destroy_Image(ximg, dummy) \
+  ns_release_object(ximg)
+
+#define Free_Pixmap(display, pixmap) \
+  ns_release_object(pixmap)
+
 #else
 
 #define Destroy_Image(ximg, dummy) \
@@ -1402,7 +1499,7 @@ four_corners_best (ximg, corners, width, height)
 #define Free_Pixmap(display, pixmap) \
   XFreePixmap (display, pixmap)
 
-#endif /* HAVE_NTGUI */
+#endif /* !HAVE_NTGUI && !HAVE_NS */
 
 
 /* Return the `background' field of IMG.  If IMG doesn't have one yet,
@@ -1525,6 +1622,7 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
     {
       Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
       img->pixmap = NO_PIXMAP;
+      /* NOTE (HAVE_NS): background color is NOT an indexed color! */
       img->background_valid = 0;
     }
 
@@ -1537,7 +1635,6 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
 
   if (colors_p && img->ncolors)
     {
-      /* MAC_TODO: color table support.  */
       /* W32_TODO: color table support.  */
 #ifdef HAVE_X_WINDOWS
       x_free_colors (f, img->colors, img->ncolors);
@@ -1547,13 +1644,6 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
       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.  */
@@ -1641,7 +1731,7 @@ search_image_cache (f, spec, hash)
      unsigned hash;
 {
   struct image *img;
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
   int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
 
   if (!c) return NULL;
@@ -1688,7 +1778,7 @@ void
 free_image_cache (f)
      struct frame *f;
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
   if (c)
     {
       int i;
@@ -1701,26 +1791,25 @@ free_image_cache (f)
       xfree (c->images);
       xfree (c->buckets);
       xfree (c);
-      FRAME_X_IMAGE_CACHE (f) = NULL;
+      FRAME_IMAGE_CACHE (f) = NULL;
     }
 }
 
 
-/* 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.  */
+/* Clear image cache of frame F.  FILTER=t means free all images.
+   FILTER=nil means clear only images that haven't been
+   displayed for some time.
+   Else, only free the images which have FILTER in their `dependencies'.
+   Should be called from time to time to 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)
-     struct frame *f;
-     int force_p;
+clear_image_cache (struct frame *f, Lisp_Object filter)
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
 
-  if (c && INTEGERP (Vimage_cache_eviction_delay))
+  if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
     {
       EMACS_TIME t;
       unsigned long old;
@@ -1737,7 +1826,9 @@ clear_image_cache (f, force_p)
        {
          struct image *img = c->images[i];
          if (img != NULL
-             && (force_p || img->timestamp < old))
+             && (NILP (filter) ? img->timestamp < old
+                 : (EQ (Qt, filter)
+                    || !NILP (Fmember (filter, img->dependencies)))))
            {
              free_image (f, img);
              ++nfreed;
@@ -1755,8 +1846,7 @@ clear_image_cache (f, force_p)
          FOR_EACH_FRAME (tail, frame)
            {
              struct frame *f = XFRAME (frame);
-             if (FRAME_WINDOW_P (f)
-                 && FRAME_X_IMAGE_CACHE (f) == c)
+             if (FRAME_IMAGE_CACHE (f) == c)
                clear_current_matrices (f);
            }
 
@@ -1767,25 +1857,33 @@ clear_image_cache (f, force_p)
     }
 }
 
+void
+clear_image_caches (Lisp_Object filter)
+{
+  /* FIXME: We want to do
+   * struct terminal *t;
+   * for (t = terminal_list; t; t = t->next_terminal)
+   *   clear_image_cache (t, filter); */
+  Lisp_Object tail, frame;
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_WINDOW_P (XFRAME (frame)))
+      clear_image_cache (XFRAME (frame), filter);
+}
 
 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
        0, 1, 0,
-       doc: /* Clear the image cache of FRAME.
-FRAME nil or omitted means use the selected frame.
-FRAME t means clear the image caches of all frames.  */)
-     (frame)
-     Lisp_Object frame;
-{
-  if (EQ (frame, Qt))
-    {
-      Lisp_Object tail;
-
-      FOR_EACH_FRAME (tail, frame)
-       if (FRAME_WINDOW_P (XFRAME (frame)))
-         clear_image_cache (XFRAME (frame), 1);
-    }
+       doc: /* Clear the image cache.
+FILTER nil or a frame means clear all images in the selected frame.
+FILTER t means clear the image caches of all frames.
+Anything else, means only clear those images which refer to FILTER,
+which is then usually a filename.  */)
+     (filter)
+     Lisp_Object filter;
+{
+  if (!(EQ (filter, Qnil) || FRAMEP (filter)))
+    clear_image_caches (filter);
   else
-    clear_image_cache (check_x_frame (frame), 1);
+    clear_image_cache (check_x_frame (filter), Qt);
 
   return Qnil;
 }
@@ -1904,6 +2002,7 @@ lookup_image (f, spec)
      struct frame *f;
      Lisp_Object spec;
 {
+  struct image_cache *c;
   struct image *img;
   unsigned hash;
   struct gcpro gcpro1;
@@ -1914,6 +2013,8 @@ lookup_image (f, spec)
   xassert (FRAME_WINDOW_P (f));
   xassert (valid_image_p (spec));
 
+  c = FRAME_IMAGE_CACHE (f);
+
   GCPRO1 (spec);
 
   /* Look up SPEC in the hash table of the image cache.  */
@@ -1980,8 +2081,8 @@ lookup_image (f, spec)
          if (INTEGERP (relief))
            {
              img->relief = XINT (relief);
-             img->hmargin += abs (img->relief);
-             img->vmargin += abs (img->relief);
+             img->hmargin += eabs (img->relief);
+             img->vmargin += eabs (img->relief);
            }
 
          if (! img->background_valid)
@@ -2023,7 +2124,7 @@ cache_image (f, img)
      struct frame *f;
      struct image *img;
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
   int i;
 
   /* Find a free slot in c->images.  */
@@ -2058,28 +2159,36 @@ cache_image (f, img)
 /* Call FN on every image in the image cache of frame F.  Used to mark
    Lisp Objects in the image cache.  */
 
+/* Mark Lisp objects in image IMG.  */
+
+static void
+mark_image (img)
+     struct image *img;
+{
+  mark_object (img->spec);
+  mark_object (img->dependencies);
+
+  if (!NILP (img->data.lisp_val))
+    mark_object (img->data.lisp_val);
+}
+
+
 void
-forall_images_in_image_cache (f, fn)
-     struct frame *f;
-     void (*fn) P_ ((struct image *img));
+mark_image_cache (struct image_cache *c)
 {
-  if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f))
+  if (c)
     {
-      struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
-      if (c)
-       {
-         int i;
-         for (i = 0; i < c->used; ++i)
-           if (c->images[i])
-             fn (c->images[i]);
-       }
+      int i;
+      for (i = 0; i < c->used; ++i)
+       if (c->images[i])
+         mark_image (c->images[i]);
     }
 }
 
 
 \f
 /***********************************************************************
-                         X / MAC / W32 support code
+                         X / NS / W32 support code
  ***********************************************************************/
 
 #ifdef HAVE_NTGUI
@@ -2095,7 +2204,7 @@ forall_images_in_image_cache (f, fn)
 
 /* Load a DLL implementing an image type.
    The `image-library-alist' variable associates a symbol,
-   identifying  an image type, to a list of possible filenames.
+   identifying an image type, to a list of possible filenames.
    The function returns NULL if no library could be loaded for
    the given image type, or if the library was previously loaded;
    else the handle of the DLL.  */
@@ -2251,7 +2360,7 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
 
   if (*pixmap == NULL)
     {
-      DWORD err = GetLastError();
+      DWORD err = GetLastError ();
       Lisp_Object errcode;
       /* All system errors are < 10000, so the following is safe.  */
       XSETINT (errcode, (int) err);
@@ -2264,26 +2373,17 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
 
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-  Display *display = FRAME_X_DISPLAY (f);
-  Window window = FRAME_X_WINDOW (f);
-
-  xassert (interrupt_input_blocked);
-
-  /* Allocate a pixmap of the same size.  */
-  *pixmap = XCreatePixmap (display, window, width, height, depth);
-  if (*pixmap == NO_PIXMAP)
+#ifdef HAVE_NS
+  *pixmap = ns_image_for_XPM(width, height, depth);
+  if (*pixmap == 0)
     {
       *ximg = NULL;
-      image_error ("Unable to create X pixmap", Qnil, Qnil);
+      image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
       return 0;
     }
-
-  LockPixels (GetGWorldPixMap (*pixmap));
   *ximg = *pixmap;
   return 1;
-
-#endif  /* MAC_OS */
+#endif
 }
 
 
@@ -2306,9 +2406,9 @@ x_destroy_x_image (ximg)
       ximg->data = NULL;
       xfree (ximg);
 #endif /* HAVE_NTGUI */
-#ifdef MAC_OS
-      XDestroyImage (ximg);
-#endif /* MAC_OS */
+#ifdef HAVE_NS
+      ns_release_object(ximg);
+#endif /* HAVE_NS */
     }
 }
 
@@ -2340,9 +2440,10 @@ x_put_x_image (f, ximg, pixmap, width, height)
 #endif
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
+#ifdef HAVE_NS
   xassert (ximg == pixmap);
-#endif  /* MAC_OS */
+  ns_retain_object(ximg);
+#endif
 }
 
 \f
@@ -2353,7 +2454,7 @@ x_put_x_image (f, ximg, pixmap, width, height)
 static unsigned char *slurp_file P_ ((char *, int *));
 
 
-/* Find image file FILE.  Look in data-directory, then
+/* Find image file FILE.  Look in data-directory/images, then
    x-bitmap-file-path.  Value is the encoded full name of the file
    found, or nil if not found.  */
 
@@ -2366,10 +2467,14 @@ x_find_image_file (file)
   int fd;
 
   file_found = Qnil;
-  search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
+  /* TODO I think this should use something like image-load-path
+     instead.  Unfortunately, that can contain non-string elements.  */
+  search_path = Fcons (Fexpand_file_name (build_string ("images"),
+                                         Vdata_directory),
+                      Vx_bitmap_file_path);
   GCPRO2 (file_found, search_path);
 
-  /* Try to find FILE in data-directory, then x-bitmap-file-path.  */
+  /* Try to find FILE in data-directory/images, then x-bitmap-file-path.  */
   fd = openp (search_path, file, Qnil, &file_found, Qnil);
 
   if (fd == -1)
@@ -2422,367 +2527,6 @@ slurp_file (file, size)
 
 
 \f
-#ifdef MAC_OS
-
-/***********************************************************************
-                       MAC Image Load Functions
- ***********************************************************************/
-
-static int image_load_quicktime P_ ((struct frame *, struct image *img,
-                                    OSType));
-#ifdef MAC_OSX
-static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
-#endif
-
-static OSErr
-find_image_fsspec (specified_file, file, fss)
-     Lisp_Object specified_file, *file;
-     FSSpec *fss;
-{
-  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.  */
-  err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
-                    SBYTES (*file), typeFSS, &desc);
-  if (err == noErr)
-    {
-#if TARGET_API_MAC_CARBON
-      err = AEGetDescData (&desc, fss, sizeof (FSSpec));
-#else
-      *fss = *(FSSpec *)(*(desc.dataHandle));
-#endif
-      AEDisposeDesc (&desc);
-    }
-  return err;
-}
-
-static int
-image_load_qt_1 (f, img, type, fss, dh)
-     struct frame *f;
-     struct image *img;
-     OSType type;
-     const FSSpec *fss;
-     Handle dh;
-{
-  ComponentResult err;
-  GraphicsImportComponent gi;
-  Rect rect;
-  int width, height;
-  ImageDescriptionHandle desc_handle;
-  short draw_all_pixels;
-  Lisp_Object specified_bg;
-  XColor color;
-  XImagePtr ximg;
-  RGBColor bg_color;
-
-  err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
-  if (err != noErr)
-    {
-      image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
-      return 0;
-    }
-  if (dh == NULL)
-    {
-      /* read from file system spec */
-      err = GraphicsImportSetDataFile (gi, fss);
-      if (err != noErr)
-       {
-         image_error ("Cannot set fsspec to graphics importer for '%s'",
-                      img->spec, Qnil);
-         goto error;
-       }
-    }
-  else
-    {
-      /* read from data handle */
-      err = GraphicsImportSetDataHandle (gi, dh);
-      if (err != noErr)
-       {
-         image_error ("Cannot set data handle to graphics importer for `%s'",
-                      img->spec, Qnil);
-         goto error;
-       }
-    }
-  err = GraphicsImportGetImageDescription (gi, &desc_handle);
-  if (err != noErr || desc_handle == NULL)
-    {
-      image_error ("Error reading `%s'", img->spec, Qnil);
-      goto error;
-    }
-  width = img->width = (*desc_handle)->width;
-  height = img->height = (*desc_handle)->height;
-  DisposeHandle ((Handle)desc_handle);
-
-  if (!check_image_size (f, width, height))
-    {
-      image_error ("Invalid image size", Qnil, Qnil);
-      goto error;
-    }
-
-  err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
-#if 0
-  /* Don't check the error code here.  It may have an undocumented
-     value -32766. */
-  if (err != noErr)
-    {
-      image_error ("Error reading `%s'", img->spec, Qnil);
-      goto error;
-    }
-#endif
-  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
-    {
-      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-      if (!STRINGP (specified_bg) ||
-         !mac_defined_color (f, SDATA (specified_bg), &color, 0))
-       {
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
-         color.red = RED16_FROM_ULONG (color.pixel);
-         color.green = GREEN16_FROM_ULONG (color.pixel);
-         color.blue = BLUE16_FROM_ULONG (color.pixel);
-       }
-    }
-
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    goto error;
-  if (draw_all_pixels != graphicsImporterDrawsAllPixels)
-    {
-      CGrafPtr old_port;
-      GDHandle old_gdh;
-
-      GetGWorld (&old_port, &old_gdh);
-      SetGWorld (ximg, NULL);
-      bg_color.red = color.red;
-      bg_color.green = color.green;
-      bg_color.blue = color.blue;
-      RGBBackColor (&bg_color);
-#if TARGET_API_MAC_CARBON
-      GetPortBounds (ximg, &rect);
-      EraseRect (&rect);
-#else
-      EraseRect (&(ximg->portRect));
-#endif
-      SetGWorld (old_port, old_gdh);
-    }
-  GraphicsImportSetGWorld (gi, ximg, NULL);
-  GraphicsImportDraw (gi);
-  CloseComponent (gi);
-
-  /* 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);
-
-  /* Put the image into the pixmap.  */
-  x_put_x_image (f, ximg, img->pixmap, width, height);
-  x_destroy_x_image (ximg);
-  return 1;
-
- error:
-  CloseComponent (gi);
-  return 0;
-}
-
-
-/* Load an image using the QuickTime Graphics Importer.
-   Note: The alpha channel does not work for PNG images. */
-static int
-image_load_quicktime (f, img, type)
-     struct frame *f;
-     struct image *img;
-     OSType type;
-{
-  Lisp_Object specified_file;
-  Lisp_Object specified_data;
-  OSErr err;
-
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
-
-  if (NILP (specified_data))
-    {
-      /* Read from a file */
-      Lisp_Object file;
-      FSSpec fss;
-
-      err = find_image_fsspec (specified_file, &file, &fss);
-      if (err != noErr)
-       {
-         if (err == fnfErr)
-           image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         else
-           image_error ("Cannot open `%s'", file, Qnil);
-         return 0;
-       }
-      return image_load_qt_1 (f, img, type, &fss, NULL);
-    }
-  else
-    {
-      /* Memory source! */
-      int success_p;
-      Handle dh;
-
-      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
-      if (err != noErr)
-       {
-         image_error ("Cannot allocate data handle for `%s'",
-                      img->spec, Qnil);
-         return 0;
-       }
-      success_p = image_load_qt_1 (f, img, type, NULL, dh);
-      DisposeHandle (dh);
-      return success_p;
-    }
-}
-
-
-#ifdef MAC_OSX
-/* Load a PNG/JPEG image using Quartz 2D decoding routines.
-   CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
-   So don't use this function directly but determine at runtime
-   whether it exists. */
-typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
-  (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
-static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
-
-
-static void
-init_image_func_pointer ()
-{
-  if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
-    {
-      MyCGImageCreateWithPNGDataProvider
-       = (CGImageCreateWithPNGDataProviderProcType)
-       NSAddressOfSymbol (NSLookupAndBindSymbol
-                          ("_CGImageCreateWithPNGDataProvider"));
-    }
-  else
-    MyCGImageCreateWithPNGDataProvider = NULL;
-}
-
-
-static int
-image_load_quartz2d (f, img, png_p)
-     struct frame *f;
-     struct image *img;
-     int png_p;
-{
-  Lisp_Object file, specified_file;
-  Lisp_Object specified_data, specified_bg;
-  struct gcpro gcpro1;
-  CGDataProviderRef source;
-  CGImageRef image;
-  int width, height;
-  XColor color;
-  XImagePtr ximg = NULL;
-  CGContextRef context;
-  CGRect rectangle;
-
-  /* Open the file.  */
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
-
-  file = Qnil;
-  GCPRO1 (file);
-
-  if (NILP (specified_data))
-    {
-      CFStringRef path;
-      CFURLRef url;
-
-      file = x_find_image_file (specified_file);
-      if (!STRINGP (file))
-       {
-         image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         UNGCPRO;
-         return 0;
-       }
-      path = cfstring_create_with_utf8_cstring (SDATA (file));
-      url = CFURLCreateWithFileSystemPath (NULL, path,
-                                          kCFURLPOSIXPathStyle, 0);
-      CFRelease (path);
-      source = CGDataProviderCreateWithURL (url);
-      CFRelease (url);
-    }
-  else
-    source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
-                                          SBYTES (specified_data), NULL);
-
-  if (png_p)
-    image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
-                                                  kCGRenderingIntentDefault);
-  else
-    image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
-                                              kCGRenderingIntentDefault);
-
-  CGDataProviderRelease (source);
-  if (image == NULL)
-    {
-      UNGCPRO;
-      image_error ("Error reading image `%s'", img->spec, Qnil);
-      return 0;
-    }
-  width = img->width = CGImageGetWidth (image);
-  height = img->height = CGImageGetHeight (image);
-
-  if (!check_image_size (f, width, height))
-    {
-      CGImageRelease (image);
-      UNGCPRO;
-      image_error ("Invalid image size", Qnil, Qnil);
-      return 0;
-    }
-
-  if (png_p)
-    {
-      specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-      if (!STRINGP (specified_bg) ||
-         !mac_defined_color (f, SDATA (specified_bg), &color, 0))
-       {
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
-         color.red = RED16_FROM_ULONG (color.pixel);
-         color.green = GREEN16_FROM_ULONG (color.pixel);
-         color.blue = BLUE16_FROM_ULONG (color.pixel);
-       }
-    }
-
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    {
-      CGImageRelease (image);
-      UNGCPRO;
-      return 0;
-    }
-  rectangle = CGRectMake (0, 0, width, height);
-  QDBeginCGContext (ximg, &context);
-  if (png_p)
-    {
-      CGContextSetRGBFillColor (context, color.red / 65535.0,
-                               color.green / 65535.0,
-                               color.blue / 65535.0, 1.0);
-      CGContextFillRect (context, rectangle);
-    }
-  CGContextDrawImage (context, rectangle, image);
-  QDEndCGContext (ximg, &context);
-  CGImageRelease (image);
-
-  /* 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);
-
-  /* Put the image into the pixmap.  */
-  x_put_x_image (f, ximg, img->pixmap, width, height);
-  x_destroy_x_image (ximg);
-  UNGCPRO;
-  return 1;
-}
-#endif
-
-#endif  /* MAC_OS */
-
-\f
 /***********************************************************************
                              XBM images
  ***********************************************************************/
@@ -2878,7 +2622,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.
 
@@ -3120,6 +2864,8 @@ 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);
+  /* Windows convention for mono bitmaps is black = background,
+     white = foreground.  */
   SetTextColor (new_img_dc, background);
   SetBkColor (new_img_dc, foreground);
 
@@ -3147,7 +2893,7 @@ convert_mono_to_color_image (f, img, foreground, background)
 
 
 static void
-Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
+Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
      struct frame *f;
      struct image *img;
      char *data;
@@ -3161,6 +2907,10 @@ Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
   /* If colors were specified, transfer the bitmap to a color one.  */
   if (non_default_colors)
     convert_mono_to_color_image (f, img, fg, bg);
+
+#elif defined (HAVE_NS)
+  img->pixmap = ns_image_from_XBM(data, img->width, img->height);
+
 #else
   img->pixmap
     = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
@@ -3169,7 +2919,7 @@ Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
                                   img->width, img->height,
                                   fg, bg,
                                   DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
-#endif /* HAVE_NTGUI */
+#endif /* !HAVE_NTGUI && !HAVE_NS */
 }
 
 
@@ -3515,6 +3265,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,
@@ -3540,13 +3303,13 @@ xbm_load (f, img)
                              XPM images
  ***********************************************************************/
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (HAVE_NS)
 
 static int xpm_image_p P_ ((Lisp_Object object));
 static int xpm_load P_ ((struct frame *f, struct image *img));
 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
 
-#endif /* HAVE_XPM || MAC_OS */
+#endif /* HAVE_XPM || HAVE_NS */
 
 #ifdef HAVE_XPM
 #ifdef HAVE_NTGUI
@@ -3569,7 +3332,7 @@ static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
 #endif /* HAVE_NTGUI */
 #endif /* HAVE_XPM */
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (HAVE_NS)
 /* The symbol `xpm' identifying XPM-format images.  */
 
 Lisp_Object Qxpm;
@@ -3896,7 +3659,7 @@ xpm_image_p (object)
              || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
-#endif /* HAVE_XPM || MAC_OS */
+#endif /* HAVE_XPM || HAVE_NS */
 
 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
 int
@@ -4175,9 +3938,9 @@ xpm_load (f, img)
 
 #endif /* HAVE_XPM */
 
-#ifdef MAC_OS
+#if defined (HAVE_NS) && !defined (HAVE_XPM)
 
-/* XPM support functions for Mac OS where libxpm is not available.
+/* XPM support functions for NS where libxpm is not available.
    Only XPM version 3 (without any extensions) is supported.  */
 
 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
@@ -4234,8 +3997,8 @@ xpm_scan (s, end, beg, len)
       if (isalpha (c) || c == '_' || c == '-' || c == '+')
        {
          *beg = *s - 1;
-         while (*s < end &&
-                (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
+         while (*s < end
+                && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
              ++*s;
          *len = *s - *beg;
          return XPM_TK_IDENT;
@@ -4275,7 +4038,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
@@ -4511,7 +4274,7 @@ xpm_load_image (f, img, contents, end)
 
          if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
            {
-             if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
+             if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
                color_val = Qt;
              else if (x_defined_color (f, SDATA (XCDR (specified_color)),
                                        &cdef, 0))
@@ -4520,7 +4283,7 @@ xpm_load_image (f, img, contents, end)
        }
       if (NILP (color_val) && max_key > 0)
        {
-         if (xstricmp (max_color, "None") == 0)
+         if (xstrcasecmp (max_color, "None") == 0)
            color_val = Qt;
          else if (x_defined_color (f, max_color, &cdef, 0))
            color_val = make_number (cdef.pixel);
@@ -4533,8 +4296,11 @@ xpm_load_image (f, img, contents, end)
 
   if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                    &ximg, &img->pixmap)
+#ifndef HAVE_NS
       || !x_create_x_image_and_pixmap (f, width, height, 1,
-                                      &mask_img, &img->mask))
+                                      &mask_img, &img->mask)
+#endif
+      )
     {
       image_error ("Out of memory (%s)", img->spec, Qnil);
       goto error;
@@ -4554,9 +4320,14 @@ xpm_load_image (f, img, contents, end)
          XPutPixel (ximg, x, y,
                     (INTEGERP (color_val) ? XINT (color_val)
                      : FRAME_FOREGROUND_PIXEL (f)));
+#ifndef HAVE_NS
          XPutPixel (mask_img, x, y,
                     (!EQ (color_val, Qt) ? PIX_MASK_DRAW
                      : (have_mask = 1, PIX_MASK_RETAIN)));
+#else
+          if (EQ(color_val, Qt))
+            ns_set_alpha(ximg, x, y, 0);
+#endif
        }
       if (y + 1 < height)
        expect (',');
@@ -4571,6 +4342,7 @@ xpm_load_image (f, img, contents, end)
 
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
+#ifndef HAVE_NS
   if (have_mask)
     {
       /* Fill in the background_transparent field while we have the
@@ -4586,7 +4358,7 @@ xpm_load_image (f, img, contents, end)
       Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
       img->mask = NO_PIXMAP;
     }
-
+#endif
   return 1;
 
  failure:
@@ -4652,7 +4424,7 @@ xpm_load (f, img)
   return success_p;
 }
 
-#endif /* MAC_OS */
+#endif /* HAVE_NS && !HAVE_XPM */
 
 
 \f
@@ -4913,15 +4685,13 @@ lookup_rgb_color (f, r, g, b)
 {
   unsigned long pixel;
 
-#ifdef MAC_OS
-  pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
-  gamma_correct (f, &pixel);
-#endif /* MAC_OS */
-
 #ifdef HAVE_NTGUI
   pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
 #endif /* HAVE_NTGUI */
 
+#ifdef HAVE_NS
+  pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
+#endif /* HAVE_NS */
   return pixel;
 }
 
@@ -5027,11 +4797,11 @@ x_to_xcolors (f, img, rgb_p)
          p->pixel = GET_PIXEL (ximg, x, y);
          if (rgb_p)
            {
-#ifdef MAC_OS
+#if defined (HAVE_NS)
              p->red = RED16_FROM_ULONG (p->pixel);
              p->green = GREEN16_FROM_ULONG (p->pixel);
              p->blue = BLUE16_FROM_ULONG (p->pixel);
-#endif  /* MAC_OS */
+#endif  /* HAVE_NS */
 #ifdef HAVE_NTGUI
              p->red = 256 * GetRValue (p->pixel);
              p->green = 256 * GetGValue (p->pixel);
@@ -5108,7 +4878,7 @@ x_from_xcolors (f, img, colors)
      XColor *colors;
 {
   int x, y;
-  XImagePtr oimg;
+  XImagePtr oimg = NULL;
   Pixmap pixmap;
   XColor *p;
 
@@ -5157,7 +4927,7 @@ x_detect_edges (f, img, matrix, color_adjust)
   int x, y, i, sum;
 
   for (i = sum = 0; i < 9; ++i)
-    sum += abs (matrix[i]);
+    sum += eabs (matrix[i]);
 
 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
@@ -5322,11 +5092,9 @@ x_disable_image (f, img)
       Display *dpy = FRAME_X_DISPLAY (f);
       GC gc;
 
-#ifdef MAC_OS
-#define MaskForeground(f)  PIX_MASK_DRAW
-#else
+#ifndef HAVE_NS  //TODO: NS support, however this not needed for toolbars
+
 #define MaskForeground(f)  WHITE_PIX_DEFAULT (f)
-#endif
 
       gc = XCreateGC (dpy, img->pixmap, 0, NULL);
       XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
@@ -5346,6 +5114,7 @@ x_disable_image (f, img)
                     img->width - 1, 0);
          XFreeGC (dpy, gc);
        }
+#endif /* !HAVE_NS */
 #else
       HDC hdc, bmpdc;
       HGDIOBJ prev;
@@ -5411,11 +5180,13 @@ x_build_heuristic_mask (f, img, how)
     }
 
 #ifndef HAVE_NTGUI
+#ifndef HAVE_NS
   /* Create an image and pixmap serving as mask.  */
   rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
                                    &mask_img, &img->mask);
   if (!rc)
     return 0;
+#endif /* !HAVE_NS */
 
   /* Get the X image of IMG->pixmap.  */
   ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
@@ -5469,16 +5240,21 @@ x_build_heuristic_mask (f, img, how)
 #ifndef HAVE_NTGUI
   for (y = 0; y < img->height; ++y)
     for (x = 0; x < img->width; ++x)
+#ifndef HAVE_NS
       XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
                                  ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
-
+#else
+      if (XGetPixel (ximg, x, y) == bg)
+        ns_set_alpha(ximg, x, y, 0);
+#endif /* HAVE_NS */
+#ifndef HAVE_NS
   /* Fill in the background_transparent field while we have the mask handy. */
   image_background_transparent (img, f, mask_img);
 
   /* Put mask_img into img->mask.  */
   x_put_x_image (f, mask_img, img->mask, img->width, img->height);
   x_destroy_x_image (mask_img);
-
+#endif /* !HAVE_NS */
 #else
   for (y = 0; y < img->height; ++y)
     for (x = 0; x < img->width; ++x)
@@ -5760,13 +5536,18 @@ pbm_load (f, img)
   if (type != PBM_MONO)
     {
       max_color_idx = pbm_scan_number (&p, end);
-      if (raw_p && max_color_idx > 255)
-       max_color_idx = 255;
+      if (max_color_idx > 65535 || max_color_idx < 0)
+       {
+         image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
+         goto error;
+       }
     }
 
-  if (!check_image_size (f, width, height)
-      || (type != PBM_MONO && max_color_idx < 0))
-    goto error;
+  if (!check_image_size (f, width, height))
+    {
+      image_error ("Invalid image size", Qnil, Qnil);
+      goto error;
+    }
 
   if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                    &ximg, &img->pixmap))
@@ -5826,10 +5607,13 @@ pbm_load (f, img)
     }
   else
     {
-      if (raw_p
-         && ((type == PBM_GRAY)
-             ? (p + height * width > end)
-             : (p + 3 * height * width > end)))
+      int expected_size = height * width;
+      if (max_color_idx > 255)
+       expected_size *= 2;
+      if (type == PBM_COLOR)
+       expected_size *= 3;
+
+      if (raw_p && p + expected_size > end)
        {
          x_destroy_x_image (ximg);
          x_clear_image (f, img);
@@ -5843,13 +5627,25 @@ pbm_load (f, img)
          {
            int r, g, b;
 
-           if (type == PBM_GRAY)
-             r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
+           if (type == PBM_GRAY && raw_p)
+             {
+               r = g = b = *p++;
+               if (max_color_idx > 255)
+                 r = g = b = r * 256 + *p++;
+             }
+           else if (type == PBM_GRAY)
+             r = g = b = pbm_scan_number (&p, end);
            else if (raw_p)
              {
                r = *p++;
+               if (max_color_idx > 255)
+                 r = r * 256 + *p++;
                g = *p++;
+               if (max_color_idx > 255)
+                 g = g * 256 + *p++;
                b = *p++;
+               if (max_color_idx > 255)
+                 b = b * 256 + *p++;
              }
            else
              {
@@ -5909,7 +5705,7 @@ pbm_load (f, img)
                                 PNG
  ***********************************************************************/
 
-#if defined (HAVE_PNG) || defined (MAC_OS)
+#if defined (HAVE_PNG) || defined (HAVE_NS)
 
 /* Function prototypes.  */
 
@@ -5981,7 +5777,7 @@ png_image_p (object)
   return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
 }
 
-#endif /* HAVE_PNG || MAC_OS */
+#endif /* HAVE_PNG || HAVE_NS */
 
 
 #ifdef HAVE_PNG
@@ -6170,7 +5966,6 @@ png_load (f, img)
   png_byte channels;
   png_uint_32 row_bytes;
   int transparent_p;
-  double screen_gamma;
   struct png_memory_storage tbr;  /* Data to be read */
 
   /* Find out what file to load.  */
@@ -6312,35 +6107,15 @@ png_load (f, img)
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     fn_png_set_gray_to_rgb (png_ptr);
 
-  screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
-
-#if 0 /* Avoid double gamma correction for PNG images. */
-  { /* Tell the PNG lib to handle gamma correction for us.  */
-    int intent;
-    double image_gamma;
-#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
-    if (png_get_sRGB (png_ptr, info_ptr, &intent))
-      /* The libpng documentation says this is right in this case.  */
-      png_set_gamma (png_ptr, screen_gamma, 0.45455);
-    else
-#endif
-      if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
-       /* Image contains gamma information.  */
-       png_set_gamma (png_ptr, screen_gamma, image_gamma);
-      else
-       /* Use the standard default for the image gamma.  */
-       png_set_gamma (png_ptr, screen_gamma, 0.45455);
-  }
-#endif /* if 0 */
-
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
      simple transparency, we prefer a clipping mask.  */
   if (!transparent_p)
     {
-      png_color_16 *image_bg;
+      /* png_color_16 *image_bg; */
       Lisp_Object specified_bg
        = image_spec_value (img->spec, QCbackground, NULL);
+      int shift = (bit_depth == 16) ? 0 : 8;
 
       if (STRINGP (specified_bg))
        /* The user specified `:background', use that.  */
@@ -6352,27 +6127,18 @@ png_load (f, img)
              png_color_16 user_bg;
 
              bzero (&user_bg, sizeof user_bg);
-             user_bg.red = color.red >> 8;
-             user_bg.green = color.green >> 8;
-             user_bg.blue = color.blue >> 8;
+             user_bg.red = color.red >> shift;
+             user_bg.green = color.green >> shift;
+             user_bg.blue = color.blue >> shift;
 
              fn_png_set_background (png_ptr, &user_bg,
                                     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))
-       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
-            to combine the image data via an alpha channel.  Use
-            the frame's background instead.  */
+         /* We use the current frame background, ignoring any default
+            background color set by the image.  */
 #ifdef HAVE_X_WINDOWS
          XColor color;
          png_color_16 frame_background;
@@ -6381,9 +6147,9 @@ png_load (f, img)
          x_query_color (f, &color);
 
          bzero (&frame_background, sizeof frame_background);
-         frame_background.red = color.red >> 8;
-         frame_background.green = color.green >> 8;
-         frame_background.blue = color.blue >> 8;
+         frame_background.red = color.red >> shift;
+         frame_background.green = color.green >> shift;
+         frame_background.blue = color.blue >> shift;
 #endif /* HAVE_X_WINDOWS */
 
 #ifdef HAVE_NTGUI
@@ -6399,19 +6165,6 @@ png_load (f, img)
          frame_background.blue = GetBValue (color);
 #endif /* HAVE_NTGUI */
 
-#ifdef MAC_OS
-         unsigned long color;
-         png_color_16 frame_background;
-         color = FRAME_BACKGROUND_PIXEL (f);
-#if 0 /* MAC/W32 TODO : Colormap support.  */
-         x_query_color (f, &color);
-#endif
-         bzero (&frame_background, sizeof frame_background);
-         frame_background.red = RED_FROM_ULONG (color);
-         frame_background.green = GREEN_FROM_ULONG (color);
-         frame_background.blue = BLUE_FROM_ULONG (color);
-#endif /* MAC_OS */
-
          fn_png_set_background (png_ptr, &frame_background,
                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }
@@ -6555,20 +6308,16 @@ png_load (f, img)
 
 #else /* HAVE_PNG */
 
-#ifdef MAC_OS
+#ifdef HAVE_NS
 static int
-png_load (f, img)
-     struct frame *f;
-     struct image *img;
+png_load (struct frame *f, struct image *img)
 {
-#ifdef MAC_OSX
-  if (MyCGImageCreateWithPNGDataProvider)
-    return image_load_quartz2d (f, img, 1);
-  else
-#endif
-    return image_load_quicktime (f, img, kQTFileTypePNG);
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
 }
-#endif  /* MAC_OS */
+#endif  /* HAVE_NS */
+
 
 #endif /* !HAVE_PNG */
 
@@ -6578,7 +6327,7 @@ png_load (f, img)
                                 JPEG
  ***********************************************************************/
 
-#if defined (HAVE_JPEG) || defined (MAC_OS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS)
 
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
@@ -6649,7 +6398,7 @@ jpeg_image_p (object)
   return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
 }
 
-#endif /* HAVE_JPEG || MAC_OS */
+#endif /* HAVE_JPEG || HAVE_NS */
 
 #ifdef HAVE_JPEG
 
@@ -6708,7 +6457,7 @@ init_jpeg_functions (Lisp_Object libraries)
 /* 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(cinfo, desired)
+jpeg_resync_to_restart_wrapper (cinfo, desired)
      j_decompress_ptr cinfo;
      int desired;
 {
@@ -6769,7 +6518,7 @@ 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 omfib_buffer[2];
+static JOCTET our_memory_buffer[2];
 
 static boolean
 our_memory_fill_input_buffer (cinfo)
@@ -6778,10 +6527,10 @@ our_memory_fill_input_buffer (cinfo)
   /* Insert a fake EOI marker.  */
   struct jpeg_source_mgr *src = cinfo->src;
 
-  omfib_buffer[0] = (JOCTET) 0xFF;
-  omfib_buffer[1] = (JOCTET) JPEG_EOI;
+  our_memory_buffer[0] = (JOCTET) 0xFF;
+  our_memory_buffer[1] = (JOCTET) JPEG_EOI;
 
-  src->next_input_byte = omfib_buffer;
+  src->next_input_byte = our_memory_buffer;
   src->bytes_in_buffer = 2;
   return 1;
 }
@@ -7133,19 +6882,15 @@ jpeg_load (f, img)
 
 #else /* HAVE_JPEG */
 
-#ifdef MAC_OS
+#ifdef HAVE_NS
 static int
-jpeg_load (f, img)
-     struct frame *f;
-     struct image *img;
+jpeg_load (struct frame *f, struct image *img)
 {
-#ifdef MAC_OSX
-  return image_load_quartz2d (f, img, 0);
-#else
-  return image_load_quicktime (f, img, kQTFileTypeJPEG);
-#endif
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
 }
-#endif  /* MAC_OS */
+#endif  /* HAVE_NS */
 
 #endif /* !HAVE_JPEG */
 
@@ -7155,7 +6900,7 @@ jpeg_load (f, img)
                                 TIFF
  ***********************************************************************/
 
-#if defined (HAVE_TIFF) || defined (MAC_OS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS)
 
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
@@ -7178,6 +6923,7 @@ enum tiff_keyword_index
   TIFF_HEURISTIC_MASK,
   TIFF_MASK,
   TIFF_BACKGROUND,
+  TIFF_INDEX,
   TIFF_LAST
 };
 
@@ -7195,7 +6941,8 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0},
+  {":index",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -7225,7 +6972,7 @@ tiff_image_p (object)
   return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
 }
 
-#endif /* HAVE_TIFF || MAC_OS */
+#endif /* HAVE_TIFF || HAVE_NS */
 
 #ifdef HAVE_TIFF
 
@@ -7241,6 +6988,7 @@ DEF_IMGLIB_FN (TIFFClientOpen);
 DEF_IMGLIB_FN (TIFFGetField);
 DEF_IMGLIB_FN (TIFFReadRGBAImage);
 DEF_IMGLIB_FN (TIFFClose);
+DEF_IMGLIB_FN (TIFFSetDirectory);
 
 static int
 init_tiff_functions (Lisp_Object libraries)
@@ -7257,6 +7005,7 @@ init_tiff_functions (Lisp_Object libraries)
   LOAD_IMGLIB_FN (library, TIFFGetField);
   LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
   LOAD_IMGLIB_FN (library, TIFFClose);
+  LOAD_IMGLIB_FN (library, TIFFSetDirectory);
   return 1;
 }
 
@@ -7269,7 +7018,7 @@ init_tiff_functions (Lisp_Object libraries)
 #define fn_TIFFGetField                        TIFFGetField
 #define fn_TIFFReadRGBAImage           TIFFReadRGBAImage
 #define fn_TIFFClose                   TIFFClose
-
+#define fn_TIFFSetDirectory            TIFFSetDirectory
 #endif /* HAVE_NTGUI */
 
 
@@ -7422,12 +7171,13 @@ tiff_load (f, img)
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
   TIFF *tiff;
-  int width, height, x, y;
+  int width, height, x, y, count;
   uint32 *buf;
-  int rc;
+  int rc, rc2;
   XImagePtr ximg;
   struct gcpro gcpro1;
   tiff_memory_source memsrc;
+  Lisp_Object image;
 
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
@@ -7483,6 +7233,20 @@ tiff_load (f, img)
        }
     }
 
+  image = image_spec_value (img->spec, QCindex, NULL);
+  if (INTEGERP (image))
+    {
+      int ino = XFASTINT (image);
+      if (!fn_TIFFSetDirectory (tiff, ino))
+       {
+         image_error ("Invalid image number `%s' in image `%s'",
+                      image, img->spec);
+         fn_TIFFClose (tiff);
+         UNGCPRO;
+         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);
@@ -7491,6 +7255,7 @@ tiff_load (f, img)
   if (!check_image_size (f, width, height))
     {
       image_error ("Invalid image size", Qnil, Qnil);
+      fn_TIFFClose (tiff);
       UNGCPRO;
       return 0;
     }
@@ -7498,6 +7263,16 @@ tiff_load (f, img)
   buf = (uint32 *) xmalloc (width * height * sizeof *buf);
 
   rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
+
+  /* Count the number of images in the file.  */
+  for (count = 1, rc2 = 1; rc2; count++)
+    rc2 = fn_TIFFSetDirectory (tiff, count);
+
+  if (count > 1)
+    img->data.lisp_val = Fcons (Qcount,
+                               Fcons (make_number (count),
+                                      img->data.lisp_val));
+
   fn_TIFFClose (tiff);
   if (!rc)
     {
@@ -7558,15 +7333,15 @@ tiff_load (f, img)
 
 #else /* HAVE_TIFF */
 
-#ifdef MAC_OS
+#ifdef HAVE_NS
 static int
-tiff_load (f, img)
-     struct frame *f;
-     struct image *img;
+tiff_load (struct frame *f, struct image *img)
 {
-  return image_load_quicktime (f, img, kQTFileTypeTIFF);
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
 }
-#endif /* MAC_OS */
+#endif  /* HAVE_NS */
 
 #endif /* !HAVE_TIFF */
 
@@ -7576,7 +7351,7 @@ tiff_load (f, img)
                                 GIF
  ***********************************************************************/
 
-#if defined (HAVE_GIF) || defined (MAC_OS)
+#if defined (HAVE_GIF) || defined (HAVE_NS)
 
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
@@ -7618,7 +7393,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
+  {":index",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0},
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
 };
 
@@ -7661,11 +7436,11 @@ gif_image_p (object)
   return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
 }
 
-#endif /* HAVE_GIF || MAC_OS */
+#endif /* HAVE_GIF */
 
 #ifdef HAVE_GIF
 
-#if defined (HAVE_NTGUI) || defined (MAC_OS)
+#if defined (HAVE_NTGUI)
 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
    Undefine before redefining to avoid a preprocessor warning.  */
 #ifdef DrawText
@@ -7676,11 +7451,11 @@ gif_image_p (object)
 #include <gif_lib.h>
 #undef DrawText
 
-#else /* HAVE_NTGUI || MAC_OS */
+#else /* HAVE_NTGUI */
 
 #include <gif_lib.h>
 
-#endif /* HAVE_NTGUI || MAC_OS */
+#endif /* HAVE_NTGUI */
 
 
 #ifdef HAVE_NTGUI
@@ -7806,7 +7581,7 @@ gif_load (f, img)
       memsrc.index = 0;
 
       /* Casting return value avoids a GCC warning on W32.  */
-      gif = (GifFileType *)fn_DGifOpen(&memsrc, gif_read_from_memory);
+      gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
        {
          image_error ("Cannot open memory source `%s'", img->spec, Qnil);
@@ -7994,214 +7769,432 @@ gif_load (f, img)
 
 #else  /* !HAVE_GIF */
 
-#ifdef MAC_OS
+#ifdef HAVE_NS
 static int
-gif_load (f, img)
-     struct frame *f;
-     struct image *img;
+gif_load (struct frame *f, struct image *img)
 {
-  Lisp_Object specified_file, file;
-  Lisp_Object specified_data;
-  OSErr err;
-  Boolean graphic_p, movie_p, prefer_graphic_p;
-  Handle dh = NULL;
-  Movie movie = NULL;
-  Lisp_Object image;
-  Track track = NULL;
-  Media media = NULL;
-  long nsamples;
-  Rect rect;
-  Lisp_Object specified_bg;
-  XColor color;
-  RGBColor bg_color;
-  int width, height;
-  XImagePtr ximg;
-  TimeScale time_scale;
-  TimeValue time, duration;
-  int ino;
-  CGrafPtr old_port;
-  GDHandle old_gdh;
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
+}
+#endif /* HAVE_NS */
 
-  specified_file = image_spec_value (img->spec, QCfile, NULL);
-  specified_data = image_spec_value (img->spec, QCdata, NULL);
+#endif /* HAVE_GIF */
 
-  /* Animated gifs use QuickTime Movie Toolbox.  So initialize it here. */
-  EnterMovies ();
 
-  if (NILP (specified_data))
+\f
+/***********************************************************************
+                                SVG
+ ***********************************************************************/
+
+#if defined (HAVE_RSVG)
+
+/* Function prototypes.  */
+
+static int svg_image_p P_ ((Lisp_Object object));
+static int svg_load P_ ((struct frame *f, struct image *img));
+
+static int svg_load_image P_ ((struct frame *, struct image *,
+                              unsigned char *, unsigned int));
+
+/* The symbol `svg' identifying images of this type. */
+
+Lisp_Object Qsvg;
+
+/* Indices of image specification fields in svg_format, below.  */
+
+enum svg_keyword_index
+{
+  SVG_TYPE,
+  SVG_DATA,
+  SVG_FILE,
+  SVG_ASCENT,
+  SVG_MARGIN,
+  SVG_RELIEF,
+  SVG_ALGORITHM,
+  SVG_HEURISTIC_MASK,
+  SVG_MASK,
+  SVG_BACKGROUND,
+  SVG_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+   of valid user-defined image specifications.  */
+
+static struct image_keyword svg_format[SVG_LAST] =
+{
+  {":type",            IMAGE_SYMBOL_VALUE,                     1},
+  {":data",            IMAGE_STRING_VALUE,                     0},
+  {":file",            IMAGE_STRING_VALUE,                     0},
+  {":ascent",          IMAGE_ASCENT_VALUE,                     0},
+  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":relief",          IMAGE_INTEGER_VALUE,                    0},
+  {":conversion",      IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":background",      IMAGE_STRING_OR_NIL_VALUE,              0}
+};
+
+/* Structure describing the image type `svg'.  Its the same type of
+   structure defined for all image formats, handled by emacs image
+   functions.  See struct image_type in dispextern.h.  */
+
+static struct image_type svg_type =
+{
+  /* An identifier showing that this is an image structure for the SVG format.  */
+  &Qsvg,
+  /* Handle to a function that can be used to identify a SVG file.  */
+  svg_image_p,
+  /* Handle to function used to load a SVG file.  */
+  svg_load,
+  /* Handle to function to free sresources for SVG.  */
+  x_clear_image,
+  /* An internal field to link to the next image type in a list of
+     image types, will be filled in when registering the format.  */
+  NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid SVG image specification.  Do
+   this by calling parse_image_spec and supplying the keywords that
+   identify the SVG format.   */
+
+static int
+svg_image_p (object)
+     Lisp_Object object;
+{
+  struct image_keyword fmt[SVG_LAST];
+  bcopy (svg_format, fmt, sizeof fmt);
+
+  if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
+    return 0;
+
+  /* Must specify either the :data or :file keyword.  */
+  return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
+}
+
+#include <librsvg/rsvg.h>
+
+#ifdef HAVE_NTGUI
+
+/* SVG library functions.  */
+DEF_IMGLIB_FN (rsvg_handle_new);
+DEF_IMGLIB_FN (rsvg_handle_get_dimensions);
+DEF_IMGLIB_FN (rsvg_handle_write);
+DEF_IMGLIB_FN (rsvg_handle_close);
+DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
+DEF_IMGLIB_FN (rsvg_handle_free);
+
+DEF_IMGLIB_FN (gdk_pixbuf_get_width);
+DEF_IMGLIB_FN (gdk_pixbuf_get_height);
+DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
+DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
+DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
+DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
+DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
+DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
+
+DEF_IMGLIB_FN (g_type_init);
+DEF_IMGLIB_FN (g_object_unref);
+DEF_IMGLIB_FN (g_error_free);
+
+Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
+
+static int
+init_svg_functions (Lisp_Object libraries)
+{
+  HMODULE library, gdklib, glib, gobject;
+
+  if (!(glib = w32_delayed_load (libraries, Qglib))
+      || !(gobject = w32_delayed_load (libraries, Qgobject))
+      || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
+      || !(library = w32_delayed_load (libraries, Qsvg)))
+    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_free);
+
+  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);
+
+  LOAD_IMGLIB_FN (gobject, g_type_init);
+  LOAD_IMGLIB_FN (gobject, g_object_unref);
+  LOAD_IMGLIB_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_free            rsvg_handle_free
+
+#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
+
+#define fn_g_type_init                    g_type_init
+#define fn_g_object_unref                 g_object_unref
+#define fn_g_error_free                   g_error_free
+#endif /* !HAVE_NTGUI  */
+
+/* Load SVG image IMG for use on frame F.  Value is non-zero if
+   successful. this function will go into the svg_type structure, and
+   the prototype thus needs to be compatible with that structure.  */
+
+static int
+svg_load (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  int success_p = 0;
+  Lisp_Object file_name;
+
+  /* If IMG->spec specifies a file name, create a non-file spec from it.  */
+  file_name = image_spec_value (img->spec, QCfile, NULL);
+  if (STRINGP (file_name))
     {
-      /* Read from a file */
-      FSSpec fss;
-      short refnum;
+      Lisp_Object file;
+      unsigned char *contents;
+      int size;
+      struct gcpro gcpro1;
 
-      err = find_image_fsspec (specified_file, &file, &fss);
-      if (err != noErr)
+      file = x_find_image_file (file_name);
+      GCPRO1 (file);
+      if (!STRINGP (file))
        {
-         if (err == fnfErr)
-           image_error ("Cannot find image file `%s'", specified_file, Qnil);
-         else
-           goto open_error;
+         image_error ("Cannot find image file `%s'", file_name, Qnil);
+         UNGCPRO;
+         return 0;
        }
 
-      err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
-                                 &graphic_p, &movie_p, &prefer_graphic_p, 0);
-      if (err != noErr)
-       goto open_error;
-
-      if (!graphic_p && !movie_p)
-       goto open_error;
-      if (prefer_graphic_p)
-       return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
-      err = OpenMovieFile (&fss, &refnum, fsRdPerm);
-      if (err != noErr)
-       goto open_error;
-      err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
-      CloseMovieFile (refnum);
-      if (err != noErr)
+      /* Read the entire file into memory.  */
+      contents = slurp_file (SDATA (file), &size);
+      if (contents == NULL)
        {
-         image_error ("Error reading `%s'", file, Qnil);
+         image_error ("Error loading SVG image `%s'", img->spec, Qnil);
+         UNGCPRO;
          return 0;
        }
+      /* If the file was slurped into memory properly, parse it.  */
+      success_p = svg_load_image (f, img, contents, size);
+      xfree (contents);
+      UNGCPRO;
     }
+  /* Else its not a file, its a lisp object.  Load the image from a
+     lisp object rather than a file.  */
   else
     {
-      /* Memory source! */
-      Handle dref = NULL;
-      long file_type_atom[3];
+      Lisp_Object data;
 
-      err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
-      if (err != noErr)
-       {
-         image_error ("Cannot allocate data handle for `%s'",
-                      img->spec, Qnil);
-         goto error;
-       }
+      data = image_spec_value (img->spec, QCdata, NULL);
+      success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
+    }
 
-      file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
-      file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
-      file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
-      err = PtrToHand (&dh, &dref, sizeof (Handle));
-      if (err == noErr)
-       /* no file name */
-       err = PtrAndHand ("\p", dref, 1);
-      if (err == noErr)
-       err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
-      if (err != noErr)
-       {
-         image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
-         goto error;
-       }
-      err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
-                                    &movie_p, &prefer_graphic_p, 0);
-      if (err != noErr)
-       goto open_error;
-
-      if (!graphic_p && !movie_p)
-       goto open_error;
-      if (prefer_graphic_p)
-       {
-         int success_p;
+  return success_p;
+}
 
-         DisposeHandle (dref);
-         success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
-         DisposeHandle (dh);
-         return success_p;
-       }
-      err = NewMovieFromDataRef (&movie, 0, NULL, dref,
-                                HandleDataHandlerSubType);
-      DisposeHandle (dref);
-      if (err != noErr)
-       goto open_error;
-    }
+/* svg_load_image is a helper function for svg_load, which does the
+   actual loading given contents and size, apart from frame and image
+   structures, passed from svg_load.
 
-  image = image_spec_value (img->spec, QCindex, NULL);
-  ino = INTEGERP (image) ? XFASTINT (image) : 0;
-  track = GetMovieIndTrack (movie, 1);
-  media = GetTrackMedia (track);
-  nsamples = GetMediaSampleCount (media);
-  if (ino >= nsamples)
+   Uses librsvg to do most of the image processing.
+
+   Returns non-zero when successful.  */
+static int
+svg_load_image (f, img, contents, size)
+    /* Pointer to emacs frame structure.  */
+     struct frame *f;
+     /* Pointer to emacs image structure.  */
+     struct image *img;
+     /* String containing the SVG XML data to be parsed.  */
+     unsigned char *contents;
+     /* Size of data in bytes.  */
+     unsigned int size;
+{
+  RsvgHandle *rsvg_handle;
+  RsvgDimensionData dimension_data;
+  GError *error = NULL;
+  GdkPixbuf *pixbuf;
+  int width;
+  int height;
+  const guint8 *pixels;
+  int rowstride;
+  XImagePtr ximg;
+  Lisp_Object specified_bg;
+  XColor background;
+  int x;
+  int y;
+
+  /* g_type_init is a glib function that must be called prior to using
+     gnome type library functions.  */
+  fn_g_type_init ();
+  /* Make a handle to a new rsvg object.  */
+  rsvg_handle = fn_rsvg_handle_new ();
+
+  /* Parse the contents argument and fill in the rsvg_handle.  */
+  fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
+  if (error) goto rsvg_error;
+
+  /* The parsing is complete, rsvg_handle is ready to used, close it
+     for further writes.  */
+  fn_rsvg_handle_close (rsvg_handle, &error);
+  if (error) goto rsvg_error;
+
+  fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
+  if (! check_image_size (f, dimension_data.width, dimension_data.height))
+    goto rsvg_error;
+
+  /* We can now get a valid pixel buffer from the svg file, if all
+     went ok.  */
+  pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
+  if (!pixbuf) goto rsvg_error;
+  fn_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);
+
+  /* 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);
+
+  /* Try to create a x pixmap to hold the svg pixmap.  */
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
     {
-      image_error ("Invalid image number `%s' in image `%s'",
-                  image, img->spec);
-      goto error;
+      fn_g_object_unref (pixbuf);
+      return 0;
     }
-  time_scale = GetMediaTimeScale (media);
 
+  init_color_table ();
+
+  /* Handle alpha channel by combining the image with a background
+     color.  */
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-  if (!STRINGP (specified_bg) ||
-      !mac_defined_color (f, SDATA (specified_bg), &color, 0))
+  if (STRINGP (specified_bg)
+      && x_defined_color (f, SDATA (specified_bg), &background, 0))
     {
-      color.pixel = FRAME_BACKGROUND_PIXEL (f);
-      color.red = RED16_FROM_ULONG (color.pixel);
-      color.green = GREEN16_FROM_ULONG (color.pixel);
-      color.blue = BLUE16_FROM_ULONG (color.pixel);
+      background.red   >>= 8;
+      background.green >>= 8;
+      background.blue  >>= 8;
     }
-  GetMovieBox (movie, &rect);
-  width = img->width = rect.right - rect.left;
-  height = img->height = rect.bottom - rect.top;
-  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
-    goto error;
+  else
+    {
+#ifdef HAVE_X_WINDOWS
+      background.pixel = FRAME_BACKGROUND_PIXEL (f);
+      x_query_color (f, &background);
+
+      /* SVG pixmaps specify transparency in the last byte, so right
+        shift 8 bits to get rid of it, since emacs doesn't support
+        transparency.  */
+      background.red   >>= 8;
+      background.green >>= 8;
+      background.blue  >>= 8;
+#elif defined (HAVE_NTGUI)
+      background.pixel = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* W32 TODO : Colormap support.  */
+      x_query_color (f, &background);
+#endif
 
-  GetGWorld (&old_port, &old_gdh);
-  SetGWorld (ximg, NULL);
-  bg_color.red = color.red;
-  bg_color.green = color.green;
-  bg_color.blue = color.blue;
-  RGBBackColor (&bg_color);
-  SetGWorld (old_port, old_gdh);
-  SetMovieActive (movie, 1);
-  SetMovieGWorld (movie, ximg, NULL);
-  SampleNumToMediaTime (media, ino + 1, &time, &duration);
-  SetMovieTimeValue (movie, time);
-  MoviesTask (movie, 0L);
-  DisposeTrackMedia (media);
-  DisposeMovieTrack (track);
-  DisposeMovie (movie);
-  if (dh)
-    DisposeHandle (dh);
+      /* SVG pixmaps specify transparency in the last byte, so right
+        shift 8 bits to get rid of it, since emacs doesn't support
+        transparency.  */
+      background.red   >>= 8;
+      background.green >>= 8;
+      background.blue  >>= 8;
+#else /* not HAVE_X_WINDOWS*/
+#error FIXME
+#endif
+    }
 
-  /* 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);
-  }
+  /* This loop handles opacity values, since Emacs assumes
+     non-transparent images.  Each pixel must be "flattened" by
+     calculating the resulting color, given the transparency of the
+     pixel, and the image background color.  */
+  for (y = 0; y < height; ++y)
+    {
+      for (x = 0; x < width; ++x)
+       {
+         unsigned red;
+         unsigned green;
+         unsigned blue;
+         unsigned opacity;
+
+         red     = *pixels++;
+         green   = *pixels++;
+         blue    = *pixels++;
+         opacity = *pixels++;
+
+         red   = ((red * opacity)
+                  + (background.red * ((1 << 8) - opacity)));
+         green = ((green * opacity)
+                  + (background.green * ((1 << 8) - opacity)));
+         blue  = ((blue * opacity)
+                  + (background.blue * ((1 << 8) - opacity)));
+
+         XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
+       }
 
-  /* 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);
+      pixels += rowstride - 4 * width;
+    }
 
-  /* Put the image into the pixmap.  */
+#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 */
+
+  fn_g_object_unref (pixbuf);
+
+  img->width  = width;
+  img->height = height;
+
+  /* Maybe fill in the background field while we have ximg handy.
+     Casting avoids a GCC warning.  */
+  IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
+
+  /* Put the image into the pixmap, then free the X image and its
+     buffer.  */
   x_put_x_image (f, ximg, img->pixmap, width, height);
   x_destroy_x_image (ximg);
+
   return 1;
 
- open_error:
-  image_error ("Cannot open `%s'", file, Qnil);
- error:
-  if (media)
-    DisposeTrackMedia (media);
-  if (track)
-    DisposeMovieTrack (track);
-  if (movie)
-    DisposeMovie (movie);
-  if (dh)
-    DisposeHandle (dh);
+ rsvg_error:
+  fn_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 (error);
   return 0;
 }
-#endif /* MAC_OS */
 
-#endif /* HAVE_GIF */
+#endif /* defined (HAVE_RSVG) */
+
 
 
 \f
@@ -8421,7 +8414,7 @@ x_kill_gs_process (pixmap, f)
      Pixmap pixmap;
      struct frame *f;
 {
-  struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
   int class, i;
   struct image *img;
 
@@ -8571,31 +8564,36 @@ of `image-library-alist', which see).  */)
   if (CONSP (tested))
     return XCDR (tested);
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (HAVE_NS)
   if (EQ (type, Qxpm))
     return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
 #endif
 
-#if defined (HAVE_JPEG) || defined (MAC_OS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS)
   if (EQ (type, Qjpeg))
     return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
 #endif
 
-#if defined (HAVE_TIFF) || defined (MAC_OS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS)
   if (EQ (type, Qtiff))
     return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
 #endif
 
-#if defined (HAVE_GIF) || defined (MAC_OS)
+#if defined (HAVE_GIF) || defined (HAVE_NS)
   if (EQ (type, Qgif))
     return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
 #endif
 
-#if defined (HAVE_PNG) || defined (MAC_OS)
+#if defined (HAVE_PNG) || defined (HAVE_NS)
   if (EQ (type, Qpng))
     return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
 #endif
 
+#if defined (HAVE_RSVG)
+  if (EQ (type, Qsvg))
+    return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
+#endif
+
 #ifdef HAVE_GHOSTSCRIPT
   if (EQ (type, Qpostscript))
     return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
@@ -8620,7 +8618,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;
 
@@ -8655,15 +8653,18 @@ non-numeric, there is no explicit limit on the size of images.  */);
 
   Qpbm = intern ("pbm");
   staticpro (&Qpbm);
-  ADD_IMAGE_TYPE(Qpbm);
+  ADD_IMAGE_TYPE (Qpbm);
 
   Qxbm = intern ("xbm");
   staticpro (&Qxbm);
-  ADD_IMAGE_TYPE(Qxbm);
+  ADD_IMAGE_TYPE (Qxbm);
 
   define_image_type (&xbm_type, 1);
   define_image_type (&pbm_type, 1);
 
+  Qcount = intern ("count");
+  staticpro (&Qcount);
+
   QCascent = intern (":ascent");
   staticpro (&QCascent);
   QCmargin = intern (":margin");
@@ -8697,7 +8698,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   Qpostscript = intern ("postscript");
   staticpro (&Qpostscript);
 #ifdef HAVE_GHOSTSCRIPT
-  ADD_IMAGE_TYPE(Qpostscript);
+  ADD_IMAGE_TYPE (Qpostscript);
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -8708,36 +8709,51 @@ non-numeric, there is no explicit limit on the size of images.  */);
   staticpro (&QCpt_height);
 #endif /* HAVE_GHOSTSCRIPT */
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (HAVE_NS)
   Qxpm = intern ("xpm");
   staticpro (&Qxpm);
-  ADD_IMAGE_TYPE(Qxpm);
+  ADD_IMAGE_TYPE (Qxpm);
 #endif
 
-#if defined (HAVE_JPEG) || defined (MAC_OS)
+#if defined (HAVE_JPEG) || defined (HAVE_NS)
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
-  ADD_IMAGE_TYPE(Qjpeg);
+  ADD_IMAGE_TYPE (Qjpeg);
 #endif
 
-#if defined (HAVE_TIFF) || defined (MAC_OS)
+#if defined (HAVE_TIFF) || defined (HAVE_NS)
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
-  ADD_IMAGE_TYPE(Qtiff);
+  ADD_IMAGE_TYPE (Qtiff);
 #endif
 
-#if defined (HAVE_GIF) || defined (MAC_OS)
+#if defined (HAVE_GIF) || defined (HAVE_NS)
   Qgif = intern ("gif");
   staticpro (&Qgif);
-  ADD_IMAGE_TYPE(Qgif);
+  ADD_IMAGE_TYPE (Qgif);
 #endif
 
-#if defined (HAVE_PNG) || defined (MAC_OS)
+#if defined (HAVE_PNG) || defined (HAVE_NS)
   Qpng = intern ("png");
   staticpro (&Qpng);
-  ADD_IMAGE_TYPE(Qpng);
+  ADD_IMAGE_TYPE (Qpng);
 #endif
 
+#if defined (HAVE_RSVG)
+  Qsvg = intern ("svg");
+  staticpro (&Qsvg);
+  ADD_IMAGE_TYPE (Qsvg);
+#ifdef HAVE_NTGUI
+  /* Other libraries used directly by svg code.  */
+  Qgdk_pixbuf = intern ("gdk-pixbuf");
+  staticpro (&Qgdk_pixbuf);
+  Qglib = intern ("glib");
+  staticpro (&Qglib);
+  Qgobject = intern ("gobject");
+  staticpro (&Qgobject);
+#endif /* HAVE_NTGUI  */
+#endif /* HAVE_RSVG  */
+
   defsubr (&Sinit_image_library);
   defsubr (&Sclear_image_cache);
   defsubr (&Simage_refresh);
@@ -8771,9 +8787,6 @@ meaning don't clear the cache.  */);
 void
 init_image ()
 {
-#if defined (MAC_OSX) && TARGET_API_MAC_CARBON
-  init_image_func_pointer ();
-#endif
 }
 
 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9