Merge from trunk.
[bpt/emacs.git] / src / image.c
index d1091ae..c8d6be3 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions for image support on window system.
-   Copyright (C) 1989, 1992-2011 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -56,7 +56,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #define COLOR_TABLE_SUPPORT 1
 
 typedef struct x_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
 #define NO_PIXMAP None
 
 #define RGB_PIXEL_COLOR unsigned long
@@ -74,7 +74,7 @@ typedef struct x_bitmap_record Bitmap_Record;
 #undef COLOR_TABLE_SUPPORT
 
 typedef struct w32_bitmap_record Bitmap_Record;
-#define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y)
 #define NO_PIXMAP 0
 
 #define RGB_PIXEL_COLOR COLORREF
@@ -106,7 +106,7 @@ Lisp_Object Qlibpng_version;
 
 typedef struct ns_bitmap_record Bitmap_Record;
 
-#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
+#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
 #define NO_PIXMAP 0
 
 #define RGB_PIXEL_COLOR unsigned long
@@ -115,7 +115,7 @@ typedef struct ns_bitmap_record Bitmap_Record;
 #define PIX_MASK_RETAIN        0
 #define PIX_MASK_DRAW  1
 
-#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
+#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
@@ -196,6 +196,7 @@ x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
 int
 x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
 {
+  /* HAVE_NTGUI needs the explicit cast here.  */
   return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
 }
 #endif
@@ -216,15 +217,6 @@ x_allocate_bitmap_record (FRAME_PTR f)
   Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   ptrdiff_t i;
 
-  if (dpyinfo->bitmaps == NULL)
-    {
-      dpyinfo->bitmaps_size = 10;
-      dpyinfo->bitmaps
-       = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
-      dpyinfo->bitmaps_last = 1;
-      return 1;
-    }
-
   if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
     return ++dpyinfo->bitmaps_last;
 
@@ -232,20 +224,16 @@ x_allocate_bitmap_record (FRAME_PTR f)
     if (dpyinfo->bitmaps[i].refcount == 0)
       return i + 1;
 
-  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2
-      < dpyinfo->bitmaps_size)
-    memory_full (SIZE_MAX);
-  dpyinfo->bitmaps_size *= 2;
-  dpyinfo->bitmaps
-    = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
-                                 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
+  dpyinfo->bitmaps =
+    xpalloc (dpyinfo->bitmaps, &dpyinfo->bitmaps_size,
+            10, -1, sizeof *dpyinfo->bitmaps);
   return ++dpyinfo->bitmaps_last;
 }
 
 /* Add one reference to the reference count of the bitmap with id ID.  */
 
 void
-x_reference_bitmap (FRAME_PTR f, int id)
+x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
 {
   ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
 }
@@ -704,7 +692,7 @@ enum image_value_type
   IMAGE_STRING_OR_NIL_VALUE,
   IMAGE_SYMBOL_VALUE,
   IMAGE_POSITIVE_INTEGER_VALUE,
-  IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
+  IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR,
   IMAGE_NON_NEGATIVE_INTEGER_VALUE,
   IMAGE_ASCENT_VALUE,
   IMAGE_INTEGER_VALUE,
@@ -783,10 +771,9 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
       /* Record that we recognized the keyword.  If a keywords
         was found more than once, it's an error.  */
       keywords[i].value = value;
-      ++keywords[i].count;
-
       if (keywords[i].count > 1)
        return 0;
+      ++keywords[i].count;
 
       /* Check type of value against allowed type.  */
       switch (keywords[i].type)
@@ -807,29 +794,30 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
          break;
 
        case IMAGE_POSITIVE_INTEGER_VALUE:
-         if (!INTEGERP (value) || XINT (value) <= 0)
+         if (! RANGED_INTEGERP (1, value, INT_MAX))
            return 0;
          break;
 
-       case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
-         if (INTEGERP (value) && XINT (value) >= 0)
+       case IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR:
+         if (RANGED_INTEGERP (0, value, INT_MAX))
            break;
          if (CONSP (value)
-             && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
-             && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+             && RANGED_INTEGERP (0, XCAR (value), INT_MAX)
+             && RANGED_INTEGERP (0, XCDR (value), INT_MAX))
            break;
          return 0;
 
        case IMAGE_ASCENT_VALUE:
          if (SYMBOLP (value) && EQ (value, Qcenter))
            break;
-         else if (INTEGERP (value)
-                  && XINT (value) >= 0
-                  && XINT (value) <= 100)
+         else if (RANGED_INTEGERP (0, value, 100))
            break;
          return 0;
 
        case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
+         /* Unlike the other integer-related cases, this one does not
+            verify that VALUE fits in 'int'.  This is because callers
+            want EMACS_INT.  */
          if (!INTEGERP (value) || XINT (value) < 0)
            return 0;
          break;
@@ -849,7 +837,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
          break;
 
        case IMAGE_INTEGER_VALUE:
