(svg_load_image): Use rsvg_handle_get_dimensions to check that image
[bpt/emacs.git] / src / image.c
index 04fda4f..5c9f5d5 100644 (file)
@@ -5,10 +5,10 @@
 
 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
@@ -16,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>
@@ -40,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"
@@ -115,10 +114,15 @@ typedef struct mac_bitmap_record Bitmap_Record;
 
 #define RGB_PIXEL_COLOR unsigned long
 
+#if USE_MAC_IMAGE_IO
+#define PIX_MASK_DRAW  255
+#define PIX_MASK_RETAIN        0
+#else
 /* 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)
+#endif
 
 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
 #define x_defined_color mac_defined_color
@@ -127,6 +131,32 @@ typedef struct mac_bitmap_record Bitmap_Record;
 #endif /* MAC_OS */
 
 
+#ifdef HAVE_NS
+#include "nsterm.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#undef COLOR_TABLE_SUPPORT
+
+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
+
+#define PIX_MASK_RETAIN        0
+#define PIX_MASK_DRAW  1
+
+#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.  */
 
 Lisp_Object Vx_bitmap_file_path;
@@ -166,6 +196,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);
   {
@@ -177,6 +208,7 @@ XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
 #endif
 
   LockPixels (GetGWorldPixMap (pixmap));
+#endif
 
   return pixmap;
 }
@@ -187,6 +219,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);
 
@@ -227,6 +265,7 @@ XPutPixel (ximage, x, y, pixel)
 
       SetGWorld (old_port, old_gdh);
     }
+#endif
 }
 
 static unsigned long
@@ -234,6 +273,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);
 
@@ -271,21 +316,80 @@ 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)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+                         | kCGBitmapByteOrder32Host
+#endif
+                         , provider, NULL, 0, kCGRenderingIntentDefault);
+  CGDataProviderRelease (provider);
+  UNBLOCK_INPUT;
+
+  return result;
+#else
   Pixmap mask;
   CGImageRef result = NULL;
 
@@ -320,10 +424,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.  */
 
@@ -440,12 +572,23 @@ x_create_bitmap_from_data (f, bits, width, height)
     return -1;
 #endif
 
+#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;
   dpyinfo->bitmaps[id - 1].width = width;
@@ -473,6 +616,8 @@ x_create_bitmap_from_file (f, file)
      struct frame *f;
      Lisp_Object file;
 {
+  Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
 #ifdef MAC_OS
   return -1;  /* MAC_TODO : bitmap support */
 #endif  /* MAC_OS */
@@ -481,8 +626,26 @@ x_create_bitmap_from_file (f, file)
   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;
@@ -551,6 +714,10 @@ free_bitmap_record (dpyinfo, bm)
   bm->bitmap_data = NULL;
 #endif  /* MAC_OS */
 
+#ifdef HAVE_NS
+  ns_release_object(bm->img);
+#endif
+
   if (bm->file)
     {
       xfree (bm->file);
@@ -1184,9 +1351,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;
@@ -1207,7 +1376,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)
@@ -1326,7 +1495,8 @@ image_ascent (img, face, slice)
             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
@@ -1395,6 +1565,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) \
@@ -1403,7 +1581,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,
@@ -1526,6 +1704,10 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
     {
       Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
       img->pixmap = NO_PIXMAP;
+#ifdef HAVE_NS
+      if (img->background_valid)
+        ns_free_indexed_color(img->background);
+#endif
       img->background_valid = 0;
     }
 
@@ -1642,7 +1824,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;
@@ -1689,7 +1871,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;
@@ -1702,26 +1884,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-cache-eviction-delay
-   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;
@@ -1738,7 +1919,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;
@@ -1756,8 +1939,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);
            }
 
@@ -1768,25 +1950,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;
 }
@@ -1916,7 +2106,7 @@ lookup_image (f, spec)
   xassert (FRAME_WINDOW_P (f));
   xassert (valid_image_p (spec));
 
-  c = FRAME_X_IMAGE_CACHE (f);
+  c = FRAME_IMAGE_CACHE (f);
 
   GCPRO1 (spec);
 
@@ -2027,7 +2217,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.  */
@@ -2062,21 +2252,29 @@ 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]);
     }
 }
 
@@ -2283,11 +2481,25 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
       return 0;
     }
 
+#if !USE_MAC_IMAGE_IO
   LockPixels (GetGWorldPixMap (*pixmap));
+#endif
   *ximg = *pixmap;
   return 1;
 
 #endif  /* MAC_OS */
