diff options
| author | Chong Yidong | 2005-10-19 03:54:56 +0000 |
|---|---|---|
| committer | Chong Yidong | 2005-10-19 03:54:56 +0000 |
| commit | f1f25b99665ac3e5cd4c6cf70be8fdf637f10b52 (patch) | |
| tree | 66f91ab3a7adf9a3ed66938d90a3da4674d916d0 /src/image.c | |
| parent | f42d19a283c2888320519c78093de6a788374634 (diff) | |
| download | emacs-f1f25b99665ac3e5cd4c6cf70be8fdf637f10b52.tar.gz emacs-f1f25b99665ac3e5cd4c6cf70be8fdf637f10b52.zip | |
* image.c (Vmax_image_size): New variable.
(check_image_size): New function.
(xbm_read_bitmap_data, pbm_load, png_load, jpeg_load, tiff_load)
(gif_load, gs_load): Use it.
(lookup_image): Try loading again if previous load failed.
(xbm_read_bitmap_data): Add a new argument, a pointer to the frame
to display in, NULL if none.
(xbm_load_image, xbm_file_p): Pass xbm_read_bitmap_data the new
argument.
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 94 |
1 files changed, 87 insertions, 7 deletions
diff --git a/src/image.c b/src/image.c index 2463c24a33a..c0702c5ea8c 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -1099,7 +1099,10 @@ or omitted means use the selected frame. */) | |||
| 1099 | 1099 | ||
| 1100 | static struct image *make_image P_ ((Lisp_Object spec, unsigned hash)); | 1100 | static struct image *make_image P_ ((Lisp_Object spec, unsigned hash)); |
| 1101 | static void free_image P_ ((struct frame *f, struct image *img)); | 1101 | static void free_image P_ ((struct frame *f, struct image *img)); |
| 1102 | static int check_image_size P_ ((struct frame *f, int width, int height)); | ||
| 1102 | 1103 | ||
| 1104 | #define MAX_IMAGE_SIZE 6.0 | ||
| 1105 | Lisp_Object Vmax_image_size; | ||
| 1103 | 1106 | ||
| 1104 | /* Allocate and return a new image structure for image specification | 1107 | /* Allocate and return a new image structure for image specification |
| 1105 | SPEC. SPEC has a hash value of HASH. */ | 1108 | SPEC. SPEC has a hash value of HASH. */ |
| @@ -1151,6 +1154,27 @@ free_image (f, img) | |||
| 1151 | } | 1154 | } |
| 1152 | } | 1155 | } |
| 1153 | 1156 | ||
| 1157 | /* Return 1 if the given widths and heights are valid for display; | ||
| 1158 | otherwise, return 0. */ | ||
| 1159 | |||
| 1160 | int | ||
| 1161 | check_image_size (f, width, height) | ||
| 1162 | struct frame *f; | ||
| 1163 | int width; | ||
| 1164 | int height; | ||
| 1165 | { | ||
| 1166 | if (width <= 0 || height <=0) | ||
| 1167 | return 0; | ||
| 1168 | |||
| 1169 | if (FLOATP (Vmax_image_size) && f | ||
| 1170 | && ((width > (int)(XFLOAT_DATA (Vmax_image_size) | ||
| 1171 | * FRAME_PIXEL_WIDTH (f))) | ||
| 1172 | || (height > (int)(XFLOAT_DATA (Vmax_image_size) | ||
| 1173 | * FRAME_PIXEL_HEIGHT (f))))) | ||
| 1174 | return 0; | ||
| 1175 | |||
| 1176 | return 1; | ||
| 1177 | } | ||
| 1154 | 1178 | ||
| 1155 | /* Prepare image IMG for display on frame F. Must be called before | 1179 | /* Prepare image IMG for display on frame F. Must be called before |
| 1156 | drawing an image. */ | 1180 | drawing an image. */ |
| @@ -1708,6 +1732,12 @@ lookup_image (f, spec) | |||
| 1708 | if (img->hash == hash && !NILP (Fequal (img->spec, spec))) | 1732 | if (img->hash == hash && !NILP (Fequal (img->spec, spec))) |
| 1709 | break; | 1733 | break; |
| 1710 | 1734 | ||
| 1735 | if (img && img->load_failed_p) | ||
| 1736 | { | ||
| 1737 | free_image (f, img); | ||
| 1738 | img = NULL; | ||
| 1739 | } | ||
| 1740 | |||
| 1711 | /* If not found, create a new image and cache it. */ | 1741 | /* If not found, create a new image and cache it. */ |
| 1712 | if (img == NULL) | 1742 | if (img == NULL) |
| 1713 | { | 1743 | { |
| @@ -2551,7 +2581,8 @@ static int xbm_load P_ ((struct frame *f, struct image *img)); | |||
| 2551 | static int xbm_load_image P_ ((struct frame *f, struct image *img, | 2581 | static int xbm_load_image P_ ((struct frame *f, struct image *img, |
| 2552 | unsigned char *, unsigned char *)); | 2582 | unsigned char *, unsigned char *)); |
| 2553 | static int xbm_image_p P_ ((Lisp_Object object)); | 2583 | static int xbm_image_p P_ ((Lisp_Object object)); |
| 2554 | static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *, | 2584 | static int xbm_read_bitmap_data P_ ((struct frame *f, |
| 2585 | unsigned char *, unsigned char *, | ||
| 2555 | int *, int *, unsigned char **)); | 2586 | int *, int *, unsigned char **)); |
| 2556 | static int xbm_file_p P_ ((Lisp_Object)); | 2587 | static int xbm_file_p P_ ((Lisp_Object)); |
| 2557 | 2588 | ||
| @@ -2939,7 +2970,8 @@ Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors) | |||
| 2939 | CONTENTS looks like an in-memory XBM file. */ | 2970 | CONTENTS looks like an in-memory XBM file. */ |
| 2940 | 2971 | ||
| 2941 | static int | 2972 | static int |
| 2942 | xbm_read_bitmap_data (contents, end, width, height, data) | 2973 | xbm_read_bitmap_data (f, contents, end, width, height, data) |
| 2974 | struct frame *f; | ||
| 2943 | unsigned char *contents, *end; | 2975 | unsigned char *contents, *end; |
| 2944 | int *width, *height; | 2976 | int *width, *height; |
| 2945 | unsigned char **data; | 2977 | unsigned char **data; |
| @@ -2992,7 +3024,7 @@ xbm_read_bitmap_data (contents, end, width, height, data) | |||
| 2992 | expect (XBM_TK_NUMBER); | 3024 | expect (XBM_TK_NUMBER); |
| 2993 | } | 3025 | } |
| 2994 | 3026 | ||
| 2995 | if (*width < 0 || *height < 0) | 3027 | if (!check_image_size (f, *width, *height)) |
| 2996 | goto failure; | 3028 | goto failure; |
| 2997 | else if (data == NULL) | 3029 | else if (data == NULL) |
| 2998 | goto success; | 3030 | goto success; |
| @@ -3096,7 +3128,7 @@ xbm_load_image (f, img, contents, end) | |||
| 3096 | unsigned char *data; | 3128 | unsigned char *data; |
| 3097 | int success_p = 0; | 3129 | int success_p = 0; |
| 3098 | 3130 | ||
| 3099 | rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data); | 3131 | rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data); |
| 3100 | if (rc) | 3132 | if (rc) |
| 3101 | { | 3133 | { |
| 3102 | unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); | 3134 | unsigned long foreground = FRAME_FOREGROUND_PIXEL (f); |
| @@ -3150,7 +3182,7 @@ xbm_file_p (data) | |||
| 3150 | { | 3182 | { |
| 3151 | int w, h; | 3183 | int w, h; |
| 3152 | return (STRINGP (data) | 3184 | return (STRINGP (data) |
| 3153 | && xbm_read_bitmap_data (SDATA (data), | 3185 | && xbm_read_bitmap_data (NULL, SDATA (data), |
| 3154 | (SDATA (data) | 3186 | (SDATA (data) |
| 3155 | + SBYTES (data)), | 3187 | + SBYTES (data)), |
| 3156 | &w, &h, NULL)); | 3188 | &w, &h, NULL)); |
| @@ -5465,8 +5497,7 @@ pbm_load (f, img) | |||
| 5465 | max_color_idx = 255; | 5497 | max_color_idx = 255; |
| 5466 | } | 5498 | } |
| 5467 | 5499 | ||
| 5468 | if (width < 0 | 5500 | if (!check_image_size (f, width, height) |
| 5469 | || height < 0 | ||
| 5470 | || (type != PBM_MONO && max_color_idx < 0)) | 5501 | || (type != PBM_MONO && max_color_idx < 0)) |
| 5471 | goto error; | 5502 | goto error; |
| 5472 | 5503 | ||
| @@ -5966,6 +5997,9 @@ png_load (f, img) | |||
| 5966 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | 5997 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, |
| 5967 | &interlace_type, NULL, NULL); | 5998 | &interlace_type, NULL, NULL); |
| 5968 | 5999 | ||
| 6000 | if (!check_image_size (f, width, height)) | ||
| 6001 | goto error; | ||
| 6002 | |||
| 5969 | /* If image contains simply transparency data, we prefer to | 6003 | /* If image contains simply transparency data, we prefer to |
| 5970 | construct a clipping mask. */ | 6004 | construct a clipping mask. */ |
| 5971 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) | 6005 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) |
| @@ -6726,6 +6760,12 @@ jpeg_load (f, img) | |||
| 6726 | width = img->width = cinfo.output_width; | 6760 | width = img->width = cinfo.output_width; |
| 6727 | height = img->height = cinfo.output_height; | 6761 | height = img->height = cinfo.output_height; |
| 6728 | 6762 | ||
| 6763 | if (!check_image_size (f, width, height)) | ||
| 6764 | { | ||
| 6765 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 6766 | longjmp (mgr.setjmp_buffer, 2); | ||
| 6767 | } | ||
| 6768 | |||
| 6729 | /* Create X image and pixmap. */ | 6769 | /* Create X image and pixmap. */ |
| 6730 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 6770 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 6731 | longjmp (mgr.setjmp_buffer, 2); | 6771 | longjmp (mgr.setjmp_buffer, 2); |
| @@ -7155,6 +7195,14 @@ tiff_load (f, img) | |||
| 7155 | of width x height 32-bit values. */ | 7195 | of width x height 32-bit values. */ |
| 7156 | fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); | 7196 | fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width); |
| 7157 | fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); | 7197 | fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height); |
| 7198 | |||
| 7199 | if (!check_image_size (f, width, height)) | ||
| 7200 | { | ||
| 7201 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7202 | UNGCPRO; | ||
| 7203 | return 0; | ||
| 7204 | } | ||
| 7205 | |||
| 7158 | buf = (uint32 *) xmalloc (width * height * sizeof *buf); | 7206 | buf = (uint32 *) xmalloc (width * height * sizeof *buf); |
| 7159 | 7207 | ||
| 7160 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); | 7208 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); |
| @@ -7459,6 +7507,15 @@ gif_load (f, img) | |||
| 7459 | } | 7507 | } |
| 7460 | } | 7508 | } |
| 7461 | 7509 | ||
| 7510 | /* Before reading entire contents, check the declared image size. */ | ||
| 7511 | if (!check_image_size (f, gif->SWidth, gif->SHeight)) | ||
| 7512 | { | ||
| 7513 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7514 | fn_DGifCloseFile (gif); | ||
| 7515 | UNGCPRO; | ||
| 7516 | return 0; | ||
| 7517 | } | ||
| 7518 | |||
| 7462 | /* Read entire contents. */ | 7519 | /* Read entire contents. */ |
| 7463 | rc = fn_DGifSlurp (gif); | 7520 | rc = fn_DGifSlurp (gif); |
| 7464 | if (rc == GIF_ERROR) | 7521 | if (rc == GIF_ERROR) |
| @@ -7492,6 +7549,14 @@ gif_load (f, img) | |||
| 7492 | max (gif->Image.Top + gif->Image.Height, | 7549 | max (gif->Image.Top + gif->Image.Height, |
| 7493 | image_top + image_height)); | 7550 | image_top + image_height)); |
| 7494 | 7551 | ||
| 7552 | if (!check_image_size (f, width, height)) | ||
| 7553 | { | ||
| 7554 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 7555 | fn_DGifCloseFile (gif); | ||
| 7556 | UNGCPRO; | ||
| 7557 | return 0; | ||
| 7558 | } | ||
| 7559 | |||
| 7495 | /* Create the X image and pixmap. */ | 7560 | /* Create the X image and pixmap. */ |
| 7496 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 7561 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 7497 | { | 7562 | { |
| @@ -7944,6 +8009,12 @@ gs_load (f, img) | |||
| 7944 | in_height = XFASTINT (pt_height) / 72.0; | 8009 | in_height = XFASTINT (pt_height) / 72.0; |
| 7945 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; | 8010 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; |
| 7946 | 8011 | ||
| 8012 | if (!check_image_size (f, img->width, img->height)) | ||
| 8013 | { | ||
| 8014 | image_error ("Invalid image size", Qnil, Qnil); | ||
| 8015 | return 0; | ||
| 8016 | } | ||
| 8017 | |||
| 7947 | /* Create the pixmap. */ | 8018 | /* Create the pixmap. */ |
| 7948 | xassert (img->pixmap == NO_PIXMAP); | 8019 | xassert (img->pixmap == NO_PIXMAP); |
| 7949 | 8020 | ||
| @@ -8217,6 +8288,15 @@ listed; they're always supported. */); | |||
| 8217 | Vimage_library_alist = Qnil; | 8288 | Vimage_library_alist = Qnil; |
| 8218 | Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt); | 8289 | Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt); |
| 8219 | 8290 | ||
| 8291 | DEFVAR_LISP ("max-image-size", &Vmax_image_size, | ||
| 8292 | doc: /* Maximum size of an image, relative to the selected frame. | ||
| 8293 | |||
| 8294 | This is a floating point number that is multiplied by the width and | ||
| 8295 | height of the selected frame, to give the maximum width and height for | ||
| 8296 | images. Emacs will not load an image into memory if its width or | ||
| 8297 | height exceeds this limit. */); | ||
| 8298 | Vmax_image_size = make_float (MAX_IMAGE_SIZE); | ||
| 8299 | |||
| 8220 | Vimage_type_cache = Qnil; | 8300 | Vimage_type_cache = Qnil; |
| 8221 | staticpro (&Vimage_type_cache); | 8301 | staticpro (&Vimage_type_cache); |
| 8222 | 8302 | ||