]> code.delx.au - gnu-emacs/blobdiff - src/image.c
Work around GCC bug 54561 in a better way
[gnu-emacs] / src / image.c
index a44b90b78e7f6b6d1dd4fb77844d68774e4d481c..1770de7e8ff1394e35f16149cd1c896dbb96666d 100644 (file)
@@ -56,6 +56,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
 
+/* Work around GCC bug 54561.  */
+#if GNUC_PREREQ (4, 3, 0)
+# pragma GCC diagnostic ignored "-Wclobbered"
+#endif
+
 #ifdef HAVE_X_WINDOWS
 typedef struct x_bitmap_record Bitmap_Record;
 #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
@@ -80,7 +85,6 @@ typedef struct w32_bitmap_record Bitmap_Record;
 #define PIX_MASK_DRAW  1
 
 #define x_defined_color w32_defined_color
-#define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
 
 #endif /* HAVE_NTGUI */
 
@@ -223,6 +227,7 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
 #endif /* HAVE_X_WINDOWS */
 
 #ifdef HAVE_NTGUI
+  Lisp_Object frame UNINIT;    /* The value is not used.  */
   Pixmap bitmap;
   bitmap = CreateBitmap (width, height,
                         FRAME_DISPLAY_INFO (XFRAME (frame))->n_planes,
@@ -270,11 +275,11 @@ x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsi
 ptrdiff_t
 x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
 {
-  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
-
 #ifdef HAVE_NTGUI
   return -1;  /* W32_TODO : bitmap support */
-#endif /* HAVE_NTGUI */
+#else
+  Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
+#endif
 
 #ifdef HAVE_NS
   ptrdiff_t id;
@@ -1142,7 +1147,8 @@ static RGB_PIXEL_COLOR
 four_corners_best (XImagePtr_or_DC ximg, int *corners,
                   unsigned long width, unsigned long height)
 {
-  RGB_PIXEL_COLOR corner_pixels[4], best IF_LINT (= 0);
+  RGB_PIXEL_COLOR corner_pixels[4];
+  RGB_PIXEL_COLOR best UNINIT;
   int i, best_count;
 
   if (corners && corners[BOT_CORNER] >= 0)
@@ -1830,6 +1836,9 @@ cache_image (struct frame *f, struct image *img)
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
   ptrdiff_t i;
 
+  if (!c)
+    c = FRAME_IMAGE_CACHE (f) = make_image_cache ();
+
   /* Find a free slot in c->images.  */
   for (i = 0; i < c->used; ++i)
     if (c->images[i] == NULL)
@@ -2297,7 +2306,7 @@ x_find_image_fd (Lisp_Object file, int *pfd)
             happens, e.g., under Auto Image File Mode.)  'openp'
             didn't open the file, so we should, because the caller
             expects that.  */
-         fd = emacs_open (SSDATA (file_found), O_RDONLY | O_BINARY, 0);
+         fd = emacs_open (SSDATA (file_found), O_RDONLY, 0);
        }
     }
   else /* fd < 0, but not -2 */
@@ -3155,16 +3164,18 @@ static bool xpm_load (struct frame *f, struct image *img);
 #define XColor xpm_XColor
 #define XImage xpm_XImage
 #define Display xpm_Display
-#define PIXEL_ALREADY_TYPEDEFED
+#ifdef CYGWIN
+#include "noX/xpm.h"
+#else  /* not CYGWIN */
 #include "X11/xpm.h"
+#endif /* not CYGWIN */
 #undef FOR_MSW
 #undef XColor
 #undef XImage
 #undef Display
-#undef PIXEL_ALREADY_TYPEDEFED
-#else
+#else  /* not HAVE_NTGUI */
 #include "X11/xpm.h"
-#endif /* HAVE_NTGUI */
+#endif /* not HAVE_NTGUI */
 #endif /* HAVE_XPM */
 
 #if defined (HAVE_XPM) || defined (HAVE_NS)
@@ -3674,7 +3685,7 @@ xpm_load (struct frame *f, struct image *img)
 #endif
       /* XpmReadFileToPixmap is not available in the Windows port of
         libxpm.  But XpmReadFileToImage almost does what we want.  */