+
+#ifdef HAVE_NS
+  *pixmap = ns_image_for_XPM(width, height, depth);
+  if (*pixmap == 0)
+    {
+      *ximg = NULL;
+      image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
+      return 0;
+    }
+  *ximg = *pixmap;
+  return 1;
+#endif
 }
 
 
@@ -2313,6 +2525,9 @@ x_destroy_x_image (ximg)
 #ifdef MAC_OS
       XDestroyImage (ximg);
 #endif /* MAC_OS */
+#ifdef HAVE_NS
+      ns_release_object(ximg);
+#endif /* HAVE_NS */
     }
 }
 
@@ -2347,6 +2562,11 @@ x_put_x_image (f, ximg, pixmap, width, height)
 #ifdef MAC_OS
   xassert (ximg == pixmap);
 #endif  /* MAC_OS */
+
+#ifdef HAVE_NS
+  xassert (ximg == pixmap);
+  ns_retain_object(ximg);
+#endif
 }
 
 \f
@@ -2436,6 +2656,256 @@ slurp_file (file, size)
                        MAC Image Load Functions
  ***********************************************************************/
 
+#if USE_MAC_IMAGE_IO
+static int
+image_load_image_io (f, img, type)
+     struct frame *f;
+     struct image *img;
+     CFStringRef type;
+{
+  CFDictionaryRef options, src_props = NULL, props = NULL;
+  CFStringRef keys[2];
+  CFTypeRef values[2];
+  Lisp_Object specified_file, specified_data;
+  CGImageSourceRef source = NULL;
+  size_t count;
+  CGImageRef image = NULL;
+  int loop_count = -1;
+  double delay_time = -1.0;
+  int width, height;
+  XImagePtr ximg = NULL;
+  CGContextRef context;
+  CGRect rectangle;
+  int has_alpha_p, gif_p;
+
+  gif_p = UTTypeEqual (type, kUTTypeGIF);
+
+  keys[0] = kCGImageSourceTypeIdentifierHint;
+  values[0] = (CFTypeRef) type;
+  keys[1] = kCGImageSourceShouldCache;
+  values[1] = (CFTypeRef) kCFBooleanFalse;
+  options = CFDictionaryCreate (NULL, (const void **) keys,
+                               (const void **) values,
+                               sizeof (keys) / sizeof (keys[0]),
+                               &kCFTypeDictionaryKeyCallBacks,
+                               &kCFTypeDictionaryValueCallBacks);
+  if (options == NULL)
+    {
+      image_error ("Error creating options for image `%s'", img->spec, Qnil);
+      return 0;
+    }
+
+  /* Open the file.  */
+  specified_file = image_spec_value (img->spec, QCfile, NULL);
+  specified_data = image_spec_value (img->spec, QCdata, NULL);
+
+  if (NILP (specified_data))
+    {
+      Lisp_Object file;
+      CFStringRef path;
+      CFURLRef url;
+
+      file = x_find_image_file (specified_file);
+      if (!STRINGP (file))
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         return 0;
+       }
+      path = cfstring_create_with_utf8_cstring (SDATA (file));
+      if (path)
+       {
+         url = CFURLCreateWithFileSystemPath (NULL, path,
+                                              kCFURLPOSIXPathStyle, 0);
+         CFRelease (path);
+         if (url)
+           {
+             source = CGImageSourceCreateWithURL (url, NULL);
+             CFRelease (url);
+           }
+       }
+    }
+  else
+    {
+      CFDataRef data = CFDataCreate (NULL, SDATA (specified_data),
+                                    SBYTES (specified_data));
+
+      if (data)
+       {
+         source = CGImageSourceCreateWithData (data, options);
+         CFRelease (data);
+       }
+    }
+  CFRelease (options);
+
+  if (source)
+    {
+      CFStringRef real_type = CGImageSourceGetType (source);
+
+      if (real_type && UTTypeEqual (type, real_type))
+       src_props = CGImageSourceCopyProperties (source, NULL);
+      if (src_props)
+       {
+         EMACS_INT ino = 0;
+
+         count = CGImageSourceGetCount (source);
+         if (gif_p)
+           {
+             Lisp_Object image = image_spec_value (img->spec, QCindex, NULL);
+
+             if (INTEGERP (image))
+               ino = XFASTINT (image);
+           }
+         if (ino >= 0 && ino < count)
+           {
+             props = CGImageSourceCopyPropertiesAtIndex (source, ino, NULL);
+             if (props)
+               image = CGImageSourceCreateImageAtIndex (source, ino, NULL);
+           }
+       }
+      CFRelease (source);
+    }
+
+  if (image == NULL)
+    {
+      if (src_props)
+       CFRelease (src_props);
+      if (props)
+       CFRelease (props);
+      image_error ("Error reading image `%s'", img->spec, Qnil);
+      return 0;
+    }
+  else
+    {
+      CFBooleanRef boolean;
+
+      if (CFDictionaryGetValueIfPresent (props, kCGImagePropertyHasAlpha,
+                                        (const void **) &boolean))
+       has_alpha_p = CFBooleanGetValue (boolean);
+      if (gif_p)
+       {
+         CFDictionaryRef dict;
+         CFNumberRef number;
+
+         dict = CFDictionaryGetValue (src_props,
+                                      kCGImagePropertyGIFDictionary);
+         if (dict
+             && CFDictionaryGetValueIfPresent (dict,
+                                               kCGImagePropertyGIFLoopCount,
+                                               (const void **) &number))
+           CFNumberGetValue (number, kCFNumberIntType, &loop_count);
+
+         dict = CFDictionaryGetValue (props, kCGImagePropertyGIFDictionary);
+         if (dict
+             && CFDictionaryGetValueIfPresent (dict,
+                                               kCGImagePropertyGIFDelayTime,
+                                               (const void **) &number))
+           CFNumberGetValue (number, kCFNumberDoubleType, &delay_time);
+       }
+      CFRelease (src_props);
+      CFRelease (props);
+    }
+
+  width = img->width = CGImageGetWidth (image);
+  height = img->height = CGImageGetHeight (image);
+
+  if (!check_image_size (f, width, height))
+    {
+      CGImageRelease (image);
+      image_error ("Invalid image size", Qnil, Qnil);
+      return 0;
+    }
+
+  if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+    {
+      CGImageRelease (image);
+      image_error ("Out of memory (%s)", img->spec, Qnil);
+      return 0;
+    }
+  rectangle = CGRectMake (0, 0, width, height);
+
+  context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
+                                  ximg->bytes_per_line,
+                                  mac_cg_color_space_rgb,
+                                  kCGImageAlphaNoneSkipFirst
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+                                  | kCGBitmapByteOrder32Host
+#endif
+                                  );
+  if (has_alpha_p)
+    {
+      Lisp_Object specified_bg;
+      XColor color;
+
+      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);
+       }
+      CGContextSetRGBFillColor (context, color.red / 65535.0,
+                               color.green / 65535.0,
+                               color.blue / 65535.0, 1.0);
+      CGContextFillRect (context, rectangle);
+    }
+  CGContextDrawImage (context, rectangle, image);
+  CGContextRelease (context);
+  CGImageRelease (image);
+
+  /* Save GIF image extension data for `image-extension-data'.
+     Format is (count IMAGES
+               0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
+               0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK).  */
+  if (gif_p)
+    {
+      img->data.lisp_val = Qnil;
+      if (delay_time >= 0)
+       {
+         Lisp_Object gce = make_uninit_string (4);
+         int centisec = delay_time * 100.0 + 0.5;
+
+         /* 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 = Fcons (make_number (0xf9),
+                                     Fcons (gce,
+                                            img->data.lisp_val));
+       }
+      if (loop_count >= 0)
+       {
+         Lisp_Object data_sub_block = make_uninit_string (3);
+
+         SSET (data_sub_block, 0, 0x01);
+         SSET (data_sub_block, 1, loop_count & 0xff);
+         SSET (data_sub_block, 2, (loop_count >> 8) & 0xff);
+         img->data.lisp_val = Fcons (make_number (0),
+                                     Fcons (data_sub_block,
+                                            img->data.lisp_val));
+         img->data.lisp_val = Fcons (make_number (0xff),
+                                     Fcons (build_string ("NETSCAPE2.0"),
+                                            img->data.lisp_val));
+       }
+      if (count > 1)
+       img->data.lisp_val = Fcons (Qcount,
+                                   Fcons (make_number (count),
+                                          img->data.lisp_val));
+    }
+
+  /* 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;
+}
+#else  /* !USE_MAC_IMAGE_IO */
 static int image_load_quicktime P_ ((struct frame *, struct image *img,
                                     OSType));
 #ifdef MAC_OSX
@@ -2648,30 +3118,6 @@ image_load_quicktime (f, img, type)
 
 
 #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;
@@ -2719,11 +3165,13 @@ image_load_quartz2d (f, img, png_p)
     source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
                                           SBYTES (specified_data), NULL);
 
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
   if (png_p)
-    image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
-                                                  kCGRenderingIntentDefault);
+    image = CGImageCreateWithPNGDataProvider (source, NULL, false,
+                                             kCGRenderingIntentDefault);
   else