-         if (!INTEGERP (value))
+         if (! TYPE_RANGED_INTEGERP (int, value))
            return 0;
          break;
 
@@ -919,7 +907,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       int width = img->width + 2 * img->hmargin;
       int height = img->height + 2 * img->vmargin;
@@ -949,7 +937,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       if (img->mask)
        mask = Qt;
@@ -972,7 +960,7 @@ or omitted means use the selected frame.  */)
   if (valid_image_p (spec))
     {
       struct frame *f = check_x_frame (frame);
-      int id = lookup_image (f, spec);
+      ptrdiff_t id = lookup_image (f, spec);
       struct image *img = IMAGE_FROM_ID (f, id);
       ext = img->lisp_data;
     }
@@ -1117,15 +1105,15 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *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 + FONT_BASE(face->font)
-                    - FONT_DESCENT(face->font) + 1) / 2;
+         ascent = (height + FONT_BASE (face->font)
+                    - FONT_DESCENT (face->font) + 1) / 2;
 #endif /* HAVE_NTGUI */
        }
       else
        ascent = height / 2;
     }
   else
-    ascent = (int) (height * img->ascent / 100.0);
+    ascent = height * (img->ascent / 100.0);
 
   return ascent;
 }
@@ -1371,11 +1359,12 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
     {
       /* This isn't called frequently so we get away with simply
         reallocating the color vector to the needed size, here.  */
-      ++img->ncolors;
+      ptrdiff_t ncolors = img->ncolors + 1;
       img->colors =
        (unsigned long *) xrealloc (img->colors,
-                                   img->ncolors * sizeof *img->colors);
-      img->colors[img->ncolors - 1] = color.pixel;
+                                   ncolors * sizeof *img->colors);
+      img->colors[ncolors - 1] = color.pixel;
+      img->ncolors = ncolors;
       result = color.pixel;
     }
   else
@@ -1403,8 +1392,9 @@ make_image_cache (void)
   int size;
 
   memset (c, 0, sizeof *c);
-  c->size = 50;
-  c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
+  size = 50;
+  c->images = (struct image **) xmalloc (size * sizeof *c->images);
+  c->size = size;
   size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
   c->buckets = (struct image **) xmalloc (size);
   memset (c->buckets, 0, size);
