diff options
| author | Stefan Monnier | 2010-09-13 16:40:48 +0200 |
|---|---|---|
| committer | Stefan Monnier | 2010-09-13 16:40:48 +0200 |
| commit | cc390e46c7ba95b76ea133d98fd386214cd01709 (patch) | |
| tree | ead4400d22bd07214b782ff7e46e79d473fac419 /src/image.c | |
| parent | c566235d981eba73c88bbff00b6a1d88360b6e9f (diff) | |
| parent | c5fe4acb5fb456d6e8e147d8bc7981ce56c5c03d (diff) | |
| download | emacs-cc390e46c7ba95b76ea133d98fd386214cd01709.tar.gz emacs-cc390e46c7ba95b76ea133d98fd386214cd01709.zip | |
Merge from trunk
Diffstat (limited to 'src/image.c')
| -rw-r--r-- | src/image.c | 710 |
1 files changed, 623 insertions, 87 deletions
diff --git a/src/image.c b/src/image.c index 916fcfe8178..499cbf298c1 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -583,7 +583,7 @@ Lisp_Object Qxbm; | |||
| 583 | 583 | ||
| 584 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; | 584 | Lisp_Object QCascent, QCmargin, QCrelief, Qcount, Qextension_data; |
| 585 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; | 585 | Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; |
| 586 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; | 586 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry, QCcrop, QCrotation; |
| 587 | 587 | ||
| 588 | /* Other symbols. */ | 588 | /* Other symbols. */ |
| 589 | 589 | ||
| @@ -1735,7 +1735,6 @@ lookup_image (struct frame *f, Lisp_Object spec) | |||
| 1735 | struct image_cache *c; | 1735 | struct image_cache *c; |
| 1736 | struct image *img; | 1736 | struct image *img; |
| 1737 | unsigned hash; | 1737 | unsigned hash; |
| 1738 | struct gcpro gcpro1; | ||
| 1739 | EMACS_TIME now; | 1738 | EMACS_TIME now; |
| 1740 | 1739 | ||
| 1741 | /* F must be a window-system frame, and SPEC must be a valid image | 1740 | /* F must be a window-system frame, and SPEC must be a valid image |
| @@ -1745,8 +1744,6 @@ lookup_image (struct frame *f, Lisp_Object spec) | |||
| 1745 | 1744 | ||
| 1746 | c = FRAME_IMAGE_CACHE (f); | 1745 | c = FRAME_IMAGE_CACHE (f); |
| 1747 | 1746 | ||
| 1748 | GCPRO1 (spec); | ||
| 1749 | |||
| 1750 | /* Look up SPEC in the hash table of the image cache. */ | 1747 | /* Look up SPEC in the hash table of the image cache. */ |
| 1751 | hash = sxhash (spec, 0); | 1748 | hash = sxhash (spec, 0); |
| 1752 | img = search_image_cache (f, spec, hash); | 1749 | img = search_image_cache (f, spec, hash); |
| @@ -1838,8 +1835,6 @@ lookup_image (struct frame *f, Lisp_Object spec) | |||
| 1838 | EMACS_GET_TIME (now); | 1835 | EMACS_GET_TIME (now); |
| 1839 | img->timestamp = EMACS_SECS (now); | 1836 | img->timestamp = EMACS_SECS (now); |
| 1840 | 1837 | ||
| 1841 | UNGCPRO; | ||
| 1842 | |||
| 1843 | /* Value is the image id. */ | 1838 | /* Value is the image id. */ |
| 1844 | return img->id; | 1839 | return img->id; |
| 1845 | } | 1840 | } |
| @@ -2179,16 +2174,13 @@ Lisp_Object | |||
| 2179 | x_find_image_file (Lisp_Object file) | 2174 | x_find_image_file (Lisp_Object file) |
| 2180 | { | 2175 | { |
| 2181 | Lisp_Object file_found, search_path; | 2176 | Lisp_Object file_found, search_path; |
| 2182 | struct gcpro gcpro1, gcpro2; | ||
| 2183 | int fd; | 2177 | int fd; |
| 2184 | 2178 | ||
| 2185 | file_found = Qnil; | ||
| 2186 | /* TODO I think this should use something like image-load-path | 2179 | /* TODO I think this should use something like image-load-path |
| 2187 | instead. Unfortunately, that can contain non-string elements. */ | 2180 | instead. Unfortunately, that can contain non-string elements. */ |
| 2188 | search_path = Fcons (Fexpand_file_name (build_string ("images"), | 2181 | search_path = Fcons (Fexpand_file_name (build_string ("images"), |
| 2189 | Vdata_directory), | 2182 | Vdata_directory), |
| 2190 | Vx_bitmap_file_path); | 2183 | Vx_bitmap_file_path); |
| 2191 | GCPRO2 (file_found, search_path); | ||
| 2192 | 2184 | ||
| 2193 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ | 2185 | /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ |
| 2194 | fd = openp (search_path, file, Qnil, &file_found, Qnil); | 2186 | fd = openp (search_path, file, Qnil, &file_found, Qnil); |
| @@ -2201,7 +2193,6 @@ x_find_image_file (Lisp_Object file) | |||
| 2201 | close (fd); | 2193 | close (fd); |
| 2202 | } | 2194 | } |
| 2203 | 2195 | ||
| 2204 | UNGCPRO; | ||
| 2205 | return file_found; | 2196 | return file_found; |
| 2206 | } | 2197 | } |
| 2207 | 2198 | ||
| @@ -2875,14 +2866,11 @@ xbm_load (struct frame *f, struct image *img) | |||
| 2875 | Lisp_Object file; | 2866 | Lisp_Object file; |
| 2876 | unsigned char *contents; | 2867 | unsigned char *contents; |
| 2877 | int size; | 2868 | int size; |
| 2878 | struct gcpro gcpro1; | ||
| 2879 | 2869 | ||
| 2880 | file = x_find_image_file (file_name); | 2870 | file = x_find_image_file (file_name); |
| 2881 | GCPRO1 (file); | ||
| 2882 | if (!STRINGP (file)) | 2871 | if (!STRINGP (file)) |
| 2883 | { | 2872 | { |
| 2884 | image_error ("Cannot find image file `%s'", file_name, Qnil); | 2873 | image_error ("Cannot find image file `%s'", file_name, Qnil); |
| 2885 | UNGCPRO; | ||
| 2886 | return 0; | 2874 | return 0; |
| 2887 | } | 2875 | } |
| 2888 | 2876 | ||
| @@ -2890,12 +2878,10 @@ xbm_load (struct frame *f, struct image *img) | |||
| 2890 | if (contents == NULL) | 2878 | if (contents == NULL) |
| 2891 | { | 2879 | { |
| 2892 | image_error ("Error loading XBM image `%s'", img->spec, Qnil); | 2880 | image_error ("Error loading XBM image `%s'", img->spec, Qnil); |
| 2893 | UNGCPRO; | ||
| 2894 | return 0; | 2881 | return 0; |
| 2895 | } | 2882 | } |
| 2896 | 2883 | ||
| 2897 | success_p = xbm_load_image (f, img, contents, contents + size); | 2884 | success_p = xbm_load_image (f, img, contents, contents + size); |
| 2898 | UNGCPRO; | ||
| 2899 | } | 2885 | } |
| 2900 | else | 2886 | else |
| 2901 | { | 2887 | { |
| @@ -3456,12 +3442,31 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3456 | CONSP (tail); | 3442 | CONSP (tail); |
| 3457 | ++i, tail = XCDR (tail)) | 3443 | ++i, tail = XCDR (tail)) |
| 3458 | { | 3444 | { |
| 3459 | Lisp_Object name = XCAR (XCAR (tail)); | 3445 | Lisp_Object name; |
| 3460 | Lisp_Object color = XCDR (XCAR (tail)); | 3446 | Lisp_Object color; |
| 3461 | xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1); | 3447 | |
| 3462 | strcpy (xpm_syms[i].name, SDATA (name)); | 3448 | if (!CONSP (XCAR (tail))) |
| 3463 | xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1); | 3449 | { |
| 3464 | strcpy (xpm_syms[i].value, SDATA (color)); | 3450 | xpm_syms[i].name = ""; |
| 3451 | xpm_syms[i].value = ""; | ||
| 3452 | continue; | ||
| 3453 | } | ||
| 3454 | name = XCAR (XCAR (tail)); | ||
| 3455 | color = XCDR (XCAR (tail)); | ||
| 3456 | if (STRINGP (name)) | ||
| 3457 | { | ||
| 3458 | xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1); | ||
| 3459 | strcpy (xpm_syms[i].name, SDATA (name)); | ||
| 3460 | } | ||
| 3461 | else | ||
| 3462 | xpm_syms[i].name = ""; | ||
| 3463 | if (STRINGP (color)) | ||
| 3464 | { | ||
| 3465 | xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1); | ||
| 3466 | strcpy (xpm_syms[i].value, SDATA (color)); | ||
| 3467 | } | ||
| 3468 | else | ||
| 3469 | xpm_syms[i].value = ""; | ||
| 3465 | } | 3470 | } |
| 3466 | } | 3471 | } |
| 3467 | 3472 | ||
| @@ -3487,6 +3492,9 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3487 | if (!STRINGP (file)) | 3492 | if (!STRINGP (file)) |
| 3488 | { | 3493 | { |
| 3489 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 3494 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 3495 | #ifdef ALLOC_XPM_COLORS | ||
| 3496 | xpm_free_color_cache (); | ||
| 3497 | #endif | ||
| 3490 | return 0; | 3498 | return 0; |
| 3491 | } | 3499 | } |
| 3492 | 3500 | ||
| @@ -3505,6 +3513,14 @@ xpm_load (struct frame *f, struct image *img) | |||
| 3505 | else | 3513 | else |
| 3506 | { | 3514 | { |
| 3507 | Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL); | 3515 | Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL); |
| 3516 | if (!STRINGP (buffer)) | ||
| 3517 | { | ||
| 3518 | image_error ("Invalid image data `%s'", buffer, Qnil); | ||
| 3519 | #ifdef ALLOC_XPM_COLORS | ||
| 3520 | xpm_free_color_cache (); | ||
| 3521 | #endif | ||
| 3522 | return 0; | ||
| 3523 | } | ||
| 3508 | #ifdef HAVE_NTGUI | 3524 | #ifdef HAVE_NTGUI |
| 3509 | /* XpmCreatePixmapFromBuffer is not available in the Windows port | 3525 | /* XpmCreatePixmapFromBuffer is not available in the Windows port |
| 3510 | of libxpm. But XpmCreateImageFromBuffer almost does what we want. */ | 3526 | of libxpm. But XpmCreateImageFromBuffer almost does what we want. */ |
| @@ -4071,14 +4087,11 @@ xpm_load (struct frame *f, | |||
| 4071 | Lisp_Object file; | 4087 | Lisp_Object file; |
| 4072 | unsigned char *contents; | 4088 | unsigned char *contents; |
| 4073 | int size; | 4089 | int size; |
| 4074 | struct gcpro gcpro1; | ||
| 4075 | 4090 | ||
| 4076 | file = x_find_image_file (file_name); | 4091 | file = x_find_image_file (file_name); |
| 4077 | GCPRO1 (file); | ||
| 4078 | if (!STRINGP (file)) | 4092 | if (!STRINGP (file)) |
| 4079 | { | 4093 | { |
| 4080 | image_error ("Cannot find image file `%s'", file_name, Qnil); | 4094 | image_error ("Cannot find image file `%s'", file_name, Qnil); |
| 4081 | UNGCPRO; | ||
| 4082 | return 0; | 4095 | return 0; |
| 4083 | } | 4096 | } |
| 4084 | 4097 | ||
| @@ -4086,19 +4099,22 @@ xpm_load (struct frame *f, | |||
| 4086 | if (contents == NULL) | 4099 | if (contents == NULL) |
| 4087 | { | 4100 | { |
| 4088 | image_error ("Error loading XPM image `%s'", img->spec, Qnil); | 4101 | image_error ("Error loading XPM image `%s'", img->spec, Qnil); |
| 4089 | UNGCPRO; | ||
| 4090 | return 0; | 4102 | return 0; |
| 4091 | } | 4103 | } |
| 4092 | 4104 | ||
| 4093 | success_p = xpm_load_image (f, img, contents, contents + size); | 4105 | success_p = xpm_load_image (f, img, contents, contents + size); |
| 4094 | xfree (contents); | 4106 | xfree (contents); |
| 4095 | UNGCPRO; | ||
| 4096 | } | 4107 | } |
| 4097 | else | 4108 | else |
| 4098 | { | 4109 | { |
| 4099 | Lisp_Object data; | 4110 | Lisp_Object data; |
| 4100 | 4111 | ||
| 4101 | data = image_spec_value (img->spec, QCdata, NULL); | 4112 | data = image_spec_value (img->spec, QCdata, NULL); |
| 4113 | if (!STRINGP (data)) | ||
| 4114 | { | ||
| 4115 | image_error ("Invalid image data `%s'", data, Qnil); | ||
| 4116 | return 0; | ||
| 4117 | } | ||
| 4102 | success_p = xpm_load_image (f, img, SDATA (data), | 4118 | success_p = xpm_load_image (f, img, SDATA (data), |
| 4103 | SDATA (data) + SBYTES (data)); | 4119 | SDATA (data) + SBYTES (data)); |
| 4104 | } | 4120 | } |
| @@ -5090,14 +5106,11 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5090 | XImagePtr ximg; | 5106 | XImagePtr ximg; |
| 5091 | Lisp_Object file, specified_file; | 5107 | Lisp_Object file, specified_file; |
| 5092 | enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; | 5108 | enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; |
| 5093 | struct gcpro gcpro1; | ||
| 5094 | unsigned char *contents = NULL; | 5109 | unsigned char *contents = NULL; |
| 5095 | unsigned char *end, *p; | 5110 | unsigned char *end, *p; |
| 5096 | int size; | 5111 | int size; |
| 5097 | 5112 | ||
| 5098 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 5113 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 5099 | file = Qnil; | ||
| 5100 | GCPRO1 (file); | ||
| 5101 | 5114 | ||
| 5102 | if (STRINGP (specified_file)) | 5115 | if (STRINGP (specified_file)) |
| 5103 | { | 5116 | { |
| @@ -5105,7 +5118,6 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5105 | if (!STRINGP (file)) | 5118 | if (!STRINGP (file)) |
| 5106 | { | 5119 | { |
| 5107 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 5120 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 5108 | UNGCPRO; | ||
| 5109 | return 0; | 5121 | return 0; |
| 5110 | } | 5122 | } |
| 5111 | 5123 | ||
| @@ -5113,7 +5125,6 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5113 | if (contents == NULL) | 5125 | if (contents == NULL) |
| 5114 | { | 5126 | { |
| 5115 | image_error ("Error reading `%s'", file, Qnil); | 5127 | image_error ("Error reading `%s'", file, Qnil); |
| 5116 | UNGCPRO; | ||
| 5117 | return 0; | 5128 | return 0; |
| 5118 | } | 5129 | } |
| 5119 | 5130 | ||
| @@ -5124,6 +5135,11 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5124 | { | 5135 | { |
| 5125 | Lisp_Object data; | 5136 | Lisp_Object data; |
| 5126 | data = image_spec_value (img->spec, QCdata, NULL); | 5137 | data = image_spec_value (img->spec, QCdata, NULL); |
| 5138 | if (!STRINGP (data)) | ||
| 5139 | { | ||
| 5140 | image_error ("Invalid image data `%s'", data, Qnil); | ||
| 5141 | return 0; | ||
| 5142 | } | ||
| 5127 | p = SDATA (data); | 5143 | p = SDATA (data); |
| 5128 | end = p + SBYTES (data); | 5144 | end = p + SBYTES (data); |
| 5129 | } | 5145 | } |
| @@ -5134,7 +5150,6 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5134 | image_error ("Not a PBM image: `%s'", img->spec, Qnil); | 5150 | image_error ("Not a PBM image: `%s'", img->spec, Qnil); |
| 5135 | error: | 5151 | error: |
| 5136 | xfree (contents); | 5152 | xfree (contents); |
| 5137 | UNGCPRO; | ||
| 5138 | return 0; | 5153 | return 0; |
| 5139 | } | 5154 | } |
| 5140 | 5155 | ||
| @@ -5336,7 +5351,6 @@ pbm_load (struct frame *f, struct image *img) | |||
| 5336 | img->width = width; | 5351 | img->width = width; |
| 5337 | img->height = height; */ | 5352 | img->height = height; */ |
| 5338 | 5353 | ||
| 5339 | UNGCPRO; | ||
| 5340 | xfree (contents); | 5354 | xfree (contents); |
| 5341 | return 1; | 5355 | return 1; |
| 5342 | } | 5356 | } |
| @@ -5576,7 +5590,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5576 | Lisp_Object specified_data; | 5590 | Lisp_Object specified_data; |
| 5577 | int x, y, i; | 5591 | int x, y, i; |
| 5578 | XImagePtr ximg, mask_img = NULL; | 5592 | XImagePtr ximg, mask_img = NULL; |
| 5579 | struct gcpro gcpro1; | ||
| 5580 | png_struct *png_ptr = NULL; | 5593 | png_struct *png_ptr = NULL; |
| 5581 | png_info *info_ptr = NULL, *end_info = NULL; | 5594 | png_info *info_ptr = NULL, *end_info = NULL; |
| 5582 | FILE *volatile fp = NULL; | 5595 | FILE *volatile fp = NULL; |
| @@ -5593,8 +5606,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5593 | /* Find out what file to load. */ | 5606 | /* Find out what file to load. */ |
| 5594 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 5607 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 5595 | specified_data = image_spec_value (img->spec, QCdata, NULL); | 5608 | specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 5596 | file = Qnil; | ||
| 5597 | GCPRO1 (file); | ||
| 5598 | 5609 | ||
| 5599 | if (NILP (specified_data)) | 5610 | if (NILP (specified_data)) |
| 5600 | { | 5611 | { |
| @@ -5602,7 +5613,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5602 | if (!STRINGP (file)) | 5613 | if (!STRINGP (file)) |
| 5603 | { | 5614 | { |
| 5604 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 5615 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 5605 | UNGCPRO; | ||
| 5606 | return 0; | 5616 | return 0; |
| 5607 | } | 5617 | } |
| 5608 | 5618 | ||
| @@ -5611,7 +5621,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5611 | if (!fp) | 5621 | if (!fp) |
| 5612 | { | 5622 | { |
| 5613 | image_error ("Cannot open image file `%s'", file, Qnil); | 5623 | image_error ("Cannot open image file `%s'", file, Qnil); |
| 5614 | UNGCPRO; | ||
| 5615 | return 0; | 5624 | return 0; |
| 5616 | } | 5625 | } |
| 5617 | 5626 | ||
| @@ -5620,13 +5629,18 @@ png_load (struct frame *f, struct image *img) | |||
| 5620 | || fn_png_sig_cmp (sig, 0, sizeof sig)) | 5629 | || fn_png_sig_cmp (sig, 0, sizeof sig)) |
| 5621 | { | 5630 | { |
| 5622 | image_error ("Not a PNG file: `%s'", file, Qnil); | 5631 | image_error ("Not a PNG file: `%s'", file, Qnil); |
| 5623 | UNGCPRO; | ||
| 5624 | fclose (fp); | 5632 | fclose (fp); |
| 5625 | return 0; | 5633 | return 0; |
| 5626 | } | 5634 | } |
| 5627 | } | 5635 | } |
| 5628 | else | 5636 | else |
| 5629 | { | 5637 | { |
| 5638 | if (!STRINGP (specified_data)) | ||
| 5639 | { | ||
| 5640 | image_error ("Invalid image data `%s'", specified_data, Qnil); | ||
| 5641 | return 0; | ||
| 5642 | } | ||
| 5643 | |||
| 5630 | /* Read from memory. */ | 5644 | /* Read from memory. */ |
| 5631 | tbr.bytes = SDATA (specified_data); | 5645 | tbr.bytes = SDATA (specified_data); |
| 5632 | tbr.len = SBYTES (specified_data); | 5646 | tbr.len = SBYTES (specified_data); |
| @@ -5637,7 +5651,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5637 | || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig)) | 5651 | || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig)) |
| 5638 | { | 5652 | { |
| 5639 | image_error ("Not a PNG image: `%s'", img->spec, Qnil); | 5653 | image_error ("Not a PNG image: `%s'", img->spec, Qnil); |
| 5640 | UNGCPRO; | ||
| 5641 | return 0; | 5654 | return 0; |
| 5642 | } | 5655 | } |
| 5643 | 5656 | ||
| @@ -5653,7 +5666,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5653 | if (!png_ptr) | 5666 | if (!png_ptr) |
| 5654 | { | 5667 | { |
| 5655 | if (fp) fclose (fp); | 5668 | if (fp) fclose (fp); |
| 5656 | UNGCPRO; | ||
| 5657 | return 0; | 5669 | return 0; |
| 5658 | } | 5670 | } |
| 5659 | 5671 | ||
| @@ -5663,7 +5675,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5663 | { | 5675 | { |
| 5664 | fn_png_destroy_read_struct (&png_ptr, NULL, NULL); | 5676 | fn_png_destroy_read_struct (&png_ptr, NULL, NULL); |
| 5665 | if (fp) fclose (fp); | 5677 | if (fp) fclose (fp); |
| 5666 | UNGCPRO; | ||
| 5667 | return 0; | 5678 | return 0; |
| 5668 | } | 5679 | } |
| 5669 | 5680 | ||
| @@ -5673,7 +5684,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5673 | { | 5684 | { |
| 5674 | fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL); | 5685 | fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL); |
| 5675 | if (fp) fclose (fp); | 5686 | if (fp) fclose (fp); |
| 5676 | UNGCPRO; | ||
| 5677 | return 0; | 5687 | return 0; |
| 5678 | } | 5688 | } |
| 5679 | 5689 | ||
| @@ -5687,7 +5697,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5687 | xfree (pixels); | 5697 | xfree (pixels); |
| 5688 | xfree (rows); | 5698 | xfree (rows); |
| 5689 | if (fp) fclose (fp); | 5699 | if (fp) fclose (fp); |
| 5690 | UNGCPRO; | ||
| 5691 | return 0; | 5700 | return 0; |
| 5692 | } | 5701 | } |
| 5693 | 5702 | ||
| @@ -5912,7 +5921,6 @@ png_load (struct frame *f, struct image *img) | |||
| 5912 | x_destroy_x_image (mask_img); | 5921 | x_destroy_x_image (mask_img); |
| 5913 | } | 5922 | } |
| 5914 | 5923 | ||
| 5915 | UNGCPRO; | ||
| 5916 | return 1; | 5924 | return 1; |
| 5917 | } | 5925 | } |
| 5918 | 5926 | ||
| @@ -6313,13 +6321,10 @@ jpeg_load (struct frame *f, struct image *img) | |||
| 6313 | int rc; | 6321 | int rc; |
| 6314 | unsigned long *colors; | 6322 | unsigned long *colors; |
| 6315 | int width, height; | 6323 | int width, height; |
| 6316 | struct gcpro gcpro1; | ||
| 6317 | 6324 | ||
| 6318 | /* Open the JPEG file. */ | 6325 | /* Open the JPEG file. */ |
| 6319 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 6326 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 6320 | specified_data = image_spec_value (img->spec, QCdata, NULL); | 6327 | specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 6321 | file = Qnil; | ||
| 6322 | GCPRO1 (file); | ||
| 6323 | 6328 | ||
| 6324 | if (NILP (specified_data)) | 6329 | if (NILP (specified_data)) |
| 6325 | { | 6330 | { |
| @@ -6327,7 +6332,6 @@ jpeg_load (struct frame *f, struct image *img) | |||
| 6327 | if (!STRINGP (file)) | 6332 | if (!STRINGP (file)) |
| 6328 | { | 6333 | { |
| 6329 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 6334 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 6330 | UNGCPRO; | ||
| 6331 | return 0; | 6335 | return 0; |
| 6332 | } | 6336 | } |
| 6333 | 6337 | ||
| @@ -6335,10 +6339,14 @@ jpeg_load (struct frame *f, struct image *img) | |||
| 6335 | if (fp == NULL) | 6339 | if (fp == NULL) |
| 6336 | { | 6340 | { |
| 6337 | image_error ("Cannot open `%s'", file, Qnil); | 6341 | image_error ("Cannot open `%s'", file, Qnil); |
| 6338 | UNGCPRO; | ||
| 6339 | return 0; | 6342 | return 0; |
| 6340 | } | 6343 | } |
| 6341 | } | 6344 | } |
| 6345 | else if (!STRINGP (specified_data)) | ||
| 6346 | { | ||
| 6347 | image_error ("Invalid image data `%s'", specified_data, Qnil); | ||
| 6348 | return 0; | ||
| 6349 | } | ||
| 6342 | 6350 | ||
| 6343 | /* Customize libjpeg's error handling to call my_error_exit when an | 6351 | /* Customize libjpeg's error handling to call my_error_exit when an |
| 6344 | error is detected. This function will perform a longjmp. | 6352 | error is detected. This function will perform a longjmp. |
| @@ -6367,8 +6375,6 @@ jpeg_load (struct frame *f, struct image *img) | |||
| 6367 | 6375 | ||
| 6368 | /* Free pixmap and colors. */ | 6376 | /* Free pixmap and colors. */ |
| 6369 | x_clear_image (f, img); | 6377 | x_clear_image (f, img); |
| 6370 | |||
| 6371 | UNGCPRO; | ||
| 6372 | return 0; | 6378 | return 0; |
| 6373 | } | 6379 | } |
| 6374 | 6380 | ||
| @@ -6466,7 +6472,6 @@ jpeg_load (struct frame *f, struct image *img) | |||
| 6466 | /* Put the image into the pixmap. */ | 6472 | /* Put the image into the pixmap. */ |
| 6467 | x_put_x_image (f, ximg, img->pixmap, width, height); | 6473 | x_put_x_image (f, ximg, img->pixmap, width, height); |
| 6468 | x_destroy_x_image (ximg); | 6474 | x_destroy_x_image (ximg); |
| 6469 | UNGCPRO; | ||
| 6470 | return 1; | 6475 | return 1; |
| 6471 | } | 6476 | } |
| 6472 | 6477 | ||
| @@ -6741,14 +6746,11 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6741 | uint32 *buf; | 6746 | uint32 *buf; |
| 6742 | int rc, rc2; | 6747 | int rc, rc2; |
| 6743 | XImagePtr ximg; | 6748 | XImagePtr ximg; |
| 6744 | struct gcpro gcpro1; | ||
| 6745 | tiff_memory_source memsrc; | 6749 | tiff_memory_source memsrc; |
| 6746 | Lisp_Object image; | 6750 | Lisp_Object image; |
| 6747 | 6751 | ||
| 6748 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 6752 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 6749 | specified_data = image_spec_value (img->spec, QCdata, NULL); | 6753 | specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 6750 | file = Qnil; | ||
| 6751 | GCPRO1 (file); | ||
| 6752 | 6754 | ||
| 6753 | fn_TIFFSetErrorHandler (tiff_error_handler); | 6755 | fn_TIFFSetErrorHandler (tiff_error_handler); |
| 6754 | fn_TIFFSetWarningHandler (tiff_warning_handler); | 6756 | fn_TIFFSetWarningHandler (tiff_warning_handler); |
| @@ -6760,7 +6762,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6760 | if (!STRINGP (file)) | 6762 | if (!STRINGP (file)) |
| 6761 | { | 6763 | { |
| 6762 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 6764 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 6763 | UNGCPRO; | ||
| 6764 | return 0; | 6765 | return 0; |
| 6765 | } | 6766 | } |
| 6766 | 6767 | ||
| @@ -6770,12 +6771,17 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6770 | if (tiff == NULL) | 6771 | if (tiff == NULL) |
| 6771 | { | 6772 | { |
| 6772 | image_error ("Cannot open `%s'", file, Qnil); | 6773 | image_error ("Cannot open `%s'", file, Qnil); |
| 6773 | UNGCPRO; | ||
| 6774 | return 0; | 6774 | return 0; |
| 6775 | } | 6775 | } |
| 6776 | } | 6776 | } |
| 6777 | else | 6777 | else |
| 6778 | { | 6778 | { |
| 6779 | if (!STRINGP (specified_data)) | ||
| 6780 | { | ||
| 6781 | image_error ("Invalid image data `%s'", specified_data, Qnil); | ||
| 6782 | return 0; | ||
| 6783 | } | ||
| 6784 | |||
| 6779 | /* Memory source! */ | 6785 | /* Memory source! */ |
| 6780 | memsrc.bytes = SDATA (specified_data); | 6786 | memsrc.bytes = SDATA (specified_data); |
| 6781 | memsrc.len = SBYTES (specified_data); | 6787 | memsrc.len = SBYTES (specified_data); |
| @@ -6794,7 +6800,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6794 | if (!tiff) | 6800 | if (!tiff) |
| 6795 | { | 6801 | { |
| 6796 | image_error ("Cannot open memory source for `%s'", img->spec, Qnil); | 6802 | image_error ("Cannot open memory source for `%s'", img->spec, Qnil); |
| 6797 | UNGCPRO; | ||
| 6798 | return 0; | 6803 | return 0; |
| 6799 | } | 6804 | } |
| 6800 | } | 6805 | } |
| @@ -6808,7 +6813,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6808 | image_error ("Invalid image number `%s' in image `%s'", | 6813 | image_error ("Invalid image number `%s' in image `%s'", |
| 6809 | image, img->spec); | 6814 | image, img->spec); |
| 6810 | fn_TIFFClose (tiff); | 6815 | fn_TIFFClose (tiff); |
| 6811 | UNGCPRO; | ||
| 6812 | return 0; | 6816 | return 0; |
| 6813 | } | 6817 | } |
| 6814 | } | 6818 | } |
| @@ -6822,7 +6826,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6822 | { | 6826 | { |
| 6823 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 6827 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 6824 | fn_TIFFClose (tiff); | 6828 | fn_TIFFClose (tiff); |
| 6825 | UNGCPRO; | ||
| 6826 | return 0; | 6829 | return 0; |
| 6827 | } | 6830 | } |
| 6828 | 6831 | ||
| @@ -6844,7 +6847,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6844 | { | 6847 | { |
| 6845 | image_error ("Error reading TIFF image `%s'", img->spec, Qnil); | 6848 | image_error ("Error reading TIFF image `%s'", img->spec, Qnil); |
| 6846 | xfree (buf); | 6849 | xfree (buf); |
| 6847 | UNGCPRO; | ||
| 6848 | return 0; | 6850 | return 0; |
| 6849 | } | 6851 | } |
| 6850 | 6852 | ||
| @@ -6852,7 +6854,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6852 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 6854 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 6853 | { | 6855 | { |
| 6854 | xfree (buf); | 6856 | xfree (buf); |
| 6855 | UNGCPRO; | ||
| 6856 | return 0; | 6857 | return 0; |
| 6857 | } | 6858 | } |
| 6858 | 6859 | ||
| @@ -6893,7 +6894,6 @@ tiff_load (struct frame *f, struct image *img) | |||
| 6893 | x_destroy_x_image (ximg); | 6894 | x_destroy_x_image (ximg); |
| 6894 | xfree (buf); | 6895 | xfree (buf); |
| 6895 | 6896 | ||
| 6896 | UNGCPRO; | ||
| 6897 | return 1; | 6897 | return 1; |
| 6898 | } | 6898 | } |
| 6899 | 6899 | ||
| @@ -7099,7 +7099,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7099 | ColorMapObject *gif_color_map; | 7099 | ColorMapObject *gif_color_map; |
| 7100 | unsigned long pixel_colors[256]; | 7100 | unsigned long pixel_colors[256]; |
| 7101 | GifFileType *gif; | 7101 | GifFileType *gif; |
| 7102 | struct gcpro gcpro1; | ||
| 7103 | Lisp_Object image; | 7102 | Lisp_Object image; |
| 7104 | int ino, image_height, image_width; | 7103 | int ino, image_height, image_width; |
| 7105 | gif_memory_source memsrc; | 7104 | gif_memory_source memsrc; |
| @@ -7107,8 +7106,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7107 | 7106 | ||
| 7108 | specified_file = image_spec_value (img->spec, QCfile, NULL); | 7107 | specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 7109 | specified_data = image_spec_value (img->spec, QCdata, NULL); | 7108 | specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 7110 | file = Qnil; | ||
| 7111 | GCPRO1 (file); | ||
| 7112 | 7109 | ||
| 7113 | if (NILP (specified_data)) | 7110 | if (NILP (specified_data)) |
| 7114 | { | 7111 | { |
| @@ -7116,7 +7113,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7116 | if (!STRINGP (file)) | 7113 | if (!STRINGP (file)) |
| 7117 | { | 7114 | { |
| 7118 | image_error ("Cannot find image file `%s'", specified_file, Qnil); | 7115 | image_error ("Cannot find image file `%s'", specified_file, Qnil); |
| 7119 | UNGCPRO; | ||
| 7120 | return 0; | 7116 | return 0; |
| 7121 | } | 7117 | } |
| 7122 | 7118 | ||
| @@ -7126,12 +7122,17 @@ gif_load (struct frame *f, struct image *img) | |||
| 7126 | if (gif == NULL) | 7122 | if (gif == NULL) |
| 7127 | { | 7123 | { |
| 7128 | image_error ("Cannot open `%s'", file, Qnil); | 7124 | image_error ("Cannot open `%s'", file, Qnil); |
| 7129 | UNGCPRO; | ||
| 7130 | return 0; | 7125 | return 0; |
| 7131 | } | 7126 | } |
| 7132 | } | 7127 | } |
| 7133 | else | 7128 | else |
| 7134 | { | 7129 | { |
| 7130 | if (!STRINGP (specified_data)) | ||
| 7131 | { | ||
| 7132 | image_error ("Invalid image data `%s'", specified_data, Qnil); | ||
| 7133 | return 0; | ||
| 7134 | } | ||
| 7135 | |||
| 7135 | /* Read from memory! */ | 7136 | /* Read from memory! */ |
| 7136 | current_gif_memory_src = &memsrc; | 7137 | current_gif_memory_src = &memsrc; |
| 7137 | memsrc.bytes = SDATA (specified_data); | 7138 | memsrc.bytes = SDATA (specified_data); |
| @@ -7143,7 +7144,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7143 | if (!gif) | 7144 | if (!gif) |
| 7144 | { | 7145 | { |
| 7145 | image_error ("Cannot open memory source `%s'", img->spec, Qnil); | 7146 | image_error ("Cannot open memory source `%s'", img->spec, Qnil); |
| 7146 | UNGCPRO; | ||
| 7147 | return 0; | 7147 | return 0; |
| 7148 | } | 7148 | } |
| 7149 | } | 7149 | } |
| @@ -7153,7 +7153,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7153 | { | 7153 | { |
| 7154 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 7154 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 7155 | fn_DGifCloseFile (gif); | 7155 | fn_DGifCloseFile (gif); |
| 7156 | UNGCPRO; | ||
| 7157 | return 0; | 7156 | return 0; |
| 7158 | } | 7157 | } |
| 7159 | 7158 | ||
| @@ -7163,7 +7162,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7163 | { | 7162 | { |
| 7164 | image_error ("Error reading `%s'", img->spec, Qnil); | 7163 | image_error ("Error reading `%s'", img->spec, Qnil); |
| 7165 | fn_DGifCloseFile (gif); | 7164 | fn_DGifCloseFile (gif); |
| 7166 | UNGCPRO; | ||
| 7167 | return 0; | 7165 | return 0; |
| 7168 | } | 7166 | } |
| 7169 | 7167 | ||
| @@ -7174,7 +7172,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7174 | image_error ("Invalid image number `%s' in image `%s'", | 7172 | image_error ("Invalid image number `%s' in image `%s'", |
| 7175 | image, img->spec); | 7173 | image, img->spec); |
| 7176 | fn_DGifCloseFile (gif); | 7174 | fn_DGifCloseFile (gif); |
| 7177 | UNGCPRO; | ||
| 7178 | return 0; | 7175 | return 0; |
| 7179 | } | 7176 | } |
| 7180 | 7177 | ||
| @@ -7196,7 +7193,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7196 | { | 7193 | { |
| 7197 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | 7194 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); |
| 7198 | fn_DGifCloseFile (gif); | 7195 | fn_DGifCloseFile (gif); |
| 7199 | UNGCPRO; | ||
| 7200 | return 0; | 7196 | return 0; |
| 7201 | } | 7197 | } |
| 7202 | 7198 | ||
| @@ -7204,7 +7200,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7204 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) | 7200 | if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) |
| 7205 | { | 7201 | { |
| 7206 | fn_DGifCloseFile (gif); | 7202 | fn_DGifCloseFile (gif); |
| 7207 | UNGCPRO; | ||
| 7208 | return 0; | 7203 | return 0; |
| 7209 | } | 7204 | } |
| 7210 | 7205 | ||
| @@ -7323,7 +7318,6 @@ gif_load (struct frame *f, struct image *img) | |||
| 7323 | x_put_x_image (f, ximg, img->pixmap, width, height); | 7318 | x_put_x_image (f, ximg, img->pixmap, width, height); |
| 7324 | x_destroy_x_image (ximg); | 7319 | x_destroy_x_image (ximg); |
| 7325 | 7320 | ||
| 7326 | UNGCPRO; | ||
| 7327 | return 1; | 7321 | return 1; |
| 7328 | } | 7322 | } |
| 7329 | 7323 | ||
| @@ -7342,6 +7336,522 @@ gif_load (struct frame *f, struct image *img) | |||
| 7342 | #endif /* HAVE_GIF */ | 7336 | #endif /* HAVE_GIF */ |
| 7343 | 7337 | ||
| 7344 | 7338 | ||
| 7339 | /*********************************************************************** | ||
| 7340 | imagemagick | ||
| 7341 | ***********************************************************************/ | ||
| 7342 | #if defined (HAVE_IMAGEMAGICK) | ||
| 7343 | Lisp_Object Vimagemagick_render_type; | ||
| 7344 | |||
| 7345 | /* The symbol `imagemagick' identifying images of this type. */ | ||
| 7346 | |||
| 7347 | Lisp_Object Qimagemagick; | ||
| 7348 | Lisp_Object Vimagemagick_render_type; | ||
| 7349 | |||
| 7350 | /* Indices of image specification fields in imagemagick_format, below. */ | ||
| 7351 | |||
| 7352 | enum imagemagick_keyword_index | ||
| 7353 | { | ||
| 7354 | IMAGEMAGICK_TYPE, | ||
| 7355 | IMAGEMAGICK_DATA, | ||
| 7356 | IMAGEMAGICK_FILE, | ||
| 7357 | IMAGEMAGICK_ASCENT, | ||
| 7358 | IMAGEMAGICK_MARGIN, | ||
| 7359 | IMAGEMAGICK_RELIEF, | ||
| 7360 | IMAGEMAGICK_ALGORITHM, | ||
| 7361 | IMAGEMAGICK_HEURISTIC_MASK, | ||
| 7362 | IMAGEMAGICK_MASK, | ||
| 7363 | IMAGEMAGICK_BACKGROUND, | ||
| 7364 | IMAGEMAGICK_HEIGHT, | ||
| 7365 | IMAGEMAGICK_WIDTH, | ||
| 7366 | IMAGEMAGICK_ROTATION, | ||
| 7367 | IMAGEMAGICK_CROP, | ||
| 7368 | IMAGEMAGICK_LAST | ||
| 7369 | }; | ||
| 7370 | |||
| 7371 | /* Vector of image_keyword structures describing the format | ||
| 7372 | of valid user-defined image specifications. */ | ||
| 7373 | |||
| 7374 | static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = | ||
| 7375 | { | ||
| 7376 | {":type", IMAGE_SYMBOL_VALUE, 1}, | ||
| 7377 | {":data", IMAGE_STRING_VALUE, 0}, | ||
| 7378 | {":file", IMAGE_STRING_VALUE, 0}, | ||
| 7379 | {":ascent", IMAGE_ASCENT_VALUE, 0}, | ||
| 7380 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0}, | ||
| 7381 | {":relief", IMAGE_INTEGER_VALUE, 0}, | ||
| 7382 | {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7383 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7384 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 7385 | {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, | ||
| 7386 | {":height", IMAGE_INTEGER_VALUE, 0}, | ||
| 7387 | {":width", IMAGE_INTEGER_VALUE, 0}, | ||
| 7388 | {":rotation", IMAGE_NUMBER_VALUE, 0}, | ||
| 7389 | {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 7390 | }; | ||
| 7391 | /* Free X resources of imagemagick image IMG which is used on frame F. */ | ||
| 7392 | |||
| 7393 | static void | ||
| 7394 | imagemagick_clear_image (struct frame *f, | ||
| 7395 | struct image *img) | ||
| 7396 | { | ||
| 7397 | x_clear_image (f, img); | ||
| 7398 | } | ||
| 7399 | |||
| 7400 | |||
| 7401 | |||
| 7402 | /* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do | ||
| 7403 | this by calling parse_image_spec and supplying the keywords that | ||
| 7404 | identify the IMAGEMAGICK format. */ | ||
| 7405 | |||
| 7406 | static int | ||
| 7407 | imagemagick_image_p (Lisp_Object object) | ||
| 7408 | { | ||
| 7409 | struct image_keyword fmt[IMAGEMAGICK_LAST]; | ||
| 7410 | memcpy (fmt, imagemagick_format, sizeof fmt); | ||
| 7411 | |||
| 7412 | if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick)) | ||
| 7413 | return 0; | ||
| 7414 | |||
| 7415 | /* Must specify either the :data or :file keyword. */ | ||
| 7416 | return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1; | ||
| 7417 | } | ||
| 7418 | |||
| 7419 | /* The GIF library also defines DrawRectangle, but its never used in Emacs. | ||
| 7420 | Therefore rename the function so it doesnt collide with ImageMagick. */ | ||
| 7421 | #define DrawRectangle DrawRectangleGif | ||
| 7422 | #include <wand/MagickWand.h> | ||
| 7423 | |||
| 7424 | /* imagemagick_load_image is a helper function for imagemagick_load, | ||
| 7425 | which does the actual loading given contents and size, apart from | ||
| 7426 | frame and image structures, passed from imagemagick_load. | ||
| 7427 | |||
| 7428 | Uses librimagemagick to do most of the image processing. | ||
| 7429 | |||
| 7430 | non-zero when successful. | ||
| 7431 | */ | ||
| 7432 | |||
| 7433 | static int | ||
| 7434 | imagemagick_load_image (/* Pointer to emacs frame structure. */ | ||
| 7435 | struct frame *f, | ||
| 7436 | /* Pointer to emacs image structure. */ | ||
| 7437 | struct image *img, | ||
| 7438 | /* String containing the IMAGEMAGICK data to | ||
| 7439 | be parsed. */ | ||
| 7440 | unsigned char *contents, | ||
| 7441 | /* Size of data in bytes. */ | ||
| 7442 | unsigned int size, | ||
| 7443 | /* Filename, either pass filename or | ||
| 7444 | contents/size. */ | ||
| 7445 | unsigned char *filename) | ||
| 7446 | { | ||
| 7447 | unsigned long width; | ||
| 7448 | unsigned long height; | ||
| 7449 | |||
| 7450 | MagickBooleanType | ||
| 7451 | status; | ||
| 7452 | |||
| 7453 | XImagePtr ximg; | ||
| 7454 | Lisp_Object specified_bg; | ||
| 7455 | XColor background; | ||
| 7456 | int x; | ||
| 7457 | int y; | ||
| 7458 | |||
| 7459 | MagickWand *image_wand; | ||
| 7460 | MagickWand *ping_wand; | ||
| 7461 | PixelIterator *iterator; | ||
| 7462 | PixelWand **pixels; | ||
| 7463 | MagickPixelPacket pixel; | ||
| 7464 | Lisp_Object image; | ||
| 7465 | Lisp_Object value; | ||
| 7466 | Lisp_Object crop, geometry; | ||
| 7467 | long ino; | ||
| 7468 | int desired_width, desired_height; | ||
| 7469 | double rotation; | ||
| 7470 | int imagemagick_rendermethod; | ||
| 7471 | int pixelwidth; | ||
| 7472 | ImageInfo *image_info; | ||
| 7473 | ExceptionInfo *exception; | ||
| 7474 | Image * im_image; | ||
| 7475 | |||
| 7476 | |||
| 7477 | /* Handle image index for image types who can contain more than one | ||
| 7478 | image. Interface :index is same as for GIF. First we "ping" the | ||
| 7479 | image to see how many sub-images it contains. Pinging is faster | ||
| 7480 | than loading the image to find out things about it. */ | ||
| 7481 | image = image_spec_value (img->spec, QCindex, NULL); | ||
| 7482 | ino = INTEGERP (image) ? XFASTINT (image) : 0; | ||
| 7483 | ping_wand = NewMagickWand (); | ||
| 7484 | MagickSetResolution (ping_wand, 2, 2); | ||
| 7485 | if (filename != NULL) | ||
| 7486 | { | ||
| 7487 | status = MagickPingImage (ping_wand, filename); | ||
| 7488 | } | ||
| 7489 | else | ||
| 7490 | { | ||
| 7491 | status = MagickPingImageBlob (ping_wand, contents, size); | ||
| 7492 | } | ||
| 7493 | |||
| 7494 | if (ino >= MagickGetNumberImages (ping_wand)) | ||
| 7495 | { | ||
| 7496 | image_error ("Invalid image number `%s' in image `%s'", | ||
| 7497 | image, img->spec); | ||
| 7498 | DestroyMagickWand (ping_wand); | ||
| 7499 | return 0; | ||
| 7500 | } | ||
| 7501 | |||
| 7502 | if (MagickGetNumberImages(ping_wand) > 1) | ||
| 7503 | img->data.lisp_val = | ||
| 7504 | Fcons (Qcount, | ||
| 7505 | Fcons (make_number (MagickGetNumberImages (ping_wand)), | ||
| 7506 | img->data.lisp_val)); | ||
| 7507 | |||
| 7508 | DestroyMagickWand (ping_wand); | ||
| 7509 | /* Now, after pinging, we know how many images are inside the | ||
| 7510 | file. If its not a bundle, just one. */ | ||
| 7511 | |||
| 7512 | if (filename != NULL) | ||
| 7513 | { | ||
| 7514 | image_info = CloneImageInfo ((ImageInfo *) NULL); | ||
| 7515 | (void) strcpy (image_info->filename, filename); | ||
| 7516 | image_info->number_scenes = 1; | ||
| 7517 | image_info->scene = ino; | ||
| 7518 | exception = AcquireExceptionInfo (); | ||
| 7519 | |||
| 7520 | im_image = ReadImage (image_info, exception); | ||
| 7521 | CatchException (exception); | ||
| 7522 | |||
| 7523 | image_wand = NewMagickWandFromImage (im_image); | ||
| 7524 | } | ||
| 7525 | else | ||
| 7526 | { | ||
| 7527 | image_wand = NewMagickWand (); | ||
| 7528 | status = MagickReadImageBlob (image_wand, contents, size); | ||
| 7529 | } | ||
| 7530 | image_error ("im read failed", Qnil, Qnil); | ||
| 7531 | if (status == MagickFalse) goto imagemagick_error; | ||
| 7532 | |||
| 7533 | /* If width and/or height is set in the display spec assume we want | ||
| 7534 | to scale to those values. if either h or w is unspecified, the | ||
| 7535 | unspecified should be calculated from the specified to preserve | ||
| 7536 | aspect ratio. */ | ||
| 7537 | |||
| 7538 | value = image_spec_value (img->spec, QCwidth, NULL); | ||
| 7539 | desired_width = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7540 | value = image_spec_value (img->spec, QCheight, NULL); | ||
| 7541 | desired_height = (INTEGERP (value) ? XFASTINT (value) : -1); | ||
| 7542 | |||
| 7543 | height = MagickGetImageHeight (image_wand); | ||
| 7544 | width = MagickGetImageWidth (image_wand); | ||
| 7545 | |||
| 7546 | if(desired_width != -1 && desired_height == -1) | ||
| 7547 | { | ||
| 7548 | /* w known, calculate h. */ | ||
| 7549 | desired_height = (double) desired_width / width * height; | ||
| 7550 | } | ||
| 7551 | if(desired_width == -1 && desired_height != -1) | ||
| 7552 | { | ||
| 7553 | /* h known, calculate w. */ | ||
| 7554 | desired_width = (double) desired_height / height * width; | ||
| 7555 | } | ||
| 7556 | if(desired_width != -1 && desired_height != -1) | ||
| 7557 | { | ||
| 7558 | status = MagickScaleImage (image_wand, desired_width, desired_height); | ||
| 7559 | if (status == MagickFalse) | ||
| 7560 | { | ||
| 7561 | image_error ("Imagemagick scale failed", Qnil, Qnil); | ||
| 7562 | goto imagemagick_error; | ||
| 7563 | } | ||
| 7564 | } | ||
| 7565 | |||
| 7566 | |||
| 7567 | /* crop behaves similar to image slicing in Emacs but is more memory | ||
| 7568 | efficient. */ | ||
| 7569 | crop = image_spec_value (img->spec, QCcrop, NULL); | ||
| 7570 | |||
| 7571 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | ||
| 7572 | { | ||
| 7573 | /* After some testing, it seems MagickCropImage is the fastest | ||
| 7574 | crop function in ImageMagick. This crop function seems to do | ||
| 7575 | less copying than the alternatives, but it still reads the | ||
| 7576 | entire image into memory before croping, which is aparently | ||
| 7577 | difficult to avoid when using imagemagick. */ | ||
| 7578 | |||
| 7579 | int w, h, x, y; | ||
| 7580 | w = XFASTINT (XCAR (crop)); | ||
| 7581 | crop = XCDR (crop); | ||
| 7582 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | ||
| 7583 | { | ||
| 7584 | h = XFASTINT (XCAR (crop)); | ||
| 7585 | crop = XCDR (crop); | ||
| 7586 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | ||
| 7587 | { | ||
| 7588 | x = XFASTINT (XCAR (crop)); | ||
| 7589 | crop = XCDR (crop); | ||
| 7590 | if (CONSP (crop) && INTEGERP (XCAR (crop))) | ||
| 7591 | { | ||
| 7592 | y = XFASTINT (XCAR (crop)); | ||
| 7593 | MagickCropImage (image_wand, w, h, x, y); | ||
| 7594 | } | ||
| 7595 | } | ||
| 7596 | } | ||
| 7597 | } | ||
| 7598 | |||
| 7599 | /* Furthermore :rotation. we need background color and angle for | ||
| 7600 | rotation. */ | ||
| 7601 | /* | ||
| 7602 | TODO background handling for rotation specified_bg = | ||
| 7603 | image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP | ||
| 7604 | (specified_bg). */ | ||
| 7605 | value = image_spec_value (img->spec, QCrotation, NULL); | ||
| 7606 | if (FLOATP (value)) | ||
| 7607 | { | ||
| 7608 | PixelWand* background = NewPixelWand (); | ||
| 7609 | PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/ | ||
| 7610 | |||
| 7611 | rotation = extract_float (value); | ||
| 7612 | |||
| 7613 | status = MagickRotateImage (image_wand, background, rotation); | ||
| 7614 | DestroyPixelWand (background); | ||
| 7615 | if (status == MagickFalse) | ||
| 7616 | { | ||
| 7617 | image_error ("Imagemagick image rotate failed", Qnil, Qnil); | ||
| 7618 | goto imagemagick_error; | ||
| 7619 | } | ||
| 7620 | } | ||
| 7621 | |||
| 7622 | /* Finaly we are done manipulating the image, figure out resulting | ||
| 7623 | width, height, and then transfer ownerwship to Emacs. */ | ||
| 7624 | height = MagickGetImageHeight (image_wand); | ||
| 7625 | width = MagickGetImageWidth (image_wand); | ||
| 7626 | if (status == MagickFalse) | ||
| 7627 | { | ||
| 7628 | image_error ("Imagemagick image get size failed", Qnil, Qnil); | ||
| 7629 | goto imagemagick_error; | ||
| 7630 | } | ||
| 7631 | |||
| 7632 | if (! check_image_size (f, width, height)) | ||
| 7633 | { | ||
| 7634 | image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil); | ||
| 7635 | goto imagemagick_error; | ||
| 7636 | } | ||
| 7637 | |||
| 7638 | /* We can now get a valid pixel buffer from the imagemagick file, if all | ||
| 7639 | went ok. */ | ||
| 7640 | |||
| 7641 | init_color_table (); | ||
| 7642 | imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type) | ||
| 7643 | ? XFASTINT (Vimagemagick_render_type) : 0); | ||
| 7644 | if (imagemagick_rendermethod == 0) | ||
| 7645 | { | ||
| 7646 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7647 | if (!x_create_x_image_and_pixmap (f, width, height, 0, | ||
| 7648 | &ximg, &img->pixmap)) | ||
| 7649 | { | ||
| 7650 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | ||
| 7651 | goto imagemagick_error; | ||
| 7652 | } | ||
| 7653 | |||
| 7654 | /* Copy imagegmagick image to x with primitive yet robust pixel | ||
| 7655 | pusher loop. This has been tested a lot with many different | ||
| 7656 | images. */ | ||
| 7657 | |||
| 7658 | /* Copy pixels from the imagemagick image structure to the x image map. */ | ||
| 7659 | iterator = NewPixelIterator (image_wand); | ||
| 7660 | if (iterator == (PixelIterator *) NULL) | ||
| 7661 | { | ||
| 7662 | image_error ("Imagemagick pixel iterator creation failed", | ||
| 7663 | Qnil, Qnil); | ||
| 7664 | goto imagemagick_error; | ||
| 7665 | } | ||
| 7666 | |||
| 7667 | for (y = 0; y < (long) MagickGetImageHeight (image_wand); y++) | ||
| 7668 | { | ||
| 7669 | pixels = PixelGetNextIteratorRow (iterator, &width); | ||
| 7670 | if (pixels == (PixelWand **) NULL) | ||
| 7671 | break; | ||
| 7672 | for (x = 0; x < (long) width; x++) | ||
| 7673 | { | ||
| 7674 | PixelGetMagickColor (pixels[x], &pixel); | ||
| 7675 | XPutPixel (ximg, x, y, | ||
| 7676 | lookup_rgb_color (f, | ||
| 7677 | pixel.red, | ||
| 7678 | pixel.green, | ||
| 7679 | pixel.blue)); | ||
| 7680 | } | ||
| 7681 | } | ||
| 7682 | DestroyPixelIterator (iterator); | ||
| 7683 | } | ||
| 7684 | |||
| 7685 | if (imagemagick_rendermethod == 1) | ||
| 7686 | { | ||
| 7687 | /* Magicexportimage is normaly faster than pixelpushing. This | ||
| 7688 | method is also well tested. Some aspects of this method are | ||
| 7689 | ad-hoc and needs to be more researched. */ | ||
| 7690 | int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/ | ||
| 7691 | char* exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/ | ||
| 7692 | /* Try to create a x pixmap to hold the imagemagick pixmap. */ | ||
| 7693 | if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, | ||
| 7694 | &ximg, &img->pixmap)) | ||
| 7695 | { | ||
| 7696 | image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil); | ||
| 7697 | goto imagemagick_error; | ||
| 7698 | } | ||
| 7699 | |||
| 7700 | |||
| 7701 | /* Oddly, the below code doesnt seem to work:*/ | ||
| 7702 | /* switch(ximg->bitmap_unit){ */ | ||
| 7703 | /* case 8: */ | ||
| 7704 | /* pixelwidth=CharPixel; */ | ||
| 7705 | /* break; */ | ||
| 7706 | /* case 16: */ | ||
| 7707 | /* pixelwidth=ShortPixel; */ | ||
| 7708 | /* break; */ | ||
| 7709 | /* case 32: */ | ||
| 7710 | /* pixelwidth=LongPixel; */ | ||
| 7711 | /* break; */ | ||
| 7712 | /* } */ | ||
| 7713 | /* | ||
| 7714 | Here im just guessing the format of the bitmap. | ||
| 7715 | happens to work fine for: | ||
| 7716 | - bw djvu images | ||
| 7717 | on rgb display. | ||
| 7718 | seems about 3 times as fast as pixel pushing(not carefully measured) | ||
| 7719 | */ | ||
| 7720 | pixelwidth = CharPixel;/*??? TODO figure out*/ | ||
| 7721 | #ifdef HAVE_MAGICKEXPORTIMAGEPIXELS | ||
| 7722 | MagickExportImagePixels (image_wand, | ||
| 7723 | 0, 0, | ||
| 7724 | width, height, | ||
| 7725 | exportdepth, | ||
| 7726 | pixelwidth, | ||
| 7727 | /*&(img->pixmap));*/ | ||
| 7728 | ximg->data); | ||
| 7729 | #else | ||
| 7730 | image_error ("You dont have MagickExportImagePixels, upgrade ImageMagick!", | ||
| 7731 | Qnil, Qnil); | ||
| 7732 | #endif | ||
| 7733 | } | ||
| 7734 | |||
| 7735 | |||
| 7736 | #ifdef COLOR_TABLE_SUPPORT | ||
| 7737 | /* Remember colors allocated for this image. */ | ||
| 7738 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7739 | free_color_table (); | ||
| 7740 | #endif /* COLOR_TABLE_SUPPORT */ | ||
| 7741 | |||
| 7742 | |||
| 7743 | img->width = width; | ||
| 7744 | img->height = height; | ||
| 7745 | |||
| 7746 | /* Put the image into the pixmap, then free the X image and its | ||
| 7747 | buffer. */ | ||
| 7748 | x_put_x_image (f, ximg, img->pixmap, width, height); | ||
| 7749 | x_destroy_x_image (ximg); | ||
| 7750 | |||
| 7751 | |||
| 7752 | /* Final cleanup. image_wand should be the only resource left. */ | ||
| 7753 | DestroyMagickWand (image_wand); | ||
| 7754 | |||
| 7755 | return 1; | ||
| 7756 | |||
| 7757 | imagemagick_error: | ||
| 7758 | /* TODO more cleanup. */ | ||
| 7759 | image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil); | ||
| 7760 | return 0; | ||
| 7761 | } | ||
| 7762 | |||
| 7763 | |||
| 7764 | /* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if | ||
| 7765 | successful. this function will go into the imagemagick_type structure, and | ||
| 7766 | the prototype thus needs to be compatible with that structure. */ | ||
| 7767 | |||
| 7768 | static int | ||
| 7769 | imagemagick_load (struct frame *f, | ||
| 7770 | struct image *img) | ||
| 7771 | { | ||
| 7772 | int success_p = 0; | ||
| 7773 | Lisp_Object file_name; | ||
| 7774 | |||
| 7775 | /* If IMG->spec specifies a file name, create a non-file spec from it. */ | ||
| 7776 | file_name = image_spec_value (img->spec, QCfile, NULL); | ||
| 7777 | if (STRINGP (file_name)) | ||
| 7778 | { | ||
| 7779 | Lisp_Object file; | ||
| 7780 | |||
| 7781 | file = x_find_image_file (file_name); | ||
| 7782 | if (!STRINGP (file)) | ||
| 7783 | { | ||
| 7784 | image_error ("Cannot find image file `%s'", file_name, Qnil); | ||
| 7785 | return 0; | ||
| 7786 | } | ||
| 7787 | success_p = imagemagick_load_image (f, img, 0, 0, SDATA (file)); | ||
| 7788 | } | ||
| 7789 | /* Else its not a file, its a lisp object. Load the image from a | ||
| 7790 | lisp object rather than a file. */ | ||
| 7791 | else | ||
| 7792 | { | ||
| 7793 | Lisp_Object data; | ||
| 7794 | |||
| 7795 | data = image_spec_value (img->spec, QCdata, NULL); | ||
| 7796 | if (!STRINGP (data)) | ||
| 7797 | { | ||
| 7798 | image_error ("Invalid image data `%s'", data, Qnil); | ||
| 7799 | return 0; | ||
| 7800 | } | ||
| 7801 | success_p = imagemagick_load_image (f, img, SDATA (data), | ||
| 7802 | SBYTES (data), NULL); | ||
| 7803 | } | ||
| 7804 | |||
| 7805 | return success_p; | ||
| 7806 | } | ||
| 7807 | |||
| 7808 | /* Structure describing the image type `imagemagick'. Its the same | ||
| 7809 | type of structure defined for all image formats, handled by Emacs | ||
| 7810 | image functions. See struct image_type in dispextern.h. */ | ||
| 7811 | |||
| 7812 | static struct image_type imagemagick_type = | ||
| 7813 | { | ||
| 7814 | /* An identifier showing that this is an image structure for the | ||
| 7815 | IMAGEMAGICK format. */ | ||
| 7816 | &Qimagemagick, | ||
| 7817 | /* Handle to a function that can be used to identify a IMAGEMAGICK | ||
| 7818 | file. */ | ||
| 7819 | imagemagick_image_p, | ||
| 7820 | /* Handle to function used to load a IMAGEMAGICK file. */ | ||
| 7821 | imagemagick_load, | ||
| 7822 | /* Handle to function to free resources for IMAGEMAGICK. */ | ||
| 7823 | imagemagick_clear_image, | ||
| 7824 | /* An internal field to link to the next image type in a list of | ||
| 7825 | image types, will be filled in when registering the format. */ | ||
| 7826 | NULL | ||
| 7827 | }; | ||
| 7828 | |||
| 7829 | |||
| 7830 | |||
| 7831 | |||
| 7832 | DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0, | ||
| 7833 | doc: /* Return image file types supported by ImageMagick. | ||
| 7834 | Since ImageMagick recognizes a lot of file-types that clash with Emacs, | ||
| 7835 | such as .c, we want to be able to alter the list at the lisp level. */) | ||
| 7836 | (void) | ||
| 7837 | { | ||
| 7838 | Lisp_Object typelist = Qnil; | ||
| 7839 | unsigned long numf; | ||
| 7840 | ExceptionInfo ex; | ||
| 7841 | char **imtypes = GetMagickList ("*", &numf, &ex); | ||
| 7842 | int i; | ||
| 7843 | Lisp_Object Qimagemagicktype; | ||
| 7844 | for (i = 0; i < numf; i++) | ||
| 7845 | { | ||
| 7846 | Qimagemagicktype = intern (imtypes[i]); | ||
| 7847 | typelist = Fcons (Qimagemagicktype, typelist); | ||
| 7848 | } | ||
| 7849 | return typelist; | ||
| 7850 | } | ||
| 7851 | |||
| 7852 | #endif /* defined (HAVE_IMAGEMAGICK) */ | ||
| 7853 | |||
| 7854 | |||
| 7345 | 7855 | ||
| 7346 | /*********************************************************************** | 7856 | /*********************************************************************** |
| 7347 | SVG | 7857 | SVG |
| @@ -7534,14 +8044,11 @@ svg_load (struct frame *f, struct image *img) | |||
| 7534 | Lisp_Object file; | 8044 | Lisp_Object file; |
| 7535 | unsigned char *contents; | 8045 | unsigned char *contents; |
| 7536 | int size; | 8046 | int size; |
| 7537 | struct gcpro gcpro1; | ||
| 7538 | 8047 | ||
| 7539 | file = x_find_image_file (file_name); | 8048 | file = x_find_image_file (file_name); |
| 7540 | GCPRO1 (file); | ||
| 7541 | if (!STRINGP (file)) | 8049 | if (!STRINGP (file)) |
| 7542 | { | 8050 | { |
| 7543 | image_error ("Cannot find image file `%s'", file_name, Qnil); | 8051 | image_error ("Cannot find image file `%s'", file_name, Qnil); |
| 7544 | UNGCPRO; | ||
| 7545 | return 0; | 8052 | return 0; |
| 7546 | } | 8053 | } |
| 7547 | 8054 | ||
| @@ -7550,13 +8057,11 @@ svg_load (struct frame *f, struct image *img) | |||
| 7550 | if (contents == NULL) | 8057 | if (contents == NULL) |
| 7551 | { | 8058 | { |
| 7552 | image_error ("Error loading SVG image `%s'", img->spec, Qnil); | 8059 | image_error ("Error loading SVG image `%s'", img->spec, Qnil); |
| 7553 | UNGCPRO; | ||
| 7554 | return 0; | 8060 | return 0; |
| 7555 | } | 8061 | } |
| 7556 | /* If the file was slurped into memory properly, parse it. */ | 8062 | /* If the file was slurped into memory properly, parse it. */ |
| 7557 | success_p = svg_load_image (f, img, contents, size); | 8063 | success_p = svg_load_image (f, img, contents, size); |
| 7558 | xfree (contents); | 8064 | xfree (contents); |
| 7559 | UNGCPRO; | ||
| 7560 | } | 8065 | } |
| 7561 | /* Else its not a file, its a lisp object. Load the image from a | 8066 | /* Else its not a file, its a lisp object. Load the image from a |
| 7562 | lisp object rather than a file. */ | 8067 | lisp object rather than a file. */ |
| @@ -7565,6 +8070,11 @@ svg_load (struct frame *f, struct image *img) | |||
| 7565 | Lisp_Object data; | 8070 | Lisp_Object data; |
| 7566 | 8071 | ||
| 7567 | data = image_spec_value (img->spec, QCdata, NULL); | 8072 | data = image_spec_value (img->spec, QCdata, NULL); |
| 8073 | if (!STRINGP (data)) | ||
| 8074 | { | ||
| 8075 | image_error ("Invalid image data `%s'", data, Qnil); | ||
| 8076 | return 0; | ||
| 8077 | } | ||
| 7568 | success_p = svg_load_image (f, img, SDATA (data), SBYTES (data)); | 8078 | success_p = svg_load_image (f, img, SDATA (data), SBYTES (data)); |
| 7569 | } | 8079 | } |
| 7570 | 8080 | ||
| @@ -7864,7 +8374,6 @@ gs_load (struct frame *f, struct image *img) | |||
| 7864 | { | 8374 | { |
| 7865 | char buffer[100]; | 8375 | char buffer[100]; |
| 7866 | Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width; | 8376 | Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width; |
| 7867 | struct gcpro gcpro1, gcpro2; | ||
| 7868 | Lisp_Object frame; | 8377 | Lisp_Object frame; |
| 7869 | double in_width, in_height; | 8378 | double in_width, in_height; |
| 7870 | Lisp_Object pixel_colors = Qnil; | 8379 | Lisp_Object pixel_colors = Qnil; |
| @@ -7874,10 +8383,10 @@ gs_load (struct frame *f, struct image *img) | |||
| 7874 | = 1/72 in, xdpi and ydpi are stored in the frame's X display | 8383 | = 1/72 in, xdpi and ydpi are stored in the frame's X display |
| 7875 | info. */ | 8384 | info. */ |
| 7876 | pt_width = image_spec_value (img->spec, QCpt_width, NULL); | 8385 | pt_width = image_spec_value (img->spec, QCpt_width, NULL); |
| 7877 | in_width = XFASTINT (pt_width) / 72.0; | 8386 | in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0; |
| 7878 | img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx; | 8387 | img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx; |
| 7879 | pt_height = image_spec_value (img->spec, QCpt_height, NULL); | 8388 | pt_height = image_spec_value (img->spec, QCpt_height, NULL); |
| 7880 | in_height = XFASTINT (pt_height) / 72.0; | 8389 | in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0; |
| 7881 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; | 8390 | img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy; |
| 7882 | 8391 | ||
| 7883 | if (!check_image_size (f, img->width, img->height)) | 8392 | if (!check_image_size (f, img->width, img->height)) |
| @@ -7906,8 +8415,6 @@ gs_load (struct frame *f, struct image *img) | |||
| 7906 | if successful. We do not record_unwind_protect here because | 8415 | if successful. We do not record_unwind_protect here because |
| 7907 | other places in redisplay like calling window scroll functions | 8416 | other places in redisplay like calling window scroll functions |
| 7908 | don't either. Let the Lisp loader use `unwind-protect' instead. */ | 8417 | don't either. Let the Lisp loader use `unwind-protect' instead. */ |
| 7909 | GCPRO2 (window_and_pixmap_id, pixel_colors); | ||
| 7910 | |||
| 7911 | sprintf (buffer, "%lu %lu", | 8418 | sprintf (buffer, "%lu %lu", |
| 7912 | (unsigned long) FRAME_X_WINDOW (f), | 8419 | (unsigned long) FRAME_X_WINDOW (f), |
| 7913 | (unsigned long) img->pixmap); | 8420 | (unsigned long) img->pixmap); |
| @@ -7928,7 +8435,6 @@ gs_load (struct frame *f, struct image *img) | |||
| 7928 | make_number (img->height), | 8435 | make_number (img->height), |
| 7929 | window_and_pixmap_id, | 8436 | window_and_pixmap_id, |
| 7930 | pixel_colors); | 8437 | pixel_colors); |
| 7931 | UNGCPRO; | ||
| 7932 | return PROCESSP (img->data.lisp_val); | 8438 | return PROCESSP (img->data.lisp_val); |
| 7933 | } | 8439 | } |
| 7934 | 8440 | ||
| @@ -8117,6 +8623,16 @@ of `image-library-alist', which see). */) | |||
| 8117 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); | 8623 | return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries); |
| 8118 | #endif | 8624 | #endif |
| 8119 | 8625 | ||
| 8626 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8627 | if (EQ (type, Qimagemagick)) | ||
| 8628 | { | ||
| 8629 | /* MagickWandGenesis() initalizes the imagemagick library. */ | ||
| 8630 | MagickWandGenesis (); | ||
| 8631 | return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions, | ||
| 8632 | libraries); | ||
| 8633 | } | ||
| 8634 | #endif | ||
| 8635 | |||
| 8120 | #ifdef HAVE_GHOSTSCRIPT | 8636 | #ifdef HAVE_GHOSTSCRIPT |
| 8121 | if (EQ (type, Qpostscript)) | 8637 | if (EQ (type, Qpostscript)) |
| 8122 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); | 8638 | return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries); |
| @@ -8202,6 +8718,12 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8202 | staticpro (&QCheuristic_mask); | 8718 | staticpro (&QCheuristic_mask); |
| 8203 | QCindex = intern_c_string (":index"); | 8719 | QCindex = intern_c_string (":index"); |
| 8204 | staticpro (&QCindex); | 8720 | staticpro (&QCindex); |
| 8721 | QCgeometry = intern (":geometry"); | ||
| 8722 | staticpro (&QCgeometry); | ||
| 8723 | QCcrop = intern (":crop"); | ||
| 8724 | staticpro (&QCcrop); | ||
| 8725 | QCrotation = intern (":rotation"); | ||
| 8726 | staticpro (&QCrotation); | ||
| 8205 | QCmatrix = intern_c_string (":matrix"); | 8727 | QCmatrix = intern_c_string (":matrix"); |
| 8206 | staticpro (&QCmatrix); | 8728 | staticpro (&QCmatrix); |
| 8207 | QCcolor_adjustment = intern_c_string (":color-adjustment"); | 8729 | QCcolor_adjustment = intern_c_string (":color-adjustment"); |
| @@ -8262,6 +8784,12 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8262 | ADD_IMAGE_TYPE (Qpng); | 8784 | ADD_IMAGE_TYPE (Qpng); |
| 8263 | #endif | 8785 | #endif |
| 8264 | 8786 | ||
| 8787 | #if defined (HAVE_IMAGEMAGICK) | ||
| 8788 | Qimagemagick = intern ("imagemagick"); | ||
| 8789 | staticpro (&Qimagemagick); | ||
| 8790 | ADD_IMAGE_TYPE (Qimagemagick); | ||
| 8791 | #endif | ||
| 8792 | |||
| 8265 | #if defined (HAVE_RSVG) | 8793 | #if defined (HAVE_RSVG) |
| 8266 | Qsvg = intern_c_string ("svg"); | 8794 | Qsvg = intern_c_string ("svg"); |
| 8267 | staticpro (&Qsvg); | 8795 | staticpro (&Qsvg); |
| @@ -8278,6 +8806,9 @@ non-numeric, there is no explicit limit on the size of images. */); | |||
| 8278 | #endif /* HAVE_RSVG */ | 8806 | #endif /* HAVE_RSVG */ |
| 8279 | 8807 | ||
| 8280 | defsubr (&Sinit_image_library); | 8808 | defsubr (&Sinit_image_library); |
| 8809 | #ifdef HAVE_IMAGEMAGICK | ||
| 8810 | defsubr (&Simagemagick_types); | ||
| 8811 | #endif | ||
| 8281 | defsubr (&Sclear_image_cache); | 8812 | defsubr (&Sclear_image_cache); |
| 8282 | defsubr (&Simage_flush); | 8813 | defsubr (&Simage_flush); |
| 8283 | defsubr (&Simage_size); | 8814 | defsubr (&Simage_size); |
| @@ -8308,6 +8839,11 @@ The value can also be nil, meaning the cache is never cleared. | |||
| 8308 | 8839 | ||
| 8309 | The function `clear-image-cache' disregards this variable. */); | 8840 | The function `clear-image-cache' disregards this variable. */); |
| 8310 | Vimage_cache_eviction_delay = make_number (300); | 8841 | Vimage_cache_eviction_delay = make_number (300); |
| 8842 | #ifdef HAVE_IMAGEMAGICK | ||
| 8843 | DEFVAR_LISP ("imagemagick-render-type", &Vimagemagick_render_type, | ||
| 8844 | doc: /* Choose between ImageMagick render methods. */); | ||
| 8845 | #endif | ||
| 8846 | |||
| 8311 | } | 8847 | } |
| 8312 | 8848 | ||
| 8313 | void | 8849 | void |