-    image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
+#endif
+    image = CGImageCreateWithJPEGDataProvider (source, NULL, false,
                                               kCGRenderingIntentDefault);
 
   CGDataProviderRelease (source);
@@ -2787,6 +3235,7 @@ image_load_quartz2d (f, img, png_p)
   return 1;
 }
 #endif
+#endif /* !USE_MAC_IMAGE_IO */
 
 #endif  /* MAC_OS */
 
@@ -3171,6 +3620,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),
@@ -3179,7 +3632,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 */
 }
 
 
@@ -3563,13 +4016,13 @@ xbm_load (f, img)
                              XPM images
  ***********************************************************************/
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (MAC_OS) || 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 || MAC_OS || HAVE_NS */
 
 #ifdef HAVE_XPM
 #ifdef HAVE_NTGUI
@@ -3592,7 +4045,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 (MAC_OS) || defined (HAVE_NS)
 /* The symbol `xpm' identifying XPM-format images.  */
 
 Lisp_Object Qxpm;
@@ -3919,7 +4372,7 @@ xpm_image_p (object)
              || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
 }
 
-#endif /* HAVE_XPM || MAC_OS */
+#endif /* HAVE_XPM || MAC_OS || HAVE_NS */
 
 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
 int
@@ -4198,7 +4651,7 @@ xpm_load (f, img)
 
 #endif /* HAVE_XPM */
 
