comparison src/glyphs-x.c @ 251:677f6a0ee643 r20-5b24

Import from CVS: tag r20-5b24
author cvs
date Mon, 13 Aug 2007 10:19:59 +0200
parents f220cc83d72e
children 11cf20601dec
comparison
equal deleted inserted replaced
250:f385a461c9aa 251:677f6a0ee643
35 Improved GIF/JPEG support added by Bill Perry for 19.14 35 Improved GIF/JPEG support added by Bill Perry for 19.14
36 Cleanup/simplification of error handling by Ben Wing for 19.14 36 Cleanup/simplification of error handling by Ben Wing for 19.14
37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14 37 Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38 38
39 TODO: 39 TODO:
40 ImageMagick support
41 Convert images.el to C and stick it in here? 40 Convert images.el to C and stick it in here?
42 */ 41 */
43 42
44 #include <config.h> 43 #include <config.h>
45 #include <setjmp.h>
46 #include "lisp.h" 44 #include "lisp.h"
47 45 #include "lstream.h"
48 #include "console-x.h" 46 #include "console-x.h"
49 #include "glyphs-x.h" 47 #include "glyphs-x.h"
50 #include "objects-x.h" 48 #include "objects-x.h"
51 #include "xmu.h" 49 #include "xmu.h"
52 50
55 #include "insdel.h" 53 #include "insdel.h"
56 #include "opaque.h" 54 #include "opaque.h"
57 55
58 #include "sysfile.h" 56 #include "sysfile.h"
59 57
60 #ifdef HAVE_IMAGEMAGICK 58 #ifdef HAVE_PNG
61 #define _XOS_H_ 59 #ifdef __cplusplus
62 #ifdef MAGICK_HEADERS_ARE_UNDER_X11 60 extern "C" {
63 #include <X11/magick/magick.h> 61 #endif
62 #include <png.h>
63 #ifdef __cplusplus
64 }
65 #endif
64 #else 66 #else
65 #include <magick/magick.h> 67 #include <setjmp.h>
66 #endif 68 #endif
67 /*#include <image.h>*/ 69
68 /*#include <assert.h>*/ 70 #ifdef MULE
69 71 #include "mule-coding.h"
70 #define OLDCOMPAT /* allow lisp code using the old names to still function */
71 #endif 72 #endif
72 73
73 #define LISP_DEVICE_TO_X_SCREEN(dev) \ 74 #define LISP_DEVICE_TO_X_SCREEN(dev) \
74 XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) 75 XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
75 76
88 #ifdef HAVE_XFACE 89 #ifdef HAVE_XFACE
89 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface); 90 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
90 Lisp_Object Qxface; 91 Lisp_Object Qxface;
91 #endif 92 #endif
92 93
93 #ifdef HAVE_IMAGEMAGICK 94 #ifdef HAVE_TIFF
94 DEFINE_IMAGE_INSTANTIATOR_FORMAT (imagick);
95 Lisp_Object Qimagick;
96
97 #ifdef OLDCOMPAT /* old compatibility */
98 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff); 95 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff);
96 Lisp_Object Qtiff;
97 #endif
98
99 #ifdef HAVE_JPEG
100 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
101 Lisp_Object Qjpeg;
102 #endif
103
104 #ifdef HAVE_GIF
105 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
106 Lisp_Object Qgif;
107 #endif
108
109 #ifdef HAVE_PNG
99 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png); 110 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png);
100 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
101 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
102 Lisp_Object Qtiff;
103 Lisp_Object Qpng; 111 Lisp_Object Qpng;
104 Lisp_Object Qgif;
105 Lisp_Object Qjpeg;
106 #endif
107 #endif 112 #endif
108 113
109 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); 114 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
110 Lisp_Object Qcursor_font; 115 Lisp_Object Qcursor_font;
111 116
437 } 442 }
438 443
439 static void 444 static void
440 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out) 445 write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out)
441 { 446 {
442 Extbyte *bytes; 447 Lisp_Object instream, outstream;
443 Extcount len; 448 Lstream *istr, *ostr;
444 FILE *stream; 449 char tempbuf[1024]; /* some random amount */
445 450 int fubar = 0;
446 /* #### This is a definite problem under Mule due to the amount of 451 FILE *tmpfil;
447 stack data it might allocate. Need to be able to convert and 452 static Extbyte_dynarr *conversion_out_dynarr = NULL;
448 write out to a file. */ 453 Bytecount bstart, bend;
449 GET_STRING_BINARY_DATA_ALLOCA (string, bytes, len); 454 struct gcpro gcpro1, gcpro2;
450 455 #ifdef MULE
451 /* Write out to a temporary file ... */ 456 Lisp_Object conv_out_stream;
457 Lstream *costr;
458 struct gcpro gcpro3;
459 #endif
460
461 /* This function can GC */
462 if (!conversion_out_dynarr)
463 conversion_out_dynarr = Dynarr_new (Extbyte);
464 else
465 Dynarr_reset (conversion_out_dynarr);
466
467 /* Create the temporary file ... */
452 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ()); 468 sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ());
453 mktemp (filename_out); 469 mktemp (filename_out);
454 stream = fopen (filename_out, "w"); 470 tmpfil = fopen (filename_out, "w");
455 if (!stream) 471 if (!tmpfil)
456 { 472 {
457 temp_file_error: 473 if (tmpfil)
458 if (stream)
459 { 474 {
460 int old_errno = errno; 475 int old_errno = errno;
461 fclose (stream); 476 fclose (tmpfil);
462 unlink (filename_out); 477 unlink (filename_out);
463 errno = old_errno; 478 errno = old_errno;
464 } 479 }
465 report_file_error ("Creating temp file", 480 report_file_error ("Creating temp file",
466 list1 (build_string (filename_out))); 481 list1 (build_string (filename_out)));
467 } 482 }
468 483
469 if (fwrite (bytes, len, 1, stream) != 1) 484 CHECK_STRING (string);
470 goto temp_file_error; 485 get_string_range_byte (string, Qnil, Qnil, &bstart, &bend,
471 486 GB_HISTORICAL_STRING_BEHAVIOR);
472 if (fclose (stream) != 0) 487 instream = make_lisp_string_input_stream (string, bstart, bend);
473 { 488 istr = XLSTREAM (instream);
474 stream = 0; 489 /* setup the out stream */
475 goto temp_file_error; 490 outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr);
476 } 491 ostr = XLSTREAM (outstream);
492 #ifdef MULE
493 /* setup the conversion stream */
494 conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary));
495 costr = XLSTREAM (conv_out_stream);
496 GCPRO3 (instream, outstream, conv_out_stream);
497 #else
498 GCPRO2 (instream, outstream);
499 #endif
500
501 /* Get the data while doing the conversion */
502 while (1) {
503 int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf));
504 if (!size_in_bytes)
505 break;
506 /* It does seem the flushes are necessary... */
507 #ifdef MULE
508 Lstream_write (costr, tempbuf, size_in_bytes);
509 Lstream_flush (costr);
510 #else
511 Lstream_write (ostr, tempbuf, size_in_bytes);
512 #endif
513 Lstream_flush (ostr);
514 if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0),
515 Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1)
516 {
517 fubar = 1;
518 break;
519 }
520 /* reset the dynarr */
521 Lstream_rewind(ostr);
522 }
523
524 if (fclose (tmpfil) != 0)
525 fubar = 1;
526 Lstream_close (istr);
527 #ifdef MULE
528 Lstream_close (costr);
529 #endif
530 Lstream_close (ostr);
531
532 UNGCPRO;
533 Lstream_delete (istr);
534 Lstream_delete (ostr);
535 #ifdef MULE
536 Lstream_delete (costr);
537 #endif
538 if (fubar)
539 report_file_error ("Writing temp file",
540 list1 (build_string (filename_out)));
477 } 541 }
478 542
479 543
480 /************************************************************************/ 544 /************************************************************************/
481 /* cursor functions */ 545 /* cursor functions */
1381 1445
1382 if (!DEVICE_X_P (XDEVICE (device))) 1446 if (!DEVICE_X_P (XDEVICE (device)))
1383 signal_simple_error ("Not an X device", device); 1447 signal_simple_error ("Not an X device", device);
1384 1448
1385 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 1449 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1386 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1387 depth = DEVICE_X_DEPTH (XDEVICE(device));
1388 xs = DefaultScreenOfDisplay (dpy); 1450 xs = DefaultScreenOfDisplay (dpy);
1389 1451
1390 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK) 1452 if (dest_mask & IMAGE_COLOR_PIXMAP_MASK)
1391 type = IMAGE_COLOR_PIXMAP; 1453 type = IMAGE_COLOR_PIXMAP;
1392 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK) 1454 else if (dest_mask & IMAGE_MONO_PIXMAP_MASK)
1396 else 1458 else
1397 incompatible_image_types (instantiator, dest_mask, 1459 incompatible_image_types (instantiator, dest_mask,
1398 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK 1460 IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
1399 | IMAGE_POINTER_MASK); 1461 | IMAGE_POINTER_MASK);
1400 force_mono = (type != IMAGE_COLOR_PIXMAP); 1462 force_mono = (type != IMAGE_COLOR_PIXMAP);
1463
1464 #if 0
1465 /* Although I haven't found it documented yet, it appears that pointers are
1466 always colored via the default window colormap... Sigh. However, with
1467 the current color structure, this will blow the doors off as things aren't set up
1468 to differenciate between two colormaps per console. AARGH! */
1469 if (type == IMAGE_POINTER)
1470 {
1471 cmap = DefaultColormap(dpy, DefaultScreen(dpy));
1472 depth = DefaultDepthOfScreen (xs);
1473 }
1474 else
1475 {
1476 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1477 depth = DEVICE_X_DEPTH (XDEVICE(device));
1478 }
1479 #else
1480 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1481 depth = DEVICE_X_DEPTH (XDEVICE(device));
1482 #endif
1401 1483
1402 x_initialize_pixmap_image_instance (ii, type); 1484 x_initialize_pixmap_image_instance (ii, type);
1403 1485
1404 assert (!NILP (data)); 1486 assert (!NILP (data));
1405 1487
1673 } 1755 }
1674 1756
1675 #endif /* HAVE_XPM */ 1757 #endif /* HAVE_XPM */
1676 1758
1677 1759
1678 #ifdef HAVE_IMAGEMAGICK 1760 #ifdef HAVE_JPEG
1761
1679 /********************************************************************** 1762 /**********************************************************************
1680 * ImageMagick * 1763 * JPEG *
1681 **********************************************************************/ 1764 **********************************************************************/
1682 JMP_BUF imagick_jump; 1765
1683 Lisp_Object imagick_err; /* slightly hackish way to return a proper error message */ 1766 #ifdef __cplusplus
1684 1767 extern "C" {
1768 #endif
1769 #include <jpeglib.h>
1770 #include <jerror.h>
1771 #ifdef __cplusplus
1772 }
1773 #endif
1774
1775 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/
1685 static void 1776 static void
1686 imagick_validate (Lisp_Object instantiator) 1777 jpeg_validate (Lisp_Object instantiator)
1687 { 1778 {
1688 file_or_data_must_be_present (instantiator); 1779 file_or_data_must_be_present (instantiator);
1689 } 1780 }
1781
1782 static Lisp_Object
1783 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type)
1784 {
1785 return simple_image_type_normalize (inst, console_type, Qjpeg);
1786 }
1787
1788 static int
1789 jpeg_possible_dest_types (void)
1790 {
1791 return IMAGE_COLOR_PIXMAP_MASK;
1792 }
1793
1794 /* To survive the otherwise baffling complexity of making sure
1795 everything gets cleaned up in the presence of an error, we
1796 use an unwind_protect(). */
1797
1798 struct jpeg_unwind_data
1799 {
1800 Display *dpy;
1801 Colormap cmap;
1802 /* Stream that we need to close */
1803 FILE *instream;
1804 /* Object that holds state info for JPEG decoding */
1805 struct jpeg_decompress_struct *cinfo_ptr;
1806 /* Pixels to keep around while the image is active */
1807 unsigned long *pixels;
1808 int npixels;
1809 /* Client-side image structure */
1810 XImage *ximage;
1811 /* Tempfile to remove */
1812 char tempfile[50];
1813 int tempfile_needs_to_be_removed;
1814 };
1815
1816 static Lisp_Object
1817 jpeg_instantiate_unwind (Lisp_Object unwind_obj)
1818 {
1819 struct jpeg_unwind_data *data =
1820 (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj);
1821
1822 free_opaque_ptr (unwind_obj);
1823 if (data->cinfo_ptr)
1824 jpeg_destroy_decompress (data->cinfo_ptr);
1825
1826 if (data->instream)
1827 fclose (data->instream);
1828
1829 if (data->tempfile_needs_to_be_removed)
1830 unlink (data->tempfile);
1831
1832 if (data->npixels > 0)
1833 {
1834 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
1835 xfree (data->pixels);
1836 }
1837
1838 if (data->ximage)
1839 {
1840 if (data->ximage->data)
1841 {
1842 xfree (data->ximage->data);
1843 data->ximage->data = 0;
1844 }
1845 XDestroyImage (data->ximage);
1846 }
1847
1848 return Qnil;
1849 }
1850
1851 /*
1852 * ERROR HANDLING:
1853 *
1854 * The JPEG library's standard error handler (jerror.c) is divided into
1855 * several "methods" which you can override individually. This lets you
1856 * adjust the behavior without duplicating a lot of code, which you might
1857 * have to update with each future release.
1858 *
1859 * Our example here shows how to override the "error_exit" method so that
1860 * control is returned to the library's caller when a fatal error occurs,
1861 * rather than calling exit() as the standard error_exit method does.
1862 *
1863 * We use C's setjmp/longjmp facility to return control. This means that the
1864 * routine which calls the JPEG library must first execute a setjmp() call to
1865 * establish the return point. We want the replacement error_exit to do a
1866 * longjmp(). But we need to make the setjmp buffer accessible to the
1867 * error_exit routine. To do this, we make a private extension of the
1868 * standard JPEG error handler object. (If we were using C++, we'd say we
1869 * were making a subclass of the regular error handler.)
1870 *
1871 * Here's the extended error handler struct:
1872 */
1873
1874 struct my_jpeg_error_mgr
1875 {
1876 struct jpeg_error_mgr pub; /* "public" fields */
1877 jmp_buf setjmp_buffer; /* for return to caller */
1878 };
1879
1880 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1881 METHODDEF(void)
1882 #else
1883 METHODDEF void
1884 #endif
1885 our_init_source (j_decompress_ptr cinfo) {
1886 }
1887
1888 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1889 METHODDEF(boolean)
1890 #else
1891 METHODDEF boolean
1892 #endif
1893 our_fill_input_buffer (j_decompress_ptr cinfo) {
1894 /* Insert a fake EOI marker */
1895 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
1896 static JOCTET buffer[2];
1897
1898 buffer[0] = (JOCTET) 0xFF;
1899 buffer[1] = (JOCTET) JPEG_EOI;
1900
1901 src->next_input_byte = buffer;
1902 src->bytes_in_buffer = 2;
1903 return TRUE;
1904 }
1905
1906 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1907 METHODDEF(void)
1908 #else
1909 METHODDEF void
1910 #endif
1911 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
1912 struct jpeg_source_mgr *src = NULL;
1913
1914 src = (struct jpeg_source_mgr *) cinfo->src;
1915
1916 if (!src) {
1917 return;
1918 } else if (num_bytes > src->bytes_in_buffer) {
1919 ERREXIT(cinfo, JERR_INPUT_EOF);
1920 /*NOTREACHED*/
1921 }
1922
1923 src->bytes_in_buffer -= num_bytes;
1924 src->next_input_byte += num_bytes;
1925 }
1926
1927 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1928 METHODDEF(void)
1929 #else
1930 METHODDEF void
1931 #endif
1932 our_term_source (j_decompress_ptr cinfo) {
1933 }
1934
1935 typedef struct {
1936 struct jpeg_source_mgr pub;
1937 } our_jpeg_source_mgr;
1690 1938
1691 static void 1939 static void
1692 imagick_error_handler (const char *message,const char *qualifier) 1940 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
1693 { 1941 {
1694 /* ImageMagick defaults to exiting on errors, which is an anti-thing. 1942 struct jpeg_source_mgr *src = NULL;
1695 * Dump the info into imagick_err, and jmp back */ 1943
1696 if (qualifier != NULL) 1944 if (cinfo->src == NULL) { /* first time for this JPEG object? */
1697 imagick_err = emacs_doprnt_string_c((CONST Bufbyte *) GETTEXT ("ImageMagick error: %s (%s)"), 1945 cinfo->src = (struct jpeg_source_mgr *)
1698 Qnil, -1, message, qualifier); 1946 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1699 else 1947 sizeof(our_jpeg_source_mgr));
1700 imagick_err = emacs_doprnt_string_c((CONST Bufbyte *) GETTEXT ("ImageMagick error: %s"), 1948 src = (struct jpeg_source_mgr *) cinfo->src;
1701 Qnil, -1, message); 1949 src->next_input_byte = data;
1702 LONGJMP(imagick_jump,1); 1950 }
1703 } 1951 src = (struct jpeg_source_mgr *) cinfo->src;
1704 1952 src->init_source = our_init_source;
1953 src->fill_input_buffer = our_fill_input_buffer;
1954 src->skip_input_data = our_skip_input_data;
1955 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
1956 src->term_source = our_term_source;
1957 src->bytes_in_buffer = len;
1958 src->next_input_byte = data;
1959 }
1960
1961 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1962 METHODDEF(void)
1963 #else
1964 METHODDEF void
1965 #endif
1966 my_jpeg_error_exit (j_common_ptr cinfo)
1967 {
1968 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
1969 struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err;
1970
1971 /* Return control to the setjmp point */
1972 longjmp (myerr->setjmp_buffer, 1);
1973 }
1974
1975 /* The code in this routine is based on example.c from the JPEG library
1976 source code and from gif_instantiate() */
1705 static void 1977 static void
1706 imagick_warning_handler (const char *message,const char *qualifier) 1978 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1707 { 1979 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1708 if (qualifier != NULL) 1980 int dest_mask, Lisp_Object domain)
1709 warn_when_safe(Qimagick, Qwarning, "ImageMagick warning: %s (%s)",message,qualifier);
1710 else
1711 warn_when_safe(Qimagick, Qwarning, "ImageMagick warning: %s",message);
1712 }
1713
1714 static Lisp_Object
1715 imagick_normalize (Lisp_Object inst, Lisp_Object console_type)
1716 {
1717 return simple_image_type_normalize (inst, console_type, Qimagick);
1718 }
1719
1720 static int
1721 imagick_possible_dest_types (void)
1722 {
1723 return IMAGE_COLOR_PIXMAP_MASK;
1724 }
1725
1726 struct imagick_unwind_data
1727 {
1728 Display *dpy;
1729 Colormap cmap;
1730 FILE *instream;
1731 Image *image;
1732 XImage *ximage;
1733 unsigned long *pixels;
1734 unsigned long npixels;
1735 char tempfile[50];
1736 int tempfile_needs_to_be_removed;
1737 };
1738
1739 static Lisp_Object
1740 imagick_instantiate_unwind (Lisp_Object unwind_obj)
1741 {
1742 struct imagick_unwind_data *data =
1743 (struct imagick_unwind_data *) get_opaque_ptr (unwind_obj);
1744
1745 free_opaque_ptr (unwind_obj);
1746 if (data->instream)
1747 fclose (data->instream);
1748 if (data->tempfile_needs_to_be_removed)
1749 unlink (data->tempfile);
1750
1751 if (data->image) {
1752 DestroyImage(data->image);
1753 }
1754
1755 if (data->ximage) {
1756 if (data->ximage->data) {
1757 xfree (data->ximage->data);
1758 data->ximage->data = NULL;
1759 }
1760 XDestroyImage (data->ximage);
1761 }
1762
1763 if (data->npixels > 0) {
1764 XFreeColors(data->dpy, data->cmap, data->pixels, data->npixels, 0L);
1765 xfree (data->pixels);
1766 }
1767
1768 return Qnil;
1769 }
1770
1771 static void
1772 imagick_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1773 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1774 int dest_mask, Lisp_Object domain)
1775 { 1981 {
1776 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); 1982 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1777 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); 1983 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1778 Display *dpy; 1984 Display *dpy;
1779 Screen *scr; 1985 Screen *scr;
1780 Visual *visual;
1781 Colormap cmap; 1986 Colormap cmap;
1782 Dimension depth; 1987 Visual *vis;
1783 struct imagick_unwind_data unwind; 1988 /* It is OK for the unwind data to be local to this function,
1784 int speccount; 1989 because the unwind-protect is always executed when this
1785 ImageInfo image_info; 1990 stack frame is still valid. */
1786 1991 struct jpeg_unwind_data unwind;
1787 /* ImageMagick variables */ 1992 int speccount = specpdl_depth ();
1788 1993
1789 /* Basic error checking */ 1994 /* This struct contains the JPEG decompression parameters and pointers to
1995 * working space (which is allocated as needed by the JPEG library).
1996 */
1997 struct jpeg_decompress_struct cinfo;
1998 /* We use our private extension JPEG error handler.
1999 * Note that this struct must live as long as the main JPEG parameter
2000 * struct, to avoid dangling-pointer problems.
2001 */
2002 struct my_jpeg_error_mgr jerr;
2003
1790 if (!DEVICE_X_P (XDEVICE (device))) 2004 if (!DEVICE_X_P (XDEVICE (device)))
1791 signal_simple_error ("Not an X device", device); 2005 signal_simple_error ("Not an X device", device);
1792 2006
1793 dpy = DEVICE_X_DISPLAY (XDEVICE (device)); 2007 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1794 scr = DefaultScreenOfDisplay (dpy); 2008 scr = DefaultScreenOfDisplay (dpy);
1795 depth = DEVICE_X_DEPTH (XDEVICE (device));
1796 visual = DEVICE_X_VISUAL (XDEVICE (device));
1797 cmap = DEVICE_X_COLORMAP (XDEVICE(device)); 2009 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1798 2010 vis = DEVICE_X_VISUAL (XDEVICE(device));
1799 /* Set up the unwind */ 2011
2012 /* Step -1: First record our unwind-protect, which will clean up after
2013 any exit, normal or not */
2014
1800 memset (&unwind, 0, sizeof (unwind)); 2015 memset (&unwind, 0, sizeof (unwind));
1801 unwind.dpy = dpy; 2016 unwind.dpy = dpy;
1802 unwind.cmap = cmap; 2017 unwind.cmap = cmap;
1803 speccount = specpdl_depth(); 2018 record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind));
1804 record_unwind_protect(imagick_instantiate_unwind,make_opaque_ptr(&unwind)); 2019
1805 2020 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1806 /* Set up error handlers */ 2021 /* Step 0: Write out to a temp file.
1807 if (SETJMP(imagick_jump)) 2022
1808 { 2023 The JPEG routines require you to read from a file unless
1809 /* signal error GCPROs it's arguments */ 2024 you provide your own special input handlers, which I don't
1810 signal_error(Qerror, list2(imagick_err, instantiator)); 2025 feel like doing. */
1811 }
1812
1813 SetErrorHandler(imagick_error_handler);
1814 SetWarningHandler(imagick_warning_handler);
1815
1816 /* Write out to a temp file - not sure if ImageMagick supports the
1817 ** notion of an abstract 'data source' right now.
1818 ** JH: It doesn't as of 3.9.3
1819 */
1820 { 2026 {
1821 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 2027 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1822 2028
1823 assert (!NILP (data)); 2029 assert (!NILP (data));
1824 2030
1825 write_lisp_string_to_temp_file (data, unwind.tempfile); 2031 write_lisp_string_to_temp_file (data, unwind.tempfile);
1826 unwind.tempfile_needs_to_be_removed = 1; 2032 unwind.tempfile_needs_to_be_removed = 1;
1827 2033
1828 if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL) 2034 /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
1829 report_file_error ("Opening ImageMagick temp file", 2035 * requires it in order to read binary files.
2036 */
2037
2038 if ((unwind.instream = fopen (unwind.tempfile, "r")) == NULL)
2039 report_file_error ("Opening JPEG temp file",
1830 list1 (build_string (unwind.tempfile))); 2040 list1 (build_string (unwind.tempfile)));
1831 } 2041 }
1832 2042 #endif
1833 /* Initialize structures and read in the image */ 2043
1834 GetImageInfo(&image_info); 2044 /* Step 1: allocate and initialize JPEG decompression object */
1835 strcpy(image_info.filename,unwind.tempfile); 2045
1836 unwind.image = ReadImage(&image_info); 2046 /* We set up the normal JPEG error routines, then override error_exit. */
1837 2047 cinfo.err = jpeg_std_error (&jerr.pub);
1838 if (unwind.image == (Image *) NULL) { 2048 jerr.pub.error_exit = my_jpeg_error_exit;
1839 signal_simple_error ("Unable to read image.",instantiator); 2049
2050 /* Establish the setjmp return context for my_error_exit to use. */
2051 if (setjmp (jerr.setjmp_buffer))
2052 {
2053 /* If we get here, the JPEG code has signaled an error.
2054 * We need to clean up the JPEG object, close the input file, and return.
2055 */
2056
2057 {
2058 Lisp_Object errstring;
2059 char buffer[JMSG_LENGTH_MAX];
2060
2061 /* Create the message */
2062 (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer);
2063 errstring = build_string (buffer);
2064
2065 signal_simple_error_2 ("JPEG decoding error",
2066 errstring, instantiator);
2067 }
2068 }
2069
2070 /* Now we can initialize the JPEG decompression object. */
2071 jpeg_create_decompress (&cinfo);
2072 unwind.cinfo_ptr = &cinfo;
2073
2074 /* Step 2: specify data source (eg, a file) */
2075
2076 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
2077 jpeg_stdio_src (&cinfo, unwind.instream);
2078 #else
2079 {
2080 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2081 Extbyte *bytes;
2082 Extcount len;
2083
2084 /* #### This is a definite problem under Mule due to the amount of
2085 stack data it might allocate. Need to be able to convert and
2086 write out to a file. */
2087 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2088 jpeg_memory_src (&cinfo, bytes, len);
1840 } 2089 }
1841 2090 #endif
1842 #if 1 2091
1843 /* 2092 /* Step 3: read file parameters with jpeg_read_header() */
1844 * For now, force dithering everything, and deal with all images as if they 2093
1845 * were PseudoClass images 2094 jpeg_read_header (&cinfo, TRUE);
2095 /* We can ignore the return value from jpeg_read_header since
2096 * (a) suspension is not possible with the stdio data source, and
2097 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
2098 * See libjpeg.doc for more info.
1846 */ 2099 */
1847 if (unwind.image->class != PseudoClass) { 2100
1848 QuantizeInfo quantize_info; 2101 /* Step 4: set parameters for decompression. */
1849 GetQuantizeInfo(&quantize_info); 2102
1850 quantize_info.number_colors=256; 2103 /* We request that the JPEG file be automatically quantized into
1851 quantize_info.tree_depth=8; 2104 8-bit color in case it's not already (many JPEGs are stored in
1852 quantize_info.dither=True; 2105 24-bit color). "Two-pass quantize" means that the colormap
1853 quantize_info.colorspace=RGBColorspace; 2106 is determined on-the-fly for this particular image rather than
1854 QuantizeImage(&quantize_info, unwind.image); 2107 quantizing to a supplied colormap. We can get away with this
1855 SyncImage(unwind.image); 2108 because we then use allocate_nearest_color().
1856 /* #### It would probably be a good idea to sort the colormap by popularity, 2109
1857 * so that in case we run out of entries in the map, it will likely be on 2110 #### Note of course that this is not the most color-effective
1858 * the less used colors 2111 way of doing things -- we could quantize an image that has
2112 lots of very similar colors, and eat up the colormap with these
2113 (useless to other images) colors. Unfortunately I don't think
2114 there's any "general" way of maximizing the overall image
2115 quality of lots of images, given that we don't know the
2116 colors of the images until we come across each one. Best we
2117 could do would be various sorts of heuristics, which I don't
2118 feel like dealing with now. A better scheme would be the
2119 way things are done under MS Windows, where the colormap is
2120 dynamically adjusted for various applications; but that kind
2121 of thing would have to be provided by X, which it isn't. */
2122
2123 cinfo.quantize_colors = TRUE;
2124 cinfo.two_pass_quantize = TRUE;
2125 cinfo.colormap = NULL;
2126
2127 /* Step 5: Start decompressor */
2128
2129 jpeg_start_decompress (&cinfo);
2130 /* We can ignore the return value since suspension is not possible
2131 * with the stdio data source.
2132 */
2133
2134 /* At this point we know the size of the image and the colormap. */
2135
2136 /* Step 5.33: Allocate the colors */
2137 {
2138 int i;
2139
2140 /* Just in case the image contains out-of-range pixels, we go
2141 ahead and allocate space for all of them. */
2142 unwind.pixels = xnew_array (unsigned long, 256);
2143 unwind.npixels = cinfo.actual_number_of_colors;
2144
2145 for (i = 0; i < 256; i++)
2146 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
2147
2148 /* Allocate pixels for the various colors. */
2149 for (i = 0; i < unwind.npixels; i++)
2150 {
2151 XColor color;
2152 int ri, gi, bi;
2153
2154 ri = 0;
2155 gi = cinfo.out_color_components > 1 ? 1 : 0;
2156 bi = cinfo.out_color_components > 2 ? 2 : 0;
2157
2158 /* Ok... apparently, an entry of cinfo.colormap can be NULL if
2159 there are no bits of that color in the image. How incredibly
2160 gross. Wouldn't it be nice to have exceptions!? */
2161 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0;
2162 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0;
2163 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0;
2164 color.flags = DoRed | DoGreen | DoBlue;
2165
2166 allocate_nearest_color (dpy, cmap, vis, &color);
2167 unwind.pixels[i] = color.pixel;
2168 }
2169 }
2170
2171 /* Step 5.66: Create the image */
2172 {
2173 int height = cinfo.output_height;
2174 int width = cinfo.output_width;
2175 int depth;
2176 int bitmap_pad;
2177
2178 depth = DEVICE_X_DEPTH(XDEVICE(device));
2179
2180 /* first get bitmap_pad (from XPM) */
2181 bitmap_pad = ((depth > 16) ? 32 :
2182 (depth > 8) ? 16 :
2183 8);
2184
2185 unwind.ximage = XCreateImage (dpy, DefaultVisualOfScreen (scr),
2186 depth, ZPixmap, 0, 0, width, height,
2187 bitmap_pad, 0);
2188
2189 if (!unwind.ximage)
2190 signal_simple_error ("Unable to create X image struct", instantiator);
2191
2192 /* now that bytes_per_line must have been set properly alloc data */
2193 unwind.ximage->data =
2194 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
2195 }
2196
2197 /* Step 6: Read in the data and put into image */
2198 {
2199 JSAMPARRAY row_buffer; /* Output row buffer */
2200 int row_stride; /* physical row width in output buffer */
2201
2202 /* We may need to do some setup of our own at this point before reading
2203 * the data. After jpeg_start_decompress() we have the correct scaled
2204 * output image dimensions available, as well as the output colormap
2205 * if we asked for color quantization.
2206 * In this example, we need to make an output work buffer of the right size.
1859 */ 2207 */
1860 } else { 2208 /* JSAMPLEs per row in output buffer.
1861 CompressColormap(unwind.image); 2209 Since we asked for quantized output, cinfo.output_components
1862 SyncImage(unwind.image); 2210 will always be 1. */
2211 row_stride = cinfo.output_width * cinfo.output_components;
2212 /* Make a one-row-high sample array that will go away when done
2213 with image */
2214 row_buffer = ((*cinfo.mem->alloc_sarray)
2215 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
2216
2217 /* Here we use the library's state variable cinfo.output_scanline as the
2218 * loop counter, so that we don't have to keep track ourselves.
2219 */
2220 while (cinfo.output_scanline < cinfo.output_height)
2221 {
2222 int i;
2223 int scanline = cinfo.output_scanline;
2224
2225 /* jpeg_read_scanlines expects an array of pointers to scanlines.
2226 * Here the array is only one element long, but you could ask for
2227 * more than one scanline at a time if that's more convenient.
2228 */
2229 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
2230
2231 for (i = 0; i < cinfo.output_width; i++)
2232 XPutPixel (unwind.ximage, i, scanline,
2233 /* Let's make sure we avoid getting bit like
2234 what happened for GIF's. It's probably the
2235 case that JSAMPLE's are unsigned chars as
2236 opposed to chars, but you never know.
2237
2238 (They could even be shorts if the library
2239 was compiled with 12-bit samples -- ####
2240 We should deal with this possibility) */
2241 unwind.pixels[(unsigned char) row_buffer[0][i]]);
2242 }
1863 } 2243 }
1864 2244
1865 #endif 2245 /* Step 6.5: Create the pixmap and set up the image instance */
1866
1867 #if 0
1868 DescribeImage(unwind.image,stderr,1);
1869 #endif
1870
1871 unwind.ximage = XCreateImage(dpy, visual, depth,
1872 (depth == 1) ? XYPixmap : ZPixmap,
1873 0, 0,
1874 unwind.image->columns,
1875 unwind.image->rows,
1876 XBitmapPad(dpy), 0);
1877
1878 if (!unwind.ximage) {
1879 signal_simple_error("Unable to allocate XImage structure",
1880 instantiator);
1881 }
1882
1883 unwind.ximage->data = (char *) xmalloc(unwind.ximage->bytes_per_line *
1884 unwind.ximage->height);
1885
1886 if (unwind.ximage->data == (char *)NULL) {
1887 signal_simple_error("Unable to allocate XImage data information",
1888 instantiator);
1889 }
1890
1891
1892 /*
1893 ** First pull out all of the colors used, and create a lookup for them
1894 */
1895
1896 if (unwind.image->class == PseudoClass) {
1897 int i;
1898
1899 unwind.npixels = unwind.image->colors;
1900 unwind.pixels = xmalloc(unwind.npixels * sizeof(unsigned long));
1901 for (i = 0; i < unwind.npixels; i++) {
1902 XColor color;
1903 /* ImageMagic uses 8bit values for colors, whilst X expects 16bits */
1904 color.red = unwind.image->colormap[i].red << 8;
1905 color.green = unwind.image->colormap[i].green << 8;
1906 color.blue = unwind.image->colormap[i].blue << 8;
1907 color.flags = DoRed | DoGreen | DoBlue;
1908 allocate_nearest_color (dpy, cmap, visual, &color);
1909 unwind.pixels[i] = color.pixel;
1910 }
1911 }
1912
1913 /*
1914 ** Need to pull the data from the 'Image' structure in
1915 ** unwind.image and convert it to an 'XImage' in unwind.ximage
1916 */
1917 {
1918 int i,j,x,b;
1919 unsigned int bytes_per_pixel, scanline_pad;
1920 unsigned long pixval;
1921 unsigned char *q, *pixar;
1922 RunlengthPacket *p;
1923
1924 q = (unsigned char *) unwind.ximage->data;
1925 x = 0;
1926 p = unwind.image->pixels;
1927 scanline_pad = unwind.ximage->bytes_per_line -
1928 ((unwind.ximage->width * unwind.ximage->bits_per_pixel) >> 3);
1929
1930 /* Convert to multi-byte color-mapped X image. */
1931 bytes_per_pixel=unwind.ximage->bits_per_pixel >> 3;
1932
1933 pixar = (unsigned char *) alloca (bytes_per_pixel);
1934
1935 for (i=0; i < unwind.image->packets; i++) {
1936 if (unwind.image->class == PseudoClass)
1937 pixval = unwind.pixels[p->index];
1938 else
1939 {
1940 /* ### NOW what? */
1941 pixval = 0;
1942 }
1943
1944 for (b=0; b < bytes_per_pixel; b++) {
1945 if (unwind.ximage->bitmap_bit_order == LSBFirst)
1946 pixar[b] = (unsigned char)pixval;
1947 else
1948 pixar[bytes_per_pixel - 1 - b] = (unsigned char)pixval;
1949 pixval>>=8;
1950 }
1951
1952 for (j=0; j <= ((int) p->length); j++) {
1953 for (b=0; b < bytes_per_pixel; b++)
1954 *q++= pixar[b];
1955 x++;
1956 if (x == unwind.ximage->width) {
1957 x=0;
1958 q+=scanline_pad;
1959 }
1960 }
1961 p++;
1962 }
1963 }
1964
1965 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask, 2246 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
1966 unwind.pixels, unwind.npixels, 2247 unwind.pixels, unwind.npixels,
1967 instantiator); 2248 instantiator);
1968 2249
1969 /* And we are done! 2250 /* Step 7: Finish decompression */
1970 ** Now that we've succeeded, we don't want the pixels 2251
1971 ** freed right now. They're kept around in the image instance 2252 jpeg_finish_decompress (&cinfo);
1972 ** structure until it's destroyed. 2253 /* We can ignore the return value since suspension is not possible
1973 */ 2254 * with the stdio data source.
2255 */
2256
2257 /* And we're done!
2258
2259 Now that we've succeeded, we don't want the pixels
2260 freed right now. They're kept around in the image instance
2261 structure until it's destroyed. */
2262 unwind.npixels = 0;
2263
2264 /* This will clean up everything else. */
2265 unbind_to (speccount, Qnil);
2266 }
2267
2268 #endif /* HAVE_JPEG */
2269
2270 #ifdef HAVE_GIF
2271
2272 /**********************************************************************
2273 * GIF *
2274 **********************************************************************/
2275
2276 #include "gif_lib.h" /* This is in our own source tree */
2277
2278 static void
2279 gif_validate (Lisp_Object instantiator)
2280 {
2281 file_or_data_must_be_present (instantiator);
2282 }
2283
2284 static Lisp_Object
2285 gif_normalize (Lisp_Object inst, Lisp_Object console_type)
2286 {
2287 return simple_image_type_normalize (inst, console_type, Qgif);
2288 }
2289
2290 static int
2291 gif_possible_dest_types (void)
2292 {
2293 return IMAGE_COLOR_PIXMAP_MASK;
2294 }
2295
2296 /* To survive the otherwise baffling complexity of making sure
2297 everything gets cleaned up in the presence of an error, we
2298 use an unwind_protect(). */
2299
2300 struct gif_unwind_data
2301 {
2302 Display *dpy;
2303 Colormap cmap;
2304 /* Object that holds the decoded data from a GIF file */
2305 GifFileType *giffile;
2306 /* Pixels to keep around while the image is active */
2307 unsigned long *pixels;
2308 int npixels;
2309 /* Client-side image structure */
2310 XImage *ximage;
2311 /* Tempfile to remove */
2312 char tempfile[50];
2313 int tempfile_needs_to_be_removed;
2314 };
2315
2316 static Lisp_Object
2317 gif_instantiate_unwind (Lisp_Object unwind_obj)
2318 {
2319 struct gif_unwind_data *data =
2320 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
2321
2322 free_opaque_ptr (unwind_obj);
2323 if (data->giffile)
2324 DGifCloseFile (data->giffile);
2325 if (data->tempfile_needs_to_be_removed)
2326 unlink (data->tempfile);
2327 if (data->npixels > 0)
2328 {
2329 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2330 xfree (data->pixels);
2331 }
2332 if (data->ximage)
2333 {
2334 if (data->ximage->data)
2335 {
2336 xfree (data->ximage->data);
2337 data->ximage->data = 0;
2338 }
2339 XDestroyImage (data->ximage);
2340 }
2341
2342 return Qnil;
2343 }
2344
2345 static void
2346 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2347 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2348 int dest_mask, Lisp_Object domain)
2349 {
2350 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2351 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2352 Display *dpy;
2353 Screen *scr;
2354 Colormap cmap;
2355 Visual *vis;
2356 /* It is OK for the unwind data to be local to this function,
2357 because the unwind-protect is always executed when this
2358 stack frame is still valid. */
2359 struct gif_unwind_data unwind;
2360 int speccount = specpdl_depth ();
2361
2362 if (!DEVICE_X_P (XDEVICE (device)))
2363 signal_simple_error ("Not an X device", device);
2364
2365 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2366 scr = DefaultScreenOfDisplay (dpy);
2367 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2368 vis = DEVICE_X_VISUAL (XDEVICE(device));
2369
2370 memset (&unwind, 0, sizeof (unwind));
2371 unwind.dpy = dpy;
2372 unwind.cmap = cmap;
2373 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
2374
2375 /* 1. Now decode the data. */
2376
2377 /* #### The GIF routines currently require that you read from a file,
2378 so write out to a temp file. We should change this. */
2379 {
2380 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2381
2382 assert (!NILP (data));
2383
2384 write_lisp_string_to_temp_file (data, unwind.tempfile);
2385 unwind.tempfile_needs_to_be_removed = 1;
2386
2387 /* Then slurp the image into memory, decoding along the way.
2388 The result is the image in a simple one-byte-per-pixel
2389 format (#### the GIF routines only support 8-bit GIFs,
2390 it appears). */
2391 unwind.giffile = DGifOpenFileName (unwind.tempfile);
2392 if (unwind.giffile == NULL)
2393 {
2394 gif_decode_error:
2395 signal_simple_error ("Unable to decode GIF",
2396 build_string (EmacsPrintGifError ()));
2397 }
2398 /* DGifSlurp() doesn't handle interlaced files. */
2399 /* Actually, it does, sort of. It just sets the Interlace flag
2400 and stores RasterBits in interlaced order. We handle that below. */
2401 if (DGifSlurp (unwind.giffile) != GIF_OK)
2402 goto gif_decode_error;
2403 }
2404
2405 /* 2. Now allocate the colors for the image. */
2406 {
2407 int i;
2408 ColorMapObject *cmo = unwind.giffile->SColorMap;
2409 /* Just in case the image contains out-of-range pixels, we go
2410 ahead and allocate space for all of them. */
2411 unwind.pixels = xnew_array (unsigned long, 256);
2412 unwind.npixels = cmo->ColorCount;
2413
2414 for (i = 0; i < 256; i++)
2415 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
2416
2417 /* Allocate pixels for the various colors. */
2418 for (i = 0; i < cmo->ColorCount; i++)
2419 {
2420 XColor color;
2421
2422 color.red = cmo->Colors[i].Red << 8;
2423 color.green = cmo->Colors[i].Green << 8;
2424 color.blue = cmo->Colors[i].Blue << 8;
2425 color.flags = DoRed | DoGreen | DoBlue;
2426
2427 allocate_nearest_color (dpy, cmap, vis, &color);
2428 unwind.pixels[i] = color.pixel;
2429 }
2430 }
2431
2432 /* 3. Now create the image */
2433 {
2434 int height = unwind.giffile->SHeight;
2435 int width = unwind.giffile->SWidth;
2436 int depth;
2437 int bitmap_pad;
2438 int i, j, row, pass, interlace;
2439 /* interlaced gifs have rows in this order:
2440 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */
2441 static int InterlacedOffset[] = { 0, 4, 2, 1 };
2442 static int InterlacedJumps[] = { 8, 8, 4, 2 };
2443
2444 depth = DEVICE_X_DEPTH(XDEVICE(device));
2445
2446 /* first get bitmap_pad (from XPM) */
2447 bitmap_pad = ((depth > 16) ? 32 :
2448 (depth > 8) ? 16 :
2449 8);
2450
2451 unwind.ximage = XCreateImage (dpy, vis,
2452 depth, ZPixmap, 0, 0, width, height,
2453 bitmap_pad, 0);
2454
2455 if (!unwind.ximage)
2456 signal_simple_error ("Unable to create X image struct", instantiator);
2457
2458 /* now that bytes_per_line must have been set properly alloc data */
2459 unwind.ximage->data =
2460 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
2461
2462 /* write the data --
2463 #### XPutPixel() is a client-side-only function but could
2464 still be slow. Another possibility is to just convert to
2465 XPM format and use the Xpm routines, which optimize this
2466 stuff; but it's doubtful that this will be faster in the
2467 long run, what with all the XPM overhead. If this proves
2468 to be a bottleneck here, maybe we should just copy the
2469 optimization routines from XPM (they're in turn mostly
2470 copied from the Xlib source code). */
2471
2472 /* Note: We just use the first image in the file and ignore the rest.
2473 We check here that that image covers the full "screen" size.
2474 I don't know whether that's always the case.
2475 -dkindred@cs.cmu.edu */
2476 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
2477 || unwind.giffile->SavedImages[0].ImageDesc.Width != width
2478 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0
2479 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
2480 signal_simple_error ("First image in GIF file is not full size",
2481 instantiator);
2482
2483 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
2484 pass = 0;
2485 row = interlace ? InterlacedOffset[pass] : 0;
2486 for (i = 0; i < height; i++)
2487 {
2488 if (interlace && row >= height)
2489 row = InterlacedOffset[++pass];
2490
2491 for (j = 0; j < width; j++)
2492 XPutPixel (unwind.ximage, j, row,
2493 unwind.pixels[(unsigned char)
2494 /* incorrect signed declaration
2495 of RasterBits[] */
2496 (unwind.giffile->SavedImages[0].
2497 RasterBits[i * width + j])]);
2498
2499 row += interlace ? InterlacedJumps[pass] : 1;
2500 }
2501 }
2502
2503 /* 4. Now create the pixmap and set up the image instance */
2504 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2505 unwind.pixels, unwind.npixels,
2506 instantiator);
2507 /* Now that we've succeeded, we don't want the pixels
2508 freed right now. They're kept around in the image instance
2509 structure until it's destroyed. */
1974 unwind.npixels = 0; 2510 unwind.npixels = 0;
1975 unbind_to (speccount, Qnil); 2511 unbind_to (speccount, Qnil);
1976 } 2512 }
1977 2513
1978 #endif /* HAVE_IMAGEMAGICK */ 2514 #endif /* HAVE_GIF */
2515
2516
2517 #ifdef HAVE_PNG
2518 /* #define USE_TEMP_FILES_FOR_PNG_IMAGES 1 */
2519
2520 /**********************************************************************
2521 * PNG *
2522 **********************************************************************/
2523 static void
2524 png_validate (Lisp_Object instantiator)
2525 {
2526 file_or_data_must_be_present (instantiator);
2527 }
2528
2529 static Lisp_Object
2530 png_normalize (Lisp_Object inst, Lisp_Object console_type)
2531 {
2532 return simple_image_type_normalize (inst, console_type, Qpng);
2533 }
2534
2535 static int
2536 png_possible_dest_types (void)
2537 {
2538 return IMAGE_COLOR_PIXMAP_MASK;
2539 }
2540
2541 #if !defined (USE_TEMP_FILES_FOR_PNG_IMAGES) && (PNG_LIBPNG_VER >= 87)
2542 struct png_memory_storage
2543 {
2544 Extbyte *bytes; /* The data */
2545 Extcount len; /* How big is it? */
2546 int index; /* Where are we? */
2547 };
2548
2549 static void png_read_from_memory(png_structp png_ptr, png_bytep data,
2550 png_uint_32 length)
2551 {
2552 struct png_memory_storage *tbr =
2553 (struct png_memory_storage *) png_get_io_ptr (png_ptr);
2554
2555 if (length > (tbr->len - tbr->index))
2556 png_error (png_ptr, (png_const_charp) "Read Error");
2557 memcpy(data,tbr->bytes + tbr->index,length);
2558 tbr->index = tbr->index + length;
2559 }
2560 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGESS || PNG_LIBPNG_VER >= 87 */
2561
2562 struct png_unwind_data
2563 {
2564 Display *dpy;
2565 Colormap cmap;
2566 FILE *instream;
2567 png_struct *png_ptr;
2568 png_info *info_ptr;
2569 unsigned long *pixels;
2570 int npixels;
2571 XImage *ximage;
2572 char tempfile[50];
2573 int tempfile_needs_to_be_removed;
2574 };
2575
2576 static Lisp_Object
2577 png_instantiate_unwind (Lisp_Object unwind_obj)
2578 {
2579 struct png_unwind_data *data =
2580 (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
2581
2582 free_opaque_ptr (unwind_obj);
2583 if (data->png_ptr)
2584 png_read_destroy (data->png_ptr, data->info_ptr, (png_info *) NULL);
2585 if (data->instream)
2586 fclose (data->instream);
2587 if (data->tempfile_needs_to_be_removed)
2588 unlink (data->tempfile);
2589 if (data->npixels > 0)
2590 {
2591 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2592 xfree (data->pixels);
2593 }
2594
2595 if (data->ximage)
2596 {
2597 if (data->ximage->data)
2598 {
2599 xfree (data->ximage->data);
2600 data->ximage->data = 0;
2601 }
2602 XDestroyImage (data->ximage);
2603 }
2604
2605 return Qnil;
2606 }
2607
2608 /* This doesn't appear to be used. */
2609 #if 0
2610 #define get_png_val(p) _get_png_val (&(p), info_ptr.bit_depth)
2611 png_uint_16
2612 _get_png_val (png_byte **pp, int bit_depth)
2613 {
2614 png_uint_16 c = 0;
2615
2616 if (bit_depth == 16) {
2617 c = (*((*pp)++)) << 8;
2618 }
2619 c |= (*((*pp)++));
2620
2621 return c;
2622 }
2623 #endif
2624
2625 static void
2626 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2627 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2628 int dest_mask, Lisp_Object domain)
2629 {
2630 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2631 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2632 Display *dpy;
2633 Colormap cmap;
2634 Visual *vis;
2635 struct png_unwind_data unwind;
2636 int speccount = specpdl_depth ();
2637
2638 /* PNG variables */
2639 png_struct *png_ptr;
2640 png_info *info_ptr;
2641
2642 if (!DEVICE_X_P (XDEVICE (device)))
2643 signal_simple_error ("Not an X device", device);
2644
2645 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2646 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2647 vis = DEVICE_X_VISUAL (XDEVICE(device));
2648
2649 png_ptr = xnew (png_struct);
2650 info_ptr = xnew (png_info);
2651
2652 memset (&unwind, 0, sizeof (unwind));
2653 unwind.png_ptr = png_ptr;
2654 unwind.info_ptr = info_ptr;
2655 unwind.dpy = dpy;
2656 unwind.cmap = cmap;
2657
2658 record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
2659
2660 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
2661 this file, example.c from the libpng 0.81 distribution, and the
2662 pngtopnm sources. -WMP-
2663 */
2664 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
2665 /* Write out to a temp file - we really should take the time to
2666 write appropriate memory bound IO stuff, but I am just trying
2667 to get the stupid thing working right now.
2668 */
2669 {
2670 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2671
2672 assert (!NILP (data));
2673
2674 write_lisp_string_to_temp_file (data, unwind.tempfile);
2675 unwind.tempfile_needs_to_be_removed = 1;
2676
2677 if ((unwind.instream = fopen (unwind.tempfile, "rb")) == NULL)
2678 report_file_error ("Opening PNG temp file",
2679 list1 (build_string (unwind.tempfile)));
2680 }
2681 #else
2682 /* Nothing */
2683 #endif
2684
2685 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then
2686 we ran into a problem somewhere, and need to clean up after ourselves. */
2687 if (setjmp (png_ptr->jmpbuf))
2688 {
2689 /* Am I doing enough here? I think so, since most things happen
2690 in png_unwind */
2691 png_read_destroy (png_ptr, info_ptr, (png_info *) NULL);
2692 signal_simple_error ("Error decoding PNG", instantiator);
2693 }
2694
2695 /* Initialize all PNG structures */
2696 png_info_init (info_ptr);
2697 png_read_init (png_ptr);
2698
2699 /* Initialize the IO layer and read in header information */
2700 #if defined (USE_TEMP_FILES_FOR_PNG_IMAGES) || (PNG_LIBPNG_VER < 87)
2701 png_init_io (png_ptr, unwind.instream);
2702 #else
2703 {
2704 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2705 Extbyte *bytes;
2706 Extcount len;
2707 struct png_memory_storage tbr; /* Data to be read */
2708
2709 assert (!NILP (data));
2710
2711 /* #### This is a definite problem under Mule due to the amount of
2712 stack data it might allocate. Need to be able to convert and
2713 write out to a file. */
2714 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2715 tbr.bytes = bytes;
2716 tbr.len = len;
2717 tbr.index = 0;
2718 png_set_read_fn(png_ptr,(void *) &tbr, png_read_from_memory);
2719 }
2720 #endif
2721
2722 png_read_info (png_ptr, info_ptr);
2723
2724 /* set up the transformations you want. Note that these are
2725 all optional. Only call them if you want them */
2726 /* tell libpng to strip 16 bit depth files down to 8 bits */
2727 if (info_ptr->bit_depth == 16)
2728 png_set_strip_16 (png_ptr);
2729 if (info_ptr->bit_depth < 8)
2730 png_set_packing (png_ptr);
2731 /* ##### Perhaps some way to specify the screen gamma should be in here? */
2732
2733 {
2734 int height = info_ptr->height;
2735 int width = info_ptr->width;
2736 int depth = info_ptr->bit_depth;
2737 int linesize = max (info_ptr->bit_depth >> 3, 1) * width;
2738 int bitmap_pad;
2739 int y;
2740 XColor color;
2741 png_byte *png_pixels;
2742 png_byte **row_pointers;
2743 png_color static_color_cube[216];
2744
2745 /* Wow, allocate all the memory. Truly, exciting. */
2746 unwind.pixels = xnew_array (unsigned long, 256);
2747 png_pixels = xnew_array (png_byte, linesize * height);
2748 row_pointers = xnew_array (png_byte *, height);
2749
2750 for (y = 0; y < 256; y++)
2751 unwind.pixels[y] = 0;
2752 for (y = 0; y < height; y++)
2753 row_pointers[y] = png_pixels + (linesize * y);
2754
2755 /* #### This is where we should handle transparency, but I am unsure of
2756 how exactly to get that information right now, in a safe manner. */
2757 #if 0
2758 {
2759 png_color_16 current_background;
2760
2761 /* Some appropriate magic should go here to get the current
2762 buffers (device?) background color and convert it to a
2763 png_color_16 struct */
2764 if (info_ptr->valid & PNG_INFO_bKGD)
2765 png_set_background (png_ptr, &(info_ptr->background), PNG_GAMMA_FILE,
2766 1, 1.0);
2767 else
2768 png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN,
2769 0, 1.0);
2770 }
2771 #endif
2772
2773 if ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2774 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA))
2775 {
2776 if (!(info_ptr->valid & PNG_INFO_PLTE))
2777 {
2778 for (y = 0; y < 216; y++)
2779 {
2780 static_color_cube[y].red = (y % 6) * 255.0 / 5;
2781 static_color_cube[y].green = ((y / 6) % 6) * 255.0 / 5;
2782 static_color_cube[y].blue = (y / 36) * 255.0 / 5;
2783 }
2784 png_set_dither (png_ptr, static_color_cube, 216, 216, NULL, 1);
2785 }
2786 else
2787 {
2788 png_set_dither (png_ptr, info_ptr->palette, info_ptr->num_palette,
2789 info_ptr->num_palette, info_ptr->hist, 1);
2790 }
2791 }
2792
2793 png_read_image (png_ptr, row_pointers);
2794 png_read_end (png_ptr, info_ptr);
2795
2796 /* Ok, now we go and allocate all the colors */
2797 if (info_ptr->valid & PNG_INFO_PLTE)
2798 {
2799 unwind.npixels = info_ptr->num_palette;
2800 for (y = 0; y < unwind.npixels; y++)
2801 {
2802 color.red = info_ptr->palette[y].red << 8;
2803 color.green = info_ptr->palette[y].green << 8;
2804 color.blue = info_ptr->palette[y].blue << 8;
2805 color.flags = DoRed | DoGreen | DoBlue;
2806 allocate_nearest_color (dpy, cmap, vis, &color);
2807 unwind.pixels[y] = color.pixel;
2808 }
2809 }
2810 else
2811 {
2812 unwind.npixels = 216;
2813 for (y = 0; y < 216; y++)
2814 {
2815 color.red = static_color_cube[y].red << 8;
2816 color.green = static_color_cube[y].green << 8;
2817 color.blue = static_color_cube[y].blue << 8;
2818 color.flags = DoRed|DoGreen|DoBlue;
2819 allocate_nearest_color (dpy, cmap, vis, &color);
2820 unwind.pixels[y] = color.pixel;
2821 }
2822 }
2823
2824 #ifdef PNG_SHOW_COMMENTS
2825 /* ####
2826 * I turn this off by default now, because the !%^@#!% comments
2827 * show up every time the image is instantiated, which can get
2828 * really really annoying. There should be some way to pass this
2829 * type of data down into the glyph code, where you can get to it
2830 * from lisp anyway. - WMP
2831 */
2832 {
2833 int i;
2834
2835 for (i = 0 ; i < info_ptr->num_text ; i++)
2836 {
2837 /* How paranoid do I have to be about no trailing NULLs, and
2838 using (int)info_ptr->text[i].text_length, and strncpy and a temp
2839 string somewhere? */
2840
2841 warn_when_safe (Qpng, Qinfo, "%s - %s",
2842 info_ptr->text[i].key,
2843 info_ptr->text[i].text);
2844 }
2845 }
2846 #endif
2847
2848 /* Now create the image */
2849
2850 depth = DEVICE_X_DEPTH(XDEVICE(device));
2851
2852 /* first get bitmap_pad (from XPM) */
2853 bitmap_pad = ((depth > 16) ? 32 :
2854 (depth > 8) ? 16 :
2855 8);
2856
2857 unwind.ximage = XCreateImage (dpy, vis,
2858 depth, ZPixmap, 0, 0, width, height,
2859 bitmap_pad, 0);
2860
2861 if (!unwind.ximage)
2862 signal_simple_error ("Unable to create X image struct",
2863 instantiator);
2864
2865 /* now that bytes_per_line must have been set properly alloc data */
2866 unwind.ximage->data = (char *) xmalloc (unwind.ximage->bytes_per_line *
2867 height);
2868
2869 {
2870 int i, j;
2871 for (i = 0; i < height; i++)
2872 for (j = 0; j < width; j++)
2873 XPutPixel (unwind.ximage, j, i,
2874 unwind.pixels[png_pixels[i * width + j]]);
2875 }
2876
2877 xfree (row_pointers);
2878 xfree (png_pixels);
2879 }
2880
2881 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2882 unwind.pixels, unwind.npixels,
2883 instantiator);
2884
2885 /* This will clean up everything else. */
2886 unwind.npixels = 0;
2887 unbind_to (speccount, Qnil);
2888 }
2889
2890 #endif /* HAVE_PNG */
2891
2892
2893 #ifdef HAVE_TIFF
2894
2895 /**********************************************************************
2896 * TIFF *
2897 **********************************************************************/
2898 static void
2899 tiff_validate (Lisp_Object instantiator)
2900 {
2901 file_or_data_must_be_present (instantiator);
2902 }
2903
2904 static Lisp_Object
2905 tiff_normalize (Lisp_Object inst, Lisp_Object console_type)
2906 {
2907 signal_simple_error ("No TIFF support yet", inst);
2908 return Qnil;
2909 }
2910
2911 static int
2912 tiff_possible_dest_types (void)
2913 {
2914 return IMAGE_COLOR_PIXMAP_MASK;
2915 }
2916
2917 static void
2918 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2919 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2920 int dest_mask, Lisp_Object domain)
2921 {
2922 abort ();
2923 }
2924
2925 #endif /* HAVE_TIFF */
1979 2926
1980 2927
1981 #ifdef HAVE_XFACE 2928 #ifdef HAVE_XFACE
1982 2929
1983 /********************************************************************** 2930 /**********************************************************************
2880 3827
2881 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); 3828 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
2882 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); 3829 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
2883 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); 3830 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
2884 3831
2885 #ifdef HAVE_IMAGEMAGICK 3832 #ifdef HAVE_JPEG
2886 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (imagick, "imagick"); 3833 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
2887 3834
2888 IIFORMAT_HAS_METHOD (imagick, validate); 3835 IIFORMAT_HAS_METHOD (jpeg, validate);
2889 IIFORMAT_HAS_METHOD (imagick, normalize); 3836 IIFORMAT_HAS_METHOD (jpeg, normalize);
2890 IIFORMAT_HAS_METHOD (imagick, possible_dest_types); 3837 IIFORMAT_HAS_METHOD (jpeg, possible_dest_types);
2891 IIFORMAT_HAS_METHOD (imagick, instantiate); 3838 IIFORMAT_HAS_METHOD (jpeg, instantiate);
2892 3839
2893 IIFORMAT_VALID_KEYWORD (imagick, Q_data, check_valid_string); 3840 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
2894 IIFORMAT_VALID_KEYWORD (imagick, Q_file, check_valid_string); 3841 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
2895 3842 #endif
2896 #ifdef OLDCOMPAT /* old graphics compatibility */ 3843
2897 #define IIFORMAT_USES_METHOD(format, source, m) \ 3844 #ifdef HAVE_GIF
2898 (format##_image_instantiator_methods->m##_method = source##_##m) 3845 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
2899 3846
3847 IIFORMAT_HAS_METHOD (gif, validate);
3848 IIFORMAT_HAS_METHOD (gif, normalize);
3849 IIFORMAT_HAS_METHOD (gif, possible_dest_types);
3850 IIFORMAT_HAS_METHOD (gif, instantiate);
3851
3852 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
3853 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
3854 #endif
3855
3856 #ifdef HAVE_PNG
3857 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
3858
3859 IIFORMAT_HAS_METHOD (png, validate);
3860 IIFORMAT_HAS_METHOD (png, normalize);
3861 IIFORMAT_HAS_METHOD (png, possible_dest_types);
3862 IIFORMAT_HAS_METHOD (png, instantiate);
3863
3864 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
3865 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
3866 #endif
3867
3868 #ifdef HAVE_TIFF
2900 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff"); 3869 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
2901 IIFORMAT_USES_METHOD (tiff, imagick, validate); 3870
2902 IIFORMAT_USES_METHOD (tiff, imagick, normalize); 3871 IIFORMAT_HAS_METHOD (tiff, validate);
2903 IIFORMAT_USES_METHOD (tiff, imagick, possible_dest_types); 3872 IIFORMAT_HAS_METHOD (tiff, normalize);
2904 IIFORMAT_USES_METHOD (tiff, imagick, instantiate); 3873 IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
3874 IIFORMAT_HAS_METHOD (tiff, instantiate);
3875
2905 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string); 3876 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
2906 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string); 3877 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
2907
2908 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
2909 IIFORMAT_USES_METHOD (png, imagick, validate);
2910 IIFORMAT_USES_METHOD (png, imagick, normalize);
2911 IIFORMAT_USES_METHOD (png, imagick, possible_dest_types);
2912 IIFORMAT_USES_METHOD (png, imagick, instantiate);
2913 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
2914 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
2915
2916 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
2917 IIFORMAT_USES_METHOD (gif, imagick, validate);
2918 IIFORMAT_USES_METHOD (gif, imagick, normalize);
2919 IIFORMAT_USES_METHOD (gif, imagick, possible_dest_types);
2920 IIFORMAT_USES_METHOD (gif, imagick, instantiate);
2921 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
2922 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
2923
2924 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
2925 IIFORMAT_USES_METHOD (jpeg, imagick, validate);
2926 IIFORMAT_USES_METHOD (jpeg, imagick, normalize);
2927 IIFORMAT_USES_METHOD (jpeg, imagick, possible_dest_types);
2928 IIFORMAT_USES_METHOD (jpeg, imagick, instantiate);
2929 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
2930 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
2931
2932 #endif /* old compat */
2933
2934 #endif 3878 #endif
2935 3879
2936 #ifdef HAVE_XPM 3880 #ifdef HAVE_XPM
2937 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm"); 3881 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xpm, "xpm");
2938 3882
2974 } 3918 }
2975 3919
2976 void 3920 void
2977 vars_of_glyphs_x (void) 3921 vars_of_glyphs_x (void)
2978 { 3922 {
3923 #ifdef HAVE_JPEG
3924 Fprovide (Qjpeg);
3925 #endif
3926
3927 #ifdef HAVE_GIF
3928 Fprovide (Qgif);
3929 #endif
3930
3931 #ifdef HAVE_PNG
3932 Fprovide (Qpng);
3933 #endif
3934
3935 #ifdef HAVE_TIFF
3936 Fprovide (Qtiff);
3937 #endif
3938
2979 #ifdef HAVE_XPM 3939 #ifdef HAVE_XPM
2980 Fprovide (Qxpm); 3940 Fprovide (Qxpm);
2981 3941
2982 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /* 3942 DEFVAR_LISP ("xpm-color-symbols", &Vxpm_color_symbols /*
2983 Definitions of logical color-names used when reading XPM files. 3943 Definitions of logical color-names used when reading XPM files.
2989 3949
2990 The default value of this variable defines the logical color names 3950 The default value of this variable defines the logical color names
2991 \"foreground\" and \"background\" to be the colors of the `default' face. 3951 \"foreground\" and \"background\" to be the colors of the `default' face.
2992 */ ); 3952 */ );
2993 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */ 3953 Vxpm_color_symbols = Qnil; /* initialized in x-faces.el */
2994 #endif
2995
2996 #ifdef HAVE_IMAGEMAGICK
2997 Fprovide (Qimagick);
2998
2999 #ifdef OLDCOMPAT
3000 Fprovide (Qtiff);
3001 Fprovide (Qpng);
3002 Fprovide (Qgif);
3003 Fprovide (Qjpeg);
3004 #endif
3005 #endif 3954 #endif
3006 3955
3007 #ifdef HAVE_XFACE 3956 #ifdef HAVE_XFACE
3008 Fprovide (Qxface); 3957 Fprovide (Qxface);
3009 #endif 3958 #endif