diff options
| author | Stefan Monnier | 2012-03-25 16:37:21 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2012-03-25 16:37:21 -0400 |
| commit | 699c782b7668c44d0fa4446331b0590a6d5dac82 (patch) | |
| tree | 5dcce364741d0761920a3d274b0fc8aba4103d45 /src/image.c | |
| parent | 98fb480ee31bf74cf554044f60f21df16566dd7f (diff) | |
| parent | e99a9b8bdccadded1f6fae88ee7a2a93dfd4eacf (diff) | |
| download | emacs-pending.tar.gz emacs-pending.zip | |
Merge from trunkpending
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 674 |
1 files changed, 405 insertions, 269 deletions
diff --git a/src/image.c b/src/image.c index 6e8440fb431..73490fe2865 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Functions for image support on window system. | 1 | /* Functions for image support on window system. |
| 2 | Copyright (C) 1989, 1992-2011 Free Software Foundation, Inc. | 2 | Copyright (C) 1989, 1992-2012 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 56 | #define COLOR_TABLE_SUPPORT 1 | 56 | #define COLOR_TABLE_SUPPORT 1 |
| 57 | 57 | ||
| 58 | typedef struct x_bitmap_record Bitmap_Record; | 58 | typedef struct x_bitmap_record Bitmap_Record; |
| 59 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) | 59 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) |
| 60 | #define NO_PIXMAP None | 60 | #define NO_PIXMAP None |
| 61 | 61 | ||
| 62 | #define RGB_PIXEL_COLOR unsigned long | 62 | #define RGB_PIXEL_COLOR unsigned long |
| @@ -74,7 +74,7 @@ typedef struct x_bitmap_record Bitmap_Record; | |||
| 74 | #undef COLOR_TABLE_SUPPORT | 74 | #undef COLOR_TABLE_SUPPORT |
| 75 | 75 | ||
| 76 | typedef struct w32_bitmap_record Bitmap_Record; | 76 | typedef struct w32_bitmap_record Bitmap_Record; |
| 77 | #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y) | 77 | #define GET_PIXEL(ximg, x, y) GetPixel (ximg, x, y) |
| 78 | #define NO_PIXMAP 0 | 78 | #define NO_PIXMAP 0 |
| 79 | 79 | ||
| 80 | #define RGB_PIXEL_COLOR COLORREF | 80 | #define RGB_PIXEL_COLOR COLORREF |
| @@ -106,7 +106,7 @@ Lisp_Object Qlibpng_version; | |||
| 106 | 106 | ||
| 107 | typedef struct ns_bitmap_record Bitmap_Record; | 107 | typedef struct ns_bitmap_record Bitmap_Record; |
| 108 | 108 | ||
| 109 | #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) | 109 | #define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) |
| 110 | #define NO_PIXMAP 0 | 110 | #define NO_PIXMAP 0 |
| 111 | 111 | ||
| 112 | #define RGB_PIXEL_COLOR unsigned long | 112 | #define RGB_PIXEL_COLOR unsigned long |
| @@ -115,7 +115,7 @@ typedef struct ns_bitmap_record Bitmap_Record; | |||
| 115 | #define PIX_MASK_RETAIN 0 | 115 | #define PIX_MASK_RETAIN 0 |
| 116 | #define PIX_MASK_DRAW 1 | 116 | #define PIX_MASK_DRAW 1 |
| 117 | 117 | ||
| 118 | #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual | 118 | #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO (f)->visual |
| 119 | #define x_defined_color(f, name, color_def, alloc) \ | 119 | #define x_defined_color(f, name, color_def, alloc) \ |
| 120 | ns_defined_color (f, name, color_def, alloc, 0) | 120 | ns_defined_color (f, name, color_def, alloc, 0) |
| 121 | #define FRAME_X_SCREEN(f) 0 | 121 | #define FRAME_X_SCREEN(f) 0 |
| @@ -136,7 +136,6 @@ static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b); | |||
| 136 | #ifdef COLOR_TABLE_SUPPORT | 136 | #ifdef COLOR_TABLE_SUPPORT |
| 137 | static void free_color_table (void); | 137 | static void free_color_table (void); |
| 138 | static unsigned long *colors_in_color_table (int *n); | 138 | static unsigned long *colors_in_color_table (int *n); |
| 139 | static unsigned long lookup_pixel_color (struct frame *f, unsigned long p); | ||
| 140 | #endif | 139 | #endif |
| 141 | static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object); | 140 | static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object); |
| 142 | 141 | ||
| @@ -197,6 +196,7 @@ x_bitmap_width (FRAME_PTR f, ptrdiff_t id) | |||
| 197 | int | 196 | int |
| 198 | x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id) | 197 | x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id) |
| 199 | { | 198 | { |
| 199 | /* HAVE_NTGUI needs the explicit cast here. */ | ||
| 200 | return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; | 200 | return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; |
| 201 | } | 201 | } |
| 202 | #endif | 202 | #endif |
| @@ -217,15 +217,6 @@ x_allocate_bitmap_record (FRAME_PTR f) | |||
| 217 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 217 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
| 218 | ptrdiff_t i; | 218 | ptrdiff_t i; |
| 219 | 219 | ||
| 220 | if (dpyinfo->bitmaps == NULL) | ||
| 221 | { | ||
| 222 | dpyinfo->bitmaps_size = 10; | ||
| 223 | dpyinfo->bitmaps | ||
| 224 | = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record)); | ||
| 225 | dpyinfo->bitmaps_last = 1; | ||
| 226 | return 1; | ||
| 227 | } | ||
| 228 | |||
| 229 | if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size) | 220 | if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size) |
| 230 | return ++dpyinfo->bitmaps_last; | 221 | return ++dpyinfo->bitmaps_last; |
| 231 | 222 | ||
| @@ -233,20 +224,16 @@ x_allocate_bitmap_record (FRAME_PTR f) | |||
| 233 | if (dpyinfo->bitmaps[i].refcount == 0) | 224 | if (dpyinfo->bitmaps[i].refcount == 0) |
| 234 | return i + 1; | 225 | return i + 1; |
| 235 | 226 | ||
| 236 | if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2 | 227 | dpyinfo->bitmaps = |
| 237 | < dpyinfo->bitmaps_size) | 228 | xpalloc (dpyinfo->bitmaps, &dpyinfo->bitmaps_size, |
| 238 | memory_full (SIZE_MAX); | 229 | 10, -1, sizeof *dpyinfo->bitmaps); |
| 239 | dpyinfo->bitmaps_size *= 2; | ||
| 240 | dpyinfo->bitmaps | ||
| 241 | = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps, | ||
| 242 | dpyinfo->bitmaps_size * sizeof (Bitmap_Record)); | ||
| 243 | return ++dpyinfo->bitmaps_last; | 230 | return ++dpyinfo->bitmaps_last; |
| 244 | } | 231 | } |
| 245 | 232 | ||
| 246 | /* Add one reference to the reference count of the bitmap with id ID. */ | 233 | /* Add one reference to the reference count of the bitmap with id ID. */ |
| 247 | 234 | ||
| 248 | void | 235 | void |
| 249 | x_reference_bitmap (FRAME_PTR f, int id) | 236 | x_reference_bitmap (FRAME_PTR f, ptrdiff_t id) |
| 250 | { | 237 | { |
| 251 | ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; | 238 | ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount; |
| 252 | } | 239 | } |
| @@ -705,7 +692,7 @@ enum image_value_type | |||
| 705 | IMAGE_STRING_OR_NIL_VALUE, | 692 | IMAGE_STRING_OR_NIL_VALUE, |
| 706 | IMAGE_SYMBOL_VALUE, | 693 | IMAGE_SYMBOL_VALUE, |
| 707 | IMAGE_POSITIVE_INTEGER_VALUE, | 694 | IMAGE_POSITIVE_INTEGER_VALUE, |
| 708 | IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, | 695 | IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, |
| 709 | IMAGE_NON_NEGATIVE_INTEGER_VALUE, | 696 | IMAGE_NON_NEGATIVE_INTEGER_VALUE, |
| 710 | IMAGE_ASCENT_VALUE, | 697 | IMAGE_ASCENT_VALUE, |
| 711 | IMAGE_INTEGER_VALUE, | 698 | IMAGE_INTEGER_VALUE, |
| @@ -808,29 +795,30 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, | |||
| 808 | break; | 795 | break; |
| 809 | 796 | ||
| 810 | case IMAGE_POSITIVE_INTEGER_VALUE: | 797 | case IMAGE_POSITIVE_INTEGER_VALUE: |
| 811 | if (!INTEGERP (value) || XINT (value) <= 0) | 798 | if (! RANGED_INTEGERP (1, value, INT_MAX)) |
| 812 | return 0; | 799 | return 0; |
| 813 | break; | 800 | break; |
| 814 | 801 | ||
| 815 | case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR: | 802 | case IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR: |
| 816 | if (INTEGERP (value) && XINT (value) >= 0) | 803 | if (RANGED_INTEGERP (0, value, INT_MAX)) |
| 817 | break; | 804 | break; |
| 818 | if (CONSP (value) | 805 | if (CONSP (value) |
| 819 | && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value)) | 806 | && RANGED_INTEGERP (0, XCAR (value), INT_MAX) |
| 820 | && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0) | 807 | && RANGED_INTEGERP (0, XCDR (value), INT_MAX)) |
| 821 | break; | 808 | break; |
| 822 | return 0; | 809 | return 0; |
| 823 | 810 | ||
| 824 | case IMAGE_ASCENT_VALUE: | 811 | case IMAGE_ASCENT_VALUE: |
| 825 | if (SYMBOLP (value) && EQ (value, Qcenter)) | 812 | if (SYMBOLP (value) && EQ (value, Qcenter)) |
| 826 | break; | 813 | break; |
| 827 | else if (INTEGERP (value) | 814 | else if (RANGED_INTEGERP (0, value, 100)) |
| 828 | && XINT (value) >= 0 | ||
| 829 | && XINT (value) <= 100) | ||
| 830 | break; | 815 | break; |
| 831 | return 0; | 816 | return 0; |
| 832 | 817 | ||
| 833 | case IMAGE_NON_NEGATIVE_INTEGER_VALUE: | 818 | case IMAGE_NON_NEGATIVE_INTEGER_VALUE: |
| 819 | /* Unlike the other integer-related cases, this one does not | ||
| 820 | verify that VALUE fits in 'int'. This is because callers | ||
| 821 | want EMACS_INT. */ | ||
| 834 | if (!INTEGERP (value) || XINT (value) < 0) | 822 | if (!INTEGERP (value) || XINT (value) < 0) |
| 835 | return 0; | 823 | return 0; |
| 836 | break; | 824 | break; |
| @@ -850,7 +838,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords, | |||
| 850 | break; | 838 | break; |
| 851 | 839 | ||
| 852 | case IMAGE_INTEGER_VALUE: | 840 | case IMAGE_INTEGER_VALUE: |
| 853 | if (!INTEGERP (value)) | 841 | if (! TYPE_RANGED_INTEGERP (int, value)) |
| 854 | return 0; | 842 | return 0; |
| 855 | break; | 843 | break; |
| 856 | 844 | ||
| @@ -920,7 +908,7 @@ or omitted means use the selected frame. */) | |||
| 920 | if (valid_image_p (spec)) | 908 | if (valid_image_p (spec)) |
| 921 | { | 909 | { |
| 922 | struct frame *f = check_x_frame (frame); | 910 | struct frame *f = check_x_frame (frame); |
| 923 | int id = lookup_image (f, spec); | 911 | ptrdiff_t id = lookup_image (f, spec); |
| 924 | struct image *img = IMAGE_FROM_ID (f, id); | 912 | struct image *img = IMAGE_FROM_ID (f, id); |
| 925 | int width = img->width + 2 * img->hmargin; | 913 | int width = img->width + 2 * img->hmargin; |
| 926 | int height = img->height + 2 * img->vmargin; | 914 | int height = img->height + 2 * img->vmargin; |
| @@ -950,7 +938,7 @@ or omitted means use the selected frame. */) | |||
| 950 | if (valid_image_p (spec)) | 938 | if (valid_image_p (spec)) |
| 951 | { | 939 | { |
| 952 | struct frame *f = check_x_frame (frame); | 940 | struct frame *f = check_x_frame (frame); |
| 953 | int id = lookup_image (f, spec); | 941 | ptrdiff_t id = lookup_image (f, spec); |
| 954 | struct image *img = IMAGE_FROM_ID (f, id); | 942 | struct image *img = IMAGE_FROM_ID (f, id); |
| 955 | if (img->mask) | 943 | if (img->mask) |
| 956 | mask = Qt; | 944 | mask = Qt; |
| @@ -973,7 +961,7 @@ or omitted means use the selected frame. */) | |||
| 973 | if (valid_image_p (spec)) | 961 | if (valid_image_p (spec)) |
| 974 | { | 962 | { |
| 975 | struct frame *f = check_x_frame (frame); | 963 | struct frame *f = check_x_frame (frame); |
| 976 | int id = lookup_image (f, spec); | 964 | ptrdiff_t id = lookup_image (f, spec); |
| 977 | struct image *img = IMAGE_FROM_ID (f, id); | 965 | struct image *img = IMAGE_FROM_ID (f, id); |
| 978 | ext = img->lisp_data; | 966 | ext = img->lisp_data; |
| 979 | } | 967 | } |
| @@ -987,9 +975,8 @@ or omitted means use the selected frame. */) | |||
| 987 | ***********************************************************************/ | 975 | ***********************************************************************/ |
| 988 | 976 | ||
| 989 | static void free_image (struct frame *f, struct image *img); | 977 | static void free_image (struct frame *f, struct image *img); |
| 990 | static int check_image_size (struct frame *f, int width, int height); | ||
| 991 | 978 | ||
| 992 | #define MAX_IMAGE_SIZE 6.0 | 979 | #define MAX_IMAGE_SIZE 10.0 |
| 993 | /* Allocate and return a new image structure for image specification | 980 | /* Allocate and return a new image structure for image specification |
| 994 | SPEC. SPEC has a hash value of HASH. */ | 981 | SPEC. SPEC has a hash value of HASH. */ |
| 995 | 982 | ||
| @@ -1042,7 +1029,7 @@ free_image (struct frame *f, struct image *img) | |||
| 1042 | /* Return 1 if the given widths and heights are valid for display; | 1029 | /* Return 1 if the given widths and heights are valid for display; |
| 1043 | otherwise, return 0. */ | 1030 | otherwise, return 0. */ |
| 1044 | 1031 | ||
| 1045 | int | 1032 | static int |
| 1046 | check_image_size (struct frame *f, int width, int height) | 1033 | check_image_size (struct frame *f, int width, int height) |
| 1047 | { | 1034 | { |
| 1048 | int w, h; | 1035 | int w, h; |
| @@ -1051,7 +1038,8 @@ check_image_size (struct frame *f, int width, int height) | |||
| 1051 | return 0; | 1038 | return 0; |
| 1052 | 1039 | ||
| 1053 | if (INTEGERP (Vmax_image_size)) | 1040 | if (INTEGERP (Vmax_image_size)) |
| 1054 | w = h = XINT (Vmax_image_size); | 1041 | return (width <= XINT (Vmax_image_size) |
| 1042 | && height <= XINT (Vmax_image_size)); | ||
| 1055 | else if (FLOATP (Vmax_image_size)) | 1043 | else if (FLOATP (Vmax_image_size)) |
| 1056 | { | 1044 | { |
| 1057 | if (f != NULL) | 1045 | if (f != NULL) |
| @@ -1061,13 +1049,11 @@ check_image_size (struct frame *f, int width, int height) | |||
| 1061 | } | 1049 | } |
| 1062 | else | 1050 | else |
| 1063 | w = h = 1024; /* Arbitrary size for unknown frame. */ | 1051 | w = h = 1024; /* Arbitrary size for unknown frame. */ |
| 1064 | w = (int) (XFLOAT_DATA (Vmax_image_size) * w); | 1052 | return (width <= XFLOAT_DATA (Vmax_image_size) * w |
| 1065 | h = (int) (XFLOAT_DATA (Vmax_image_size) * h); | 1053 | && height <= XFLOAT_DATA (Vmax_image_size) * h); |
| 1066 | } | 1054 | } |
| 1067 | else | 1055 | else |
| 1068 | return 1; | 1056 | return 1; |
| 1069 | |||
| 1070 | return (width <= w && height <= h); | ||
| 1071 | } | 1057 | } |
| 1072 | 1058 | ||
| 1073 | /* Prepare image IMG for display on frame F. Must be called before | 1059 | /* Prepare image IMG for display on frame F. Must be called before |
| @@ -1120,15 +1106,15 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) | |||
| 1120 | because a typical font is `top-heavy' (due to the presence | 1106 | because a typical font is `top-heavy' (due to the presence |
| 1121 | uppercase letters), so the image placement should err towards | 1107 | uppercase letters), so the image placement should err towards |
| 1122 | being top-heavy too. It also just generally looks better. */ | 1108 | being top-heavy too. It also just generally looks better. */ |
| 1123 | ascent = (height + FONT_BASE(face->font) | 1109 | ascent = (height + FONT_BASE (face->font) |
| 1124 | - FONT_DESCENT(face->font) + 1) / 2; | 1110 | - FONT_DESCENT (face->font) + 1) / 2; |
| 1125 | #endif /* HAVE_NTGUI */ | 1111 | #endif /* HAVE_NTGUI */ |
| 1126 | } | 1112 | } |
| 1127 | else | 1113 | else |
| 1128 | ascent = height / 2; | 1114 | ascent = height / 2; |
| 1129 | } | 1115 | } |
| 1130 | else | 1116 | else |
| 1131 | ascent = (int) (height * img->ascent / 100.0); | 1117 | ascent = height * (img->ascent / 100.0); |
| 1132 | 1118 | ||
| 1133 | return ascent; | 1119 | return ascent; |
| 1134 | } | 1120 | } |
| @@ -1368,15 +1354,18 @@ x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name, | |||
| 1368 | 1354 | ||
| 1369 | xassert (STRINGP (color_name)); | 1355 | xassert (STRINGP (color_name)); |
| 1370 | 1356 | ||
| 1371 | if (x_defined_color (f, SSDATA (color_name), &color, 1)) | 1357 | if (x_defined_color (f, SSDATA (color_name), &color, 1) |
| 1358 | && img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors, | ||
| 1359 | INT_MAX)) | ||
| 1372 | { | 1360 | { |
| 1373 | /* This isn't called frequently so we get away with simply | 1361 | /* This isn't called frequently so we get away with simply |
| 1374 | reallocating the color vector to the needed size, here. */ | 1362 | reallocating the color vector to the needed size, here. */ |
| 1375 | ++img->ncolors; | 1363 | ptrdiff_t ncolors = img->ncolors + 1; |
| 1376 | img->colors = | 1364 | img->colors = |
| 1377 | (unsigned long *) xrealloc (img->colors, | 1365 | (unsigned long *) xrealloc (img->colors, |
| 1378 | img->ncolors * sizeof *img->colors); | 1366 | ncolors * sizeof *img->colors); |
| 1379 | img->colors[img->ncolors - 1] = color.pixel; | 1367 | img->colors[ncolors - 1] = color.pixel; |
| 1368 | img->ncolors = ncolors; | ||
| 1380 | result = color.pixel; | 1369 | result = color.pixel; |
| 1381 | } | 1370 | } |
| 1382 | else | 1371 | else |
| @@ -1404,8 +1393,9 @@ make_image_cache (void) | |||
| 1404 | int size; | 1393 | int size; |
| 1405 | 1394 | ||
| 1406 | memset (c, 0, sizeof *c); | 1395 | memset (c, 0, sizeof *c); |
| 1407 | c->size = 50; | 1396 | size = 50; |
| 1408 | c->images = (struct image **) xmalloc (c->size * sizeof *c->images); | 1397 | c->images = (struct image **) xmalloc (size * sizeof *c->images); |
| 1398 | c->size = size; | ||
| 1409 | size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets; | 1399 | size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets; |
| 1410 | c->buckets = (struct image **) xmalloc (size); | 1400 | c->buckets = (struct image **) xmalloc (size); |
| 1411 | memset (c->buckets, 0, size); | 1401 | memset (c->buckets, 0, size); |
| @@ -1471,7 +1461,7 @@ free_image_cache (struct frame *f) | |||
| 1471 | struct image_cache *c = FRAME_IMAGE_CACHE (f); | 1461 | struct image_cache *c = FRAME_IMAGE_CACHE (f); |
| 1472 | if (c) | 1462 | if (c) |
| 1473 | { | 1463 | { |
| 1474 | int i; | 1464 | ptrdiff_t i; |
| 1475 | 1465 | ||
| 1476 | /* Cache should not be referenced by any frame when freed. */ | 1466 | /* Cache should not be referenced by any frame when freed. */ |
| 1477 | xassert (c->refcount == 0); | 1467 | xassert (c->refcount == 0); |
| @@ -1501,7 +1491,7 @@ clear_image_cache (struct frame *f, Lisp_Object filter) | |||
| 1501 | 1491 | ||
| 1502 | if (c) | 1492 | if (c) |
| 1503 | { | 1493 | { |
| 1504 | int i, nfreed = 0; | 1494 | ptrdiff_t i, nfreed = 0; |
| 1505 | 1495 | ||
| 1506 | /* Block input so that we won't be interrupted by a SIGIO | 1496 | /* Block input so that we won't be interrupted by a SIGIO |
| 1507 | while being in an inconsistent state. */ | 1497 | while being in an inconsistent state. */ |
| @@ -1525,8 +1515,8 @@ clear_image_cache (struct frame *f, Lisp_Object filter) | |||
| 1525 | { | 1515 | { |
| 1526 | /* Free cache based on timestamp. */ | 1516 | /* Free cache based on timestamp. */ |
| 1527 | EMACS_TIME t; | 1517 | EMACS_TIME t; |
| 1528 | time_t old; | 1518 | double old, delay; |
| 1529 | int delay, nimages = 0; | 1519 | ptrdiff_t nimages = 0; |
| 1530 | 1520 | ||
| 1531 | for (i = 0; i < c->used; ++i) | 1521 | for (i = 0; i < c->used; ++i) |
| 1532 | if (c->images[i]) | 1522 | if (c->images[i]) |
| @@ -1534,9 +1524,10 @@ clear_image_cache (struct frame *f, Lisp_Object filter) | |||
| 1534 | 1524 | ||
| 1535 | /* If the number of cached images has grown unusually large, | 1525 | /* If the number of cached images has grown unusually large, |
| 1536 | decrease the cache eviction delay (Bug#6230). */ | 1526 | decrease the cache eviction delay (Bug#6230). */ |
| 1537 | delay = XFASTINT (Vimage_cache_eviction_delay); | 1527 | delay = XINT (Vimage_cache_eviction_delay); |
| 1538 | if (nimages > 40) | 1528 | if (nimages > 40) |
| 1539 | delay = max (1, 1600 * delay / (nimages*nimages)); | 1529 | delay = 1600 * delay / nimages / nimages; |
| 1530 | delay = max (delay, 1); | ||
| 1540 | 1531 | ||
| 1541 | EMACS_GET_TIME (t); | 1532 | EMACS_GET_TIME (t); |
| 1542 | old = EMACS_SECS (t) - delay; | 1533 | old = EMACS_SECS (t) - delay; |
| @@ -1712,7 +1703,7 @@ postprocess_image (struct frame *f, struct image *img) | |||
| 1712 | /* Return the id of image with Lisp specification SPEC on frame F. | 1703 | /* Return the id of image with Lisp specification SPEC on frame F. |
| 1713 | SPEC must be a valid Lisp image specification (see valid_image_p). */ | 1704 | SPEC must be a valid Lisp image specification (see valid_image_p). */ |
| 1714 | 1705 | ||
| 1715 | int | 1706 | ptrdiff_t |
| 1716 | lookup_image (struct frame *f, Lisp_Object spec) | 1707 | lookup_image (struct frame *f, Lisp_Object spec) |
| 1717 | { | 1708 | { |
| 1718 | struct image *img; | 1709 | struct image *img; |
| @@ -1771,15 +1762,12 @@ lookup_image (struct frame *f, Lisp_Object spec) | |||
| 1771 | img->ascent = CENTERED_IMAGE_ASCENT; | 1762 | img->ascent = CENTERED_IMAGE_ASCENT; |
| 1772 | 1763 | ||
| 1773 | margin = image_spec_value (spec, QCmargin, NULL); | 1764 | margin = image_spec_value (spec, QCmargin, NULL); |
| 1774 | if (INTEGERP (margin) && XINT (margin) >= 0) | 1765 | if (INTEGERP (margin)) |
| 1775 | img->vmargin = img->hmargin = XFASTINT (margin); | 1766 | img->vmargin = img->hmargin = XFASTINT (margin); |
| 1776 | else if (CONSP (margin) && INTEGERP (XCAR (margin)) | 1767 | else if (CONSP (margin)) |
| 1777 | && INTEGERP (XCDR (margin))) | ||
| 1778 | { | 1768 | { |
| 1779 | if (XINT (XCAR (margin)) > 0) | 1769 | img->hmargin = XFASTINT (XCAR (margin)); |
| 1780 | img->hmargin = XFASTINT (XCAR (margin)); | 1770 | img->vmargin = XFASTINT (XCDR (margin)); |
| 1781 | if (XINT (XCDR (margin)) > 0) | ||
| 1782 | img->vmargin = XFASTINT (XCDR (margin)); | ||
| 1783 | } | 1771 | } |
| 1784 | 1772 | ||
| 1785 | relief = image_spec_value (spec, QCrelief, NULL); | 1773 | relief = image_spec_value (spec, QCrelief, NULL); |
| @@ -1826,7 +1814,7 @@ static void | |||
| 1826 | cache_image (struct frame *f, struct image *img) | 1814 | cache_image (struct frame *f, struct image *img) |
| 1827 | { | 1815 | { |
| 1828 | struct image_cache *c = FRAME_IMAGE_CACHE (f); | 1816 | struct image_cache *c = FRAME_IMAGE_CACHE (f); |
| 1829 | int i; | 1817 | ptrdiff_t i; |
| 1830 | 1818 | ||
| 1831 | /* Find a free slot in c->images. */ | 1819 | /* Find a free slot in c->images. */ |
| 1832 | for (i = 0; i < c->used; ++i) | 1820 | for (i = 0; i < c->used; ++i) |
| @@ -1835,13 +1823,7 @@ cache_image (struct frame *f, struct image *img) | |||
| 1835 | 1823 | ||
| 1836 | /* If no free slot found, maybe enlarge c->images. */ | 1824 | /* If no free slot found, maybe enlarge c->images. */ |
| 1837 | if (i == c->used && c->used == c->size) | 1825 | if (i == c->used && c->used == c->size) |
| 1838 | { | 1826 | c->images = xpalloc (c->images, &c->size, 1, -1, sizeof *c->images); |
| 1839 | if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size) | ||
| 1840 | memory_full (SIZE_MAX); | ||
| 1841 | c->size *= 2; | ||
| 1842 | c->images = (struct image **) xrealloc (c->images, | ||
| 1843 | c->size * sizeof *c->images); | ||
| 1844 | } | ||
| 1845 | 1827 | ||
| 1846 | /* Add IMG to c->images, and assign IMG an id. */ | 1828 | /* Add IMG to c->images, and assign IMG an id. */ |
| 1847 | c->images[i] = img; | 1829 | c->images[i] = img; |
| @@ -1880,7 +1862,7 @@ mark_image_cache (struct image_cache *c) | |||
| 1880 | { | 1862 | { |
| 1881 | if (c) | 1863 | if (c) |
| 1882 | { | 1864 | { |
| 1883 | int i; | 1865 | ptrdiff_t i; |
| 1884 | for (i = 0; i < c->used; ++i) | 1866 | for (i = 0; i < c->used; ++i) |
| 1885 | if (c->images[i]) | 1867 | if (c->images[i]) |
| 1886 | mark_image (c->images[i]); | 1868 | mark_image (c->images[i]); |
| @@ -1911,6 +1893,44 @@ static int x_create_x_image_and_pixmap (struct frame *, int, int, int, | |||
| 1911 | static void x_destroy_x_image (XImagePtr); | 1893 | static void x_destroy_x_image (XImagePtr); |
| 1912 | static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int); | 1894 | static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int); |
| 1913 | 1895 | ||
| 1896 | /* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break the | ||
| 1897 | windowing system. | ||
| 1898 | WIDTH and HEIGHT must both be positive. | ||
| 1899 | If XIMG is null, assume it is a bitmap. */ | ||
| 1900 | static int | ||
| 1901 | x_check_image_size (XImagePtr ximg, int width, int height) | ||
| 1902 | { | ||
| 1903 | #ifdef HAVE_X_WINDOWS | ||
| 1904 | /* Respect Xlib's limits: it cannot deal with images that have more | ||
| 1905 | than INT_MAX (and/or UINT_MAX) bytes. And respect Emacs's limits | ||
| 1906 | of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object. */ | ||
| 1907 | enum | ||
| 1908 | { | ||
| 1909 | XLIB_BYTES_MAX = min (INT_MAX, UINT_MAX), | ||
| 1910 | X_IMAGE_BYTES_MAX = min (XLIB_BYTES_MAX, min (PTRDIFF_MAX, SIZE_MAX)) | ||
| 1911 | }; | ||
| 1912 | |||
| 1913 | int bitmap_pad, depth, bytes_per_line; | ||
| 1914 | if (ximg) | ||
| 1915 | { | ||
| 1916 | bitmap_pad = ximg->bitmap_pad; | ||
| 1917 | depth = ximg->depth; | ||
| 1918 | bytes_per_line = ximg->bytes_per_line; | ||
| 1919 | } | ||
| 1920 | else | ||
| 1921 | { | ||
| 1922 | bitmap_pad = 8; | ||
| 1923 | depth = 1; | ||
| 1924 | bytes_per_line = (width >> 3) + ((width & 7) != 0); | ||
| 1925 | } | ||
| 1926 | return (width <= (INT_MAX - (bitmap_pad - 1)) / depth | ||
| 1927 | && height <= X_IMAGE_BYTES_MAX / bytes_per_line); | ||
| 1928 | #else | ||
| 1929 | /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases. | ||
| 1930 | For now, assume that every image size is allowed on these systems. */ | ||
| 1931 | return 1; | ||
| 1932 | #endif | ||
| 1933 | } | ||
| 1914 | 1934 | ||
| 1915 | /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on | 1935 | /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on |
| 1916 | frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created. | 1936 | frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created. |
| @@ -1943,6 +1963,15 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 1943 | return 0; | 1963 | return 0; |
| 1944 | } | 1964 | } |
| 1945 | 1965 | ||
| 1966 | if (! x_check_image_size (*ximg, width, height)) | ||
| 1967 | { | ||
| 1968 | x_destroy_x_image (*ximg); | ||
| 1969 | *ximg = NULL; | ||
| 1970 | image_error ("Image too large (%dx%d)", | ||
| 1971 | make_number (width), make_number (height)); | ||
| 1972 | return 0; | ||
| 1973 | } | ||
| 1974 | |||
| 1946 | /* Allocate image raster. */ | 1975 | /* Allocate image raster. */ |
| 1947 | (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height); | 1976 | (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height); |
| 1948 | 1977 | ||
| @@ -1986,14 +2015,9 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 1986 | /* Bitmaps with a depth less than 16 need a palette. */ | 2015 | /* Bitmaps with a depth less than 16 need a palette. */ |
| 1987 | /* BITMAPINFO structure already contains the first RGBQUAD. */ | 2016 | /* BITMAPINFO structure already contains the first RGBQUAD. */ |
| 1988 | if (depth < 16) | 2017 | if (depth < 16) |
| 1989 | palette_colors = 1 << depth - 1; | 2018 | palette_colors = 1 << (depth - 1); |
| 1990 | 2019 | ||
| 1991 | *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD)); | 2020 | *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD)); |
| 1992 | if (*ximg == NULL) | ||
| 1993 | { | ||
| 1994 | image_error ("Unable to allocate memory for XImage", Qnil, Qnil); | ||
| 1995 | return 0; | ||
| 1996 | } | ||
| 1997 | 2021 | ||
| 1998 | header = &(*ximg)->info.bmiHeader; | 2022 | header = &(*ximg)->info.bmiHeader; |
| 1999 | memset (&(*ximg)->info, 0, sizeof (BITMAPINFO)); | 2023 | memset (&(*ximg)->info, 0, sizeof (BITMAPINFO)); |
| @@ -2035,7 +2059,7 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth, | |||
| 2035 | DWORD err = GetLastError (); | 2059 | DWORD err = GetLastError (); |
| 2036 | Lisp_Object errcode; | 2060 | Lisp_Object errcode; |
| 2037 | /* All system errors are < 10000, so the following is safe. */ | 2061 | /* All system errors are < 10000, so the following is safe. */ |
| 2038 | XSETINT (errcode, (int) err); | 2062 | XSETINT (errcode, err); |
| 2039 | image_error ("Unable to create bitmap, error code %d", errcode, Qnil); | 2063 | image_error ("Unable to create bitmap, error code %d", errcode, Qnil); |
| 2040 | x_destroy_x_image (*ximg); | 2064 | x_destroy_x_image (*ximg); |
| 2041 | return 0; | 2065 | return 0; |
| @@ -2233,7 +2257,7 @@ static const struct image_keyword xbm_format[XBM_LAST] = | |||
| 2233 | {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0}, | 2257 | {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0}, |
| 2234 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, | 2258 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, |
| 2235 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 2259 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 2236 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 2260 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 2237 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 2261 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 2238 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 2262 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 2239 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 2263 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -2314,7 +2338,7 @@ xbm_image_p (Lisp_Object object) | |||
| 2314 | else | 2338 | else |
| 2315 | { | 2339 | { |
| 2316 | Lisp_Object data; | 2340 | Lisp_Object data; |
| 2317 | EMACS_INT width, height; | 2341 | int width, height; |
| 2318 | 2342 | ||
| 2319 | /* Entries for `:width', `:height' and `:data' must be present. */ | 2343 | /* Entries for `:width', `:height' and `:data' must be present. */ |
| 2320 | if (!kw[XBM_WIDTH].count | 2344 | if (!kw[XBM_WIDTH].count |
| @@ -2365,7 +2389,7 @@ xbm_image_p (Lisp_Object object) | |||
| 2365 | } | 2389 | } |
| 2366 | else if (BOOL_VECTOR_P (data)) | 2390 | else if (BOOL_VECTOR_P (data)) |
| 2367 | { | 2391 | { |
| 2368 | if (XBOOL_VECTOR (data)->size < width * height) | 2392 | if (XBOOL_VECTOR (data)->size / height < width) |
| 2369 | return 0; | 2393 | return 0; |
| 2370 | } | 2394 | } |
| 2371 | else | 2395 | else |
| @@ -2561,13 +2585,15 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, | |||
| 2561 | img->pixmap = ns_image_from_XBM (data, img->width, img->height); | 2585 | img->pixmap = ns_image_from_XBM (data, img->width, img->height); |
| 2562 | 2586 | ||
| 2563 | #else | 2587 | #else |
| 2564 | img->pixmap | 2588 | img->pixmap = |
| 2565 | = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), | 2589 | (x_check_image_size (0, img->width, img->height) |
| 2590 | ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), | ||
| 2566 | FRAME_X_WINDOW (f), | 2591 | FRAME_X_WINDOW (f), |
| 2567 | data, | 2592 | data, |
| 2568 | img->width, img->height, | 2593 | img->width, img->height, |
| 2569 | fg, bg, | 2594 | fg, bg, |
| 2570 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); | 2595 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))) |
| 2596 | : NO_PIXMAP); | ||
| 2571 | #endif /* !HAVE_NTGUI && !HAVE_NS */ | 2597 | #endif /* !HAVE_NTGUI && !HAVE_NS */ |
| 2572 | } | 2598 | } |
| 2573 | 2599 | ||
| @@ -2674,6 +2700,13 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e | |||
| 2674 | expect ('='); | 2700 | expect ('='); |
| 2675 | expect ('{'); | 2701 | expect ('{'); |
| 2676 | 2702 | ||
| 2703 | if (! x_check_image_size (0, *width, *height)) | ||
| 2704 | { | ||
| 2705 | if (!inhibit_image_error) | ||
| 2706 | image_error ("Image too large (%dx%d)", | ||
| 2707 | make_number (*width), make_number (*height)); | ||
| 2708 | goto failure; | ||
| 2709 | } | ||
| 2677 | bytes_per_line = (*width + 7) / 8 + padding_p; | 2710 | bytes_per_line = (*width + 7) / 8 + padding_p; |
| 2678 | nbytes = bytes_per_line * *height; | 2711 | nbytes = bytes_per_line * *height; |
| 2679 | p = *data = (char *) xmalloc (nbytes); | 2712 | p = *data = (char *) xmalloc (nbytes); |
| @@ -2864,6 +2897,12 @@ xbm_load (struct frame *f, struct image *img) | |||
| 2864 | img->width = XFASTINT (fmt[XBM_WIDTH].value); | 2897 | img->width = XFASTINT (fmt[XBM_WIDTH].value); |
| 2865 | img->height = XFASTINT (fmt[XBM_HEIGHT].value); | 2898 | img->height = XFASTINT (fmt[XBM_HEIGHT].value); |
| 2866 | xassert (img->width > 0 && img->height > 0); | 2899 | xassert (img->width > 0 && img->height > 0); |
| 2900 | if (!check_image_size (f, img->width, img->height)) | ||
| 2901 | { | ||
| 2902 | image_error ("Invalid image size (see `max-image-size')", | ||
| 2903 | Qnil, Qnil); | ||
| 2904 | return 0; | ||
| 2905 | } | ||
| 2867 | } | 2906 | } |
| 2868 | 2907 | ||
| 2869 | /* Get foreground and background colors, maybe allocate colors. */ | 2908 | /* Get foreground and background colors, maybe allocate colors. */ |
| @@ -2925,9 +2964,13 @@ xbm_load (struct frame *f, struct image *img) | |||
| 2925 | #endif | 2964 | #endif |
| 2926 | /* Create the pixmap. */ | 2965 | /* Create the pixmap. */ |
| 2927 | 2966 | ||
| 2928 | Create_Pixmap_From_Bitmap_Data (f, img, bits, | 2967 | if (x_check_image_size (0, img->width, img->height)) |
| 2929 | foreground, background, | 2968 | Create_Pixmap_From_Bitmap_Data (f, img, bits, |
| 2930 | non_default_colors); | 2969 | foreground, background, |
| 2970 | non_default_colors); | ||
| 2971 | else | ||
| 2972 | img->pixmap = NO_PIXMAP; | ||
| 2973 | |||
| 2931 | if (img->pixmap) | 2974 | if (img->pixmap) |
| 2932 | success_p = 1; | 2975 | success_p = 1; |
| 2933 | else | 2976 | else |
| @@ -3009,7 +3052,7 @@ static const struct image_keyword xpm_format[XPM_LAST] = | |||
| 3009 | {":file", IMAGE_STRING_VALUE, 0}, | 3052 | {":file", IMAGE_STRING_VALUE, 0}, |
| 3010 | {":data", IMAGE_STRING_VALUE, 0}, | 3053 | {":data", IMAGE_STRING_VALUE, 0}, |
| 3011 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 3054 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 3012 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 3055 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 3013 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 3056 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 3014 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 3057 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 3015 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 3058 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -3125,12 +3168,8 @@ xpm_free_color_cache (void) | |||
| 3125 | static int | 3168 | static int |
| 3126 | xpm_color_bucket (char *color_name) | 3169 | xpm_color_bucket (char *color_name) |
| 3127 | { | 3170 | { |
| 3128 | unsigned h = 0; | 3171 | EMACS_UINT hash = hash_string (color_name, strlen (color_name)); |
| 3129 | char *s; | 3172 | return hash % XPM_COLOR_CACHE_BUCKETS; |
| 3130 | |||
| 3131 | for (s = color_name; *s; ++s) | ||
| 3132 | h = (h << 2) ^ *s; | ||
| 3133 | return h %= XPM_COLOR_CACHE_BUCKETS; | ||
| 3134 | } | 3173 | } |
| 3135 | 3174 | ||
| 3136 | 3175 | ||
| @@ -3147,7 +3186,7 @@ xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket) | |||
| 3147 | if (bucket < 0) | 3186 | if (bucket < 0) |
| 3148 | bucket = xpm_color_bucket (color_name); | 3187 | bucket = xpm_color_bucket (color_name); |
| 3149 | 3188 | ||
| 3150 | nbytes = sizeof *p + strlen (color_name); | 3189 | nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1; |
| 3151 | p = (struct xpm_cached_color *) xmalloc (nbytes); | 3190 | p = (struct xpm_cached_color *) xmalloc (nbytes); |
| 3152 | strcpy (p->name, color_name); | 3191 | strcpy (p->name, color_name); |
| 3153 | p->color = *color; | 3192 | p->color = *color; |
| @@ -3531,9 +3570,8 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3531 | #endif /* HAVE_NTGUI */ | 3570 | #endif /* HAVE_NTGUI */ |
| 3532 | 3571 | ||
| 3533 | /* Remember allocated colors. */ | 3572 | /* Remember allocated colors. */ |
| 3573 | img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors); | ||
| 3534 | img->ncolors = attrs.nalloc_pixels; | 3574 | img->ncolors = attrs.nalloc_pixels; |
| 3535 | img->colors = (unsigned long *) xmalloc (img->ncolors | ||
| 3536 | * sizeof *img->colors); | ||
| 3537 | for (i = 0; i < attrs.nalloc_pixels; ++i) | 3575 | for (i = 0; i < attrs.nalloc_pixels; ++i) |
| 3538 | { | 3576 | { |
| 3539 | img->colors[i] = attrs.alloc_pixels[i]; | 3577 | img->colors[i] = attrs.alloc_pixels[i]; |
| @@ -3757,8 +3795,8 @@ xpm_get_color_table_h (Lisp_Object color_table, | |||
| 3757 | int chars_len) | 3795 | int chars_len) |
| 3758 | { | 3796 | { |
| 3759 | struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); | 3797 | struct Lisp_Hash_Table *table = XHASH_TABLE (color_table); |
| 3760 | int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len), | 3798 | ptrdiff_t i = |
| 3761 | NULL); | 3799 | hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL); |
| 3762 | 3800 | ||
| 3763 | return i >= 0 ? HASH_VALUE (table, i) : Qnil; | 3801 | return i >= 0 ? HASH_VALUE (table, i) : Qnil; |
| 3764 | } | 3802 | } |
| @@ -3849,6 +3887,18 @@ xpm_load_image (struct frame *f, | |||
| 3849 | goto failure; | 3887 | goto failure; |
| 3850 | } | 3888 | } |
| 3851 | 3889 | ||
| 3890 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 3891 | &ximg, &img->pixmap) | ||
| 3892 | #ifndef HAVE_NS | ||
| 3893 | || !x_create_x_image_and_pixmap (f, width, height, 1, | ||
| 3894 | &mask_img, &img->mask) | ||
| 3895 | #endif | ||
| 3896 | ) | ||
| 3897 | { | ||
| 3898 | image_error ("Image too large", Qnil, Qnil); | ||
| 3899 | goto failure; | ||
| 3900 | } | ||
| 3901 | |||
| 3852 | expect (','); | 3902 | expect (','); |
| 3853 | 3903 | ||
| 3854 | XSETFRAME (frame, f); | 3904 | XSETFRAME (frame, f); |
| @@ -3942,18 +3992,6 @@ xpm_load_image (struct frame *f, | |||
| 3942 | expect (','); | 3992 | expect (','); |
| 3943 | } | 3993 | } |
| 3944 | 3994 | ||
| 3945 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 3946 | &ximg, &img->pixmap) | ||
| 3947 | #ifndef HAVE_NS | ||
| 3948 | || !x_create_x_image_and_pixmap (f, width, height, 1, | ||
| 3949 | &mask_img, &img->mask) | ||
| 3950 | #endif | ||
| 3951 | ) | ||
| 3952 | { | ||
| 3953 | image_error ("Out of memory (%s)", img->spec, Qnil); | ||
| 3954 | goto error; | ||
| 3955 | } | ||
| 3956 | |||
| 3957 | for (y = 0; y < height; y++) | 3995 | for (y = 0; y < height; y++) |
| 3958 | { | 3996 | { |
| 3959 | expect (XPM_TK_STRING); | 3997 | expect (XPM_TK_STRING); |
| @@ -4107,6 +4145,12 @@ static struct ct_color **ct_table; | |||
| 4107 | /* Number of entries in the color table. */ | 4145 | /* Number of entries in the color table. */ |
| 4108 | 4146 | ||
| 4109 | static int ct_colors_allocated; | 4147 | static int ct_colors_allocated; |
| 4148 | enum | ||
| 4149 | { | ||
| 4150 | ct_colors_allocated_max = | ||
| 4151 | min (INT_MAX, | ||
| 4152 | min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long)) | ||
| 4153 | }; | ||
| 4110 | 4154 | ||
| 4111 | /* Initialize the color table. */ | 4155 | /* Initialize the color table. */ |
| 4112 | 4156 | ||
| @@ -4193,7 +4237,14 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) | |||
| 4193 | XColor color; | 4237 | XColor color; |
| 4194 | Colormap cmap; | 4238 | Colormap cmap; |
| 4195 | int rc; | 4239 | int rc; |
| 4240 | #else | ||
| 4241 | COLORREF color; | ||
| 4242 | #endif | ||
| 4196 | 4243 | ||
| 4244 | if (ct_colors_allocated_max <= ct_colors_allocated) | ||
| 4245 | return FRAME_FOREGROUND_PIXEL (f); | ||
| 4246 | |||
| 4247 | #ifdef HAVE_X_WINDOWS | ||
| 4197 | color.red = r; | 4248 | color.red = r; |
| 4198 | color.green = g; | 4249 | color.green = g; |
| 4199 | color.blue = b; | 4250 | color.blue = b; |
| @@ -4215,7 +4266,6 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) | |||
| 4215 | return FRAME_FOREGROUND_PIXEL (f); | 4266 | return FRAME_FOREGROUND_PIXEL (f); |
| 4216 | 4267 | ||
| 4217 | #else | 4268 | #else |
| 4218 | COLORREF color; | ||
| 4219 | #ifdef HAVE_NTGUI | 4269 | #ifdef HAVE_NTGUI |
| 4220 | color = PALETTERGB (r, g, b); | 4270 | color = PALETTERGB (r, g, b); |
| 4221 | #else | 4271 | #else |
| @@ -4256,6 +4306,9 @@ lookup_pixel_color (struct frame *f, unsigned long pixel) | |||
| 4256 | Colormap cmap; | 4306 | Colormap cmap; |
| 4257 | int rc; | 4307 | int rc; |
| 4258 | 4308 | ||
| 4309 | if (ct_colors_allocated_max <= ct_colors_allocated) | ||
| 4310 | return FRAME_FOREGROUND_PIXEL (f); | ||
| 4311 | |||
| 4259 | #ifdef HAVE_X_WINDOWS | 4312 | #ifdef HAVE_X_WINDOWS |
| 4260 | cmap = FRAME_X_COLORMAP (f); | 4313 | cmap = FRAME_X_COLORMAP (f); |
| 4261 | color.pixel = pixel; | 4314 | color.pixel = pixel; |
| @@ -4394,7 +4447,9 @@ x_to_xcolors (struct frame *f, struct image *img, int rgb_p) | |||
| 4394 | HGDIOBJ prev; | 4447 | HGDIOBJ prev; |
| 4395 | #endif /* HAVE_NTGUI */ | 4448 | #endif /* HAVE_NTGUI */ |
| 4396 | 4449 | ||
| 4397 | colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors); | 4450 | if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height) |
| 4451 | memory_full (SIZE_MAX); | ||
| 4452 | colors = (XColor *) xmalloc (sizeof *colors * img->width * img->height); | ||
| 4398 | 4453 | ||
| 4399 | #ifndef HAVE_NTGUI | 4454 | #ifndef HAVE_NTGUI |
| 4400 | /* Get the X image IMG->pixmap. */ | 4455 | /* Get the X image IMG->pixmap. */ |
| @@ -4546,7 +4601,9 @@ x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjus | |||
| 4546 | 4601 | ||
| 4547 | #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X)) | 4602 | #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X)) |
| 4548 | 4603 | ||
| 4549 | new = (XColor *) xmalloc (img->width * img->height * sizeof *new); | 4604 | if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height) |
| 4605 | memory_full (SIZE_MAX); | ||
| 4606 | new = (XColor *) xmalloc (sizeof *new * img->width * img->height); | ||
| 4550 | 4607 | ||
| 4551 | for (y = 0; y < img->height; ++y) | 4608 | for (y = 0; y < img->height; ++y) |
| 4552 | { | 4609 | { |
| @@ -4924,7 +4981,7 @@ static const struct image_keyword pbm_format[PBM_LAST] = | |||
| 4924 | {":file", IMAGE_STRING_VALUE, 0}, | 4981 | {":file", IMAGE_STRING_VALUE, 0}, |
| 4925 | {":data", IMAGE_STRING_VALUE, 0}, | 4982 | {":data", IMAGE_STRING_VALUE, 0}, |
| 4926 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 4983 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 4927 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 4984 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 4928 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 4985 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 4929 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 4986 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 4930 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 4987 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -5007,9 +5064,7 @@ pbm_scan_number (unsigned char **s, unsigned char *end) | |||
| 5007 | occurred. *SIZE is set to the size of the file. */ | 5064 | occurred. *SIZE is set to the size of the file. */ |
| 5008 | 5065 | ||
| 5009 | static char * | 5066 | static char * |
| 5010 | pbm_read_file (file, size) | 5067 | pbm_read_file (Lisp_Object file, int *size) |
| 5011 | Lisp_Object file; | ||
| 5012 | int *size; | ||
| 5013 | { | 5068 | { |
| 5014 | FILE *fp = NULL; | 5069 | FILE *fp = NULL; |
| 5015 | char *buf = NULL; | 5070 | char *buf = NULL; |
| @@ -5341,7 +5396,7 @@ static const struct image_keyword png_format[PNG_LAST] = | |||
| 5341 | {":data", IMAGE_STRING_VALUE, 0}, | 5396 | {":data", IMAGE_STRING_VALUE, 0}, |
| 5342 | {":file", IMAGE_STRING_VALUE, 0}, | 5397 | {":file", IMAGE_STRING_VALUE, 0}, |
| 5343 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 5398 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 5344 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 5399 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 5345 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 5400 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 5346 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 5401 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 5347 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 5402 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -5490,7 +5545,7 @@ init_png_functions (Lisp_Object libraries) | |||
| 5490 | /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */ | 5545 | /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */ |
| 5491 | #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1)) | 5546 | #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1)) |
| 5492 | #define PNG_JMPBUF(ptr) \ | 5547 | #define PNG_JMPBUF(ptr) \ |
| 5493 | (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf))) | 5548 | (*fn_png_set_longjmp_fn ((ptr), longjmp, sizeof (jmp_buf))) |
| 5494 | #endif | 5549 | #endif |
| 5495 | 5550 | ||
| 5496 | /* Error and warning handlers installed when the PNG library | 5551 | /* Error and warning handlers installed when the PNG library |
| @@ -5520,8 +5575,8 @@ my_png_warning (png_struct *png_ptr, const char *msg) | |||
| 5520 | struct png_memory_storage | 5575 | struct png_memory_storage |
| 5521 | { | 5576 | { |
| 5522 | unsigned char *bytes; /* The data */ | 5577 | unsigned char *bytes; /* The data */ |
| 5523 | size_t len; /* How big is it? */ | 5578 | ptrdiff_t len; /* How big is it? */ |
| 5524 | int index; /* Where are we? */ | 5579 | ptrdiff_t index; /* Where are we? */ |
| 5525 | }; | 5580 | }; |
| 5526 | 5581 | ||
| 5527 | 5582 | ||
| @@ -5565,7 +5620,8 @@ png_load (struct frame *f, struct image *img) | |||
| 5565 | { | 5620 | { |
| 5566 | Lisp_Object file, specified_file; | 5621 | Lisp_Object file, specified_file; |
| 5567 | Lisp_Object specified_data; | 5622 | Lisp_Object specified_data; |
| 5568 | int x, y, i; | 5623 | int x, y; |
| 5624 | ptrdiff_t i; | ||
| 5569 | XImagePtr ximg, mask_img = NULL; | 5625 | XImagePtr ximg, mask_img = NULL; |
| 5570 | png_struct *png_ptr = NULL; | 5626 | png_struct *png_ptr = NULL; |
| 5571 | png_info *info_ptr = NULL, *end_info = NULL; | 5627 | png_info *info_ptr = NULL, *end_info = NULL; |
| @@ -5685,11 +5741,19 @@ png_load (struct frame *f, struct image *img) | |||
| 5685 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | 5741 | fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, |
| 5686 | &interlace_type, NULL, NULL); | 5742 | &interlace_type, NULL, NULL); |
| 5687 | 5743 | ||
| 5688 | if (!check_image_size (f, width, height)) | 5744 | if (! (width <= INT_MAX && height <= INT_MAX |
| 5745 | && check_image_size (f, width, height))) | ||
| 5689 | { | 5746 | { |
| 5690 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 5747 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 5691 | goto error; | 5748 | goto error; |
| 5692 | } | 5749 | } |
| 5750 | |||
| 5751 | /* Create the X image and pixmap now, so that the work below can be | ||
| 5752 | omitted if the image is too large for X. */ | ||
| 5753 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, | ||
| 5754 | &img->pixmap)) | ||
| 5755 | goto error; | ||
| 5756 | |||
| 5693 | /* If image contains simply transparency data, we prefer to | 5757 | /* If image contains simply transparency data, we prefer to |
| 5694 | construct a clipping mask. */ | 5758 | construct a clipping mask. */ |
| 5695 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) | 5759 | if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) |
| @@ -5778,7 +5842,10 @@ png_load (struct frame *f, struct image *img) | |||
| 5778 | row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr); | 5842 | row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr); |
| 5779 | 5843 | ||
| 5780 | /* Allocate memory for the image. */ | 5844 | /* Allocate memory for the image. */ |
| 5781 | pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels); | 5845 | if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height |
| 5846 | || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes) | ||
| 5847 | memory_full (SIZE_MAX); | ||
| 5848 | pixels = (png_byte *) xmalloc (sizeof *pixels * row_bytes * height); | ||
| 5782 | rows = (png_byte **) xmalloc (height * sizeof *rows); | 5849 | rows = (png_byte **) xmalloc (height * sizeof *rows); |
| 5783 | for (i = 0; i < height; ++i) | 5850 | for (i = 0; i < height; ++i) |
| 5784 | rows[i] = pixels + i * row_bytes; | 5851 | rows[i] = pixels + i * row_bytes; |
| @@ -5792,11 +5859,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5792 | fp = NULL; | 5859 | fp = NULL; |
| 5793 | } | 5860 | } |
| 5794 | 5861 | ||
| 5795 | /* Create the X image and pixmap. */ | ||
| 5796 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, | ||
| 5797 | &img->pixmap)) | ||
| 5798 | goto error; | ||
| 5799 | |||
| 5800 | /* Create an image and pixmap serving as mask if the PNG image | 5862 | /* Create an image and pixmap serving as mask if the PNG image |
| 5801 | contains an alpha channel. */ | 5863 | contains an alpha channel. */ |
| 5802 | if (channels == 4 | 5864 | if (channels == 4 |
| @@ -5819,7 +5881,7 @@ png_load (struct frame *f, struct image *img) | |||
| 5819 | 5881 | ||
| 5820 | for (x = 0; x < width; ++x) | 5882 | for (x = 0; x < width; ++x) |
| 5821 | { | 5883 | { |
| 5822 | unsigned r, g, b; | 5884 | int r, g, b; |
| 5823 | 5885 | ||
| 5824 | r = *p++ << 8; | 5886 | r = *p++ << 8; |
| 5825 | g = *p++ << 8; | 5887 | g = *p++ << 8; |
| @@ -5904,9 +5966,9 @@ png_load (struct frame *f, struct image *img) | |||
| 5904 | static int | 5966 | static int |
| 5905 | png_load (struct frame *f, struct image *img) | 5967 | png_load (struct frame *f, struct image *img) |
| 5906 | { | 5968 | { |
| 5907 | return ns_load_image(f, img, | 5969 | return ns_load_image (f, img, |
| 5908 | image_spec_value (img->spec, QCfile, NULL), | 5970 | image_spec_value (img->spec, QCfile, NULL), |
| 5909 | image_spec_value (img->spec, QCdata, NULL)); | 5971 | image_spec_value (img->spec, QCdata, NULL)); |
| 5910 | } | 5972 | } |
| 5911 | #endif /* HAVE_NS */ | 5973 | #endif /* HAVE_NS */ |
| 5912 | 5974 | ||
| @@ -5954,7 +6016,7 @@ static const struct image_keyword jpeg_format[JPEG_LAST] = | |||
| 5954 | {":data", IMAGE_STRING_VALUE, 0}, | 6016 | {":data", IMAGE_STRING_VALUE, 0}, |
| 5955 | {":file", IMAGE_STRING_VALUE, 0}, | 6017 | {":file", IMAGE_STRING_VALUE, 0}, |
| 5956 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 6018 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 5957 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 6019 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 5958 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 6020 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 5959 | {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6021 | {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 5960 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6022 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -6053,7 +6115,7 @@ jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired) | |||
| 6053 | 6115 | ||
| 6054 | #else | 6116 | #else |
| 6055 | 6117 | ||
| 6056 | #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a) | 6118 | #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress (a) |
| 6057 | #define fn_jpeg_start_decompress jpeg_start_decompress | 6119 | #define fn_jpeg_start_decompress jpeg_start_decompress |
| 6058 | #define fn_jpeg_finish_decompress jpeg_finish_decompress | 6120 | #define fn_jpeg_finish_decompress jpeg_finish_decompress |
| 6059 | #define fn_jpeg_destroy_decompress jpeg_destroy_decompress | 6121 | #define fn_jpeg_destroy_decompress jpeg_destroy_decompress |
| @@ -6194,7 +6256,7 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo) | |||
| 6194 | src = (struct jpeg_stdio_mgr *) cinfo->src; | 6256 | src = (struct jpeg_stdio_mgr *) cinfo->src; |
| 6195 | if (!src->finished) | 6257 | if (!src->finished) |
| 6196 | { | 6258 | { |
| 6197 | size_t bytes; | 6259 | ptrdiff_t bytes; |
| 6198 | 6260 | ||
| 6199 | bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file); | 6261 | bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file); |
| 6200 | if (bytes > 0) | 6262 | if (bytes > 0) |
| @@ -6504,7 +6566,7 @@ static const struct image_keyword tiff_format[TIFF_LAST] = | |||
| 6504 | {":data", IMAGE_STRING_VALUE, 0}, | 6566 | {":data", IMAGE_STRING_VALUE, 0}, |
| 6505 | {":file", IMAGE_STRING_VALUE, 0}, | 6567 | {":file", IMAGE_STRING_VALUE, 0}, |
| 6506 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 6568 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 6507 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 6569 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 6508 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 6570 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 6509 | {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6571 | {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6510 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6572 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -6604,34 +6666,33 @@ init_tiff_functions (Lisp_Object libraries) | |||
| 6604 | typedef struct | 6666 | typedef struct |
| 6605 | { | 6667 | { |
| 6606 | unsigned char *bytes; | 6668 | unsigned char *bytes; |
| 6607 | size_t len; | 6669 | ptrdiff_t len; |
| 6608 | int index; | 6670 | ptrdiff_t index; |
| 6609 | } | 6671 | } |
| 6610 | tiff_memory_source; | 6672 | tiff_memory_source; |
| 6611 | 6673 | ||
| 6612 | static size_t | 6674 | static tsize_t |
| 6613 | tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size) | 6675 | tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size) |
| 6614 | { | 6676 | { |
| 6615 | tiff_memory_source *src = (tiff_memory_source *) data; | 6677 | tiff_memory_source *src = (tiff_memory_source *) data; |
| 6616 | 6678 | ||
| 6617 | if (size > src->len - src->index) | 6679 | size = min (size, src->len - src->index); |
| 6618 | return (size_t) -1; | ||
| 6619 | memcpy (buf, src->bytes + src->index, size); | 6680 | memcpy (buf, src->bytes + src->index, size); |
| 6620 | src->index += size; | 6681 | src->index += size; |
| 6621 | return size; | 6682 | return size; |
| 6622 | } | 6683 | } |
| 6623 | 6684 | ||
| 6624 | static size_t | 6685 | static tsize_t |
| 6625 | tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size) | 6686 | tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size) |
| 6626 | { | 6687 | { |
| 6627 | return (size_t) -1; | 6688 | return -1; |
| 6628 | } | 6689 | } |
| 6629 | 6690 | ||
| 6630 | static toff_t | 6691 | static toff_t |
| 6631 | tiff_seek_in_memory (thandle_t data, toff_t off, int whence) | 6692 | tiff_seek_in_memory (thandle_t data, toff_t off, int whence) |
| 6632 | { | 6693 | { |
| 6633 | tiff_memory_source *src = (tiff_memory_source *) data; | 6694 | tiff_memory_source *src = (tiff_memory_source *) data; |
| 6634 | int idx; | 6695 | ptrdiff_t idx; |
| 6635 | 6696 | ||
| 6636 | switch (whence) | 6697 | switch (whence) |
| 6637 | { | 6698 | { |
| @@ -6684,18 +6745,41 @@ tiff_size_of_memory (thandle_t data) | |||
| 6684 | return ((tiff_memory_source *) data)->len; | 6745 | return ((tiff_memory_source *) data)->len; |
| 6685 | } | 6746 | } |
| 6686 | 6747 | ||
| 6748 | /* GCC 3.x on x86 Windows targets has a bug that triggers an internal | ||
| 6749 | compiler error compiling tiff_handler, see Bugzilla bug #17406 | ||
| 6750 | (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring | ||
| 6751 | this function as external works around that problem. */ | ||
| 6752 | #if defined (__MINGW32__) && __GNUC__ == 3 | ||
| 6753 | # define MINGW_STATIC | ||
| 6754 | #else | ||
| 6755 | # define MINGW_STATIC static | ||
| 6756 | #endif | ||
| 6757 | |||
| 6758 | MINGW_STATIC void | ||
| 6759 | tiff_handler (const char *, const char *, const char *, va_list) | ||
| 6760 | ATTRIBUTE_FORMAT_PRINTF (3, 0); | ||
| 6761 | MINGW_STATIC void | ||
| 6762 | tiff_handler (const char *log_format, const char *title, | ||
| 6763 | const char *format, va_list ap) | ||
| 6764 | { | ||
| 6765 | /* doprnt is not suitable here, as TIFF handlers are called from | ||
| 6766 | libtiff and are passed arbitrary printf directives. Instead, use | ||
| 6767 | vsnprintf, taking care to be portable to nonstandard environments | ||
| 6768 | where vsnprintf returns -1 on buffer overflow. Since it's just a | ||
| 6769 | log entry, it's OK to truncate it. */ | ||
| 6770 | char buf[4000]; | ||
| 6771 | int len = vsnprintf (buf, sizeof buf, format, ap); | ||
| 6772 | add_to_log (log_format, build_string (title), | ||
| 6773 | make_string (buf, max (0, min (len, sizeof buf - 1)))); | ||
| 6774 | } | ||
| 6775 | #undef MINGW_STATIC | ||
| 6687 | 6776 | ||
| 6688 | static void tiff_error_handler (const char *, const char *, va_list) | 6777 | static void tiff_error_handler (const char *, const char *, va_list) |
| 6689 | ATTRIBUTE_FORMAT_PRINTF (2, 0); | 6778 | ATTRIBUTE_FORMAT_PRINTF (2, 0); |
| 6690 | static void | 6779 | static void |
| 6691 | tiff_error_handler (const char *title, const char *format, va_list ap) | 6780 | tiff_error_handler (const char *title, const char *format, va_list ap) |
| 6692 | { | 6781 | { |
| 6693 | char buf[512]; | 6782 | tiff_handler ("TIFF error: %s %s", title, format, ap); |
| 6694 | int len; | ||
| 6695 | |||
| 6696 | len = sprintf (buf, "TIFF error: %s ", title); | ||
| 6697 | vsprintf (buf + len, format, ap); | ||
| 6698 | add_to_log (buf, Qnil, Qnil); | ||
| 6699 | } | 6783 | } |
| 6700 | 6784 | ||
| 6701 | 6785 | ||
| @@ -6704,12 +6788,7 @@ static void tiff_warning_handler (const char *, const char *, va_list) | |||
| 6704 | static void | 6788 | static void |
| 6705 | tiff_warning_handler (const char *title, const char *format, va_list ap) | 6789 | tiff_warning_handler (const char *title, const char *format, va_list ap) |
| 6706 | { | 6790 | { |
| 6707 | char buf[512]; | 6791 | tiff_handler ("TIFF warning: %s %s", title, format, ap); |
| 6708 | int len; | ||
| 6709 | |||
| 6710 | len = sprintf (buf, "TIFF warning: %s ", title); | ||
| 6711 | vsprintf (buf + len, format, ap); | ||
| 6712 | add_to_log (buf, Qnil, Qnil); | ||
| 6713 | } | 6792 | } |
| 6714 | 6793 | ||
| 6715 | 6794 | ||
| @@ -6767,8 +6846,8 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6767 | memsrc.index = 0; | 6846 | memsrc.index = 0; |
| 6768 | 6847 | ||
| 6769 | tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc, | 6848 | tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc, |
| 6770 | (TIFFReadWriteProc) tiff_read_from_memory, | 6849 | tiff_read_from_memory, |
| 6771 | (TIFFReadWriteProc) tiff_write_from_memory, | 6850 | tiff_write_from_memory, |
| 6772 | tiff_seek_in_memory, | 6851 | tiff_seek_in_memory, |
| 6773 | tiff_close_memory, | 6852 | tiff_close_memory, |
| 6774 | tiff_size_of_memory, | 6853 | tiff_size_of_memory, |
| @@ -6785,8 +6864,9 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6785 | image = image_spec_value (img->spec, QCindex, NULL); | 6864 | image = image_spec_value (img->spec, QCindex, NULL); |
| 6786 | if (INTEGERP (image)) | 6865 | if (INTEGERP (image)) |
| 6787 | { | 6866 | { |
| 6788 | int ino = XFASTINT (image); | 6867 | EMACS_INT ino = XFASTINT (image); |
| 6789 | if (!fn_TIFFSetDirectory (tiff, ino)) | 6868 | if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t) |
| 6869 | && fn_TIFFSetDirectory (tiff, ino))) | ||
| 6790 | { | 6870 | { |
| 6791 | image_error ("Invalid image number `%s' in image `%s'", | 6871 | image_error ("Invalid image number `%s' in image `%s'", |
| 6792 | image, img->spec); | 6872 | image, img->spec); |
| @@ -6807,7 +6887,16 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6807 | return 0; | 6887 | return 0; |
| 6808 | } | 6888 | } |
| 6809 | 6889 | ||
| 6810 | buf = (uint32 *) xmalloc (width * height * sizeof *buf); | 6890 | /* Create the X image and pixmap. */ |
| 6891 | if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width | ||
| 6892 | && x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 6893 | &ximg, &img->pixmap))) | ||
| 6894 | { | ||
| 6895 | fn_TIFFClose (tiff); | ||
| 6896 | return 0; | ||
| 6897 | } | ||
| 6898 | |||
| 6899 | buf = (uint32 *) xmalloc (sizeof *buf * width * height); | ||
| 6811 | 6900 | ||
| 6812 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); | 6901 | rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0); |
| 6813 | 6902 | ||
| @@ -6828,13 +6917,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6828 | return 0; | 6917 | return 0; |
| 6829 | } | 6918 | } |
| 6830 | 6919 | ||
| 6831 | /* Create the X image and pixmap. */ | ||
| 6832 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | ||
| 6833 | { | ||
| 6834 | xfree (buf); | ||
| 6835 | return 0; | ||
| 6836 | } | ||
| 6837 | |||
| 6838 | /* Initialize the color table. */ | 6920 | /* Initialize the color table. */ |
| 6839 | init_color_table (); | 6921 | init_color_table (); |
| 6840 | 6922 | ||
| @@ -6932,7 +7014,7 @@ static const struct image_keyword gif_format[GIF_LAST] = | |||
| 6932 | {":data", IMAGE_STRING_VALUE, 0}, | 7014 | {":data", IMAGE_STRING_VALUE, 0}, |
| 6933 | {":file", IMAGE_STRING_VALUE, 0}, | 7015 | {":file", IMAGE_STRING_VALUE, 0}, |
| 6934 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 7016 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 6935 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 7017 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 6936 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 7018 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 6937 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7019 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6938 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7020 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -7036,8 +7118,8 @@ init_gif_functions (Lisp_Object libraries) | |||
| 7036 | typedef struct | 7118 | typedef struct |
| 7037 | { | 7119 | { |
| 7038 | unsigned char *bytes; | 7120 | unsigned char *bytes; |
| 7039 | size_t len; | 7121 | ptrdiff_t len; |
| 7040 | int index; | 7122 | ptrdiff_t index; |
| 7041 | } | 7123 | } |
| 7042 | gif_memory_source; | 7124 | gif_memory_source; |
| 7043 | 7125 | ||
| @@ -7077,13 +7159,12 @@ gif_load (struct frame *f, struct image *img) | |||
| 7077 | ColorMapObject *gif_color_map; | 7159 | ColorMapObject *gif_color_map; |
| 7078 | unsigned long pixel_colors[256]; | 7160 | unsigned long pixel_colors[256]; |
| 7079 | GifFileType *gif; | 7161 | GifFileType *gif; |
| 7080 | int image_height, image_width; | ||
| 7081 | gif_memory_source memsrc; | 7162 | gif_memory_source memsrc; |
| 7082 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); | 7163 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); |
| 7083 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); | 7164 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 7084 | Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); | 7165 | Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 7085 | unsigned long bgcolor = 0; | 7166 | unsigned long bgcolor = 0; |
| 7086 | int idx; | 7167 | EMACS_INT idx; |
| 7087 | 7168 | ||
| 7088 | if (NILP (specified_data)) | 7169 | if (NILP (specified_data)) |
| 7089 | { | 7170 | { |
| @@ -7154,19 +7235,15 @@ gif_load (struct frame *f, struct image *img) | |||
| 7154 | } | 7235 | } |
| 7155 | } | 7236 | } |
| 7156 | 7237 | ||
| 7157 | img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top; | 7238 | width = img->width = gif->SWidth; |
| 7158 | img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left; | 7239 | height = img->height = gif->SHeight; |
| 7159 | image_height = gif->SavedImages[idx].ImageDesc.Height; | ||
| 7160 | img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height; | ||
| 7161 | image_width = gif->SavedImages[idx].ImageDesc.Width; | ||
| 7162 | img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width; | ||
| 7163 | 7240 | ||
| 7164 | width = img->width = max (gif->SWidth, | 7241 | img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top; |
| 7165 | max (gif->Image.Left + gif->Image.Width, | 7242 | img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left; |
| 7166 | img->corners[RIGHT_CORNER])); | 7243 | img->corners[BOT_CORNER] |
| 7167 | height = img->height = max (gif->SHeight, | 7244 | = img->corners[TOP_CORNER] + gif->SavedImages[0].ImageDesc.Height; |
| 7168 | max (gif->Image.Top + gif->Image.Height, | 7245 | img->corners[RIGHT_CORNER] |
| 7169 | img->corners[BOT_CORNER])); | 7246 | = img->corners[LEFT_CORNER] + gif->SavedImages[0].ImageDesc.Width; |
| 7170 | 7247 | ||
| 7171 | if (!check_image_size (f, width, height)) | 7248 | if (!check_image_size (f, width, height)) |
| 7172 | { | 7249 | { |
| @@ -7221,6 +7298,10 @@ gif_load (struct frame *f, struct image *img) | |||
| 7221 | unsigned char *raster = (unsigned char *) subimage->RasterBits; | 7298 | unsigned char *raster = (unsigned char *) subimage->RasterBits; |
| 7222 | int transparency_color_index = -1; | 7299 | int transparency_color_index = -1; |
| 7223 | int disposal = 0; | 7300 | int disposal = 0; |
| 7301 | int subimg_width = subimage->ImageDesc.Width; | ||
| 7302 | int subimg_height = subimage->ImageDesc.Height; | ||
| 7303 | int subimg_top = subimage->ImageDesc.Top; | ||
| 7304 | int subimg_left = subimage->ImageDesc.Left; | ||
| 7224 | 7305 | ||
| 7225 | /* Find the Graphic Control Extension block for this sub-image. | 7306 | /* Find the Graphic Control Extension block for this sub-image. |
| 7226 | Extract the disposal method and transparency color. */ | 7307 | Extract the disposal method and transparency color. */ |
| @@ -7244,6 +7325,13 @@ gif_load (struct frame *f, struct image *img) | |||
| 7244 | if (j == 0) | 7325 | if (j == 0) |
| 7245 | disposal = 2; | 7326 | disposal = 2; |
| 7246 | 7327 | ||
| 7328 | /* For disposal == 0, the spec says "No disposal specified. The | ||
| 7329 | decoder is not required to take any action." In practice, it | ||
| 7330 | seems we need to treat this like "keep in place", see e.g. | ||
| 7331 | http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */ | ||
| 7332 | if (disposal == 0) | ||
| 7333 | disposal = 1; | ||
| 7334 | |||
| 7247 | /* Allocate subimage colors. */ | 7335 | /* Allocate subimage colors. */ |
| 7248 | memset (pixel_colors, 0, sizeof pixel_colors); | 7336 | memset (pixel_colors, 0, sizeof pixel_colors); |
| 7249 | gif_color_map = subimage->ImageDesc.ColorMap; | 7337 | gif_color_map = subimage->ImageDesc.ColorMap; |
| @@ -7271,34 +7359,34 @@ gif_load (struct frame *f, struct image *img) | |||
| 7271 | int row, pass; | 7359 | int row, pass; |
| 7272 | 7360 | ||
| 7273 | for (y = 0, row = interlace_start[0], pass = 0; | 7361 | for (y = 0, row = interlace_start[0], pass = 0; |
| 7274 | y < image_height; | 7362 | y < subimg_height; |
| 7275 | y++, row += interlace_increment[pass]) | 7363 | y++, row += interlace_increment[pass]) |
| 7276 | { | 7364 | { |
| 7277 | if (row >= image_height) | 7365 | if (row >= subimg_height) |
| 7278 | { | 7366 | { |
| 7279 | row = interlace_start[++pass]; | 7367 | row = interlace_start[++pass]; |
| 7280 | while (row >= image_height) | 7368 | while (row >= subimg_height) |
| 7281 | row = interlace_start[++pass]; | 7369 | row = interlace_start[++pass]; |
| 7282 | } | 7370 | } |
| 7283 | 7371 | ||
| 7284 | for (x = 0; x < image_width; x++) | 7372 | for (x = 0; x < subimg_width; x++) |
| 7285 | { | 7373 | { |
| 7286 | int c = raster[y * image_width + x]; | 7374 | int c = raster[y * subimg_width + x]; |
| 7287 | if (transparency_color_index != c || disposal != 1) | 7375 | if (transparency_color_index != c || disposal != 1) |
| 7288 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], | 7376 | XPutPixel (ximg, x + subimg_left, row + subimg_top, |
| 7289 | row + img->corners[TOP_CORNER], pixel_colors[c]); | 7377 | pixel_colors[c]); |
| 7290 | } | 7378 | } |
| 7291 | } | 7379 | } |
| 7292 | } | 7380 | } |
| 7293 | else | 7381 | else |
| 7294 | { | 7382 | { |
| 7295 | for (y = 0; y < image_height; ++y) | 7383 | for (y = 0; y < subimg_height; ++y) |
| 7296 | for (x = 0; x < image_width; ++x) | 7384 | for (x = 0; x < subimg_width; ++x) |
| 7297 | { | 7385 | { |
| 7298 | int c = raster[y * image_width + x]; | 7386 | int c = raster[y * subimg_width + x]; |
| 7299 | if (transparency_color_index != c || disposal != 1) | 7387 | if (transparency_color_index != c || disposal != 1) |
| 7300 | XPutPixel (ximg, x + img->corners[LEFT_CORNER], | 7388 | XPutPixel (ximg, x + subimg_left, y + subimg_top, |
| 7301 | y + img->corners[TOP_CORNER], pixel_colors[c]); | 7389 | pixel_colors[c]); |
| 7302 | } | 7390 | } |
| 7303 | } | 7391 | } |
| 7304 | } | 7392 | } |
| @@ -7313,7 +7401,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 7313 | img->lisp_data = Qnil; | 7401 | img->lisp_data = Qnil; |
| 7314 | if (gif->SavedImages[idx].ExtensionBlockCount > 0) | 7402 | if (gif->SavedImages[idx].ExtensionBlockCount > 0) |
| 7315 | { | 7403 | { |
| 7316 | unsigned int delay = 0; | 7404 | int delay = 0; |
| 7317 | ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks; | 7405 | ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks; |
| 7318 | for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++) | 7406 | for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++) |
| 7319 | /* Append (... FUNCTION "BYTES") */ | 7407 | /* Append (... FUNCTION "BYTES") */ |
| @@ -7334,7 +7422,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 7334 | if (delay) | 7422 | if (delay) |
| 7335 | img->lisp_data | 7423 | img->lisp_data |
| 7336 | = Fcons (Qdelay, | 7424 | = Fcons (Qdelay, |
| 7337 | Fcons (make_float (((double) delay) * 0.01), | 7425 | Fcons (make_float (delay / 100.0), |
| 7338 | img->lisp_data)); | 7426 | img->lisp_data)); |
| 7339 | } | 7427 | } |
| 7340 | 7428 | ||
| @@ -7413,7 +7501,7 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | |||
| 7413 | {":data", IMAGE_STRING_VALUE, 0}, | 7501 | {":data", IMAGE_STRING_VALUE, 0}, |
| 7414 | {":file", IMAGE_STRING_VALUE, 0}, | 7502 | {":file", IMAGE_STRING_VALUE, 0}, |
| 7415 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 7503 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 7416 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 7504 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 7417 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 7505 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 7418 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7506 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7419 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7507 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -7464,7 +7552,7 @@ imagemagick_image_p (Lisp_Object object) | |||
| 7464 | } | 7552 | } |
| 7465 | 7553 | ||
| 7466 | /* The GIF library also defines DrawRectangle, but its never used in Emacs. | 7554 | /* The GIF library also defines DrawRectangle, but its never used in Emacs. |
| 7467 | Therefore rename the function so it doesnt collide with ImageMagick. */ | 7555 | Therefore rename the function so it doesn't collide with ImageMagick. */ |
| 7468 | #define DrawRectangle DrawRectangleGif | 7556 | #define DrawRectangle DrawRectangleGif |
| 7469 | #include <wand/MagickWand.h> | 7557 | #include <wand/MagickWand.h> |
| 7470 | 7558 | ||
| @@ -7476,6 +7564,22 @@ extern WandExport void PixelGetMagickColor (const PixelWand *, | |||
| 7476 | MagickPixelPacket *); | 7564 | MagickPixelPacket *); |
| 7477 | #endif | 7565 | #endif |
| 7478 | 7566 | ||
| 7567 | /* Log ImageMagick error message. | ||
| 7568 | Useful when a ImageMagick function returns the status `MagickFalse'. */ | ||
| 7569 | |||
| 7570 | static void | ||
| 7571 | imagemagick_error (MagickWand *wand) | ||
| 7572 | { | ||
| 7573 | char *description; | ||
| 7574 | ExceptionType severity; | ||
| 7575 | |||
| 7576 | description = MagickGetException (wand, &severity); | ||
| 7577 | image_error ("ImageMagick error: %s", | ||
| 7578 | make_string (description, strlen (description)), | ||
| 7579 | Qnil); | ||
| 7580 | description = (char *) MagickRelinquishMemory (description); | ||
| 7581 | } | ||
| 7582 | |||
| 7479 | /* Helper function for imagemagick_load, which does the actual loading | 7583 | /* Helper function for imagemagick_load, which does the actual loading |
| 7480 | given contents and size, apart from frame and image structures, | 7584 | given contents and size, apart from frame and image structures, |
| 7481 | passed from imagemagick_load. Uses librimagemagick to do most of | 7585 | passed from imagemagick_load. Uses librimagemagick to do most of |
| @@ -7510,10 +7614,9 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7510 | Lisp_Object image; | 7614 | Lisp_Object image; |
| 7511 | Lisp_Object value; | 7615 | Lisp_Object value; |
| 7512 | Lisp_Object crop; | 7616 | Lisp_Object crop; |
| 7513 | long ino; | 7617 | EMACS_INT ino; |
| 7514 | int desired_width, desired_height; | 7618 | int desired_width, desired_height; |
| 7515 | double rotation; | 7619 | double rotation; |
| 7516 | int imagemagick_rendermethod; | ||
| 7517 | int pixelwidth; | 7620 | int pixelwidth; |
| 7518 | ImageInfo *image_info; | 7621 | ImageInfo *image_info; |
| 7519 | ExceptionInfo *exception; | 7622 | ExceptionInfo *exception; |
| @@ -7530,7 +7633,8 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7530 | image = image_spec_value (img->spec, QCindex, NULL); | 7633 | image = image_spec_value (img->spec, QCindex, NULL); |
| 7531 | ino = INTEGERP (image) ? XFASTINT (image) : 0; | 7634 | ino = INTEGERP (image) ? XFASTINT (image) : 0; |
| 7532 | ping_wand = NewMagickWand (); | 7635 | ping_wand = NewMagickWand (); |
| 7533 | MagickSetResolution (ping_wand, 2, 2); | 7636 | /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */ |
| 7637 | |||
| 7534 | if (filename != NULL) | 7638 | if (filename != NULL) |
| 7535 | { | 7639 | { |
| 7536 | status = MagickPingImage (ping_wand, filename); | 7640 | status = MagickPingImage (ping_wand, filename); |
| @@ -7540,7 +7644,14 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7540 | status = MagickPingImageBlob (ping_wand, contents, size); | 7644 | status = MagickPingImageBlob (ping_wand, contents, size); |
| 7541 | } | 7645 | } |
| 7542 | 7646 | ||
| 7543 | if (ino >= MagickGetNumberImages (ping_wand)) | 7647 | if (status == MagickFalse) |
| 7648 | { | ||
| 7649 | imagemagick_error (ping_wand); | ||
| 7650 | DestroyMagickWand (ping_wand); | ||
| 7651 | return 0; | ||
| 7652 | } | ||
| 7653 | |||
| 7654 | if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand))) | ||
| 7544 | { | 7655 | { |
| 7545 | image_error ("Invalid image number `%s' in image `%s'", | 7656 | image_error ("Invalid image number `%s' in image `%s'", |
| 7546 | image, img->spec); | 7657 | image, img->spec); |
| @@ -7548,7 +7659,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7548 | return 0; | 7659 | return 0; |
| 7549 | } | 7660 | } |
| 7550 | 7661 | ||
| 7551 | if (MagickGetNumberImages(ping_wand) > 1) | 7662 | if (MagickGetNumberImages (ping_wand) > 1) |
| 7552 | img->lisp_data = | 7663 | img->lisp_data = |
| 7553 | Fcons (Qcount, | 7664 | Fcons (Qcount, |
| 7554 | Fcons (make_number (MagickGetNumberImages (ping_wand)), | 7665 | Fcons (make_number (MagickGetNumberImages (ping_wand)), |
| @@ -7573,13 +7684,16 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7573 | if (im_image == NULL) | 7684 | if (im_image == NULL) |
| 7574 | goto imagemagick_no_wand; | 7685 | goto imagemagick_no_wand; |
| 7575 | image_wand = NewMagickWandFromImage (im_image); | 7686 | image_wand = NewMagickWandFromImage (im_image); |
| 7576 | DestroyImage(im_image); | 7687 | DestroyImage (im_image); |
| 7577 | } | 7688 | } |
| 7578 | else | 7689 | else |
| 7579 | { | 7690 | { |
| 7580 | image_wand = NewMagickWand (); | 7691 | image_wand = NewMagickWand (); |
| 7581 | if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse) | 7692 | if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse) |
| 7582 | goto imagemagick_error; | 7693 | { |
| 7694 | imagemagick_error (image_wand); | ||
| 7695 | goto imagemagick_error; | ||
| 7696 | } | ||
| 7583 | } | 7697 | } |
| 7584 | 7698 | ||
| 7585 | /* If width and/or height is set in the display spec assume we want | 7699 | /* If width and/or height is set in the display spec assume we want |
| @@ -7607,6 +7721,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7607 | if (status == MagickFalse) | 7721 | if (status == MagickFalse) |
| 7608 | { | 7722 | { |
| 7609 | image_error ("Imagemagick scale failed", Qnil, Qnil); | 7723 | image_error ("Imagemagick scale failed", Qnil, Qnil); |
| 7724 | imagemagick_error (image_wand); | ||
| 7610 | goto imagemagick_error; | 7725 | goto imagemagick_error; |
| 7611 | } | 7726 | } |
| 7612 | } | 7727 | } |
| @@ -7615,28 +7730,28 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7615 | efficient. */ | 7730 | efficient. */ |
| 7616 | crop = image_spec_value (img->spec, QCcrop, NULL); | 7731 | crop = image_spec_value (img->spec, QCcrop, NULL); |
| 7617 | 7732 | ||
| 7618 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | 7733 | if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop))) |
| 7619 | { | 7734 | { |
| 7620 | /* After some testing, it seems MagickCropImage is the fastest crop | 7735 | /* After some testing, it seems MagickCropImage is the fastest crop |
| 7621 | function in ImageMagick. This crop function seems to do less copying | 7736 | function in ImageMagick. This crop function seems to do less copying |
| 7622 | than the alternatives, but it still reads the entire image into memory | 7737 | than the alternatives, but it still reads the entire image into memory |
| 7623 | before croping, which is aparently difficult to avoid when using | 7738 | before cropping, which is apparently difficult to avoid when using |
| 7624 | imagemagick. */ | 7739 | imagemagick. */ |
| 7625 | int w, h; | 7740 | size_t crop_width = XINT (XCAR (crop)); |
| 7626 | w = XFASTINT (XCAR (crop)); | ||
| 7627 | crop = XCDR (crop); | 7741 | crop = XCDR (crop); |
| 7628 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | 7742 | if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop))) |
| 7629 | { | 7743 | { |
| 7630 | h = XFASTINT (XCAR (crop)); | 7744 | size_t crop_height = XINT (XCAR (crop)); |
| 7631 | crop = XCDR (crop); | 7745 | crop = XCDR (crop); |
| 7632 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | 7746 | if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop))) |
| 7633 | { | 7747 | { |
| 7634 | x = XFASTINT (XCAR (crop)); | 7748 | ssize_t crop_x = XINT (XCAR (crop)); |
| 7635 | crop = XCDR (crop); | 7749 | crop = XCDR (crop); |
| 7636 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | 7750 | if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop))) |
| 7637 | { | 7751 | { |
| 7638 | y = XFASTINT (XCAR (crop)); | 7752 | ssize_t crop_y = XINT (XCAR (crop)); |
| 7639 | MagickCropImage (image_wand, w, h, x, y); | 7753 | MagickCropImage (image_wand, crop_width, crop_height, |
| 7754 | crop_x, crop_y); | ||
| 7640 | } | 7755 | } |
| 7641 | } | 7756 | } |
| 7642 | } | 7757 | } |
| @@ -7661,16 +7776,18 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7661 | if (status == MagickFalse) | 7776 | if (status == MagickFalse) |
| 7662 | { | 7777 | { |
| 7663 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); | 7778 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); |
| 7779 | imagemagick_error (image_wand); | ||
| 7664 | goto imagemagick_error; | 7780 | goto imagemagick_error; |
| 7665 | } | 7781 | } |
| 7666 | } | 7782 | } |
| 7667 | 7783 | ||
| 7668 | /* Finally we are done manipulating the image. Figure out the | 7784 | /* Finally we are done manipulating the image. Figure out the |
| 7669 | resulting width/height and transfer ownerwship to Emacs. */ | 7785 | resulting width/height and transfer ownership to Emacs. */ |
| 7670 | height = MagickGetImageHeight (image_wand); | 7786 | height = MagickGetImageHeight (image_wand); |
| 7671 | width = MagickGetImageWidth (image_wand); | 7787 | width = MagickGetImageWidth (image_wand); |
| 7672 | 7788 | ||
| 7673 | if (! check_image_size (f, width, height)) | 7789 | if (! (width <= INT_MAX && height <= INT_MAX |
| 7790 | && check_image_size (f, width, height))) | ||
| 7674 | { | 7791 | { |
| 7675 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 7792 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 7676 | goto imagemagick_error; | 7793 | goto imagemagick_error; |
| @@ -7680,10 +7797,11 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7680 | went ok. */ | 7797 | went ok. */ |
| 7681 | 7798 | ||
| 7682 | init_color_table (); | 7799 | init_color_table (); |
| 7683 | imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) | 7800 | |
| 7684 | ? XFASTINT (Vimagemagick_render_type) : 0); | 7801 | if (imagemagick_render_type == 0) |
| 7685 | if (imagemagick_rendermethod == 0) | ||
| 7686 | { | 7802 | { |
| 7803 | size_t image_height; | ||
| 7804 | |||
| 7687 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | 7805 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ |
| 7688 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | 7806 | if (!x_create_x_image_and_pixmap (f, width, height, 0, |
| 7689 | &ximg, &img->pixmap)) | 7807 | &ximg, &img->pixmap)) |
| @@ -7691,11 +7809,11 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7691 | #ifdef COLOR_TABLE_SUPPORT | 7809 | #ifdef COLOR_TABLE_SUPPORT |
| 7692 | free_color_table (); | 7810 | free_color_table (); |
| 7693 | #endif | 7811 | #endif |
| 7694 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | 7812 | image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil); |
| 7695 | goto imagemagick_error; | 7813 | goto imagemagick_error; |
| 7696 | } | 7814 | } |
| 7697 | 7815 | ||
| 7698 | /* Copy imagegmagick image to x with primitive yet robust pixel | 7816 | /* Copy imagemagick image to x with primitive yet robust pixel |
| 7699 | pusher loop. This has been tested a lot with many different | 7817 | pusher loop. This has been tested a lot with many different |
| 7700 | images. */ | 7818 | images. */ |
| 7701 | 7819 | ||
| @@ -7712,7 +7830,8 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7712 | goto imagemagick_error; | 7830 | goto imagemagick_error; |
| 7713 | } | 7831 | } |
| 7714 | 7832 | ||
| 7715 | for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++) | 7833 | image_height = MagickGetImageHeight (image_wand); |
| 7834 | for (y = 0; y < image_height; y++) | ||
| 7716 | { | 7835 | { |
| 7717 | pixels = PixelGetNextIteratorRow (iterator, &width); | 7836 | pixels = PixelGetNextIteratorRow (iterator, &width); |
| 7718 | if (pixels == (PixelWand **) NULL) | 7837 | if (pixels == (PixelWand **) NULL) |
| @@ -7729,10 +7848,9 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7729 | } | 7848 | } |
| 7730 | DestroyPixelIterator (iterator); | 7849 | DestroyPixelIterator (iterator); |
| 7731 | } | 7850 | } |
| 7732 | 7851 | else /* imagemagick_render_type != 0 */ | |
| 7733 | if (imagemagick_rendermethod == 1) | ||
| 7734 | { | 7852 | { |
| 7735 | /* Magicexportimage is normaly faster than pixelpushing. This | 7853 | /* Magicexportimage is normally faster than pixelpushing. This |
| 7736 | method is also well tested. Some aspects of this method are | 7854 | method is also well tested. Some aspects of this method are |
| 7737 | ad-hoc and needs to be more researched. */ | 7855 | ad-hoc and needs to be more researched. */ |
| 7738 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ | 7856 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ |
| @@ -7744,12 +7862,12 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7744 | #ifdef COLOR_TABLE_SUPPORT | 7862 | #ifdef COLOR_TABLE_SUPPORT |
| 7745 | free_color_table (); | 7863 | free_color_table (); |
| 7746 | #endif | 7864 | #endif |
| 7747 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | 7865 | image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil); |
| 7748 | goto imagemagick_error; | 7866 | goto imagemagick_error; |
| 7749 | } | 7867 | } |
| 7750 | 7868 | ||
| 7751 | 7869 | ||
| 7752 | /* Oddly, the below code doesnt seem to work:*/ | 7870 | /* Oddly, the below code doesn't seem to work:*/ |
| 7753 | /* switch(ximg->bitmap_unit){ */ | 7871 | /* switch(ximg->bitmap_unit){ */ |
| 7754 | /* case 8: */ | 7872 | /* case 8: */ |
| 7755 | /* pixelwidth=CharPixel; */ | 7873 | /* pixelwidth=CharPixel; */ |
| @@ -7778,7 +7896,7 @@ imagemagick_load_image (struct frame *f, struct image *img, | |||
| 7778 | /*&(img->pixmap));*/ | 7896 | /*&(img->pixmap));*/ |
| 7779 | ximg->data); | 7897 | ximg->data); |
| 7780 | #else | 7898 | #else |
| 7781 | image_error ("You dont have MagickExportImagePixels, upgrade ImageMagick!", | 7899 | image_error ("You don't have MagickExportImagePixels, upgrade ImageMagick!", |
| 7782 | Qnil, Qnil); | 7900 | Qnil, Qnil); |
| 7783 | #endif | 7901 | #endif |
| 7784 | } | 7902 | } |
| @@ -7865,6 +7983,7 @@ DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, | |||
| 7865 | Each entry in this list is a symbol named after an ImageMagick format | 7983 | Each entry in this list is a symbol named after an ImageMagick format |
| 7866 | tag. See the ImageMagick manual for a list of ImageMagick formats and | 7984 | tag. See the ImageMagick manual for a list of ImageMagick formats and |
| 7867 | their descriptions (http://www.imagemagick.org/script/formats.php). | 7985 | their descriptions (http://www.imagemagick.org/script/formats.php). |
| 7986 | You can also try the shell command: `identify -list format'. | ||
| 7868 | 7987 | ||
| 7869 | Note that ImageMagick recognizes many file-types that Emacs does not | 7988 | Note that ImageMagick recognizes many file-types that Emacs does not |
| 7870 | recognize as images, such as C. See `imagemagick-types-inhibit'. */) | 7989 | recognize as images, such as C. See `imagemagick-types-inhibit'. */) |
| @@ -7874,14 +7993,14 @@ recognize as images, such as C. See `imagemagick-types-inhibit'. */) | |||
| 7874 | size_t numf = 0; | 7993 | size_t numf = 0; |
| 7875 | ExceptionInfo ex; | 7994 | ExceptionInfo ex; |
| 7876 | char **imtypes = GetMagickList ("*", &numf, &ex); | 7995 | char **imtypes = GetMagickList ("*", &numf, &ex); |
| 7877 | int i; | 7996 | size_t i; |
| 7878 | Lisp_Object Qimagemagicktype; | 7997 | Lisp_Object Qimagemagicktype; |
| 7879 | for (i = 0; i < numf; i++) | 7998 | for (i = 0; i < numf; i++) |
| 7880 | { | 7999 | { |
| 7881 | Qimagemagicktype = intern (imtypes[i]); | 8000 | Qimagemagicktype = intern (imtypes[i]); |
| 7882 | typelist = Fcons (Qimagemagicktype, typelist); | 8001 | typelist = Fcons (Qimagemagicktype, typelist); |
| 7883 | } | 8002 | } |
| 7884 | return typelist; | 8003 | return Fnreverse (typelist); |
| 7885 | } | 8004 | } |
| 7886 | 8005 | ||
| 7887 | #endif /* defined (HAVE_IMAGEMAGICK) */ | 8006 | #endif /* defined (HAVE_IMAGEMAGICK) */ |
| @@ -7932,7 +8051,7 @@ static const struct image_keyword svg_format[SVG_LAST] = | |||
| 7932 | {":data", IMAGE_STRING_VALUE, 0}, | 8051 | {":data", IMAGE_STRING_VALUE, 0}, |
| 7933 | {":file", IMAGE_STRING_VALUE, 0}, | 8052 | {":file", IMAGE_STRING_VALUE, 0}, |
| 7934 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 8053 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 7935 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 8054 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 7936 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 8055 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 7937 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8056 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7938 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8057 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -8218,10 +8337,10 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. * | |||
| 8218 | { | 8337 | { |
| 8219 | for (x = 0; x < width; ++x) | 8338 | for (x = 0; x < width; ++x) |
| 8220 | { | 8339 | { |
| 8221 | unsigned red; | 8340 | int red; |
| 8222 | unsigned green; | 8341 | int green; |
| 8223 | unsigned blue; | 8342 | int blue; |
| 8224 | unsigned opacity; | 8343 | int opacity; |
| 8225 | 8344 | ||
| 8226 | red = *pixels++; | 8345 | red = *pixels++; |
| 8227 | green = *pixels++; | 8346 | green = *pixels++; |
| @@ -8327,7 +8446,7 @@ static const struct image_keyword gs_format[GS_LAST] = | |||
| 8327 | {":loader", IMAGE_FUNCTION_VALUE, 0}, | 8446 | {":loader", IMAGE_FUNCTION_VALUE, 0}, |
| 8328 | {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1}, | 8447 | {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1}, |
| 8329 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | 8448 | {":ascent", IMAGE_ASCENT_VALUE, 0}, |
| 8330 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | 8449 | {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0}, |
| 8331 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 8450 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 8332 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8451 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8333 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8452 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| @@ -8402,7 +8521,8 @@ gs_image_p (Lisp_Object object) | |||
| 8402 | static int | 8521 | static int |
| 8403 | gs_load (struct frame *f, struct image *img) | 8522 | gs_load (struct frame *f, struct image *img) |
| 8404 | { | 8523 | { |
| 8405 | char buffer[100]; | 8524 | uprintmax_t printnum1, printnum2; |
| 8525 | char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)]; | ||
| 8406 | Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width; | 8526 | Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width; |
| 8407 | Lisp_Object frame; | 8527 | Lisp_Object frame; |
| 8408 | double in_width, in_height; | 8528 | double in_width, in_height; |
| @@ -8414,26 +8534,32 @@ gs_load (struct frame *f, struct image *img) | |||
| 8414 | info. */ | 8534 | info. */ |
| 8415 | pt_width = image_spec_value (img->spec, QCpt_width, NULL); | 8535 | pt_width = image_spec_value (img->spec, QCpt_width, NULL); |
| 8416 | in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0; | 8536 | in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0; |
| 8417 | img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx; | 8537 | in_width *= FRAME_X_DISPLAY_INFO (f)->resx; |
| 8418 | pt_height = image_spec_value (img->spec, QCpt_height, NULL); | 8538 | pt_height = image_spec_value (img->spec, QCpt_height, NULL); |
| 8419 | in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0; | 8539 | in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0; |
| 8420 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; | 8540 | in_height *= FRAME_X_DISPLAY_INFO (f)->resy; |
| 8421 | 8541 | ||
| 8422 | if (!check_image_size (f, img->width, img->height)) | 8542 | if (! (in_width <= INT_MAX && in_height <= INT_MAX |
| 8543 | && check_image_size (f, in_width, in_height))) | ||
| 8423 | { | 8544 | { |
| 8424 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 8545 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 8425 | return 0; | 8546 | return 0; |
| 8426 | } | 8547 | } |
| 8548 | img->width = in_width; | ||
| 8549 | img->height = in_height; | ||
| 8427 | 8550 | ||
| 8428 | /* Create the pixmap. */ | 8551 | /* Create the pixmap. */ |
| 8429 | xassert (img->pixmap == NO_PIXMAP); | 8552 | xassert (img->pixmap == NO_PIXMAP); |
| 8430 | 8553 | ||
| 8431 | /* Only W32 version did BLOCK_INPUT here. ++kfs */ | 8554 | if (x_check_image_size (0, img->width, img->height)) |
| 8432 | BLOCK_INPUT; | 8555 | { |
| 8433 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | 8556 | /* Only W32 version did BLOCK_INPUT here. ++kfs */ |
| 8434 | img->width, img->height, | 8557 | BLOCK_INPUT; |
| 8435 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); | 8558 | img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
| 8436 | UNBLOCK_INPUT; | 8559 | img->width, img->height, |
| 8560 | DefaultDepthOfScreen (FRAME_X_SCREEN (f))); | ||
| 8561 | UNBLOCK_INPUT; | ||
| 8562 | } | ||
| 8437 | 8563 | ||
| 8438 | if (!img->pixmap) | 8564 | if (!img->pixmap) |
| 8439 | { | 8565 | { |
| @@ -8445,14 +8571,14 @@ gs_load (struct frame *f, struct image *img) | |||
| 8445 | if successful. We do not record_unwind_protect here because | 8571 | if successful. We do not record_unwind_protect here because |
| 8446 | other places in redisplay like calling window scroll functions | 8572 | other places in redisplay like calling window scroll functions |
| 8447 | don't either. Let the Lisp loader use `unwind-protect' instead. */ | 8573 | don't either. Let the Lisp loader use `unwind-protect' instead. */ |
| 8448 | sprintf (buffer, "%lu %lu", | 8574 | printnum1 = FRAME_X_WINDOW (f); |
| 8449 | (unsigned long) FRAME_X_WINDOW (f), | 8575 | printnum2 = img->pixmap; |
| 8450 | (unsigned long) img->pixmap); | 8576 | sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); |
| 8451 | window_and_pixmap_id = build_string (buffer); | 8577 | window_and_pixmap_id = build_string (buffer); |
| 8452 | 8578 | ||
| 8453 | sprintf (buffer, "%lu %lu", | 8579 | printnum1 = FRAME_FOREGROUND_PIXEL (f); |
| 8454 | FRAME_FOREGROUND_PIXEL (f), | 8580 | printnum2 = FRAME_BACKGROUND_PIXEL (f); |
| 8455 | FRAME_BACKGROUND_PIXEL (f)); | 8581 | sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2); |
| 8456 | pixel_colors = build_string (buffer); | 8582 | pixel_colors = build_string (buffer); |
| 8457 | 8583 | ||
| 8458 | XSETFRAME (frame, f); | 8584 | XSETFRAME (frame, f); |
| @@ -8477,7 +8603,8 @@ void | |||
| 8477 | x_kill_gs_process (Pixmap pixmap, struct frame *f) | 8603 | x_kill_gs_process (Pixmap pixmap, struct frame *f) |
| 8478 | { | 8604 | { |
| 8479 | struct image_cache *c = FRAME_IMAGE_CACHE (f); | 8605 | struct image_cache *c = FRAME_IMAGE_CACHE (f); |
| 8480 | int class, i; | 8606 | int class; |
| 8607 | ptrdiff_t i; | ||
| 8481 | struct image *img; | 8608 | struct image *img; |
| 8482 | 8609 | ||
| 8483 | /* Find the image containing PIXMAP. */ | 8610 | /* Find the image containing PIXMAP. */ |
| @@ -8581,7 +8708,7 @@ DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0, | |||
| 8581 | DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") | 8708 | DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "") |
| 8582 | (Lisp_Object spec) | 8709 | (Lisp_Object spec) |
| 8583 | { | 8710 | { |
| 8584 | int id = -1; | 8711 | ptrdiff_t id = -1; |
| 8585 | 8712 | ||
| 8586 | if (valid_image_p (spec)) | 8713 | if (valid_image_p (spec)) |
| 8587 | id = lookup_image (SELECTED_FRAME (), spec); | 8714 | id = lookup_image (SELECTED_FRAME (), spec); |
| @@ -8681,7 +8808,7 @@ syms_of_image (void) | |||
| 8681 | operation on GNU/Linux of calling dump-emacs after loading some images. */ | 8808 | operation on GNU/Linux of calling dump-emacs after loading some images. */ |
| 8682 | image_types = NULL; | 8809 | image_types = NULL; |
| 8683 | 8810 | ||
| 8684 | /* Must be defined now becase we're going to update it below, while | 8811 | /* Must be defined now because we're going to update it below, while |
| 8685 | defining the supported image types. */ | 8812 | defining the supported image types. */ |
| 8686 | DEFVAR_LISP ("image-types", Vimage_types, | 8813 | DEFVAR_LISP ("image-types", Vimage_types, |
| 8687 | doc: /* List of potentially supported image types. | 8814 | doc: /* List of potentially supported image types. |
| @@ -8829,8 +8956,17 @@ The value can also be nil, meaning the cache is never cleared. | |||
| 8829 | The function `clear-image-cache' disregards this variable. */); | 8956 | The function `clear-image-cache' disregards this variable. */); |
| 8830 | Vimage_cache_eviction_delay = make_number (300); | 8957 | Vimage_cache_eviction_delay = make_number (300); |
| 8831 | #ifdef HAVE_IMAGEMAGICK | 8958 | #ifdef HAVE_IMAGEMAGICK |
| 8832 | DEFVAR_LISP ("imagemagick-render-type", Vimagemagick_render_type, | 8959 | DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type, |
| 8833 | doc: /* Choose between ImageMagick render methods. */); | 8960 | doc: /* Integer indicating which ImageMagick rendering method to use. |
| 8961 | The options are: | ||
| 8962 | 0 -- the default method (pixel pushing) | ||
| 8963 | 1 -- a newer method ("MagickExportImagePixels") that may perform | ||
| 8964 | better (speed etc) in some cases, but has not been as thoroughly | ||
| 8965 | tested with Emacs as the default method. This method requires | ||
| 8966 | ImageMagick version 6.4.6 (approximately) or later. | ||
| 8967 | */); | ||
| 8968 | /* MagickExportImagePixels is in 6.4.6-9, but not 6.4.4-10. */ | ||
| 8969 | imagemagick_render_type = 0; | ||
| 8834 | #endif | 8970 | #endif |
| 8835 | 8971 | ||
| 8836 | } | 8972 | } |