-#ifdef MAC_OS
+#if defined (MAC_OS) || ( defined (HAVE_NS) && !defined (HAVE_XPM) )
 
 /* XPM support functions for Mac OS where libxpm is not available.
    Only XPM version 3 (without any extensions) is supported.  */
@@ -4257,8 +4710,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;
@@ -4534,7 +4987,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))
@@ -4543,7 +4996,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);
@@ -4556,8 +5009,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;
@@ -4577,9 +5033,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 (',');
@@ -4594,6 +5055,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
@@ -4609,7 +5071,7 @@ xpm_load_image (f, img, contents, end)
       Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
       img->mask = NO_PIXMAP;
     }
-
+#endif
   return 1;
 
  failure:
@@ -4675,7 +5137,7 @@ xpm_load (f, img)
   return success_p;
 }
 
-#endif /* MAC_OS */
+#endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */
 
 
 \f
@@ -4945,6 +5407,9 @@ lookup_rgb_color (f, r, g, b)
   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;
 }
 
@@ -5050,7 +5515,7 @@ x_to_xcolors (f, img, rgb_p)
          p->pixel = GET_PIXEL (ximg, x, y);
          if (rgb_p)
            {
-#ifdef MAC_OS
+#if defined (MAC_OS) || defined (HAVE_NS)
              p->red = RED16_FROM_ULONG (p->pixel);
              p->green = GREEN16_FROM_ULONG (p->pixel);
              p->blue = BLUE16_FROM_ULONG (p->pixel);
@@ -5131,8 +5596,8 @@ x_from_xcolors (f, img, colors)
      XColor *colors;
 {
   int x, y;
-  XImagePtr oimg;
-  Pixmap pixmap;
+  XImagePtr oimg = NULL;
+  Pixmap pixmap = NULL;
   XColor *p;
 
   init_color_table ();
@@ -5345,6 +5810,8 @@ x_disable_image (f, img)
       Display *dpy = FRAME_X_DISPLAY (f);
       GC gc;
 
+#ifndef HAVE_NS  //TODO: NS support, however this not needed for toolbars
+
 #ifdef MAC_OS
 #define MaskForeground(f)  PIX_MASK_DRAW
 #else
@@ -5369,6 +5836,7 @@ x_disable_image (f, img)
                     img->width - 1, 0);
          XFreeGC (dpy, gc);
        }
+#endif /* !HAVE_NS */
 #else
       HDC hdc, bmpdc;
       HGDIOBJ prev;
@@ -5434,11 +5902,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,
@@ -5492,16 +5962,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)
@@ -5783,13 +6258,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))
@@ -5849,10 +6329,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);
@@ -5866,13 +6349,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
              {
@@ -5932,7 +6427,7 @@ pbm_load (f, img)
                                 PNG
  ***********************************************************************/
 
-#if defined (HAVE_PNG) || defined (MAC_OS)
+#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
 
 /* Function prototypes.  */
 
@@ -6004,7 +6499,7 @@ png_image_p (object)
   return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
 }
 
