aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann1999-12-31 16:47:13 +0000
committerGerd Moellmann1999-12-31 16:47:13 +0000
commit5ad6a5fb896e298052f0d08480933336833b986f (patch)
tree1833ce96327acab7f5b5039a2f3e28e2d6470545 /src
parentbc28370787eb85b1df6dfa89b015750b60fb69d5 (diff)
downloademacs-5ad6a5fb896e298052f0d08480933336833b986f.tar.gz
emacs-5ad6a5fb896e298052f0d08480933336833b986f.zip
New image functions adapted to Emacs conventions.
(png_load, tiff_load, jpeg_load, gif_load): Always GCPRO local variable `file'.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/xfns.c554
2 files changed, 306 insertions, 254 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 8992497582b..ea19bf734eb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
11999-12-31 Gerd Moellmann <gerd@gnu.org>
2
3 * xfns.c: New image functions adapted to Emacs conventions.
4 (png_load, tiff_load, jpeg_load, gif_load): Always GCPRO local
5 variable `file'.
6
11999-12-31 William M. Perry <wmperry@aventail.com> 71999-12-31 William M. Perry <wmperry@aventail.com>
2 8
3 * xfns.c (jpeg_format): Added the :data keyword 9 * xfns.c (jpeg_format): Added the :data keyword
diff --git a/src/xfns.c b/src/xfns.c
index f17455ef05a..c1c1eaf5c75 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7941,7 +7941,7 @@ enum png_keyword_index
7941static struct image_keyword png_format[PNG_LAST] = 7941static struct image_keyword png_format[PNG_LAST] =
7942{ 7942{
7943 {":type", IMAGE_SYMBOL_VALUE, 1}, 7943 {":type", IMAGE_SYMBOL_VALUE, 1},
7944 {":data", IMAGE_STRING_VALUE, 0}, 7944 {":data", IMAGE_STRING_VALUE, 0},
7945 {":file", IMAGE_STRING_VALUE, 0}, 7945 {":file", IMAGE_STRING_VALUE, 0},
7946 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 7946 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7947 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 7947 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
@@ -7977,12 +7977,9 @@ png_image_p (object)
7977 return 0; 7977 return 0;
7978 7978
7979 /* Must specify either the :data or :file keyword. This should 7979 /* Must specify either the :data or :file keyword. This should
7980 ** probably be moved up into parse_image_spec, since it seems to be 7980 probably be moved up into parse_image_spec, since it seems to be
7981 ** a general requirement. 7981 a general requirement. */
7982 */ 7982 return fmt[PNG_FILE].count || fmt[PNG_DATA].count;
7983 if (!fmt[PNG_FILE].count && !fmt[PNG_DATA].count)
7984 return 0;
7985 return 1;
7986} 7983}
7987 7984
7988 7985
@@ -8009,27 +8006,34 @@ my_png_warning (png_ptr, msg)
8009 image_error ("PNG warning: %s", build_string (msg), Qnil); 8006 image_error ("PNG warning: %s", build_string (msg), Qnil);
8010} 8007}
8011 8008
8012/* Memory source for PNG decoding. Originally written for XEmacs by 8009/* Memory source for PNG decoding. */
8013 William Perry <wmperry@gnu.org>, who has paperwork on file, and so 8010
8014 it is safe to use. */
8015struct png_memory_storage 8011struct png_memory_storage
8016{ 8012{
8017 unsigned char *bytes; /* The data */ 8013 unsigned char *bytes; /* The data */
8018 size_t len; /* How big is it? */ 8014 size_t len; /* How big is it? */
8019 int index; /* Where are we? */ 8015 int index; /* Where are we? */
8020}; 8016};
8021 8017
8018
8019/* Function set as reader function when reading PNG image from memory.
8020 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
8021 bytes from the input to DATA. */
8022
8022static void 8023static void
8023png_read_from_memory(png_structp png_ptr, png_bytep data, 8024png_read_from_memory (png_ptr, data, length)
8024 png_size_t length) 8025 png_structp png_ptr;
8026 png_bytep data;
8027 png_size_t length;
8025{ 8028{
8026 struct png_memory_storage *tbr = 8029 struct png_memory_storage *tbr
8027 (struct png_memory_storage *) png_get_io_ptr (png_ptr); 8030 = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
8028 8031
8029 if (length > (tbr->len - tbr->index)) 8032 if (length > tbr->len - tbr->index)
8030 png_error (png_ptr, (png_const_charp) "Read Error"); 8033 png_error (png_ptr, "Read error");
8031 memcpy (data,tbr->bytes + tbr->index,length); 8034
8032 tbr->index = tbr->index + length; 8035 bcopy (tbr->bytes + tbr->index, data, length);
8036 tbr->index = tbr->index + length;
8033} 8037}
8034 8038
8035/* Load PNG image IMG for use on frame F. Value is non-zero if 8039/* Load PNG image IMG for use on frame F. Value is non-zero if
@@ -8064,58 +8068,59 @@ png_load (f, img)
8064 /* Find out what file to load. */ 8068 /* Find out what file to load. */
8065 specified_file = image_spec_value (img->spec, QCfile, NULL); 8069 specified_file = image_spec_value (img->spec, QCfile, NULL);
8066 specified_data = image_spec_value (img->spec, QCdata, NULL); 8070 specified_data = image_spec_value (img->spec, QCdata, NULL);
8071 file = Qnil;
8072 GCPRO1 (file);
8067 8073
8068 if (NILP (specified_data)) 8074 if (NILP (specified_data))
8075 {
8076 file = x_find_image_file (specified_file);
8077 if (!STRINGP (file))
8069 { 8078 {
8070 file = x_find_image_file (specified_file); 8079 image_error ("Cannot find image file %s", specified_file, Qnil);
8071 GCPRO1 (file); 8080 UNGCPRO;
8072 if (!STRINGP (file)) 8081 return 0;
8073 { 8082 }
8074 image_error ("Cannot find image file %s", specified_file, Qnil);
8075 UNGCPRO;
8076 return 0;
8077 }
8078 8083
8079 /* Open the image file. */ 8084 /* Open the image file. */
8080 fp = fopen (XSTRING (file)->data, "rb"); 8085 fp = fopen (XSTRING (file)->data, "rb");
8081 if (!fp) 8086 if (!fp)
8082 { 8087 {
8083 image_error ("Cannot open image file %s", file, Qnil); 8088 image_error ("Cannot open image file %s", file, Qnil);
8084 UNGCPRO; 8089 UNGCPRO;
8085 fclose (fp); 8090 fclose (fp);
8086 return 0; 8091 return 0;
8087 } 8092 }
8088 8093
8089 /* Check PNG signature. */ 8094 /* Check PNG signature. */
8090 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 8095 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
8091 || !png_check_sig (sig, sizeof sig)) 8096 || !png_check_sig (sig, sizeof sig))
8092 { 8097 {
8093 image_error ("Not a PNG file: %s", file, Qnil); 8098 image_error ("Not a PNG file: %s", file, Qnil);
8094 UNGCPRO; 8099 UNGCPRO;
8095 fclose (fp); 8100 fclose (fp);
8096 return 0; 8101 return 0;
8097 }
8098 } 8102 }
8103 }
8099 else 8104 else
8100 { 8105 {
8101 /* Read from memory */ 8106 /* Read from memory. */
8102 tbr.bytes = XSTRING (specified_data)->data; 8107 tbr.bytes = XSTRING (specified_data)->data;
8103 tbr.len = STRING_BYTES (XSTRING (specified_data)); 8108 tbr.len = STRING_BYTES (XSTRING (specified_data));
8104 tbr.index = 0; 8109 tbr.index = 0;
8105
8106 /* Chekc PNG signature */
8107 if ((tbr.len < sizeof(sig)) ||
8108 !png_check_sig (tbr.bytes, sizeof(sig)))
8109 {
8110 image_error ("Not a PNG file: %s", file, Qnil);
8111 UNGCPRO;
8112 return 0;
8113 }
8114 8110
8115 /* Need to skip past the signature */ 8111 /* Check PNG signature. */
8116 tbr.bytes += sizeof(sig); 8112 if (tbr.len < sizeof sig
8113 || !png_check_sig (tbr.bytes, sizeof sig))
8114 {
8115 image_error ("Not a PNG file: %s", file, Qnil);
8116 UNGCPRO;
8117 return 0;
8117 } 8118 }
8118 8119
8120 /* Need to skip past the signature. */
8121 tbr.bytes += sizeof (sig);
8122 }
8123
8119 /* Initialize read and info structs for PNG lib. */ 8124 /* Initialize read and info structs for PNG lib. */
8120 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, 8125 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
8121 my_png_error, my_png_warning); 8126 my_png_error, my_png_warning);
@@ -8160,9 +8165,9 @@ png_load (f, img)
8160 8165
8161 /* Read image info. */ 8166 /* Read image info. */
8162 if (!NILP (specified_data)) 8167 if (!NILP (specified_data))
8163 png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory); 8168 png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
8164 else 8169 else
8165 png_init_io (png_ptr, fp); 8170 png_init_io (png_ptr, fp);
8166 8171
8167 png_set_sig_bytes (png_ptr, sizeof sig); 8172 png_set_sig_bytes (png_ptr, sizeof sig);
8168 png_read_info (png_ptr, info_ptr); 8173 png_read_info (png_ptr, info_ptr);
@@ -8272,8 +8277,11 @@ png_load (f, img)
8272 /* Read the entire image. */ 8277 /* Read the entire image. */
8273 png_read_image (png_ptr, rows); 8278 png_read_image (png_ptr, rows);
8274 png_read_end (png_ptr, info_ptr); 8279 png_read_end (png_ptr, info_ptr);
8275 if (fp) fclose (fp); 8280 if (fp)
8276 fp = NULL; 8281 {
8282 fclose (fp);
8283 fp = NULL;
8284 }
8277 8285
8278 BLOCK_INPUT; 8286 BLOCK_INPUT;
8279 8287
@@ -8421,7 +8429,7 @@ enum jpeg_keyword_index
8421static struct image_keyword jpeg_format[JPEG_LAST] = 8429static struct image_keyword jpeg_format[JPEG_LAST] =
8422{ 8430{
8423 {":type", IMAGE_SYMBOL_VALUE, 1}, 8431 {":type", IMAGE_SYMBOL_VALUE, 1},
8424 {":data", IMAGE_STRING_VALUE, 0}, 8432 {":data", IMAGE_STRING_VALUE, 0},
8425 {":file", IMAGE_STRING_VALUE, 0}, 8433 {":file", IMAGE_STRING_VALUE, 0},
8426 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 8434 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8427 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 8435 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
@@ -8454,7 +8462,7 @@ jpeg_image_p (object)
8454 8462
8455 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg) 8463 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
8456 || (fmt[JPEG_ASCENT].count 8464 || (fmt[JPEG_ASCENT].count
8457 && XFASTINT (fmt[JPEG_ASCENT].value) > 100)) 8465 && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
8458 return 0; 8466 return 0;
8459 8467
8460 /* Must specify either the :data or :file keyword. This should 8468 /* Must specify either the :data or :file keyword. This should
@@ -8523,10 +8531,7 @@ our_skip_input_data (cinfo, num_bytes)
8523 if (src) 8531 if (src)
8524 { 8532 {
8525 if (num_bytes > src->bytes_in_buffer) 8533 if (num_bytes > src->bytes_in_buffer)
8526 { 8534 ERREXIT (cinfo, JERR_INPUT_EOF);
8527 ERREXIT (cinfo, JERR_INPUT_EOF);
8528 /*NOTREACHED*/
8529 }
8530 8535
8531 src->bytes_in_buffer -= num_bytes; 8536 src->bytes_in_buffer -= num_bytes;
8532 src->next_input_byte += num_bytes; 8537 src->next_input_byte += num_bytes;
@@ -8576,6 +8581,7 @@ jpeg_memory_src (cinfo, data, len)
8576 src->next_input_byte = data; 8581 src->next_input_byte = data;
8577} 8582}
8578 8583
8584
8579/* Load image IMG for use on frame F. Patterned after example.c 8585/* Load image IMG for use on frame F. Patterned after example.c
8580 from the JPEG lib. */ 8586 from the JPEG lib. */
8581 8587
@@ -8600,12 +8606,13 @@ jpeg_load (f, img)
8600 /* Open the JPEG file. */ 8606 /* Open the JPEG file. */
8601 specified_file = image_spec_value (img->spec, QCfile, NULL); 8607 specified_file = image_spec_value (img->spec, QCfile, NULL);
8602 specified_data = image_spec_value (img->spec, QCdata, NULL); 8608 specified_data = image_spec_value (img->spec, QCdata, NULL);
8609 file = Qnil;
8610 GCPRO1 (file);
8603 8611
8604 /* Reading from :data takes precedence. */ 8612 /* Reading from :data takes precedence. */
8605 if (NILP (specified_data)) 8613 if (NILP (specified_data))
8606 { 8614 {
8607 file = x_find_image_file (specified_file); 8615 file = x_find_image_file (specified_file);
8608 GCPRO1 (file);
8609 if (!STRINGP (file)) 8616 if (!STRINGP (file))
8610 { 8617 {
8611 image_error ("Cannot find image file %s", specified_file, Qnil); 8618 image_error ("Cannot find image file %s", specified_file, Qnil);
@@ -8622,38 +8629,38 @@ jpeg_load (f, img)
8622 } 8629 }
8623 } 8630 }
8624 8631
8625 /* Customize libjpeg's error handling to call my_error_exit 8632 /* Customize libjpeg's error handling to call my_error_exit when an
8626 when an error is detected. This function will perform 8633 error is detected. This function will perform a longjmp. */
8627 a longjmp. */
8628 mgr.pub.error_exit = my_error_exit; 8634 mgr.pub.error_exit = my_error_exit;
8629 cinfo.err = jpeg_std_error (&mgr.pub); 8635 cinfo.err = jpeg_std_error (&mgr.pub);
8630 8636
8631 if ((rc = setjmp (mgr.setjmp_buffer)) != 0) 8637 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
8632 { 8638 {
8633 if (rc == 1) 8639 if (rc == 1)
8634 { 8640 {
8635 /* Called from my_error_exit. Display a JPEG error. */ 8641 /* Called from my_error_exit. Display a JPEG error. */
8636 char buffer[JMSG_LENGTH_MAX]; 8642 char buffer[JMSG_LENGTH_MAX];
8637 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer); 8643 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
8638 image_error ("Error reading JPEG file `%s': %s", file, 8644 image_error ("Error reading JPEG file `%s': %s", file,
8639 build_string (buffer)); 8645 build_string (buffer));
8640 } 8646 }
8641 8647
8642 /* Close the input file and destroy the JPEG object. */ 8648 /* Close the input file and destroy the JPEG object. */
8643 if (fp) fclose (fp); 8649 if (fp)
8650 fclose (fp);
8644 jpeg_destroy_decompress (&cinfo); 8651 jpeg_destroy_decompress (&cinfo);
8645 8652
8646 BLOCK_INPUT; 8653 BLOCK_INPUT;
8647 8654
8648 /* If we already have an XImage, free that. */ 8655 /* If we already have an XImage, free that. */
8649 x_destroy_x_image (ximg); 8656 x_destroy_x_image (ximg);
8650 8657
8651 /* Free pixmap and colors. */ 8658 /* Free pixmap and colors. */
8652 x_clear_image (f, img); 8659 x_clear_image (f, img);
8653 8660
8654 UNBLOCK_INPUT; 8661 UNBLOCK_INPUT;
8655 UNGCPRO; 8662 UNGCPRO;
8656 return 0; 8663 return 0;
8657 } 8664 }
8658 8665
8659 /* Create the JPEG decompression object. Let it read from fp. 8666 /* Create the JPEG decompression object. Let it read from fp.
@@ -8681,63 +8688,64 @@ jpeg_load (f, img)
8681 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg, 8688 if (!x_create_x_image_and_pixmap (f, file, width, height, 0, &ximg,
8682 &img->pixmap)) 8689 &img->pixmap))
8683 { 8690 {
8684 UNBLOCK_INPUT; 8691 UNBLOCK_INPUT;
8685 longjmp (mgr.setjmp_buffer, 2); 8692 longjmp (mgr.setjmp_buffer, 2);
8686 } 8693 }
8687 8694
8688 /* Allocate colors. When color quantization is used, 8695 /* Allocate colors. When color quantization is used,
8689 cinfo.actual_number_of_colors has been set with the number of 8696 cinfo.actual_number_of_colors has been set with the number of
8690 colors generated, and cinfo.colormap is a two-dimensional array 8697 colors generated, and cinfo.colormap is a two-dimensional array
8691 of color indices in the range 0..cinfo.actual_number_of_colors. 8698 of color indices in the range 0..cinfo.actual_number_of_colors.
8692 No more than 255 colors will be generated. */ 8699 No more than 255 colors will be generated. */
8693 { 8700 {
8694 int i, ir, ig, ib; 8701 int i, ir, ig, ib;
8695 8702
8696 if (cinfo.out_color_components > 2) 8703 if (cinfo.out_color_components > 2)
8697 ir = 0, ig = 1, ib = 2; 8704 ir = 0, ig = 1, ib = 2;
8698 else if (cinfo.out_color_components > 1) 8705 else if (cinfo.out_color_components > 1)
8699 ir = 0, ig = 1, ib = 0; 8706 ir = 0, ig = 1, ib = 0;
8700 else 8707 else
8701 ir = 0, ig = 0, ib = 0; 8708 ir = 0, ig = 0, ib = 0;
8702 8709
8703 /* Use the color table mechanism because it handles colors that 8710 /* Use the color table mechanism because it handles colors that
8704 cannot be allocated nicely. Such colors will be replaced with 8711 cannot be allocated nicely. Such colors will be replaced with
8705 a default color, and we don't have to care about which colors 8712 a default color, and we don't have to care about which colors
8706 can be freed safely, and which can't. */ 8713 can be freed safely, and which can't. */
8707 init_color_table (); 8714 init_color_table ();
8708 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors 8715 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
8709 * sizeof *colors); 8716 * sizeof *colors);
8710 8717
8711 for (i = 0; i < cinfo.actual_number_of_colors; ++i) 8718 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
8712 { 8719 {
8713 /* Multiply RGB values with 255 because X expects RGB values 8720 /* Multiply RGB values with 255 because X expects RGB values
8714 in the range 0..0xffff. */ 8721 in the range 0..0xffff. */
8715 int r = cinfo.colormap[ir][i] << 8; 8722 int r = cinfo.colormap[ir][i] << 8;
8716 int g = cinfo.colormap[ig][i] << 8; 8723 int g = cinfo.colormap[ig][i] << 8;
8717 int b = cinfo.colormap[ib][i] << 8; 8724 int b = cinfo.colormap[ib][i] << 8;
8718 colors[i] = lookup_rgb_color (f, r, g, b); 8725 colors[i] = lookup_rgb_color (f, r, g, b);
8719 } 8726 }
8720 8727
8721 /* Remember those colors actually allocated. */ 8728 /* Remember those colors actually allocated. */
8722 img->colors = colors_in_color_table (&img->ncolors); 8729 img->colors = colors_in_color_table (&img->ncolors);
8723 free_color_table (); 8730 free_color_table ();
8724 } 8731 }
8725 8732
8726 /* Read pixels. */ 8733 /* Read pixels. */
8727 row_stride = width * cinfo.output_components; 8734 row_stride = width * cinfo.output_components;
8728 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE, 8735 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
8729 row_stride, 1); 8736 row_stride, 1);
8730 for (y = 0; y < height; ++y) 8737 for (y = 0; y < height; ++y)
8731 { 8738 {
8732 jpeg_read_scanlines (&cinfo, buffer, 1); 8739 jpeg_read_scanlines (&cinfo, buffer, 1);
8733 for (x = 0; x < cinfo.output_width; ++x) 8740 for (x = 0; x < cinfo.output_width; ++x)
8734 XPutPixel (ximg, x, y, colors[buffer[0][x]]); 8741 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
8735 } 8742 }
8736 8743
8737 /* Clean up. */ 8744 /* Clean up. */
8738 jpeg_finish_decompress (&cinfo); 8745 jpeg_finish_decompress (&cinfo);
8739 jpeg_destroy_decompress (&cinfo); 8746 jpeg_destroy_decompress (&cinfo);
8740 if (fp) fclose (fp); 8747 if (fp)
8748 fclose (fp);
8741 8749
8742 /* Put the image into the pixmap. */ 8750 /* Put the image into the pixmap. */
8743 x_put_x_image (f, ximg, img->pixmap, width, height); 8751 x_put_x_image (f, ximg, img->pixmap, width, height);
@@ -8787,7 +8795,7 @@ enum tiff_keyword_index
8787static struct image_keyword tiff_format[TIFF_LAST] = 8795static struct image_keyword tiff_format[TIFF_LAST] =
8788{ 8796{
8789 {":type", IMAGE_SYMBOL_VALUE, 1}, 8797 {":type", IMAGE_SYMBOL_VALUE, 1},
8790 {":data", IMAGE_STRING_VALUE, 0}, 8798 {":data", IMAGE_STRING_VALUE, 0},
8791 {":file", IMAGE_STRING_VALUE, 0}, 8799 {":file", IMAGE_STRING_VALUE, 0},
8792 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 8800 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
8793 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 8801 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
@@ -8821,91 +8829,121 @@ tiff_image_p (object)
8821 || (fmt[TIFF_ASCENT].count 8829 || (fmt[TIFF_ASCENT].count
8822 && XFASTINT (fmt[TIFF_ASCENT].value) > 100)) 8830 && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
8823 return 0; 8831 return 0;
8832
8824 /* Must specify either the :data or :file keyword. This should 8833 /* Must specify either the :data or :file keyword. This should
8825 ** probably be moved up into parse_image_spec, since it seems to be 8834 probably be moved up into parse_image_spec, since it seems to be
8826 ** a general requirement. 8835 a general requirement. */
8827 */ 8836 return fmt[TIFF_FILE].count || fmt[TIFF_DATA].count;
8828 if (!fmt[TIFF_FILE].count && !fmt[TIFF_DATA].count)
8829 return 0;
8830 return 1;
8831} 8837}
8832 8838
8833/* Reading from a memory buffer for TIFF images 8839
8834 Based on the PNG memory source, but we have to provide a lot of 8840/* Reading from a memory buffer for TIFF images Based on the PNG
8835 extra functions. Blah. 8841 memory source, but we have to provide a lot of extra functions.
8842 Blah.
8836 8843
8837 We really only need to implement read and seek, but I am not 8844 We really only need to implement read and seek, but I am not
8838 convinced that the TIFF library is smart enough not to destroy 8845 convinced that the TIFF library is smart enough not to destroy
8839 itself if we only hand it the function pointers we need to 8846 itself if we only hand it the function pointers we need to
8840 override. */ 8847 override. */
8841typedef struct { 8848
8849typedef struct
8850{
8842 unsigned char *bytes; 8851 unsigned char *bytes;
8843 size_t len; 8852 size_t len;
8844 int index; 8853 int index;
8845} tiff_memory_source; 8854}
8855tiff_memory_source;
8846 8856
8847static size_t tiff_read_from_memory(thandle_t data, tdata_t buf, tsize_t size) 8857static size_t
8858tiff_read_from_memory (data, buf, size)
8859 thandle_t data;
8860 tdata_t buf;
8861 tsize_t size;
8848{ 8862{
8849 tiff_memory_source *src = (tiff_memory_source *)data; 8863 tiff_memory_source *src = (tiff_memory_source *) data;
8850 8864
8851 if (size > src->len - src->index) 8865 if (size > src->len - src->index)
8852 return (size_t) -1; 8866 return (size_t) -1;
8853 memcpy(buf, src->bytes + src->index, size); 8867 bcopy (src->bytes + src->index, buf, size);
8854 src->index += size; 8868 src->index += size;
8855 return size; 8869 return size;
8856} 8870}
8857 8871
8858static size_t tiff_write_from_memory(thandle_t data, tdata_t buf, tsize_t size) 8872static size_t
8873tiff_write_from_memory (data, buf, size)
8874 thandle_t data;
8875 tdata_t buf;
8876 tsize_t size;
8859{ 8877{
8860 return (size_t) -1; 8878 return (size_t) -1;
8861} 8879}
8862 8880
8863static toff_t tiff_seek_in_memory(thandle_t data, toff_t off, int whence) 8881static toff_t
8882tiff_seek_in_memory (data, off, whence)
8883 thandle_t data;
8884 toff_t off;
8885 int whence;
8864{ 8886{
8865 tiff_memory_source *src = (tiff_memory_source *)data; 8887 tiff_memory_source *src = (tiff_memory_source *) data;
8866 int idx; 8888 int idx;
8867 8889
8868 switch (whence) 8890 switch (whence)
8869 { 8891 {
8870 case SEEK_SET: /* Go from beginning of source */ 8892 case SEEK_SET: /* Go from beginning of source. */
8871 idx = off; 8893 idx = off;
8872 break; 8894 break;
8873 case SEEK_END: /* Go from end of source */ 8895
8874 idx = src->len + off; 8896 case SEEK_END: /* Go from end of source. */
8875 break; 8897 idx = src->len + off;
8876 case SEEK_CUR: /* Go from current position */ 8898 break;
8877 idx = src->index + off; 8899
8878 break; 8900 case SEEK_CUR: /* Go from current position. */
8879 default: /* Invalid `whence' */ 8901 idx = src->index + off;
8880 return(-1); 8902 break;
8881 } 8903
8882 if ((idx > src->len) || (idx < 0)) 8904 default: /* Invalid `whence'. */
8883 return -1; 8905 return -1;
8906 }
8907
8908 if (idx > src->len || idx < 0)
8909 return -1;
8910
8884 src->index = idx; 8911 src->index = idx;
8885 return src->index; 8912 return src->index;
8886} 8913}
8887 8914
8888static int tiff_close_memory(thandle_t data) 8915static int
8916tiff_close_memory (data)
8917 thandle_t data;
8889{ 8918{
8890 /* NOOP */ 8919 /* NOOP */
8891 return(0); 8920 return 0;
8892} 8921}
8893 8922
8894static int tiff_mmap_memory(thandle_t data, tdata_t *pbase, toff_t *psize) 8923static int
8924tiff_mmap_memory (data, pbase, psize)
8925 thandle_t data;
8926 tdata_t *pbase;
8927 toff_t *psize;
8895{ 8928{
8896 /* It is already _IN_ memory. */ 8929 /* It is already _IN_ memory. */
8897 return(0); 8930 return 0;
8898} 8931}
8899 8932
8900static void tiff_unmap_memory(thandle_t data, tdata_t base, toff_t size) 8933static void
8934tiff_unmap_memory (data, base, size)
8935 thandle_t data;
8936 tdata_t base;
8937 toff_t size;
8901{ 8938{
8902 /* We don't need to do this. */ 8939 /* We don't need to do this. */
8903 return;
8904} 8940}
8905 8941
8906static toff_t tiff_size_of_memory(thandle_t data) 8942static toff_t
8943tiff_size_of_memory (data)
8944 thandle_t data;
8907{ 8945{
8908 return(((tiff_memory_source *) data)->len); 8946 return ((tiff_memory_source *) data)->len;
8909} 8947}
8910 8948
8911/* Load TIFF image IMG for use on frame F. Value is non-zero if 8949/* Load TIFF image IMG for use on frame F. Value is non-zero if
@@ -8928,51 +8966,53 @@ tiff_load (f, img)
8928 8966
8929 specified_file = image_spec_value (img->spec, QCfile, NULL); 8967 specified_file = image_spec_value (img->spec, QCfile, NULL);
8930 specified_data = image_spec_value (img->spec, QCdata, NULL); 8968 specified_data = image_spec_value (img->spec, QCdata, NULL);
8969 file = Qnil;
8970 GCPRO1 (file);
8931 8971
8932 if (NILP (specified_data)) 8972 if (NILP (specified_data))
8973 {
8974 /* Read from a file */
8975 file = x_find_image_file (specified_file);
8976 if (!STRINGP (file))
8933 { 8977 {
8934 /* Read from a file */ 8978 image_error ("Cannot find image file %s", file, Qnil);
8935 file = x_find_image_file (specified_file); 8979 UNGCPRO;
8936 GCPRO1 (file); 8980 return 0;
8937 if (!STRINGP (file)) 8981 }
8938 {
8939 image_error ("Cannot find image file %s", file, Qnil);
8940 UNGCPRO;
8941 return 0;
8942 }
8943 8982
8944 /* Try to open the image file. */ 8983 /* Try to open the image file. */
8945 tiff = TIFFOpen (XSTRING (file)->data, "r"); 8984 tiff = TIFFOpen (XSTRING (file)->data, "r");
8946 if (tiff == NULL) 8985 if (tiff == NULL)
8947 { 8986 {
8948 image_error ("Cannot open `%s'", file, Qnil); 8987 image_error ("Cannot open `%s'", file, Qnil);
8949 UNGCPRO; 8988 UNGCPRO;
8950 return 0; 8989 return 0;
8951 }
8952 } 8990 }
8991 }
8953 else 8992 else
8993 {
8994 /* Memory source! */
8995 memsrc.bytes = XSTRING (specified_data)->data;
8996 memsrc.len = STRING_BYTES (XSTRING (specified_data));
8997 memsrc.index = 0;
8998
8999 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
9000 (TIFFReadWriteProc) tiff_read_from_memory,
9001 (TIFFReadWriteProc) tiff_write_from_memory,
9002 tiff_seek_in_memory,
9003 tiff_close_memory,
9004 tiff_size_of_memory,
9005 tiff_mmap_memory,
9006 tiff_unmap_memory);
9007
9008 if (!tiff)
8954 { 9009 {
8955 /* Memory source! */ 9010 image_error ("Cannot open memory source `%s'. ",
8956 memsrc.bytes = XSTRING (specified_data)->data; 9011 specified_data, Qnil);
8957 memsrc.len = STRING_BYTES (XSTRING (specified_data)); 9012 UNGCPRO;
8958 memsrc.index = 0; 9013 return 0;
8959
8960 tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
8961 (TIFFReadWriteProc)tiff_read_from_memory,
8962 (TIFFReadWriteProc)tiff_write_from_memory,
8963 tiff_seek_in_memory,
8964 tiff_close_memory,
8965 tiff_size_of_memory,
8966 tiff_mmap_memory,
8967 tiff_unmap_memory);
8968
8969 if (!tiff)
8970 {
8971 image_error ("Cannot open memory source `%s'. ", specified_data, Qnil);
8972 UNGCPRO;
8973 return 0;
8974 }
8975 } 9014 }
9015 }
8976 9016
8977 /* Get width and height of the image, and allocate a raster buffer 9017 /* Get width and height of the image, and allocate a raster buffer
8978 of width x height 32-bit values. */ 9018 of width x height 32-bit values. */
@@ -9078,7 +9118,7 @@ enum gif_keyword_index
9078static struct image_keyword gif_format[GIF_LAST] = 9118static struct image_keyword gif_format[GIF_LAST] =
9079{ 9119{
9080 {":type", IMAGE_SYMBOL_VALUE, 1}, 9120 {":type", IMAGE_SYMBOL_VALUE, 1},
9081 {":data", IMAGE_STRING_VALUE, 0}, 9121 {":data", IMAGE_STRING_VALUE, 0},
9082 {":file", IMAGE_STRING_VALUE, 0}, 9122 {":file", IMAGE_STRING_VALUE, 0},
9083 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}, 9123 {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
9084 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, 9124 {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0},
@@ -9113,36 +9153,41 @@ gif_image_p (object)
9113 || (fmt[GIF_ASCENT].count 9153 || (fmt[GIF_ASCENT].count
9114 && XFASTINT (fmt[GIF_ASCENT].value) > 100)) 9154 && XFASTINT (fmt[GIF_ASCENT].value) > 100))
9115 return 0; 9155 return 0;
9156
9116 /* Must specify either the :data or :file keyword. This should 9157 /* Must specify either the :data or :file keyword. This should
9117 ** probably be moved up into parse_image_spec, since it seems to be 9158 probably be moved up into parse_image_spec, since it seems to be
9118 ** a general requirement. 9159 a general requirement. */
9119 */ 9160 return fmt[GIF_FILE].count || fmt[GIF_DATA].count;
9120 if (!fmt[GIF_FILE].count && !fmt[GIF_DATA].count)
9121 return 0;
9122 return 1;
9123} 9161}
9124 9162
9125/* Reading a GIF image from memory 9163/* Reading a GIF image from memory
9126 Based on the PNG memory stuff to a certain extent. */ 9164 Based on the PNG memory stuff to a certain extent. */
9127 9165
9128typedef struct { 9166typedef struct
9167{
9129 unsigned char *bytes; 9168 unsigned char *bytes;
9130 size_t len; 9169 size_t len;
9131 int index; 9170 int index;
9132} gif_memory_source; 9171}
9172gif_memory_source;
9133 9173
9134static int gif_read_from_memory(GifFileType *file, GifByteType *buf, int len) 9174static int
9175gif_read_from_memory (file, buf, len)
9176 GifFileType *file;
9177 GifByteType *buf;
9178 int len;
9135{ 9179{
9136 gif_memory_source *src = (gif_memory_source *) file->UserData; 9180 gif_memory_source *src = (gif_memory_source *) file->UserData;
9137 9181
9138 if (len > (src->len - src->index)) 9182 if (len > src->len - src->index)
9139 return -1; 9183 return -1;
9140 9184
9141 memcpy(buf, src->bytes + src->index, len); 9185 bcopy (src->bytes + src->index, buf, len);
9142 src->index += len; 9186 src->index += len;
9143 return len; 9187 return len;
9144} 9188}
9145 9189
9190
9146/* Load GIF image IMG for use on frame F. Value is non-zero if 9191/* Load GIF image IMG for use on frame F. Value is non-zero if
9147 successful. */ 9192 successful. */
9148 9193
@@ -9165,42 +9210,43 @@ gif_load (f, img)
9165 9210
9166 specified_file = image_spec_value (img->spec, QCfile, NULL); 9211 specified_file = image_spec_value (img->spec, QCfile, NULL);
9167 specified_data = image_spec_value (img->spec, QCdata, NULL); 9212 specified_data = image_spec_value (img->spec, QCdata, NULL);
9213 file = Qnil;
9214 GCPRO1 (file);
9168 9215
9169 if (NILP (specified_data)) 9216 if (NILP (specified_data))
9217 {
9218 file = x_find_image_file (specified_file);
9219 if (!STRINGP (file))
9170 { 9220 {
9171 file = x_find_image_file (specified_file); 9221 image_error ("Cannot find image file %s", specified_file, Qnil);
9172 GCPRO1 (file); 9222 UNGCPRO;
9173 if (!STRINGP (file)) 9223 return 0;
9174 { 9224 }
9175 image_error ("Cannot find image file %s", specified_file, Qnil);
9176 UNGCPRO;
9177 return 0;
9178 }
9179 9225
9180 /* Open the GIF file. */ 9226 /* Open the GIF file. */
9181 gif = DGifOpenFileName (XSTRING (file)->data); 9227 gif = DGifOpenFileName (XSTRING (file)->data);
9182 if (gif == NULL) 9228 if (gif == NULL)
9183 { 9229 {
9184 image_error ("Cannot open `%s'", file, Qnil); 9230 image_error ("Cannot open `%s'", file, Qnil);
9185 UNGCPRO; 9231 UNGCPRO;
9186 return 0; 9232 return 0;
9187 }
9188 } 9233 }
9234 }
9189 else 9235 else
9190 { 9236 {
9191 /* Read from memory! */ 9237 /* Read from memory! */
9192 memsrc.bytes = XSTRING (specified_data)->data; 9238 memsrc.bytes = XSTRING (specified_data)->data;
9193 memsrc.len = STRING_BYTES (XSTRING (specified_data)); 9239 memsrc.len = STRING_BYTES (XSTRING (specified_data));
9194 memsrc.index = 0; 9240 memsrc.index = 0;
9195 9241
9196 gif = DGifOpen(&memsrc, gif_read_from_memory); 9242 gif = DGifOpen(&memsrc, gif_read_from_memory);
9197 if (!gif) 9243 if (!gif)
9198 { 9244 {
9199 image_error ("Cannot open memory source `%s'",specified_data, Qnil); 9245 image_error ("Cannot open memory source `%s'",specified_data, Qnil);
9200 UNGCPRO; 9246 UNGCPRO;
9201 return 0; 9247 return 0;
9202 }
9203 } 9248 }
9249 }
9204 9250
9205 /* Read entire contents. */ 9251 /* Read entire contents. */
9206 rc = DGifSlurp (gif); 9252 rc = DGifSlurp (gif);