@@ -1470,7 +1460,7 @@ free_image_cache (struct frame *f)
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
   if (c)
     {
-      int i;
+      ptrdiff_t i;
 
       /* Cache should not be referenced by any frame when freed.  */
       xassert (c->refcount == 0);
@@ -1500,7 +1490,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
 
   if (c)
     {
-      int i, nfreed = 0;
+      ptrdiff_t i, nfreed = 0;
 
       /* Block input so that we won't be interrupted by a SIGIO
         while being in an inconsistent state.  */
@@ -1524,8 +1514,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
        {
          /* Free cache based on timestamp.  */
          EMACS_TIME t;
-         time_t old;
-         int delay, nimages = 0;
+         double old, delay;
+         ptrdiff_t nimages = 0;
 
          for (i = 0; i < c->used; ++i)
            if (c->images[i])
@@ -1533,9 +1523,10 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
 
          /* If the number of cached images has grown unusually large,
             decrease the cache eviction delay (Bug#6230).  */
-         delay = XFASTINT (Vimage_cache_eviction_delay);
+         delay = XINT (Vimage_cache_eviction_delay);
          if (nimages > 40)
-           delay = max (1, 1600 * delay / (nimages*nimages));
+           delay = 1600 * delay / nimages / nimages;
+         delay = max (delay, 1);
 
          EMACS_GET_TIME (t);
          old = EMACS_SECS (t) - delay;
@@ -1711,7 +1702,7 @@ postprocess_image (struct frame *f, struct image *img)
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
 
-int
+ptrdiff_t
 lookup_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img;
@@ -1762,6 +1753,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
             `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
             `:background COLOR'.  */
          Lisp_Object ascent, margin, relief, bg;
+         int relief_bound;
 
          ascent = image_spec_value (spec, QCascent, NULL);
          if (INTEGERP (ascent))
@@ -1770,19 +1762,17 @@ lookup_image (struct frame *f, Lisp_Object spec)
            img->ascent = CENTERED_IMAGE_ASCENT;
 
          margin = image_spec_value (spec, QCmargin, NULL);
-         if (INTEGERP (margin) && XINT (margin) >= 0)
+         if (INTEGERP (margin))
            img->vmargin = img->hmargin = XFASTINT (margin);
-         else if (CONSP (margin) && INTEGERP (XCAR (margin))
-                  && INTEGERP (XCDR (margin)))
+         else if (CONSP (margin))
            {
-             if (XINT (XCAR (margin)) > 0)
-               img->hmargin = XFASTINT (XCAR (margin));
-             if (XINT (XCDR (margin)) > 0)
-               img->vmargin = XFASTINT (XCDR (margin));
+             img->hmargin = XFASTINT (XCAR (margin));
+             img->vmargin = XFASTINT (XCDR (margin));
            }
 
          relief = image_spec_value (spec, QCrelief, NULL);
-         if (INTEGERP (relief))
+         relief_bound = INT_MAX - max (img->hmargin, img->vmargin);
+         if (RANGED_INTEGERP (- relief_bound, relief, relief_bound))
            {
              img->relief = XINT (relief);
              img->hmargin += eabs (img->relief);
@@ -1825,7 +1815,7 @@ static void
 cache_image (struct frame *f, struct image *img)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int i;
+  ptrdiff_t i;
 
   /* Find a free slot in c->images.  */
   for (i = 0; i < c->used; ++i)
@@ -1834,13 +1824,7 @@ cache_image (struct frame *f, struct image *img)
 
   /* If no free slot found, maybe enlarge c->images.  */
   if (i == c->used && c->used == c->size)
-    {
-      if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size)
-       memory_full (SIZE_MAX);
-      c->size *= 2;
-      c->images = (struct image **) xrealloc (c->images,
-                                             c->size * sizeof *c->images);
-    }
+    c->images = xpalloc (c->images, &c->size, 1, -1, sizeof *c->images);
 
   /* Add IMG to c->images, and assign IMG an id.  */
   c->images[i] = img;
@@ -1879,7 +1863,7 @@ mark_image_cache (struct image_cache *c)
 {
   if (c)
     {
-      int i;
+      ptrdiff_t i;
       for (i = 0; i < c->used; ++i)
        if (c->images[i])
          mark_image (c->images[i]);
@@ -2032,7 +2016,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
   /* Bitmaps with a depth less than 16 need a palette.  */
   /* BITMAPINFO structure already contains the first RGBQUAD.  */
   if (depth < 16)
-    palette_colors = 1 << depth - 1;
+    palette_colors = 1 << (depth - 1);
 
   *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
 
@@ -2076,7 +2060,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
       DWORD err = GetLastError ();
       Lisp_Object errcode;
       /* All system errors are < 10000, so the following is safe.  */
-      XSETINT (errcode, (int) err);
+      XSETINT (errcode, err);
       image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
       x_destroy_x_image (*ximg);
       return 0;
@@ -2274,7 +2258,7 @@ static const struct image_keyword xbm_format[XBM_LAST] =
   {":foreground",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":background",      IMAGE_STRING_OR_NIL_VALUE,              0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -2355,7 +2339,7 @@ xbm_image_p (Lisp_Object object)
   else
     {
       Lisp_Object data;
-      EMACS_INT width, height;
+      int width, height;
 
       /* Entries for `:width', `:height' and `:data' must be present.  */
       if (!kw[XBM_WIDTH].count
@@ -3069,7 +3053,7 @@ static const struct image_keyword xpm_format[XPM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -3587,9 +3571,8 @@ xpm_load (struct frame *f, struct image *img)
 #endif /* HAVE_NTGUI */
 
       /* Remember allocated colors.  */
+      img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors);
       img->ncolors = attrs.nalloc_pixels;
-      img->colors = (unsigned long *) xmalloc (img->ncolors
-                                              * sizeof *img->colors);
       for (i = 0; i < attrs.nalloc_pixels; ++i)
        {
          img->colors[i] = attrs.alloc_pixels[i];
@@ -3813,8 +3796,8 @@ xpm_get_color_table_h (Lisp_Object color_table,
                        int chars_len)
 {
   struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
-  int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
-                      NULL);
+  ptrdiff_t i =
+    hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
 
   return i >= 0 ? HASH_VALUE (table, i) : Qnil;
 }
@@ -4163,6 +4146,12 @@ static struct ct_color **ct_table;
 /* Number of entries in the color table.  */
 
 static int ct_colors_allocated;
+enum
+{
+  ct_colors_allocated_max =
+    min (INT_MAX,
+        min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long))
+};
 
 /* Initialize the color table.  */
 
@@ -4249,7 +4238,14 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
       XColor color;
       Colormap cmap;
       int rc;
+#else
+      COLORREF color;
+#endif
+
+      if (ct_colors_allocated_max <= ct_colors_allocated)
+       return FRAME_FOREGROUND_PIXEL (f);
 
+#ifdef HAVE_X_WINDOWS
       color.red = r;
       color.green = g;
       color.blue = b;
@@ -4271,7 +4267,6 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
        return FRAME_FOREGROUND_PIXEL (f);
 
 #else
-      COLORREF color;
 #ifdef HAVE_NTGUI
       color = PALETTERGB (r, g, b);
 #else
@@ -4312,6 +4307,9 @@ lookup_pixel_color (struct frame *f, unsigned long pixel)
       Colormap cmap;
       int rc;
 
+      if (ct_colors_allocated_max <= ct_colors_allocated)
+       return FRAME_FOREGROUND_PIXEL (f);
+
 #ifdef HAVE_X_WINDOWS
       cmap = FRAME_X_COLORMAP (f);
       color.pixel = pixel;
@@ -4450,7 +4448,9 @@ x_to_xcolors (struct frame *f, struct image *img, int rgb_p)
   HGDIOBJ prev;
 #endif /* HAVE_NTGUI */
 
-  colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
+    memory_full (SIZE_MAX);
+  colors = (XColor *) xmalloc (sizeof *colors * img->width * img->height);
 
 #ifndef HAVE_NTGUI
   /* Get the X image IMG->pixmap.  */
@@ -4602,7 +4602,9 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus
 
 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
-  new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+  if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
+    memory_full (SIZE_MAX);
+  new = (XColor *) xmalloc (sizeof *new * img->width * img->height);
 
   for (y = 0; y < img->height; ++y)
     {
@@ -4980,7 +4982,7 @@ static const struct image_keyword pbm_format[PBM_LAST] =
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -5395,7 +5397,7 @@ static const struct image_keyword png_format[PNG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -5544,7 +5546,7 @@ init_png_functions (Lisp_Object libraries)
 /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908)  */
 #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
 #define PNG_JMPBUF(ptr) \
-  (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf)))
+  (*fn_png_set_longjmp_fn ((ptr), longjmp, sizeof (jmp_buf)))
 #endif
 
 /* Error and warning handlers installed when the PNG library
@@ -5880,7 +5882,7 @@ png_load (struct frame *f, struct image *img)
 
       for (x = 0; x < width; ++x)
        {
-         unsigned r, g, b;
+         int r, g, b;
 
          r = *p++ << 8;
          g = *p++ << 8;
@@ -5965,9 +5967,9 @@ png_load (struct frame *f, struct image *img)
 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));
+  return ns_load_image (f, img,
+                        image_spec_value (img->spec, QCfile, NULL),
+                        image_spec_value (img->spec, QCdata, NULL));
 }
 #endif  /* HAVE_NS */
 
@@ -6015,7 +6017,7 @@ static const struct image_keyword jpeg_format[JPEG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6114,7 +6116,7 @@ jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
 
 #else
 
-#define fn_jpeg_CreateDecompress(a,b,c)        jpeg_create_decompress(a)
+#define fn_jpeg_CreateDecompress(a,b,c)        jpeg_create_decompress (a)
 #define fn_jpeg_start_decompress       jpeg_start_decompress
 #define fn_jpeg_finish_decompress      jpeg_finish_decompress
 #define fn_jpeg_destroy_decompress     jpeg_destroy_decompress
@@ -6565,7 +6567,7 @@ static const struct image_keyword tiff_format[TIFF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":conversions",     IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
@@ -6744,18 +6746,41 @@ tiff_size_of_memory (thandle_t data)
   return ((tiff_memory_source *) data)->len;
 }
 
+/* GCC 3.x on x86 Windows targets has a bug that triggers an internal
+   compiler error compiling tiff_handler, see Bugzilla bug #17406
+   (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406).  Declaring
+   this function as external works around that problem.  */
+#if defined (__MINGW32__) && __GNUC__ == 3
+# define MINGW_STATIC
+#else
+# define MINGW_STATIC static
+#endif
+
+MINGW_STATIC void
+tiff_handler (const char *, const char *, const char *, va_list)
+  ATTRIBUTE_FORMAT_PRINTF (3, 0);
+MINGW_STATIC void
+tiff_handler (const char *log_format, const char *title,
+             const char *format, va_list ap)
+{
+  /* doprnt is not suitable here, as TIFF handlers are called from
+     libtiff and are passed arbitrary printf directives.  Instead, use
+     vsnprintf, taking care to be portable to nonstandard environments
+     where vsnprintf returns -1 on buffer overflow.  Since it's just a
+     log entry, it's OK to truncate it.  */
+  char buf[4000];
+  int len = vsnprintf (buf, sizeof buf, format, ap);
+  add_to_log (log_format, build_string (title),
+             make_string (buf, max (0, min (len, sizeof buf - 1))));
+}
+#undef MINGW_STATIC
 
 static void tiff_error_handler (const char *, const char *, va_list)
   ATTRIBUTE_FORMAT_PRINTF (2, 0);
 static void
 tiff_error_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF error: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF error: %s %s", title, format, ap);
 }
 
 
@@ -6764,12 +6789,7 @@ static void tiff_warning_handler (const char *, const char *, va_list)
 static void
 tiff_warning_handler (const char *title, const char *format, va_list ap)
 {
-  char buf[512];
-  int len;
-
-  len = sprintf (buf, "TIFF warning: %s ", title);
-  vsprintf (buf + len, format, ap);
-  add_to_log (buf, Qnil, Qnil);
+  tiff_handler ("TIFF warning: %s %s", title, format, ap);
 }
 
 
@@ -6845,8 +6865,9 @@ tiff_load (struct frame *f, struct image *img)
   image = image_spec_value (img->spec, QCindex, NULL);
   if (INTEGERP (image))
     {
-      int ino = XFASTINT (image);
-      if (!fn_TIFFSetDirectory (tiff, ino))
+      EMACS_INT ino = XFASTINT (image);
+      if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
+            && fn_TIFFSetDirectory (tiff, ino)))
        {
          image_error ("Invalid image number `%s' in image `%s'",
                       image, img->spec);
@@ -6994,7 +7015,7 @@ static const struct image_keyword gif_format[GIF_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -7139,13 +7160,12 @@ gif_load (struct frame *f, struct image *img)
   ColorMapObject *gif_color_map;
   unsigned long pixel_colors[256];
   GifFileType *gif;
-  int image_height, image_width;
   gif_memory_source memsrc;
   Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
   Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
   unsigned long bgcolor = 0;
-  int idx;
+  EMACS_INT idx;
 
   if (NILP (specified_data))
     {
@@ -7216,19 +7236,15 @@ gif_load (struct frame *f, struct image *img)
       }
   }
 
-  img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
-  img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
-  image_height = gif->SavedImages[idx].ImageDesc.Height;
-  img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
-  image_width = gif->SavedImages[idx].ImageDesc.Width;
-  img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
+  width = img->width = gif->SWidth;
+  height = img->height = gif->SHeight;
 
-  width = img->width = max (gif->SWidth,
-                           max (gif->Image.Left + gif->Image.Width,
-                                img->corners[RIGHT_CORNER]));
-  height = img->height = max (gif->SHeight,
-                             max (gif->Image.Top + gif->Image.Height,
-                                  img->corners[BOT_CORNER]));
+  img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
+  img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
+  img->corners[BOT_CORNER]
+    = img->corners[TOP_CORNER] + gif->SavedImages[0].ImageDesc.Height;
+  img->corners[RIGHT_CORNER]
+    = img->corners[LEFT_CORNER] + gif->SavedImages[0].ImageDesc.Width;
 
   if (!check_image_size (f, width, height))
     {
@@ -7283,6 +7299,10 @@ gif_load (struct frame *f, struct image *img)
       unsigned char *raster = (unsigned char *) subimage->RasterBits;
       int transparency_color_index = -1;
       int disposal = 0;
+      int subimg_width = subimage->ImageDesc.Width;
+      int subimg_height = subimage->ImageDesc.Height;
+      int subimg_top = subimage->ImageDesc.Top;
+      int subimg_left = subimage->ImageDesc.Left;
 
       /* Find the Graphic Control Extension block for this sub-image.
         Extract the disposal method and transparency color.  */
@@ -7306,6 +7326,13 @@ gif_load (struct frame *f, struct image *img)
       if (j == 0)
        disposal = 2;
 
+      /* For disposal == 0, the spec says "No disposal specified. The
+        decoder is not required to take any action."  In practice, it
+        seems we need to treat this like "keep in place", see e.g.
+        http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */
+      if (disposal == 0)
+       disposal = 1;
+
       /* Allocate subimage colors.  */
       memset (pixel_colors, 0, sizeof pixel_colors);
       gif_color_map = subimage->ImageDesc.ColorMap;
@@ -7333,34 +7360,34 @@ gif_load (struct frame *f, struct image *img)
          int row, pass;
 
          for (y = 0, row = interlace_start[0], pass = 0;
-              y < image_height;
+              y < subimg_height;
               y++, row += interlace_increment[pass])
            {
-             if (row >= image_height)
+             if (row >= subimg_height)
                {
                  row = interlace_start[++pass];
-                 while (row >= image_height)
+                 while (row >= subimg_height)
                    row = interlace_start[++pass];
                }
 
-             for (x = 0; x < image_width; x++)
+             for (x = 0; x < subimg_width; x++)
                {
-                 int c = raster[y * image_width + x];
+                 int c = raster[y * subimg_width + x];
                  if (transparency_color_index != c || disposal != 1)
-                   XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                              row + img->corners[TOP_CORNER], pixel_colors[c]);
+                   XPutPixel (ximg, x + subimg_left, row + subimg_top,
+                              pixel_colors[c]);
                }
            }
        }
       else
        {
-         for (y = 0; y < image_height; ++y)
-           for (x = 0; x < image_width; ++x)
+         for (y = 0; y < subimg_height; ++y)
+           for (x = 0; x < subimg_width; ++x)
              {
-               int c = raster[y * image_width + x];
+               int c = raster[y * subimg_width + x];
                if (transparency_color_index != c || disposal != 1)
-                 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
-                            y + img->corners[TOP_CORNER], pixel_colors[c]);
+                 XPutPixel (ximg, x + subimg_left, y + subimg_top,
+                            pixel_colors[c]);
              }
        }
     }
@@ -7375,7 +7402,7 @@ gif_load (struct frame *f, struct image *img)
   img->lisp_data = Qnil;
   if (gif->SavedImages[idx].ExtensionBlockCount > 0)
     {
-      unsigned int delay = 0;
+      int delay = 0;
       ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
       for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
        /* Append (... FUNCTION "BYTES") */
@@ -7396,7 +7423,7 @@ gif_load (struct frame *f, struct image *img)
       if (delay)
        img->lisp_data
          = Fcons (Qdelay,
-                  Fcons (make_float (((double) delay) * 0.01),
+                  Fcons (make_float (delay / 100.0),
                          img->lisp_data));
     }
 
@@ -7475,7 +7502,7 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
     {":data",          IMAGE_STRING_VALUE,                     0},
     {":file",          IMAGE_STRING_VALUE,                     0},
     {":ascent",                IMAGE_ASCENT_VALUE,                     0},
-    {":margin",                IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+    {":margin",                IMAGE_NON_NEGATIVE_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},
@@ -7526,7 +7553,7 @@ imagemagick_image_p (Lisp_Object object)
 }
 
 /* The GIF library also defines DrawRectangle, but its never used in Emacs.
-   Therefore rename the function so it doesnt collide with ImageMagick.  */
+   Therefore rename the function so it doesn't collide with ImageMagick.  */
 #define DrawRectangle DrawRectangleGif
 #include <wand/MagickWand.h>
 
@@ -7538,6 +7565,22 @@ extern WandExport void PixelGetMagickColor (const PixelWand *,
                                            MagickPixelPacket *);
 #endif
 
+/* Log ImageMagick error message.
+   Useful when a ImageMagick function returns the status `MagickFalse'.  */
+
+static void
+imagemagick_error (MagickWand *wand)
+{
+  char *description;
+  ExceptionType severity;
+
+  description = MagickGetException (wand, &severity);
+  image_error ("ImageMagick error: %s",
+              make_string (description, strlen (description)),
+              Qnil);
+  description = (char *) MagickRelinquishMemory (description);
+}
+
 /* Helper function for imagemagick_load, which does the actual loading
    given contents and size, apart from frame and image structures,
    passed from imagemagick_load.  Uses librimagemagick to do most of
@@ -7572,10 +7615,9 @@ imagemagick_load_image (struct frame *f, struct image *img,
   Lisp_Object image;
   Lisp_Object value;
   Lisp_Object crop;
-  long ino;
+  EMACS_INT ino;
   int desired_width, desired_height;
   double rotation;
-  int imagemagick_rendermethod;
   int pixelwidth;
   ImageInfo  *image_info;
   ExceptionInfo *exception;
@@ -7592,7 +7634,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
   image = image_spec_value (img->spec, QCindex, NULL);
   ino = INTEGERP (image) ? XFASTINT (image) : 0;
   ping_wand = NewMagickWand ();
-  MagickSetResolution (ping_wand, 2, 2);
+  /* MagickSetResolution (ping_wand, 2, 2);   (Bug#10112)  */
+
   if (filename != NULL)
     {
       status = MagickPingImage (ping_wand, filename);
@@ -7602,7 +7645,14 @@ imagemagick_load_image (struct frame *f, struct image *img,
       status = MagickPingImageBlob (ping_wand, contents, size);
     }
 
-  if (ino >= MagickGetNumberImages (ping_wand))
+  if (status == MagickFalse)
+    {
+      imagemagick_error (ping_wand);
+      DestroyMagickWand (ping_wand);
+      return 0;
+    }
+
+  if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand)))
     {
       image_error ("Invalid image number `%s' in image `%s'",
                   image, img->spec);
@@ -7610,7 +7660,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
       return 0;
     }
 
-  if (MagickGetNumberImages(ping_wand) > 1)
+  if (MagickGetNumberImages (ping_wand) > 1)
     img->lisp_data =
       Fcons (Qcount,
              Fcons (make_number (MagickGetNumberImages (ping_wand)),
@@ -7635,13 +7685,16 @@ imagemagick_load_image (struct frame *f, struct image *img,
       if (im_image == NULL)
        goto imagemagick_no_wand;
       image_wand = NewMagickWandFromImage (im_image);
-      DestroyImage(im_image);
+      DestroyImage (im_image);
     }
   else
     {
       image_wand = NewMagickWand ();
       if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
-       goto imagemagick_error;
+       {
+         imagemagick_error (image_wand);
+         goto imagemagick_error;
+       }
     }
 
   /* If width and/or height is set in the display spec assume we want
@@ -7669,6 +7722,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
       if (status == MagickFalse)
        {
          image_error ("Imagemagick scale failed", Qnil, Qnil);
+         imagemagick_error (image_wand);
          goto imagemagick_error;
        }
     }
@@ -7677,28 +7731,28 @@ imagemagick_load_image (struct frame *f, struct image *img,
      efficient.  */
   crop = image_spec_value (img->spec, QCcrop, NULL);
 
-  if (CONSP (crop) && INTEGERP (XCAR (crop)))
+  if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
     {
       /* After some testing, it seems MagickCropImage is the fastest crop
          function in ImageMagick.  This crop function seems to do less copying
          than the alternatives, but it still reads the entire image into memory
-         before croping, which is aparently difficult to avoid when using
+         before cropping, which is apparently difficult to avoid when using
          imagemagick.  */
-      int w, h;
-      w = XFASTINT (XCAR (crop));
+      size_t crop_width = XINT (XCAR (crop));
       crop = XCDR (crop);
-      if (CONSP (crop) && INTEGERP (XCAR (crop)))
+      if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
        {
-         h = XFASTINT (XCAR (crop));
+         size_t crop_height = XINT (XCAR (crop));
          crop = XCDR (crop);
-         if (CONSP (crop) && INTEGERP (XCAR (crop)))
+         if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
            {
-             x = XFASTINT (XCAR (crop));
+             ssize_t crop_x = XINT (XCAR (crop));
              crop = XCDR (crop);
-             if (CONSP (crop) && INTEGERP (XCAR (crop)))
+             if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
                {
-                 y = XFASTINT (XCAR (crop));
-                 MagickCropImage (image_wand, w, h, x, y);
+                 ssize_t crop_y = XINT (XCAR (crop));
+                 MagickCropImage (image_wand, crop_width, crop_height,
+                                  crop_x, crop_y);
                }
            }
        }
@@ -7723,12 +7777,13 @@ imagemagick_load_image (struct frame *f, struct image *img,
       if (status == MagickFalse)
         {
           image_error ("Imagemagick image rotate failed", Qnil, Qnil);
+         imagemagick_error (image_wand);
           goto imagemagick_error;
         }
     }
 
   /* Finally we are done manipulating the image.  Figure out the
-     resulting width/height and transfer ownerwship to Emacs.  */
+     resulting width/height and transfer ownership to Emacs.  */
   height = MagickGetImageHeight (image_wand);
   width = MagickGetImageWidth (image_wand);
 
@@ -7743,10 +7798,11 @@ imagemagick_load_image (struct frame *f, struct image *img,
      went ok.  */
 
   init_color_table ();
-  imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type)
-                              ? XFASTINT (Vimagemagick_render_type) : 0);
-  if (imagemagick_rendermethod == 0)
+
+  if (imagemagick_render_type == 0)
     {
+      size_t image_height;
+
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!x_create_x_image_and_pixmap (f, width, height, 0,
                                         &ximg, &img->pixmap))
@@ -7754,11 +7810,11 @@ imagemagick_load_image (struct frame *f, struct image *img,
 #ifdef COLOR_TABLE_SUPPORT
          free_color_table ();
 #endif
-          image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+          image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
           goto imagemagick_error;
         }
 
-      /* Copy imagegmagick image to x with primitive yet robust pixel
+      /* Copy imagemagick image to x with primitive yet robust pixel
          pusher loop.  This has been tested a lot with many different
          images.  */
 
@@ -7775,7 +7831,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
           goto imagemagick_error;
         }
 
-      for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++)
+      image_height = MagickGetImageHeight (image_wand);
+      for (y = 0; y < image_height; y++)
         {
           pixels = PixelGetNextIteratorRow (iterator, &width);
           if (pixels == (PixelWand **) NULL)
@@ -7792,10 +7849,9 @@ imagemagick_load_image (struct frame *f, struct image *img,
         }
       DestroyPixelIterator (iterator);
     }
-
-  if (imagemagick_rendermethod == 1)
+  else                          /* imagemagick_render_type != 0 */
     {
-      /* Magicexportimage is normaly faster than pixelpushing.  This
+      /* Magicexportimage is normally faster than pixelpushing.  This
          method is also well tested. Some aspects of this method are
          ad-hoc and needs to be more researched. */
       int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
@@ -7807,12 +7863,12 @@ imagemagick_load_image (struct frame *f, struct image *img,
 #ifdef COLOR_TABLE_SUPPORT
          free_color_table ();
 #endif
-         image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
+         image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
          goto imagemagick_error;
        }
 
 
-      /* Oddly, the below code doesnt seem to work:*/
+      /* Oddly, the below code doesn't seem to work:*/
       /* switch(ximg->bitmap_unit){ */
       /* case 8: */
       /*   pixelwidth=CharPixel; */
@@ -7841,7 +7897,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
                               /*&(img->pixmap));*/
                               ximg->data);
 #else
-      image_error ("You dont have MagickExportImagePixels, upgrade ImageMagick!",
+      image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!",
                   Qnil, Qnil);
 #endif
     }
@@ -7928,6 +7984,7 @@ DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
 Each entry in this list is a symbol named after an ImageMagick format
 tag.  See the ImageMagick manual for a list of ImageMagick formats and
 their descriptions (http://www.imagemagick.org/script/formats.php).
+You can also try the shell command: `identify -list format'.
 
 Note that ImageMagick recognizes many file-types that Emacs does not
 recognize as images, such as C.  See `imagemagick-types-inhibit'.  */)
@@ -7944,7 +8001,7 @@ recognize as images, such as C.  See `imagemagick-types-inhibit'.  */)
       Qimagemagicktype = intern (imtypes[i]);
       typelist = Fcons (Qimagemagicktype, typelist);
     }
-  return typelist;
+  return Fnreverse (typelist);
 }
 
 #endif /* defined (HAVE_IMAGEMAGICK) */
@@ -7995,7 +8052,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -8281,10 +8338,10 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
     {
       for (x = 0; x < width; ++x)
        {
-         unsigned red;
-         unsigned green;
-         unsigned blue;
-         unsigned opacity;
+         int red;
+         int green;
+         int blue;
+         int opacity;
 
          red     = *pixels++;
          green   = *pixels++;
@@ -8390,7 +8447,7 @@ static const struct image_keyword gs_format[GS_LAST] =
   {":loader",          IMAGE_FUNCTION_VALUE,                   0},
   {":bounding-box",    IMAGE_DONT_CHECK_VALUE_TYPE,            1},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
-  {":margin",          IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,   0},
+  {":margin",          IMAGE_NON_NEGATIVE_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},
@@ -8465,7 +8522,8 @@ gs_image_p (Lisp_Object object)
 static int
 gs_load (struct frame *f, struct image *img)
 {
-  char buffer[100];
+  uprintmax_t printnum1, printnum2;
+  char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
   Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
   Lisp_Object frame;
   double in_width, in_height;
@@ -8477,16 +8535,19 @@ gs_load (struct frame *f, struct image *img)
      info.  */
   pt_width = image_spec_value (img->spec, QCpt_width, NULL);
   in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
-  img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
+  in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
   pt_height = image_spec_value (img->spec, QCpt_height, NULL);
   in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
-  img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
+  in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
 
-  if (!check_image_size (f, img->width, img->height))
+  if (! (in_width <= INT_MAX && in_height <= INT_MAX
+        && check_image_size (f, in_width, in_height)))
     {
       image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
       return 0;
     }
+  img->width = in_width;
+  img->height = in_height;
 
   /* Create the pixmap.  */
   xassert (img->pixmap == NO_PIXMAP);
@@ -8511,14 +8572,14 @@ gs_load (struct frame *f, struct image *img)
      if successful.  We do not record_unwind_protect here because
      other places in redisplay like calling window scroll functions
      don't either.  Let the Lisp loader use `unwind-protect' instead.  */
-  sprintf (buffer, "%lu %lu",
-          (unsigned long) FRAME_X_WINDOW (f),
-          (unsigned long) img->pixmap);
+  printnum1 = FRAME_X_WINDOW (f);
+  printnum2 = img->pixmap;
+  sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
   window_and_pixmap_id = build_string (buffer);
 
-  sprintf (buffer, "%lu %lu",
-          FRAME_FOREGROUND_PIXEL (f),
-          FRAME_BACKGROUND_PIXEL (f));
+  printnum1 = FRAME_FOREGROUND_PIXEL (f);
+  printnum2 = FRAME_BACKGROUND_PIXEL (f);
+  sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
   pixel_colors = build_string (buffer);
 
   XSETFRAME (frame, f);
@@ -8543,7 +8604,8 @@ void
 x_kill_gs_process (Pixmap pixmap, struct frame *f)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int class, i;
+  int class;
+  ptrdiff_t i;
   struct image *img;
 
   /* Find the image containing PIXMAP.  */
@@ -8647,7 +8709,7 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
   (Lisp_Object spec)
 {
-  int id = -1;
+  ptrdiff_t id = -1;
 
   if (valid_image_p (spec))
     id = lookup_image (SELECTED_FRAME (), spec);
@@ -8747,7 +8809,7 @@ syms_of_image (void)
      operation on GNU/Linux of calling dump-emacs after loading some images.  */
   image_types = NULL;
 
-  /* Must be defined now becase we're going to update it below, while
+  /* Must be defined now because we're going to update it below, while
      defining the supported image types.  */
   DEFVAR_LISP ("image-types", Vimage_types,
     doc: /* List of potentially supported image types.
@@ -8895,8 +8957,17 @@ The value can also be nil, meaning the cache is never cleared.
 The function `clear-image-cache' disregards this variable.  */);
   Vimage_cache_eviction_delay = make_number (300);
 #ifdef HAVE_IMAGEMAGICK
-  DEFVAR_LISP ("imagemagick-render-type", Vimagemagick_render_type,
-               doc: /* Choose between ImageMagick render methods.  */);
+  DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type,
+    doc: /* Integer indicating which ImageMagick rendering method to use.
+The options are:
+  0 -- the default method (pixel pushing)
+  1 -- a newer method ("MagickExportImagePixels") that may perform
+       better (speed etc) in some cases, but has not been as thoroughly
+       tested with Emacs as the default method.  This method requires
+       ImageMagick version 6.4.6 (approximately) or later.
+*/);
+  /* MagickExportImagePixels is in 6.4.6-9, but not 6.4.4-10.  */
+  imagemagick_render_type = 0;
 #endif
 
 }