-#endif /* HAVE_PNG || MAC_OS */
+#endif /* HAVE_PNG || MAC_OS || HAVE_NS */
 
 
 #ifdef HAVE_PNG
@@ -6193,7 +6688,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.  */
@@ -6335,27 +6829,6 @@ 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.  */
@@ -6364,6 +6837,7 @@ png_load (f, img)
       /* 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.  */
@@ -6375,27 +6849,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;
@@ -6404,9 +6869,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
@@ -6584,15 +7049,27 @@ png_load (f, img)
      struct frame *f;
      struct image *img;
 {
-#ifdef MAC_OSX
-  if (MyCGImageCreateWithPNGDataProvider)
-    return image_load_quartz2d (f, img, 1);
-  else
+#if USE_MAC_IMAGE_IO
+  return image_load_image_io (f, img, kUTTypePNG);
+#elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+  return image_load_quartz2d (f, img, 1);
+#else
+  return image_load_quicktime (f, img, kQTFileTypePNG);
 #endif
-    return image_load_quicktime (f, img, kQTFileTypePNG);
 }
 #endif  /* MAC_OS */
 
+#ifdef HAVE_NS
+static int
+png_load (struct frame *f, struct image *img)
+{
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
+}
+#endif  /* HAVE_NS */
+
+
 #endif /* !HAVE_PNG */
 
 
@@ -6601,7 +7078,7 @@ png_load (f, img)
                                 JPEG
  ***********************************************************************/
 
-#if defined (HAVE_JPEG) || defined (MAC_OS)
+#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
 
 static int jpeg_image_p P_ ((Lisp_Object object));
 static int jpeg_load P_ ((struct frame *f, struct image *img));
@@ -6672,7 +7149,7 @@ jpeg_image_p (object)
   return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
 }
 
-#endif /* HAVE_JPEG || MAC_OS */
+#endif /* HAVE_JPEG || MAC_OS || HAVE_NS */
 
 #ifdef HAVE_JPEG
 
@@ -7162,7 +7639,9 @@ jpeg_load (f, img)
      struct frame *f;
      struct image *img;
 {
-#ifdef MAC_OSX
+#if USE_MAC_IMAGE_IO
+  return image_load_image_io (f, img, kUTTypeJPEG);
+#elif defined (MAC_OSX)
   return image_load_quartz2d (f, img, 0);
 #else
   return image_load_quicktime (f, img, kQTFileTypeJPEG);
@@ -7170,6 +7649,16 @@ jpeg_load (f, img)
 }
 #endif  /* MAC_OS */
 
+#ifdef HAVE_NS
+static int
+jpeg_load (struct frame *f, struct image *img)
+{
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
+}
+#endif  /* HAVE_NS */
+
 #endif /* !HAVE_JPEG */
 
 
@@ -7178,7 +7667,7 @@ jpeg_load (f, img)
                                 TIFF
  ***********************************************************************/
 
-#if defined (HAVE_TIFF) || defined (MAC_OS)
+#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
 
 static int tiff_image_p P_ ((Lisp_Object object));
 static int tiff_load P_ ((struct frame *f, struct image *img));
@@ -7248,7 +7737,7 @@ tiff_image_p (object)
   return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
 }
 
-#endif /* HAVE_TIFF || MAC_OS */
+#endif /* HAVE_TIFF || MAC_OS || HAVE_NS */
 
 #ifdef HAVE_TIFF
 
@@ -7587,10 +8076,24 @@ tiff_load (f, img)
      struct frame *f;
      struct image *img;
 {
+#if USE_MAC_IMAGE_IO
+  return image_load_image_io (f, img, kUTTypeTIFF);
+#else
   return image_load_quicktime (f, img, kQTFileTypeTIFF);
+#endif
 }
 #endif /* MAC_OS */
 
+#ifdef HAVE_NS
+static int
+tiff_load (struct frame *f, struct image *img)
+{
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
+}
+#endif  /* HAVE_NS */
+
 #endif /* !HAVE_TIFF */
 
 
@@ -7599,7 +8102,7 @@ tiff_load (f, img)
                                 GIF
  ***********************************************************************/
 