-      rc = XpmReadFileToImage (&hdc, SDATA (file),
+      rc = XpmReadFileToImage (&hdc, SSDATA (file),
                               &xpm_image, &xpm_mask,
                               &attrs);
 #else
@@ -3698,7 +3709,7 @@ xpm_load (struct frame *f, struct image *img)
 #ifdef HAVE_NTGUI
       /* XpmCreatePixmapFromBuffer is not available in the Windows port
         of libxpm.  But XpmCreateImageFromBuffer almost does what we want.  */
-      rc = XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
+      rc = XpmCreateImageFromBuffer (&hdc, SSDATA (buffer),
                                     &xpm_image, &xpm_mask,
                                     &attrs);
 #else
@@ -5891,13 +5902,12 @@ struct png_load_context
 static bool
 png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 {
-  Lisp_Object specified_file;
-  Lisp_Object specified_data;
+  Lisp_Object specified_file, specified_data;
+  FILE *fp = NULL;
   int x, y;
   ptrdiff_t i;
   png_struct *png_ptr;
   png_info *info_ptr = NULL, *end_info = NULL;
-  FILE *fp = NULL;
   png_byte sig[8];
   png_byte *pixels = NULL;
   png_byte **rows = NULL;
@@ -5919,7 +5929,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   /* Find out what file to load.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
-  IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
 
   if (NILP (specified_data))
     {
@@ -6015,10 +6024,6 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       return 0;
     }
 
-  /* Silence a bogus diagnostic; see GCC bug 54561.  */
-  IF_LINT (fp = c->fp);
-  IF_LINT (specified_data = specified_data_volatile);
-
   /* Read image info.  */
   if (!NILP (specified_data))
     png_set_read_fn (png_ptr, &tbr, png_read_from_memory);
@@ -6668,10 +6673,8 @@ static bool
 jpeg_load_body (struct frame *f, struct image *img,
                struct my_jpeg_error_mgr *mgr)
 {
-  Lisp_Object specified_file;
-  Lisp_Object specified_data;
-  /* The 'volatile' silences a bogus diagnostic; see GCC bug 54561.  */
-  FILE * IF_LINT (volatile) fp = NULL;
+  Lisp_Object specified_file, specified_data;
+  FILE *volatile fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
   unsigned long *colors;
@@ -6684,7 +6687,6 @@ jpeg_load_body (struct frame *f, struct image *img,
   /* Open the JPEG file.  */
   specified_file = image_spec_value (img->spec, QCfile, NULL);
   specified_data = image_spec_value (img->spec, QCdata, NULL);
-  IF_LINT (Lisp_Object volatile specified_data_volatile = specified_data);
 
   if (NILP (specified_data))
     {
@@ -6748,9 +6750,6 @@ jpeg_load_body (struct frame *f, struct image *img,
       return 0;
     }
 
-  /* Silence a bogus diagnostic; see GCC bug 54561.  */
-  IF_LINT (specified_data = specified_data_volatile);
-
   /* Create the JPEG decompression object.  Let it read from fp.
         Read the JPEG image header.  */
   jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
@@ -7976,7 +7975,8 @@ gif_load (struct frame *f, struct image *img)
        {
          img->lisp_data
            = Fcons (make_number (ext->Function),
-                    Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
+                    Fcons (make_unibyte_string ((char *) ext->Bytes,
+                                                ext->ByteCount),
                            img->lisp_data));
          if (ext->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION
              && ext->ByteCount == 4)
@@ -8073,15 +8073,25 @@ compute_image_size (size_t width, size_t height,
 {
   Lisp_Object value;
   int desired_width, desired_height;
+  double scale = 1;
+
+  value = image_spec_value (spec, QCscale, NULL);
+  if (NUMBERP (value))
+    scale = extract_float (value);
 
   /* If width and/or height is set in the display spec assume we want
      to scale to those values.  If either h or w is unspecified, the
      unspecified should be calculated from the specified to preserve
      aspect ratio.  */
   value = image_spec_value (spec, QCwidth, NULL);
-  desired_width = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
+  desired_width = NATNUMP (value) ?
+    min (XFASTINT (value) * scale, INT_MAX) : -1;
   value = image_spec_value (spec, QCheight, NULL);
-  desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
+  desired_height = NATNUMP (value) ?
+    min (XFASTINT (value) * scale, INT_MAX) : -1;
+
+  width = width * scale;
+  height = height * scale;
 
   if (desired_width == -1)
     {
@@ -8132,6 +8142,13 @@ compute_image_size (size_t width, size_t height,
     /* h known, calculate w.  */
     desired_width = scale_image_size (desired_height, height, width);
 
+  /* We have no width/height settings, so just apply the scale. */
+  if (desired_width == -1 && desired_height == -1)
+    {
+      desired_width = width;
+      desired_height = height;
+    }
+
   *d_width = desired_width;
   *d_height = desired_height;
 }
@@ -8546,6 +8563,18 @@ imagemagick_load_image (struct frame *f, struct image *img,
       return 0;
     }
 
+#ifdef HAVE_MAGICKAUTOORIENTIMAGE
+  /* If no :rotation is explicitly specified, apply the automatic
+     rotation from EXIF. */
+  if (NILP (image_spec_value (img->spec, QCrotation, NULL)))
+    if (MagickAutoOrientImage (image_wand) == MagickFalse)
+      {
+        image_error ("Error applying automatic orientation in image `%s'", img->spec);
+        DestroyMagickWand (image_wand);
+        return 0;
+      }
+#endif
+
   if (ino < 0 || ino >= MagickGetNumberImages (image_wand))
     {
       image_error ("Invalid image number `%s' in image `%s'", image, img->spec);
@@ -9228,8 +9257,8 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   eassert (gdk_pixbuf_get_has_alpha (pixbuf));
   eassert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
 
-#ifdef USE_CAIRO
   {
+#ifdef USE_CAIRO
     unsigned char *data = (unsigned char *) xmalloc (width*height*4);
     uint32_t bgcolor = get_spec_bg_or_alpha_as_argb (img, f);
 
@@ -9255,82 +9284,77 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
 
     create_cairo_image_surface (img, data, width, height);
     g_object_unref (pixbuf);
-  }
 #else
-  /* Try to create a x pixmap to hold the svg pixmap.  */
-  XImagePtr ximg;
-  if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
-    {
-      g_object_unref (pixbuf);
-      return 0;
-    }
+    /* Try to create a x pixmap to hold the svg pixmap.  */
+    XImagePtr ximg;
+    if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
+      {
+       g_object_unref (pixbuf);
+       return 0;
+      }
 
-  init_color_table ();
+    init_color_table ();
 
-  /* Handle alpha channel by combining the image with a background
-     color.  */
-  XColor background;
-  Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
-  if (!STRINGP (specified_bg)
-      || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
-    x_query_frame_background_color (f, &background);
-
-  /* SVG pixmaps specify transparency in the last byte, so right
-     shift 8 bits to get rid of it, since emacs doesn't support
-     transparency.  */
-  background.red   >>= 8;
-  background.green >>= 8;
-  background.blue  >>= 8;
-
-  /* This loop handles opacity values, since Emacs assumes
-     non-transparent images.  Each pixel must be "flattened" by
-     calculating the resulting color, given the transparency of the
-     pixel, and the image background color.  */
-  for (int y = 0; y < height; ++y)
-    {
-      for (int x = 0; x < width; ++x)
-       {
-         int red;
-         int green;
-         int blue;
-         int opacity;
-
-         red     = *pixels++;
-         green   = *pixels++;
-         blue    = *pixels++;
-         opacity = *pixels++;
-
-         red   = ((red * opacity)
-                  + (background.red * ((1 << 8) - opacity)));
-         green = ((green * opacity)
-                  + (background.green * ((1 << 8) - opacity)));
-         blue  = ((blue * opacity)
-                  + (background.blue * ((1 << 8) - opacity)));
-
-         XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
-       }
+    /* Handle alpha channel by combining the image with a background
+       color.  */
+    XColor background;
+    Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
+    if (!STRINGP (specified_bg)
+       || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
+      x_query_frame_background_color (f, &background);
+
+    /* SVG pixmaps specify transparency in the last byte, so right
+       shift 8 bits to get rid of it, since emacs doesn't support
+       transparency.  */
+    background.red   >>= 8;
+    background.green >>= 8;
+    background.blue  >>= 8;
+
+    /* This loop handles opacity values, since Emacs assumes
+       non-transparent images.  Each pixel must be "flattened" by
+       calculating the resulting color, given the transparency of the
+       pixel, and the image background color.  */
+    for (int y = 0; y < height; ++y)
+      {
+       for (int x = 0; x < width; ++x)
+         {
+           int red     = *pixels++;
+           int green   = *pixels++;
+           int blue    = *pixels++;
+           int opacity = *pixels++;
+
+           red   = ((red * opacity)
+                    + (background.red * ((1 << 8) - opacity)));
+           green = ((green * opacity)
+                    + (background.green * ((1 << 8) - opacity)));
+           blue  = ((blue * opacity)
+                    + (background.blue * ((1 << 8) - opacity)));
+
+           XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
+         }
 
-      pixels += rowstride - 4 * width;
-    }
+       pixels += rowstride - 4 * width;
+      }
 
 #ifdef COLOR_TABLE_SUPPORT
-  /* Remember colors allocated for this image.  */
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
+    /* Remember colors allocated for this image.  */
+    img->colors = colors_in_color_table (&img->ncolors);
+    free_color_table ();
 #endif /* COLOR_TABLE_SUPPORT */
 
-  g_object_unref (pixbuf);
+    g_object_unref (pixbuf);
 
-  img->width  = width;
-  img->height = height;
+    img->width  = width;
+    img->height = height;
 
-  /* Maybe fill in the background field while we have ximg handy.
-     Casting avoids a GCC warning.  */
-  IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
+    /* Maybe fill in the background field while we have ximg handy.
+       Casting avoids a GCC warning.  */
+    IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
 
-  /* Put ximg into the image.  */
-  image_put_x_image (f, img, ximg, 0);
+    /* Put ximg into the image.  */
+    image_put_x_image (f, img, ximg, 0);
 #endif /* ! USE_CAIRO */
+  }
 
   return 1;
 
@@ -9795,6 +9819,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   DEFSYM (QCcrop, ":crop");
   DEFSYM (QCrotation, ":rotation");
   DEFSYM (QCmatrix, ":matrix");
+  DEFSYM (QCscale, ":scale");
   DEFSYM (QCcolor_adjustment, ":color-adjustment");
   DEFSYM (QCmask, ":mask");