static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
static void free_image P_ ((struct frame *f, struct image *img));
+static int check_image_size P_ ((struct frame *f, int width, int height));
+#define MAX_IMAGE_SIZE 6.0
+Lisp_Object Vmax_image_size;
/* Allocate and return a new image structure for image specification
SPEC. SPEC has a hash value of HASH. */
}
}
+/* Return 1 if the given widths and heights are valid for display;
+ otherwise, return 0. */
+
+int
+check_image_size (f, width, height)
+ struct frame *f;
+ int width;
+ int height;
+{
+ int w, h;
+
+ if (width <= 0 || height <= 0)
+ return 0;
+
+ if (INTEGERP (Vmax_image_size))
+ w = h = XINT (Vmax_image_size);
+ else if (FLOATP (Vmax_image_size))
+ {
+ if (f != NULL)
+ {
+ w = FRAME_PIXEL_WIDTH (f);
+ h = FRAME_PIXEL_HEIGHT (f);
+ }
+ else
+ w = h = 1024; /* Arbitrary size for unknown frame. */
+ w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
+ h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
+ }
+ else
+ return 1;
+
+ return (width <= w && height <= h);
+}
/* Prepare image IMG for display on frame F. Must be called before
drawing an image. */
if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
break;
+ if (img && img->load_failed_p)
+ {
+ free_image (f, img);
+ img = NULL;
+ }
+
/* If not found, create a new image and cache it. */
if (img == NULL)
{
Lisp_Object specified_file, *file;
FSSpec *fss;
{
-#if MAC_OSX
- FSRef fsr;
-#endif
OSErr err;
+ AEDesc desc;
*file = x_find_image_file (specified_file);
if (!STRINGP (*file))
return fnfErr; /* file or directory not found;
incomplete pathname */
/* Try to open the image file. */
-#if MAC_OSX
- err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
+ err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
+ SBYTES (*file), typeFSS, &desc);
if (err == noErr)
- err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
+ {
+#if TARGET_API_MAC_CARBON
+ err = AEGetDescData (&desc, fss, sizeof (FSSpec));
#else
- err = posix_pathname_to_fsspec (SDATA (*file), fss);
+ *fss = *(FSSpec *)(*(desc.dataHandle));
#endif
+ AEDisposeDesc (&desc);
+ }
return err;
}
GraphicsImportComponent gi;
Rect rect;
int width, height;
+ ImageDescriptionHandle desc_handle;
short draw_all_pixels;
Lisp_Object specified_bg;
XColor color;
goto error;
}
}
- err = GraphicsImportGetNaturalBounds (gi, &rect);
- if (err != noErr)
+ err = GraphicsImportGetImageDescription (gi, &desc_handle);
+ if (err != noErr || desc_handle == NULL)
{
image_error ("Error reading `%s'", img->spec, Qnil);
goto error;
}
- width = img->width = rect.right - rect.left;
- height = img->height = rect.bottom - rect.top;
+ width = img->width = (*desc_handle)->width;
+ height = img->height = (*desc_handle)->height;
+ DisposeHandle ((Handle)desc_handle);
+
+ if (!check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ goto error;
+ }
+
err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
#if 0
/* Don't check the error code here. It may have an undocumented
image_error ("Error reading image `%s'", img->spec, Qnil);
return 0;
}
+ width = img->width = CGImageGetWidth (image);
+ height = img->height = CGImageGetHeight (image);
+
+ if (!check_image_size (f, width, height))
+ {
+ CGImageRelease (image);
+ UNGCPRO;
+ image_error ("Invalid image size", Qnil, Qnil);
+ return 0;
+ }
if (png_p)
{
color.blue = BLUE16_FROM_ULONG (color.pixel);
}
}
- width = img->width = CGImageGetWidth (image);
- height = img->height = CGImageGetHeight (image);
+
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
CGImageRelease (image);
static int xbm_load_image P_ ((struct frame *f, struct image *img,
unsigned char *, unsigned char *));
static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *,
+static int xbm_read_bitmap_data P_ ((struct frame *f,
+ unsigned char *, unsigned char *,
int *, int *, unsigned char **));
static int xbm_file_p P_ ((Lisp_Object));
CONTENTS looks like an in-memory XBM file. */
static int
-xbm_read_bitmap_data (contents, end, width, height, data)
+xbm_read_bitmap_data (f, contents, end, width, height, data)
+ struct frame *f;
unsigned char *contents, *end;
int *width, *height;
unsigned char **data;
expect (XBM_TK_NUMBER);
}
- if (*width < 0 || *height < 0)
+ if (!check_image_size (f, *width, *height))
goto failure;
else if (data == NULL)
goto success;
unsigned char *data;
int success_p = 0;
- rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
+ rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
if (rc)
{
unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
{
int w, h;
return (STRINGP (data)
- && xbm_read_bitmap_data (SDATA (data),
+ && xbm_read_bitmap_data (NULL, SDATA (data),
(SDATA (data)
+ SBYTES (data)),
&w, &h, NULL));
#endif /* HAVE_XPM || MAC_OS */
+#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
+int
+x_create_bitmap_from_xpm_data (f, bits)
+ struct frame *f;
+ char **bits;
+{
+ Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ int id, rc;
+ XpmAttributes attrs;
+ Pixmap bitmap, mask;
+
+ bzero (&attrs, sizeof attrs);
+
+ attrs.visual = FRAME_X_VISUAL (f);
+ attrs.colormap = FRAME_X_COLORMAP (f);
+ attrs.valuemask |= XpmVisual;
+ attrs.valuemask |= XpmColormap;
+
+ rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ bits, &bitmap, &mask, &attrs);
+ if (rc != XpmSuccess)
+ {
+ XpmFreeAttributes (&attrs);
+ return -1;
+ }
+
+ id = x_allocate_bitmap_record (f);
+ dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+ dpyinfo->bitmaps[id - 1].have_mask = 1;
+ dpyinfo->bitmaps[id - 1].mask = mask;
+ dpyinfo->bitmaps[id - 1].file = NULL;
+ dpyinfo->bitmaps[id - 1].height = attrs.height;
+ dpyinfo->bitmaps[id - 1].width = attrs.width;
+ dpyinfo->bitmaps[id - 1].depth = attrs.depth;
+ dpyinfo->bitmaps[id - 1].refcount = 1;
+
+ XpmFreeAttributes (&attrs);
+ return id;
+}
+#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
+
/* Load image IMG which will be displayed on frame F. Value is
non-zero if successful. */
attrs.valuemask |= XpmCloseness;
#endif /* not XpmAllocCloseColors */
#endif /* ALLOC_XPM_COLORS */
+#ifdef ALLOC_XPM_COLORS
+ xpm_init_color_cache (f, &attrs);
+#endif
/* If image specification contains symbolic color definitions, add
these to `attrs'. */
|| width <= 0 || height <= 0
|| num_colors <= 0 || chars_per_pixel <= 0)
goto failure;
+
+ if (!check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ goto failure;
+ }
+
expect (',');
XSETFRAME (frame, f);
max_color_idx = 255;
}
- if (width < 0
- || height < 0
+ if (!check_image_size (f, width, height)
|| (type != PBM_MONO && max_color_idx < 0))
goto error;
fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
+ if (!check_image_size (f, width, height))
+ goto error;
+
/* If image contains simply transparency data, we prefer to
construct a clipping mask. */
if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
width = img->width = cinfo.output_width;
height = img->height = cinfo.output_height;
+ if (!check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ longjmp (mgr.setjmp_buffer, 2);
+ }
+
/* Create X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
longjmp (mgr.setjmp_buffer, 2);
of width x height 32-bit values. */
fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+
+ if (!check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
buf = (uint32 *) xmalloc (width * height * sizeof *buf);
rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
}
}
+ /* Before reading entire contents, check the declared image size. */
+ if (!check_image_size (f, gif->SWidth, gif->SHeight))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ fn_DGifCloseFile (gif);
+ UNGCPRO;
+ return 0;
+ }
+
/* Read entire contents. */
rc = fn_DGifSlurp (gif);
if (rc == GIF_ERROR)
max (gif->Image.Top + gif->Image.Height,
image_top + image_height));
+ if (!check_image_size (f, width, height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ fn_DGifCloseFile (gif);
+ UNGCPRO;
+ return 0;
+ }
+
/* Create the X image and pixmap. */
if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
{
specified_file = image_spec_value (img->spec, QCfile, NULL);
specified_data = image_spec_value (img->spec, QCdata, NULL);
+ /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
+ EnterMovies ();
+
if (NILP (specified_data))
{
/* Read from a file */
in_height = XFASTINT (pt_height) / 72.0;
img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
+ if (!check_image_size (f, img->width, img->height))
+ {
+ image_error ("Invalid image size", Qnil, Qnil);
+ return 0;
+ }
+
/* Create the pixmap. */
xassert (img->pixmap == NO_PIXMAP);
Vimage_library_alist = Qnil;
Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
+ DEFVAR_LISP ("max-image-size", &Vmax_image_size,
+ doc: /* Maximum size of images.
+Emacs will not load an image into memory if its pixel width or
+pixel height exceeds this limit.
+
+If the value is an integer, it directly specifies the maximum
+image height and width, measured in pixels. If it is a floating
+point number, it specifies the maximum image height and width
+as a ratio to the frame height and width. If the value is
+non-numeric, there is no explicit limit on the size of images. */);
+ Vmax_image_size = make_float (MAX_IMAGE_SIZE);
+
Vimage_type_cache = Qnil;
staticpro (&Vimage_type_cache);
void
init_image ()
{
-#ifdef MAC_OS
- /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
- EnterMovies ();
-#ifdef MAC_OSX
+#if defined (MAC_OSX) && TARGET_API_MAC_CARBON
init_image_func_pointer ();
#endif
-#endif
}
/* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9