-#if defined (HAVE_GIF) || defined (MAC_OS)
+#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
 
 static int gif_image_p P_ ((Lisp_Object object));
 static int gif_load P_ ((struct frame *f, struct image *img));
@@ -8023,6 +8526,9 @@ gif_load (f, img)
      struct frame *f;
      struct image *img;
 {
+#if USE_MAC_IMAGE_IO
+  return image_load_image_io (f, img, kUTTypeGIF);
+#else  /* !USE_MAC_IMAGE_IO */
   Lisp_Object specified_file, file;
   Lisp_Object specified_data;
   OSErr err;
@@ -8151,8 +8657,8 @@ gif_load (f, img)
   time_scale = GetMediaTimeScale (media);
 
   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)
+      || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
     {
       color.pixel = FRAME_BACKGROUND_PIXEL (f);
       color.red = RED16_FROM_ULONG (color.pixel);
@@ -8221,9 +8727,20 @@ gif_load (f, img)
   if (dh)
     DisposeHandle (dh);
   return 0;
+#endif /* !USE_MAC_IMAGE_IO */
 }
 #endif /* MAC_OS */
 
+#ifdef HAVE_NS
+static int
+gif_load (struct frame *f, struct image *img)
+{
+  return ns_load_image(f, img,
+                       image_spec_value (img->spec, QCfile, NULL),
+                       image_spec_value (img->spec, QCdata, NULL));
+}
+#endif /* HAVE_NS */
+
 #endif /* HAVE_GIF */
 
 
@@ -8324,7 +8841,7 @@ svg_image_p (object)
 
 /* SVG library functions.  */
 DEF_IMGLIB_FN (rsvg_handle_new);
-DEF_IMGLIB_FN (rsvg_handle_set_size_callback);
+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);
@@ -8356,7 +8873,7 @@ init_svg_functions (Lisp_Object libraries)
     return 0;
 
   LOAD_IMGLIB_FN (library, rsvg_handle_new);
-  LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback);
+  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);
@@ -8381,7 +8898,7 @@ init_svg_functions (Lisp_Object libraries)
 /* 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_set_size_callback rsvg_handle_set_size_callback
+#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
@@ -8476,6 +8993,7 @@ svg_load_image (f, img, contents, size)
      unsigned int size;
 {
   RsvgHandle *rsvg_handle;
+  RsvgDimensionData dimension_data;
   GError *error = NULL;
   GdkPixbuf *pixbuf;
   int width;
@@ -8496,18 +9014,22 @@ svg_load_image (f, img, contents, size)
 
   /* Parse the contents argument and fill in the rsvg_handle.  */
   fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
-  if (error)
-    goto rsvg_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)
+  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);
-  eassert (pixbuf);
+  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);
@@ -8628,6 +9150,7 @@ svg_load_image (f, img, contents, size)
   return 1;
 
  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);
@@ -8856,7 +9379,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;
 
@@ -9006,27 +9529,27 @@ of `image-library-alist', which see).  */)
   if (CONSP (tested))
     return XCDR (tested);
 
-#if defined (HAVE_XPM) || defined (MAC_OS)
+#if defined (HAVE_XPM) || defined (MAC_OS) || 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 (MAC_OS) || 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 (MAC_OS) || 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 (MAC_OS) || 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 (MAC_OS) || defined (HAVE_NS)
   if (EQ (type, Qpng))
     return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
 #endif
@@ -9151,31 +9674,31 @@ 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 (MAC_OS) || defined (HAVE_NS)
   Qxpm = intern ("xpm");
   staticpro (&Qxpm);
   ADD_IMAGE_TYPE (Qxpm);
 #endif
 
-#if defined (HAVE_JPEG) || defined (MAC_OS)
+#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
   Qjpeg = intern ("jpeg");
   staticpro (&Qjpeg);
   ADD_IMAGE_TYPE (Qjpeg);
 #endif
 
-#if defined (HAVE_TIFF) || defined (MAC_OS)
+#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
   Qtiff = intern ("tiff");
   staticpro (&Qtiff);
   ADD_IMAGE_TYPE (Qtiff);
 #endif
 
-#if defined (HAVE_GIF) || defined (MAC_OS)
+#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
   Qgif = intern ("gif");
   staticpro (&Qgif);
   ADD_IMAGE_TYPE (Qgif);
 #endif
 
-#if defined (HAVE_PNG) || defined (MAC_OS)
+#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
   Qpng = intern ("png");
   staticpro (&Qpng);
   ADD_IMAGE_TYPE (Qpng);
@@ -9226,9 +9749,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