comparison src/glyphs-x.c @ 290:c9fe270a4101 r21-0b43

Import from CVS: tag r21-0b43
author cvs
date Mon, 13 Aug 2007 10:36:47 +0200
parents e11d67e05968
children 70ad99077275
comparison
equal deleted inserted replaced
289:6e6992ccc4b6 290:c9fe270a4101
59 59
60 #include "imgproc.h" 60 #include "imgproc.h"
61 61
62 #include "sysfile.h" 62 #include "sysfile.h"
63 63
64 #ifdef HAVE_PNG
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68 #include <png.h>
69 #ifdef __cplusplus
70 }
71 #endif
72 #else
73 #include <setjmp.h> 64 #include <setjmp.h>
74 #endif 65
75 #ifdef FILE_CODING 66 #ifdef FILE_CODING
76 #include "file-coding.h" 67 #include "file-coding.h"
77 #endif 68 #endif
78
79 #undef HAVE_PNG
80 #undef HAVE_TIFF
81 #undef HAVE_JPEG
82 #undef HAVE_GIF
83 69
84 #if INTBITS == 32 70 #if INTBITS == 32
85 # define FOUR_BYTE_TYPE unsigned int 71 # define FOUR_BYTE_TYPE unsigned int
86 #elif LONGBITS == 32 72 #elif LONGBITS == 32
87 # define FOUR_BYTE_TYPE unsigned long 73 # define FOUR_BYTE_TYPE unsigned long
94 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev))) 80 #define LISP_DEVICE_TO_X_SCREEN(dev) XDefaultScreenOfDisplay (DEVICE_X_DISPLAY (XDEVICE (dev)))
95 81
96 #ifdef HAVE_XFACE 82 #ifdef HAVE_XFACE
97 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface); 83 DEFINE_IMAGE_INSTANTIATOR_FORMAT (xface);
98 Lisp_Object Qxface; 84 Lisp_Object Qxface;
99 #endif
100
101 #ifdef HAVE_TIFF
102 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff);
103 Lisp_Object Qtiff;
104 #endif
105
106 #ifdef HAVE_JPEG
107 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
108 Lisp_Object Qjpeg;
109 #endif
110
111 #ifdef HAVE_GIF
112 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
113 Lisp_Object Qgif;
114 #endif
115
116 #ifdef HAVE_PNG
117 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png);
118 Lisp_Object Qpng;
119 #endif 85 #endif
120 86
121 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font); 87 DEFINE_IMAGE_INSTANTIATOR_FORMAT (cursor_font);
122 Lisp_Object Qcursor_font; 88 Lisp_Object Qcursor_font;
123 89
1497 } 1463 }
1498 1464
1499 #endif /* HAVE_XPM */ 1465 #endif /* HAVE_XPM */
1500 1466
1501 1467
1502 #ifdef HAVE_JPEG
1503
1504 /**********************************************************************
1505 * JPEG *
1506 **********************************************************************/
1507
1508 #ifdef __cplusplus
1509 extern "C" {
1510 #endif
1511 #include <jpeglib.h>
1512 #include <jerror.h>
1513 #ifdef __cplusplus
1514 }
1515 #endif
1516
1517 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/
1518 static void
1519 jpeg_validate (Lisp_Object instantiator)
1520 {
1521 file_or_data_must_be_present (instantiator);
1522 }
1523
1524 static Lisp_Object
1525 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type)
1526 {
1527 return simple_image_type_normalize (inst, console_type, Qjpeg);
1528 }
1529
1530 static int
1531 jpeg_possible_dest_types (void)
1532 {
1533 return IMAGE_COLOR_PIXMAP_MASK;
1534 }
1535
1536 /* To survive the otherwise baffling complexity of making sure
1537 everything gets cleaned up in the presence of an error, we
1538 use an unwind_protect(). */
1539
1540 struct jpeg_unwind_data
1541 {
1542 Display *dpy;
1543 Colormap cmap;
1544 /* Stream that we need to close */
1545 FILE *instream;
1546 /* Object that holds state info for JPEG decoding */
1547 struct jpeg_decompress_struct *cinfo_ptr;
1548 /* EImage data */
1549 unsigned char *eimage;
1550 /* Pixels to keep around while the image is active */
1551 unsigned long *pixels;
1552 int npixels, pixcount;
1553 /* Client-side image structure */
1554 XImage *ximage;
1555 /* Tempfile to remove */
1556 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1557 char tempfile[50];
1558 int tempfile_needs_to_be_removed;
1559 #endif
1560 };
1561
1562 static Lisp_Object
1563 jpeg_instantiate_unwind (Lisp_Object unwind_obj)
1564 {
1565 struct jpeg_unwind_data *data =
1566 (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj);
1567
1568 free_opaque_ptr (unwind_obj);
1569 if (data->cinfo_ptr)
1570 jpeg_destroy_decompress (data->cinfo_ptr);
1571
1572 if (data->instream)
1573 fclose (data->instream);
1574
1575 if (data->eimage) xfree (data->eimage);
1576
1577 if (data->npixels > 0)
1578 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
1579 if (data->pixcount)
1580 xfree (data->pixels);
1581
1582 if (data->ximage)
1583 {
1584 if (data->ximage->data)
1585 {
1586 xfree (data->ximage->data);
1587 data->ximage->data = 0;
1588 }
1589 XDestroyImage (data->ximage);
1590 }
1591 #if USE_TEMP_FILES_FOR_JPEG_IMAGES
1592 if (data->tempfile_needs_to_be_removed)
1593 unlink (data->tempfile);
1594 #endif
1595
1596 return Qnil;
1597 }
1598
1599 /*
1600 * ERROR HANDLING:
1601 *
1602 * The JPEG library's standard error handler (jerror.c) is divided into
1603 * several "methods" which you can override individually. This lets you
1604 * adjust the behavior without duplicating a lot of code, which you might
1605 * have to update with each future release.
1606 *
1607 * Our example here shows how to override the "error_exit" method so that
1608 * control is returned to the library's caller when a fatal error occurs,
1609 * rather than calling exit() as the standard error_exit method does.
1610 *
1611 * We use C's setjmp/longjmp facility to return control. This means that the
1612 * routine which calls the JPEG library must first execute a setjmp() call to
1613 * establish the return point. We want the replacement error_exit to do a
1614 * longjmp(). But we need to make the setjmp buffer accessible to the
1615 * error_exit routine. To do this, we make a private extension of the
1616 * standard JPEG error handler object. (If we were using C++, we'd say we
1617 * were making a subclass of the regular error handler.)
1618 *
1619 * Here's the extended error handler struct:
1620 */
1621
1622 struct my_jpeg_error_mgr
1623 {
1624 struct jpeg_error_mgr pub; /* "public" fields */
1625 jmp_buf setjmp_buffer; /* for return to caller */
1626 };
1627
1628 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1629 METHODDEF(void)
1630 #else
1631 METHODDEF void
1632 #endif
1633 our_init_source (j_decompress_ptr cinfo)
1634 {
1635 }
1636
1637 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1638 METHODDEF(boolean)
1639 #else
1640 METHODDEF boolean
1641 #endif
1642 our_fill_input_buffer (j_decompress_ptr cinfo)
1643 {
1644 /* Insert a fake EOI marker */
1645 struct jpeg_source_mgr *src = cinfo->src;
1646 static JOCTET buffer[2];
1647
1648 buffer[0] = (JOCTET) 0xFF;
1649 buffer[1] = (JOCTET) JPEG_EOI;
1650
1651 src->next_input_byte = buffer;
1652 src->bytes_in_buffer = 2;
1653 return TRUE;
1654 }
1655
1656 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1657 METHODDEF(void)
1658 #else
1659 METHODDEF void
1660 #endif
1661 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
1662 {
1663 struct jpeg_source_mgr *src = NULL;
1664
1665 src = (struct jpeg_source_mgr *) cinfo->src;
1666
1667 if (!src)
1668 {
1669 return;
1670 } else if (num_bytes > src->bytes_in_buffer)
1671 {
1672 ERREXIT(cinfo, JERR_INPUT_EOF);
1673 /*NOTREACHED*/
1674 }
1675
1676 src->bytes_in_buffer -= num_bytes;
1677 src->next_input_byte += num_bytes;
1678 }
1679
1680 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1681 METHODDEF(void)
1682 #else
1683 METHODDEF void
1684 #endif
1685 our_term_source (j_decompress_ptr cinfo)
1686 {
1687 }
1688
1689 typedef struct
1690 {
1691 struct jpeg_source_mgr pub;
1692 } our_jpeg_source_mgr;
1693
1694 static void
1695 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
1696 {
1697 struct jpeg_source_mgr *src;
1698
1699 if (cinfo->src == NULL)
1700 { /* first time for this JPEG object? */
1701 cinfo->src = (struct jpeg_source_mgr *)
1702 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
1703 sizeof(our_jpeg_source_mgr));
1704 src = (struct jpeg_source_mgr *) cinfo->src;
1705 src->next_input_byte = data;
1706 }
1707 src = (struct jpeg_source_mgr *) cinfo->src;
1708 src->init_source = our_init_source;
1709 src->fill_input_buffer = our_fill_input_buffer;
1710 src->skip_input_data = our_skip_input_data;
1711 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
1712 src->term_source = our_term_source;
1713 src->bytes_in_buffer = len;
1714 src->next_input_byte = data;
1715 }
1716
1717 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1718 METHODDEF(void)
1719 #else
1720 METHODDEF void
1721 #endif
1722 my_jpeg_error_exit (j_common_ptr cinfo)
1723 {
1724 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
1725 struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err;
1726
1727 /* Return control to the setjmp point */
1728 longjmp (myerr->setjmp_buffer, 1);
1729 }
1730
1731 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
1732 METHODDEF(void)
1733 #else
1734 METHODDEF void
1735 #endif
1736 my_jpeg_output_message (j_common_ptr cinfo)
1737 {
1738 char buffer[JMSG_LENGTH_MAX];
1739
1740 /* Create the message */
1741 (*cinfo->err->format_message) (cinfo, buffer);
1742 warn_when_safe (Qjpeg, Qinfo, "%s", buffer);
1743 }
1744
1745 /* The code in this routine is based on example.c from the JPEG library
1746 source code and from gif_instantiate() */
1747 static void
1748 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1749 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1750 int dest_mask, Lisp_Object domain)
1751 {
1752 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1753 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
1754 Display *dpy;
1755 Colormap cmap;
1756 Visual *vis;
1757 /* It is OK for the unwind data to be local to this function,
1758 because the unwind-protect is always executed when this
1759 stack frame is still valid. */
1760 struct jpeg_unwind_data unwind;
1761 int speccount = specpdl_depth ();
1762
1763 /* This struct contains the JPEG decompression parameters and pointers to
1764 * working space (which is allocated as needed by the JPEG library).
1765 */
1766 struct jpeg_decompress_struct cinfo;
1767 /* We use our private extension JPEG error handler.
1768 * Note that this struct must live as long as the main JPEG parameter
1769 * struct, to avoid dangling-pointer problems.
1770 */
1771 struct my_jpeg_error_mgr jerr;
1772
1773 if (!DEVICE_X_P (XDEVICE (device)))
1774 signal_simple_error ("Not an X device", device);
1775
1776 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
1777 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
1778 vis = DEVICE_X_VISUAL (XDEVICE(device));
1779
1780 /* Step -1: First record our unwind-protect, which will clean up after
1781 any exit, normal or not */
1782
1783 xzero (unwind);
1784 unwind.dpy = dpy;
1785 unwind.cmap = cmap;
1786 record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind));
1787
1788 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1789 /* Step 0: Write out to a temp file.
1790
1791 The JPEG routines require you to read from a file unless
1792 you provide your own special input handlers, which I don't
1793 feel like doing. */
1794 {
1795 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1796
1797 assert (!NILP (data));
1798
1799 write_lisp_string_to_temp_file (data, unwind.tempfile);
1800 unwind.tempfile_needs_to_be_removed = 1;
1801
1802 /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
1803 * requires it in order to read binary files.
1804 */
1805
1806 if ((unwind.instream = fopen (unwind.tempfile, "r")) == NULL)
1807 report_file_error ("Opening JPEG temp file",
1808 list1 (build_string (unwind.tempfile)));
1809 }
1810 #endif
1811
1812 /* Step 1: allocate and initialize JPEG decompression object */
1813
1814 /* We set up the normal JPEG error routines, then override error_exit. */
1815 cinfo.err = jpeg_std_error (&jerr.pub);
1816 jerr.pub.error_exit = my_jpeg_error_exit;
1817 jerr.pub.output_message = my_jpeg_output_message;
1818
1819 /* Establish the setjmp return context for my_error_exit to use. */
1820 if (setjmp (jerr.setjmp_buffer))
1821 {
1822 /* If we get here, the JPEG code has signaled an error.
1823 * We need to clean up the JPEG object, close the input file, and return.
1824 */
1825
1826 {
1827 Lisp_Object errstring;
1828 char buffer[JMSG_LENGTH_MAX];
1829
1830 /* Create the message */
1831 (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer);
1832 errstring = build_string (buffer);
1833
1834 signal_image_error_2 ("JPEG decoding error",
1835 errstring, instantiator);
1836 }
1837 }
1838
1839 /* Now we can initialize the JPEG decompression object. */
1840 jpeg_create_decompress (&cinfo);
1841 unwind.cinfo_ptr = &cinfo;
1842
1843 /* Step 2: specify data source (eg, a file) */
1844
1845 #ifdef USE_TEMP_FILES_FOR_JPEG_IMAGES
1846 jpeg_stdio_src (&cinfo, unwind.instream);
1847 #else
1848 {
1849 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1850 CONST Extbyte *bytes;
1851 Extcount len;
1852
1853 /* #### This is a definite problem under Mule due to the amount of
1854 stack data it might allocate. Need to be able to convert and
1855 write out to a file. */
1856 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
1857 jpeg_memory_src (&cinfo, (JOCTET *) bytes, len);
1858 }
1859 #endif
1860
1861 /* Step 3: read file parameters with jpeg_read_header() */
1862
1863 jpeg_read_header (&cinfo, TRUE);
1864 /* We can ignore the return value from jpeg_read_header since
1865 * (a) suspension is not possible with the stdio data source, and
1866 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
1867 * See libjpeg.doc for more info.
1868 */
1869
1870 #if 0
1871 /* Step 4: set parameters for decompression. */
1872
1873 if (vis->class == PseudoColor)
1874 {
1875
1876 /* We request that the JPEG file be automatically quantized into
1877 8-bit color in case it's not already (many JPEGs are stored in
1878 24-bit color). "Two-pass quantize" means that the colormap
1879 is determined on-the-fly for this particular image rather than
1880 quantizing to a supplied colormap. We can get away with this
1881 because we then use allocate_nearest_color().
1882
1883 #### Note of course that this is not the most color-effective
1884 way of doing things -- we could quantize an image that has
1885 lots of very similar colors, and eat up the colormap with these
1886 (useless to other images) colors. Unfortunately I don't think
1887 there's any "general" way of maximizing the overall image
1888 quality of lots of images, given that we don't know the
1889 colors of the images until we come across each one. Best we
1890 could do would be various sorts of heuristics, which I don't
1891 feel like dealing with now. A better scheme would be the
1892 way things are done under MS Windows, where the colormap is
1893 dynamically adjusted for various applications; but that kind
1894 of thing would have to be provided by X, which it isn't. */
1895
1896 cinfo.quantize_colors = TRUE;
1897 cinfo.two_pass_quantize = TRUE;
1898 cinfo.colormap = NULL;
1899 }
1900
1901 /* Step 5: Start decompressor */
1902
1903 jpeg_start_decompress (&cinfo);
1904 /* We can ignore the return value since suspension is not possible
1905 * with the stdio data source.
1906 */
1907
1908 /* At this point we know the size of the image and the colormap. */
1909
1910 /* Step 5.33: Allocate the colors */
1911 if (vis->class == PseudoColor)
1912 {
1913 int i;
1914 unwind.pixcount = 32;
1915 unwind.pixels = xnew_array (unsigned long, unwind.pixcount);
1916 unwind.npixels = 0;
1917
1918 /* Allocate pixels for the various colors. */
1919 for (i = 0; i < cinfo.actual_number_of_colors; i++)
1920 {
1921 XColor color;
1922 int ri, gi, bi, res;
1923
1924 ri = 0;
1925 gi = cinfo.out_color_components > 1 ? 1 : 0;
1926 bi = cinfo.out_color_components > 2 ? 2 : 0;
1927
1928 /* Ok... apparently, an entry of cinfo.colormap can be NULL if
1929 there are no bits of that color in the image. How incredibly
1930 gross. Wouldn't it be nice to have exceptions!? */
1931 color.red = cinfo.colormap[ri] ? cinfo.colormap[ri][i] << 8 : 0;
1932 color.green = cinfo.colormap[gi] ? cinfo.colormap[gi][i] << 8 : 0;
1933 color.blue = cinfo.colormap[bi] ? cinfo.colormap[bi][i] << 8 : 0;
1934 color.flags = DoRed | DoGreen | DoBlue;
1935
1936 res = allocate_nearest_color (dpy, cmap, vis, &color);
1937 if (res > 0 && res < 3)
1938 {
1939 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long);
1940 unwind.pixels[unwind.npixels] = color.pixel;
1941 unwind.npixels++;
1942 }
1943 }
1944 }
1945
1946 /* Step 5.66: Create the image */
1947 {
1948 int height = cinfo.output_height;
1949 int width = cinfo.output_width;
1950 int depth;
1951 int bitmap_pad;
1952
1953 depth = DEVICE_X_DEPTH(XDEVICE(device));
1954
1955 /* first get bitmap_pad (from XPM) */
1956 bitmap_pad = ((depth > 16) ? 32 :
1957 (depth > 8) ? 16 :
1958 8);
1959
1960 unwind.ximage = XCreateImage (dpy, vis, depth, ZPixmap, 0, 0, width, height,
1961 bitmap_pad, 0);
1962
1963 if (!unwind.ximage)
1964 signal_image_error ("Unable to create X image struct", instantiator);
1965
1966 /* now that bytes_per_line must have been set properly alloc data */
1967 unwind.ximage->data =
1968 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
1969 }
1970
1971 /* Step 6: Read in the data and put into image */
1972 {
1973 JSAMPARRAY row_buffer; /* Output row buffer */
1974 int row_stride; /* physical row width in output buffer */
1975
1976 /* We may need to do some setup of our own at this point before reading
1977 * the data. After jpeg_start_decompress() we have the correct scaled
1978 * output image dimensions available, as well as the output colormap
1979 * if we asked for color quantization.
1980 * In this example, we need to make an output work buffer of the right size.
1981 */
1982 /* JSAMPLEs per row in output buffer.
1983 Since we asked for quantized output, cinfo.output_components
1984 will always be 1. */
1985 row_stride = cinfo.output_width * cinfo.output_components;
1986 /* Make a one-row-high sample array that will go away when done
1987 with image */
1988 row_buffer = ((*cinfo.mem->alloc_sarray)
1989 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
1990
1991 /* Here we use the library's state variable cinfo.output_scanline as the
1992 * loop counter, so that we don't have to keep track ourselves.
1993 */
1994 while (cinfo.output_scanline < cinfo.output_height)
1995 {
1996 int i;
1997 int scanline = cinfo.output_scanline;
1998
1999 /* jpeg_read_scanlines expects an array of pointers to scanlines.
2000 * Here the array is only one element long, but you could ask for
2001 * more than one scanline at a time if that's more convenient.
2002 */
2003 jpeg_read_scanlines (&cinfo, row_buffer, 1);
2004
2005 for (i = 0; i < (int) cinfo.output_width; i++)
2006 XPutPixel (unwind.ximage, i, scanline,
2007 /* Let's make sure we avoid getting bit like
2008 what happened for GIF's. It's probably the
2009 case that JSAMPLE's are unsigned chars as
2010 opposed to chars, but you never know.
2011
2012 (They could even be shorts if the library
2013 was compiled with 12-bit samples -- ####
2014 We should deal with this possibility) */
2015 unwind.pixels[(unsigned char) row_buffer[0][i]]);
2016 }
2017 }
2018 #else
2019 {
2020 /* Step 4: set parameters for decompression. */
2021
2022 /* Now that we're using EImages, use the default of all data in 24bit color.
2023 The backend routine will take care of any necessary reductions. */
2024
2025 /* Step 5: Start decompressor */
2026 jpeg_start_decompress (&cinfo);
2027
2028 /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/
2029
2030 unwind.eimage = (unsigned char*) xmalloc (cinfo.output_width * cinfo.output_height * 3);
2031 if (!unwind.eimage)
2032 signal_image_error("Unable to allocate enough memory for image", instantiator);
2033
2034 {
2035 JSAMPARRAY row_buffer; /* Output row buffer */
2036 JSAMPLE *jp;
2037 int row_stride; /* physical row width in output buffer */
2038 unsigned char *op = unwind.eimage;
2039
2040 /* We may need to do some setup of our own at this point before reading
2041 * the data. After jpeg_start_decompress() we have the correct scaled
2042 * output image dimensions available
2043 * We need to make an output work buffer of the right size.
2044 */
2045 /* JSAMPLEs per row in output buffer. */
2046 row_stride = cinfo.output_width * cinfo.output_components;
2047 /* Make a one-row-high sample array that will go away when done
2048 with image */
2049 row_buffer = ((*cinfo.mem->alloc_sarray)
2050 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
2051
2052 /* Here we use the library's state variable cinfo.output_scanline as the
2053 * loop counter, so that we don't have to keep track ourselves.
2054 */
2055 while (cinfo.output_scanline < cinfo.output_height)
2056 {
2057 int i;
2058
2059 /* jpeg_read_scanlines expects an array of pointers to scanlines.
2060 * Here the array is only one element long, but you could ask for
2061 * more than one scanline at a time if that's more convenient.
2062 */
2063 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
2064 jp = row_buffer[0];
2065 for (i = 0; i < cinfo.output_width; i++)
2066 {
2067 int clr;
2068 #if (BITS_IN_JSAMPLE == 8)
2069 for (clr = 0; clr < 3; clr++)
2070 *op++ = (unsigned char)*jp++;
2071 #else /* other option is 12 */
2072 for (clr = 0; clr < 3; clr++)
2073 *op++ = (unsigned char)(*jp++ >> 4);
2074 #endif
2075 }
2076 }
2077 unwind.ximage = convert_EImage_to_XImage (device, cinfo.output_width, cinfo.output_height, unwind.eimage,
2078 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
2079 if (!unwind.ximage)
2080 signal_image_error("JPEG conversion failed", instantiator);
2081 }
2082 }
2083
2084 #endif
2085 /* Step 6.5: Create the pixmap and set up the image instance */
2086 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2087 cmap, unwind.pixels, unwind.npixels,
2088 instantiator);
2089
2090 /* Step 7: Finish decompression */
2091
2092 jpeg_finish_decompress (&cinfo);
2093 /* We can ignore the return value since suspension is not possible
2094 * with the stdio data source.
2095 */
2096
2097 /* And we're done!
2098
2099 Now that we've succeeded, we don't want the pixels
2100 freed right now. They're kept around in the image instance
2101 structure until it's destroyed. */
2102 unwind.npixels = 0;
2103 unwind.pixcount = 0;
2104
2105 /* This will clean up everything else. */
2106 unbind_to (speccount, Qnil);
2107 }
2108
2109 #endif /* HAVE_JPEG */
2110
2111 #ifdef HAVE_GIF
2112 /* #define USE_TEMP_FILES_FOR_GIF_IMAGES */
2113 /**********************************************************************
2114 * GIF *
2115 **********************************************************************/
2116
2117 #include <gif_lib.h>
2118
2119 static void
2120 gif_validate (Lisp_Object instantiator)
2121 {
2122 file_or_data_must_be_present (instantiator);
2123 }
2124
2125 static Lisp_Object
2126 gif_normalize (Lisp_Object inst, Lisp_Object console_type)
2127 {
2128 return simple_image_type_normalize (inst, console_type, Qgif);
2129 }
2130
2131 static int
2132 gif_possible_dest_types (void)
2133 {
2134 return IMAGE_COLOR_PIXMAP_MASK;
2135 }
2136
2137 /* To survive the otherwise baffling complexity of making sure
2138 everything gets cleaned up in the presence of an error, we
2139 use an unwind_protect(). */
2140
2141 struct gif_unwind_data
2142 {
2143 Display *dpy;
2144 Colormap cmap;
2145 unsigned char *eimage;
2146 /* Object that holds the decoded data from a GIF file */
2147 GifFileType *giffile;
2148 /* Pixels to keep around while the image is active */
2149 unsigned long *pixels;
2150 int npixels, pixcount;
2151 /* Client-side image structure */
2152 XImage *ximage;
2153 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2154 /* Tempfile to remove */
2155 char tempfile[50];
2156 int tempfile_needs_to_be_removed;
2157 #endif
2158 };
2159
2160 static Lisp_Object
2161 gif_instantiate_unwind (Lisp_Object unwind_obj)
2162 {
2163 struct gif_unwind_data *data =
2164 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
2165
2166 free_opaque_ptr (unwind_obj);
2167 if (data->giffile)
2168 {
2169 DGifCloseFile (data->giffile);
2170 GifFree(data->giffile);
2171 }
2172 if (data->eimage) xfree(data->eimage);
2173 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2174 if (data->tempfile_needs_to_be_removed)
2175 unlink (data->tempfile);
2176 #endif
2177 if (data->npixels > 0)
2178 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2179 if (data->pixcount > 0)
2180 xfree (data->pixels);
2181 if (data->ximage)
2182 {
2183 if (data->ximage->data)
2184 {
2185 xfree (data->ximage->data);
2186 data->ximage->data = 0;
2187 }
2188 XDestroyImage (data->ximage);
2189 }
2190
2191 return Qnil;
2192 }
2193
2194 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES
2195 typedef struct gif_memory_storage
2196 {
2197 Extbyte *bytes; /* The data */
2198 Extcount len; /* How big is it? */
2199 int index; /* Where are we? */
2200 } gif_memory_storage;
2201
2202 static size_t
2203 gif_read_from_memory(GifByteType *buf, size_t size, VoidPtr data)
2204 {
2205 gif_memory_storage *mem = (gif_memory_storage*)data;
2206
2207 if (size > (mem->len - mem->index))
2208 return -1;
2209 memcpy(buf, mem->bytes + mem->index, size);
2210 mem->index = mem->index + size;
2211 return size;
2212 }
2213
2214 static int
2215 gif_memory_close(VoidPtr data)
2216 {
2217 return 0;
2218 }
2219
2220 #endif
2221 struct gif_error_struct
2222 {
2223 CONST char *err_str; /* return the error string */
2224 jmp_buf setjmp_buffer; /* for return to caller */
2225 };
2226
2227 static void
2228 gif_error_func(CONST char *err_str, VoidPtr error_ptr)
2229 {
2230 struct gif_error_struct *error_data = (struct gif_error_struct*)error_ptr;
2231
2232 /* return to setjmp point */
2233 error_data->err_str = err_str;
2234 longjmp (error_data->setjmp_buffer, 1);
2235 }
2236
2237 static void
2238 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2239 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2240 int dest_mask, Lisp_Object domain)
2241 {
2242 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2243 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2244 Display *dpy;
2245 Colormap cmap;
2246 Visual *vis;
2247 /* It is OK for the unwind data to be local to this function,
2248 because the unwind-protect is always executed when this
2249 stack frame is still valid. */
2250 struct gif_unwind_data unwind;
2251 int speccount = specpdl_depth ();
2252 #ifndef USE_TEMP_FILES_FOR_GIF_IMAGES
2253 gif_memory_storage mem_struct;
2254 struct gif_error_struct gif_err;
2255 Extbyte *bytes;
2256 Extcount len;
2257 #endif
2258 if (!DEVICE_X_P (XDEVICE (device)))
2259 signal_simple_error ("Not an X device", device);
2260
2261 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2262 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2263 vis = DEVICE_X_VISUAL (XDEVICE(device));
2264
2265 xzero (unwind);
2266 unwind.dpy = dpy;
2267 unwind.cmap = cmap;
2268 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
2269
2270 /* 1. Now decode the data. */
2271
2272 {
2273 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2274
2275 assert (!NILP (data));
2276
2277 if (!(unwind.giffile = GifSetup()))
2278 signal_image_error ("Insufficent memory to instantiate GIF image", instantiator);
2279
2280 /* set up error facilities */
2281 if (setjmp(gif_err.setjmp_buffer))
2282 {
2283 /* An error was signaled. No clean up is needed, as unwind handles that
2284 for us. Just pass the error along. */
2285 Lisp_Object errstring;
2286 errstring = build_string (gif_err.err_str);
2287 signal_image_error_2 ("GIF decoding error", errstring, instantiator);
2288 }
2289 GifSetErrorFunc(unwind.giffile, (Gif_error_func)gif_error_func, (VoidPtr)&gif_err);
2290
2291 #ifdef USE_TEMP_FILES_FOR_GIF_IMAGES
2292 write_lisp_string_to_temp_file (data, unwind.tempfile);
2293 unwind.tempfile_needs_to_be_removed = 1;
2294 DGifOpenFileName (unwind.giffile, unwind.tempfile);
2295 #else
2296 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2297 mem_struct.bytes = bytes;
2298 mem_struct.len = len;
2299 mem_struct.index = 0;
2300 GifSetReadFunc(unwind.giffile, gif_read_from_memory, (VoidPtr)&mem_struct);
2301 GifSetCloseFunc(unwind.giffile, gif_memory_close, (VoidPtr)&mem_struct);
2302 DGifInitRead(unwind.giffile);
2303 #endif
2304 /* Then slurp the image into memory, decoding along the way.
2305 The result is the image in a simple one-byte-per-pixel
2306 format (#### the GIF routines only support 8-bit GIFs,
2307 it appears). */
2308 DGifSlurp (unwind.giffile);
2309 }
2310
2311 #if 0
2312 /* 2. Now allocate the colors for the image. */
2313 {
2314 int i;
2315 ColorMapObject *cmo = unwind.giffile->SColorMap;
2316 /* Just in case the image contains out-of-range pixels, we go
2317 ahead and allocate space for all of them. */
2318 unwind.pixels = xnew_array (unsigned long, 256);
2319 unwind.npixels = 0;
2320
2321 for (i = 0; i < 256; i++)
2322 unwind.pixels[i] = 0; /* Use a reasonable color for out of range. */
2323
2324 /* Allocate pixels for the various colors. */
2325 for (i = 0; i < cmo->ColorCount; i++)
2326 {
2327 int res;
2328 XColor color;
2329
2330 color.red = cmo->Colors[i].Red << 8;
2331 color.green = cmo->Colors[i].Green << 8;
2332 color.blue = cmo->Colors[i].Blue << 8;
2333 color.flags = DoRed | DoGreen | DoBlue;
2334
2335 res = allocate_nearest_color (dpy, cmap, vis, &color);
2336 if (res > 0 && res < 3)
2337 {
2338 unwind.pixels[unwind.npixels] = color.pixel;
2339 unwind.npixels++;
2340 }
2341 }
2342 }
2343
2344 /* 3. Now create the image */
2345 {
2346 int height = unwind.giffile->SHeight;
2347 int width = unwind.giffile->SWidth;
2348 int depth;
2349 int bitmap_pad;
2350 int i, j, row, pass, interlace;
2351 /* interlaced gifs have rows in this order:
2352 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */
2353 static int InterlacedOffset[] = { 0, 4, 2, 1 };
2354 static int InterlacedJumps[] = { 8, 8, 4, 2 };
2355
2356 depth = DEVICE_X_DEPTH(XDEVICE(device));
2357
2358 /* first get bitmap_pad (from XPM) */
2359 bitmap_pad = ((depth > 16) ? 32 :
2360 (depth > 8) ? 16 :
2361 8);
2362
2363 unwind.ximage = XCreateImage (dpy, vis,
2364 depth, ZPixmap, 0, 0, width, height,
2365 bitmap_pad, 0);
2366
2367 if (!unwind.ximage)
2368 signal_image_error ("Unable to create X image struct", instantiator);
2369
2370 /* now that bytes_per_line must have been set properly alloc data */
2371 unwind.ximage->data =
2372 (char *) xmalloc (unwind.ximage->bytes_per_line * height);
2373
2374 /* write the data --
2375 #### XPutPixel() is a client-side-only function but could
2376 still be slow. Another possibility is to just convert to
2377 XPM format and use the Xpm routines, which optimize this
2378 stuff; but it's doubtful that this will be faster in the
2379 long run, what with all the XPM overhead. If this proves
2380 to be a bottleneck here, maybe we should just copy the
2381 optimization routines from XPM (they're in turn mostly
2382 copied from the Xlib source code). */
2383
2384 /* Note: We just use the first image in the file and ignore the rest.
2385 We check here that that image covers the full "screen" size.
2386 I don't know whether that's always the case.
2387 -dkindred@cs.cmu.edu */
2388 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
2389 || unwind.giffile->SavedImages[0].ImageDesc.Width != width
2390 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0
2391 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
2392 signal_image_error ("First image in GIF file is not full size",
2393 instantiator);
2394
2395 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
2396 pass = 0;
2397 row = interlace ? InterlacedOffset[pass] : 0;
2398 for (i = 0; i < height; i++)
2399 {
2400 if (interlace && row >= height)
2401 row = InterlacedOffset[++pass];
2402
2403 for (j = 0; j < width; j++)
2404 XPutPixel (unwind.ximage, j, row,
2405 unwind.pixels[(unsigned char)
2406 /* incorrect signed declaration
2407 of RasterBits[] */
2408 (unwind.giffile->SavedImages[0].
2409 RasterBits[i * width + j])]);
2410
2411 row += interlace ? InterlacedJumps[pass] : 1;
2412 }
2413 }
2414 #else
2415 /* 3. Now create the EImage */
2416 {
2417 ColorMapObject *cmo = unwind.giffile->SColorMap;
2418 int height = unwind.giffile->SHeight;
2419 int width = unwind.giffile->SWidth;
2420 int i, j, row, pass, interlace;
2421 unsigned char *eip;
2422 /* interlaced gifs have rows in this order:
2423 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */
2424 static int InterlacedOffset[] = { 0, 4, 2, 1 };
2425 static int InterlacedJumps[] = { 8, 8, 4, 2 };
2426
2427 unwind.eimage = (unsigned char*) xmalloc (width * height * 3);
2428 if (!unwind.eimage)
2429 signal_image_error("Unable to allocate enough memory for image", instantiator);
2430
2431 /* write the data in EImage format (8bit RGB triples) */
2432
2433 /* Note: We just use the first image in the file and ignore the rest.
2434 We check here that that image covers the full "screen" size.
2435 I don't know whether that's always the case.
2436 -dkindred@cs.cmu.edu */
2437 if (unwind.giffile->SavedImages[0].ImageDesc.Height != height
2438 || unwind.giffile->SavedImages[0].ImageDesc.Width != width
2439 || unwind.giffile->SavedImages[0].ImageDesc.Left != 0
2440 || unwind.giffile->SavedImages[0].ImageDesc.Top != 0)
2441 signal_image_error ("First image in GIF file is not full size",
2442 instantiator);
2443
2444 interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace;
2445 pass = 0;
2446 row = interlace ? InterlacedOffset[pass] : 0;
2447 eip = unwind.eimage;
2448 for (i = 0; i < height; i++)
2449 {
2450 if (interlace && row >= height)
2451 row = InterlacedOffset[++pass];
2452 eip = unwind.eimage + (row * width * 3);
2453 for (j = 0; j < width; j++)
2454 {
2455 unsigned char pixel = unwind.giffile->SavedImages[0].RasterBits[(i * width) + j];
2456 *eip++ = cmo->Colors[pixel].Red;
2457 *eip++ = cmo->Colors[pixel].Green;
2458 *eip++ = cmo->Colors[pixel].Blue;
2459 }
2460 row += interlace ? InterlacedJumps[pass] : 1;
2461 }
2462 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage,
2463 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
2464 if (!unwind.ximage)
2465 signal_image_error("GIF conversion failed", instantiator);
2466 }
2467 #endif
2468 /* 4. Now create the pixmap and set up the image instance */
2469 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2470 cmap, unwind.pixels, unwind.npixels,
2471 instantiator);
2472 /* Now that we've succeeded, we don't want the pixels
2473 freed right now. They're kept around in the image instance
2474 structure until it's destroyed. */
2475 unwind.npixels = 0;
2476 unwind.pixcount = 0;
2477 unbind_to (speccount, Qnil);
2478 }
2479
2480 #endif /* HAVE_GIF */
2481
2482
2483 #ifdef HAVE_PNG
2484 /* #define USE_TEMP_FILES_FOR_PNG_IMAGES 1 */
2485
2486 /**********************************************************************
2487 * PNG *
2488 **********************************************************************/
2489 static void
2490 png_validate (Lisp_Object instantiator)
2491 {
2492 file_or_data_must_be_present (instantiator);
2493 }
2494
2495 static Lisp_Object
2496 png_normalize (Lisp_Object inst, Lisp_Object console_type)
2497 {
2498 return simple_image_type_normalize (inst, console_type, Qpng);
2499 }
2500
2501 static int
2502 png_possible_dest_types (void)
2503 {
2504 return IMAGE_COLOR_PIXMAP_MASK;
2505 }
2506
2507 #ifndef USE_TEMP_FILES_FOR_PNG_IMAGES
2508 struct png_memory_storage
2509 {
2510 CONST Extbyte *bytes; /* The data */
2511 Extcount len; /* How big is it? */
2512 int index; /* Where are we? */
2513 };
2514
2515 static void
2516 png_read_from_memory(png_structp png_ptr, png_bytep data,
2517 png_size_t length)
2518 {
2519 struct png_memory_storage *tbr =
2520 (struct png_memory_storage *) png_get_io_ptr (png_ptr);
2521
2522 if (length > (tbr->len - tbr->index))
2523 png_error (png_ptr, (png_const_charp) "Read Error");
2524 memcpy (data,tbr->bytes + tbr->index,length);
2525 tbr->index = tbr->index + length;
2526 }
2527 #endif /* !USE_TEMP_FILES_FOR_PNG_IMAGES */
2528
2529 struct png_error_struct
2530 {
2531 CONST char *err_str;
2532 jmp_buf setjmp_buffer; /* for return to caller */
2533 };
2534
2535 /* jh 98/03/12 - #### AARRRGH! libpng includes jmp_buf inside its own
2536 structure, and there are cases where the size can be different from
2537 between inside the libarary, and inside the code! To do an end run
2538 around this, use our own error functions, and don't rely on things
2539 passed in the png_ptr to them. This is an ugly hack and must
2540 go away when the lisp engine is threaded! */
2541 static struct png_error_struct png_err_stct;
2542
2543 static void
2544 png_error_func (png_structp png_ptr, png_const_charp msg)
2545 {
2546 png_err_stct.err_str = msg;
2547 longjmp (png_err_stct.setjmp_buffer, 1);
2548 }
2549
2550 static void
2551 png_warning_func (png_structp png_ptr, png_const_charp msg)
2552 {
2553 warn_when_safe (Qpng, Qinfo, "%s", msg);
2554 }
2555
2556 struct png_unwind_data
2557 {
2558 Display *dpy;
2559 Colormap cmap;
2560 FILE *instream;
2561 unsigned char *eimage;
2562 png_structp png_ptr;
2563 png_infop info_ptr;
2564 unsigned long *pixels;
2565 int npixels, pixcount;
2566 XImage *ximage;
2567 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGESS
2568 char tempfile[50];
2569 int tempfile_needs_to_be_removed;
2570 #endif
2571 };
2572
2573 static Lisp_Object
2574 png_instantiate_unwind (Lisp_Object unwind_obj)
2575 {
2576 struct png_unwind_data *data =
2577 (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
2578
2579 free_opaque_ptr (unwind_obj);
2580 if (data->png_ptr)
2581 png_destroy_read_struct (&(data->png_ptr), &(data->info_ptr), (png_infopp)NULL);
2582 if (data->instream)
2583 fclose (data->instream);
2584 if (data->npixels > 0)
2585 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
2586 if (data->pixcount > 0)
2587 xfree (data->pixels);
2588
2589 if (data->eimage)
2590 xfree (data->eimage);
2591 if (data->ximage)
2592 {
2593 if (data->ximage->data)
2594 {
2595 xfree (data->ximage->data);
2596 data->ximage->data = 0;
2597 }
2598 XDestroyImage (data->ximage);
2599 }
2600 #ifdef USE_TEMP_FILES_FOR_PNG_IMAGES
2601 if (data->tempfile_needs_to_be_removed)
2602 unlink (data->tempfile);
2603 #endif
2604 return Qnil;
2605 }
2606
2607 static void
2608 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
2609 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
2610 int dest_mask, Lisp_Object domain)
2611 {
2612 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
2613 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
2614 Display *dpy;
2615 Colormap cmap;
2616 Visual *vis;
2617 struct png_unwind_data unwind;
2618 int speccount = specpdl_depth ();
2619
2620 /* PNG variables */
2621 png_structp png_ptr;
2622 png_infop info_ptr;
2623
2624 if (!DEVICE_X_P (XDEVICE (device)))
2625 signal_simple_error ("Not an X device", device);
2626
2627 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
2628 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
2629 vis = DEVICE_X_VISUAL (XDEVICE(device));
2630
2631 /* Initialize all PNG structures */
2632 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (void*)&png_err_stct,
2633 png_error_func, png_warning_func);
2634 if (!png_ptr)
2635 signal_image_error ("Error obtaining memory for png_read", instantiator);
2636 info_ptr = png_create_info_struct (png_ptr);
2637 if (!info_ptr)
2638 {
2639 png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
2640 signal_image_error ("Error obtaining memory for png_read", instantiator);
2641 }
2642
2643 xzero (unwind);
2644 unwind.png_ptr = png_ptr;
2645 unwind.info_ptr = info_ptr;
2646 unwind.dpy = dpy;
2647 unwind.cmap = cmap;
2648
2649 record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
2650
2651 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
2652 this file, example.c from the libpng 0.81 distribution, and the
2653 pngtopnm sources. -WMP-
2654 */
2655 /* It has been further modified to handle the API changes for 0.96,
2656 and is no longer usable for previous versions. jh
2657 */
2658
2659 /* Set the jmp_buf reurn context for png_error ... if this returns !0, then
2660 we ran into a problem somewhere, and need to clean up after ourselves. */
2661 if (setjmp (png_err_stct.setjmp_buffer))
2662 {
2663 /* Something blew up: just display the error (cleanup happens in the unwind) */
2664 signal_image_error_2 ("Error decoding PNG",
2665 build_string(png_err_stct.err_str),
2666 instantiator);
2667 }
2668
2669 /* Initialize the IO layer and read in header information */
2670 {
2671 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
2672 CONST Extbyte *bytes;
2673 Extcount len;
2674 struct png_memory_storage tbr; /* Data to be read */
2675
2676 assert (!NILP (data));
2677
2678 /* #### This is a definite problem under Mule due to the amount of
2679 stack data it might allocate. Need to think about using Lstreams */
2680 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
2681 tbr.bytes = bytes;
2682 tbr.len = len;
2683 tbr.index = 0;
2684 png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory);
2685 }
2686
2687 png_read_info (png_ptr, info_ptr);
2688
2689 #if 0
2690 /* set up the transformations you want. Note that these are
2691 all optional. Only call them if you want them */
2692 /* tell libpng to strip 16 bit depth files down to 8 bits */
2693 if (info_ptr->bit_depth == 16)
2694 png_set_strip_16 (png_ptr);
2695 if (info_ptr->bit_depth < 8)
2696 png_set_packing (png_ptr);
2697 /* ##### Perhaps some way to specify the screen gamma should be in here? */
2698
2699 {
2700 int height = info_ptr->height;
2701 int width = info_ptr->width;
2702 int depth = info_ptr->bit_depth;
2703 int linesize = max (info_ptr->bit_depth >> 3, 1) * width;
2704 int bitmap_pad;
2705 int y;
2706 XColor color;
2707 png_byte *png_pixels;
2708 png_byte **row_pointers;
2709 png_color static_color_cube[216];
2710
2711 /* Wow, allocate all the memory. Truly, exciting. */
2712 unwind.pixcount = 32;
2713 unwind.pixels = xnew_array (unsigned long, unwind.pixcount);
2714 png_pixels = xnew_array (png_byte, linesize * height);
2715 row_pointers = xnew_array (png_byte *, height);
2716
2717 for (y = 0; y < height; y++)
2718 row_pointers[y] = png_pixels + (linesize * y);
2719
2720 /* #### This is where we should handle transparency, but I am unsure of
2721 how exactly to get that information right now, in a safe manner. */
2722 #if 0
2723 {
2724 png_color_16 current_background;
2725
2726 /* Some appropriate magic should go here to get the current
2727 buffers (device?) background color and convert it to a
2728 png_color_16 struct */
2729 if (info_ptr->valid & PNG_INFO_bKGD)
2730 png_set_background (png_ptr, &(info_ptr->background), PNG_GAMMA_FILE,
2731 1, 1.0);
2732 else
2733 png_set_background (png_ptr, &current_background, PNG_GAMMA_SCREEN,
2734 0, 1.0);
2735 }
2736 #endif
2737
2738 if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
2739 (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
2740 (vis->class == PseudoColor))
2741 {
2742 if (!(info_ptr->valid & PNG_INFO_PLTE))
2743 {
2744 for (y = 0; y < 216; y++)
2745 {
2746 static_color_cube[y].red = (png_byte) ((y % 6) * 255.0 / 5);
2747 static_color_cube[y].green = (png_byte) (((y / 6) % 6) * 255.0 / 5);
2748 static_color_cube[y].blue = (png_byte) ((y / 36) * 255.0 / 5);
2749 }
2750 png_set_dither (png_ptr, static_color_cube, 216, 216, NULL, 1);
2751 }
2752 else
2753 {
2754 png_set_dither (png_ptr, info_ptr->palette, info_ptr->num_palette,
2755 info_ptr->num_palette, info_ptr->hist, 1);
2756 }
2757 }
2758
2759 png_read_image (png_ptr, row_pointers);
2760 png_read_end (png_ptr, info_ptr);
2761
2762 /* Ok, now we go and allocate all the colors */
2763 if (info_ptr->valid & PNG_INFO_PLTE)
2764 {
2765 unwind.npixels = 0;
2766 for (y = 0; y < info_ptr->num_palette; y++)
2767 {
2768 int res;
2769 color.red = info_ptr->palette[y].red << 8;
2770 color.green = info_ptr->palette[y].green << 8;
2771 color.blue = info_ptr->palette[y].blue << 8;
2772 color.flags = DoRed | DoGreen | DoBlue;
2773 res = allocate_nearest_color (dpy, cmap, vis, &color);
2774 if (res > 0 && res < 3)
2775 {
2776 DO_REALLOC(unwind.pixels, unwind.pixcount, unwind.npixels+1, unsigned long);
2777 unwind.pixels[unwind.npixels] = color.pixel;
2778 unwind.npixels++;
2779 }
2780 }
2781 }
2782 else
2783 {
2784 unwind.npixels = 0;
2785 for (y = 0; y < 216; y++)
2786 {
2787 int res;
2788 color.red = static_color_cube[y].red << 8;
2789 color.green = static_color_cube[y].green << 8;
2790 color.blue = static_color_cube[y].blue << 8;
2791 color.flags = DoRed|DoGreen|DoBlue;
2792 res = allocate_nearest_color (dpy, cmap, vis, &color);
2793 if (res > 0 && res < 3)
2794 {
2795 unwind.pixels[unwind.npixels] = color.pixel;
2796 unwind.npixels++;
2797 }
2798 }
2799 }
2800
2801 #ifdef PNG_SHOW_COMMENTS
2802 /* ####
2803 * I turn this off by default now, because the !%^@#!% comments
2804 * show up every time the image is instantiated, which can get
2805 * really really annoying. There should be some way to pass this
2806 * type of data down into the glyph code, where you can get to it
2807 * from lisp anyway. - WMP
2808 */
2809 {
2810 int i;
2811
2812 for (i = 0 ; i < info_ptr->num_text ; i++)
2813 {
2814 /* How paranoid do I have to be about no trailing NULLs, and
2815 using (int)info_ptr->text[i].text_length, and strncpy and a temp
2816 string somewhere? */
2817
2818 warn_when_safe (Qpng, Qinfo, "%s - %s",
2819 info_ptr->text[i].key,
2820 info_ptr->text[i].text);
2821 }
2822 }
2823 #endif
2824
2825 /* Now create the image */
2826
2827 depth = DEVICE_X_DEPTH(XDEVICE(device));
2828
2829 /* first get bitmap_pad (from XPM) */
2830 bitmap_pad = ((depth > 16) ? 32 :
2831 (depth > 8) ? 16 :
2832 8);
2833
2834 unwind.ximage = XCreateImage (dpy, vis,
2835 depth, ZPixmap, 0, 0, width, height,
2836 bitmap_pad, 0);
2837
2838 if (!unwind.ximage)
2839 signal_image_error ("Unable to create X image struct",
2840 instantiator);
2841
2842 /* now that bytes_per_line must have been set properly alloc data */
2843 unwind.ximage->data = (char *) xmalloc (unwind.ximage->bytes_per_line *
2844 height);
2845
2846 {
2847 int i, j;
2848 for (i = 0; i < height; i++)
2849 for (j = 0; j < width; j++)
2850 XPutPixel (unwind.ximage, j, i,
2851 unwind.pixels[png_pixels[i * width + j]]);
2852 }
2853
2854 xfree (row_pointers);
2855 xfree (png_pixels);
2856 }
2857 #else
2858 {
2859 int height = info_ptr->height;
2860 int width = info_ptr->width;
2861 int y;
2862 unsigned char **row_pointers;
2863
2864 /* Wow, allocate all the memory. Truly, exciting. */
2865 unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 3);
2866 /* libpng expects that the image buffer passed in contains a
2867 picture to draw on top of if the png has any transparencies.
2868 This could be a good place to pass that in... */
2869
2870 row_pointers = xnew_array (png_byte *, height);
2871
2872 for (y = 0; y < height; y++)
2873 row_pointers[y] = unwind.eimage + (width * 3 * y);
2874
2875 /* Now that we're using EImage, ask for 8bit RGB triples for any type
2876 of image*/
2877 /* convert palatte images to full RGB */
2878 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2879 png_set_expand (png_ptr);
2880 /* send grayscale images to RGB too */
2881 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
2882 info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2883 png_set_gray_to_rgb (png_ptr);
2884 /* we can't handle alpha values */
2885 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
2886 png_set_strip_alpha (png_ptr);
2887 /* rip out any transparancy layers/colors */
2888 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
2889 {
2890 png_set_expand (png_ptr);
2891 png_set_strip_alpha (png_ptr);
2892 }
2893 /* tell libpng to strip 16 bit depth files down to 8 bits */
2894 if (info_ptr->bit_depth == 16)
2895 png_set_strip_16 (png_ptr);
2896 /* if the image is < 8 bits, pad it out */
2897 if (info_ptr->bit_depth < 8)
2898 {
2899 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2900 png_set_expand (png_ptr);
2901 else
2902 png_set_packing (png_ptr);
2903 }
2904
2905 #if 1 /* tests? or permanent? */
2906 {
2907 /* if the png specifies a background chunk, go ahead and
2908 use it */
2909 png_color_16 my_background, *image_background;
2910
2911 /* ### how do I get the background of the current frame? */
2912 my_background.red = 0x7fff;
2913 my_background.green = 0x7fff;
2914 my_background.blue = 0x7fff;
2915
2916 if (png_get_bKGD (png_ptr, info_ptr, &image_background))
2917 png_set_background (png_ptr, image_background,
2918 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
2919 else
2920 png_set_background (png_ptr, &my_background,
2921 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
2922 }
2923 #endif
2924 png_read_image (png_ptr, row_pointers);
2925 png_read_end (png_ptr, info_ptr);
2926
2927 #ifdef PNG_SHOW_COMMENTS
2928 /* ####
2929 * I turn this off by default now, because the !%^@#!% comments
2930 * show up every time the image is instantiated, which can get
2931 * really really annoying. There should be some way to pass this
2932 * type of data down into the glyph code, where you can get to it
2933 * from lisp anyway. - WMP
2934 */
2935 {
2936 int i;
2937
2938 for (i = 0 ; i < info_ptr->num_text ; i++)
2939 {
2940 /* How paranoid do I have to be about no trailing NULLs, and
2941 using (int)info_ptr->text[i].text_length, and strncpy and a temp
2942 string somewhere? */
2943
2944 warn_when_safe (Qpng, Qinfo, "%s - %s",
2945 info_ptr->text[i].key,
2946 info_ptr->text[i].text);
2947 }
2948 }
2949 #endif
2950
2951 xfree (row_pointers);
2952 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage,
2953 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
2954 if (!unwind.ximage)
2955 signal_image_error ("PNG conversion failed", instantiator);
2956 }
2957 #endif
2958
2959 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
2960 cmap, unwind.pixels, unwind.npixels,
2961 instantiator);
2962
2963 /* This will clean up everything else. */
2964 unwind.npixels = 0;
2965 unwind.pixcount = 0;
2966 unbind_to (speccount, Qnil);
2967 }
2968
2969 #endif /* HAVE_PNG */
2970
2971
2972 #ifdef HAVE_TIFF
2973 #include "tiffio.h"
2974
2975 /**********************************************************************
2976 * TIFF *
2977 **********************************************************************/
2978 static void
2979 tiff_validate (Lisp_Object instantiator)
2980 {
2981 file_or_data_must_be_present (instantiator);
2982 }
2983
2984 static Lisp_Object
2985 tiff_normalize (Lisp_Object inst, Lisp_Object console_type)
2986 {
2987 return simple_image_type_normalize (inst, console_type, Qtiff);
2988 }
2989
2990 static int
2991 tiff_possible_dest_types (void)
2992 {
2993 return IMAGE_COLOR_PIXMAP_MASK;
2994 }
2995
2996 struct tiff_unwind_data
2997 {
2998 Display *dpy;
2999 Colormap cmap;
3000 unsigned char *eimage;
3001 /* Object that holds the decoded data from a TIFF file */
3002 TIFF *tiff;
3003 /* Pixels to keep around while the image is active */
3004 unsigned long *pixels;
3005 int npixels,pixcount;
3006 /* Client-side image structure */
3007 XImage *ximage;
3008 };
3009
3010 static Lisp_Object
3011 tiff_instantiate_unwind (Lisp_Object unwind_obj)
3012 {
3013 struct tiff_unwind_data *data =
3014 (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj);
3015
3016 free_opaque_ptr (unwind_obj);
3017 if (data->tiff)
3018 {
3019 TIFFClose(data->tiff);
3020 }
3021 if (data->eimage)
3022 xfree (data->eimage);
3023 if (data->npixels > 0)
3024 XFreeColors (data->dpy, data->cmap, data->pixels, data->npixels, 0L);
3025 if (data->pixcount)
3026 xfree (data->pixels);
3027 if (data->ximage)
3028 {
3029 if (data->ximage->data)
3030 {
3031 xfree (data->ximage->data);
3032 data->ximage->data = 0;
3033 }
3034 XDestroyImage (data->ximage);
3035 }
3036
3037 return Qnil;
3038 }
3039
3040 typedef struct tiff_memory_storage
3041 {
3042 Extbyte *bytes; /* The data */
3043 Extcount len; /* How big is it? */
3044 int index; /* Where are we? */
3045 } tiff_memory_storage;
3046
3047 static size_t
3048 tiff_memory_read(thandle_t data, tdata_t buf, tsize_t size)
3049 {
3050 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3051
3052 if (size > (mem->len - mem->index))
3053 return (size_t) -1;
3054 memcpy(buf, mem->bytes + mem->index, size);
3055 mem->index = mem->index + size;
3056 return size;
3057 }
3058
3059 static size_t tiff_memory_write(thandle_t data, tdata_t buf, tsize_t size)
3060 {
3061 abort();
3062 return 0; /* Shut up warnings. */
3063 }
3064
3065 static toff_t tiff_memory_seek(thandle_t data, toff_t off, int whence)
3066 {
3067 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3068 int newidx;
3069 switch(whence) {
3070 case SEEK_SET:
3071 newidx = off;
3072 break;
3073 case SEEK_END:
3074 newidx = mem->len + off;
3075 break;
3076 case SEEK_CUR:
3077 newidx = mem->index + off;
3078 break;
3079 default:
3080 fprintf(stderr,"Eh? invalid seek mode in tiff_memory_seek\n");
3081 return -1;
3082 }
3083
3084 if ((newidx > mem->len) || (newidx < 0))
3085 return -1;
3086
3087 mem->index = newidx;
3088 return newidx;
3089 }
3090
3091 static int
3092 tiff_memory_close(thandle_t data)
3093 {
3094 return 0;
3095 }
3096
3097 static int
3098 tiff_map_noop(thandle_t data, tdata_t* pbase, toff_t* psize)
3099 {
3100 return 0;
3101 }
3102
3103 static void
3104 tiff_unmap_noop(thandle_t data, tdata_t pbase, toff_t psize)
3105 {
3106 return;
3107 }
3108
3109 static toff_t
3110 tiff_memory_size(thandle_t data)
3111 {
3112 tiff_memory_storage *mem = (tiff_memory_storage*)data;
3113 return mem->len;
3114 }
3115
3116 struct tiff_error_struct
3117 {
3118 #if HAVE_VSNPRINTF
3119 char err_str[256];
3120 #else
3121 char err_str[1024]; /* return the error string */
3122 #endif
3123 jmp_buf setjmp_buffer; /* for return to caller */
3124 };
3125
3126 /* jh 98/03/12 - ###This struct for passing data to the error functions
3127 is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't
3128 have any place to store error func data. This should be rectified
3129 before XEmacs gets threads! */
3130 static struct tiff_error_struct tiff_err_data;
3131
3132 static void
3133 tiff_error_func(CONST char *module, CONST char *fmt, ...)
3134 {
3135 va_list vargs;
3136
3137 va_start (vargs, fmt);
3138 #if HAVE_VSNPRINTF
3139 vsnprintf (tiff_err_data.err_str, 255, fmt, vargs);
3140 #else
3141 /* pray this doesn't overflow... */
3142 vsprintf (tiff_err_data.err_str, fmt, vargs);
3143 #endif
3144 va_end (vargs);
3145 /* return to setjmp point */
3146 longjmp (tiff_err_data.setjmp_buffer, 1);
3147 }
3148
3149 static void
3150 tiff_warning_func(CONST char *module, CONST char *fmt, ...)
3151 {
3152 va_list vargs;
3153 #if HAVE_VSNPRINTF
3154 char warn_str[256];
3155 #else
3156 char warn_str[1024];
3157 #endif
3158
3159 va_start (vargs, fmt);
3160 #if HAVE_VSNPRINTF
3161 vsnprintf (warn_str, 255, fmt, vargs);
3162 #else
3163 vsprintf (warn_str, fmt, vargs);
3164 #endif
3165 va_end (vargs);
3166 warn_when_safe (Qtiff, Qinfo, "%s - %s",
3167 module, warn_str);
3168 }
3169
3170 static void
3171 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
3172 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
3173 int dest_mask, Lisp_Object domain)
3174 {
3175 struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
3176 Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
3177 Colormap cmap;
3178 Display *dpy;
3179 tiff_memory_storage mem_struct;
3180 /* It is OK for the unwind data to be local to this function,
3181 because the unwind-protect is always executed when this
3182 stack frame is still valid. */
3183 struct tiff_unwind_data unwind;
3184 int speccount = specpdl_depth ();
3185
3186 if (!DEVICE_X_P (XDEVICE (device)))
3187 signal_simple_error ("Not an X device", device);
3188
3189 dpy = DEVICE_X_DISPLAY (XDEVICE (device));
3190 cmap = DEVICE_X_COLORMAP (XDEVICE(device));
3191
3192 xzero (unwind);
3193 unwind.dpy = dpy;
3194 unwind.cmap = cmap;
3195 record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind));
3196
3197 /* set up error facilities */
3198 if (setjmp (tiff_err_data.setjmp_buffer))
3199 {
3200 /* An error was signaled. No clean up is needed, as unwind handles that
3201 for us. Just pass the error along. */
3202 signal_image_error_2 ("TIFF decoding error",
3203 build_string(tiff_err_data.err_str),
3204 instantiator);
3205 }
3206 TIFFSetErrorHandler ((TIFFErrorHandler)tiff_error_func);
3207 TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func);
3208 {
3209 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
3210 Extbyte *bytes;
3211 Extcount len;
3212
3213 uint32 width, height;
3214 uint32 *raster;
3215 unsigned char *ep;
3216
3217 assert (!NILP (data));
3218
3219 /* #### This is a definite problem under Mule due to the amount of
3220 stack data it might allocate. Think about Lstreams... */
3221 GET_STRING_BINARY_DATA_ALLOCA (data, bytes, len);
3222 mem_struct.bytes = bytes;
3223 mem_struct.len = len;
3224 mem_struct.index = 0;
3225
3226 unwind.tiff = TIFFClientOpen ("memfile", "r", &mem_struct,
3227 (TIFFReadWriteProc)tiff_memory_read,
3228 (TIFFReadWriteProc)tiff_memory_write,
3229 tiff_memory_seek, tiff_memory_close, tiff_memory_size,
3230 tiff_map_noop, tiff_unmap_noop);
3231 if (!unwind.tiff)
3232 signal_image_error ("Insufficent memory to instantiate TIFF image", instantiator);
3233
3234 TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
3235 TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
3236 unwind.eimage = (unsigned char *) xmalloc (width * height * 3);
3237
3238 /* ### This is little more than proof-of-concept/function testing.
3239 It needs to be reimplimented via scanline reads for both memory
3240 compactness. */
3241 raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32));
3242 if (raster != NULL)
3243 {
3244 int i,j;
3245 uint32 *rp;
3246 ep = unwind.eimage;
3247 rp = raster;
3248 if (TIFFReadRGBAImage (unwind.tiff, width, height, raster, 0))
3249 {
3250 for (i = height - 1; i >= 0; i--)
3251 {
3252 /* This is to get around weirdness in the libtiff library where properly
3253 made TIFFs will come out upside down. libtiff bug or jhod-brainlock? */
3254 rp = raster + (i * width);
3255 for (j = 0; j < width; j++)
3256 {
3257 *ep++ = (unsigned char)TIFFGetR(*rp);
3258 *ep++ = (unsigned char)TIFFGetG(*rp);
3259 *ep++ = (unsigned char)TIFFGetB(*rp);
3260 rp++;
3261 }
3262 }
3263 }
3264 _TIFFfree (raster);
3265 } else
3266 signal_image_error ("Unable to allocate memory for TIFFReadRGBA", instantiator);
3267
3268 unwind.ximage = convert_EImage_to_XImage (device, width, height, unwind.eimage,
3269 &unwind.pixels, &unwind.pixcount, &unwind.npixels);
3270 if (!unwind.ximage)
3271 signal_image_error ("TIFF conversion failed", instantiator);
3272 }
3273 /* Now create the pixmap and set up the image instance */
3274 init_image_instance_from_x_image (ii, unwind.ximage, dest_mask,
3275 cmap, unwind.pixels, unwind.npixels,
3276 instantiator);
3277 /* Now that we've succeeded, we don't want the pixels
3278 freed right now. They're kept around in the image instance
3279 structure until it's destroyed. */
3280 unwind.npixels = 0;
3281 unwind.pixcount = 0;
3282 unbind_to (speccount, Qnil);
3283 }
3284
3285 #endif /* HAVE_TIFF */
3286
3287
3288 #ifdef HAVE_XFACE 1468 #ifdef HAVE_XFACE
3289 1469
3290 /********************************************************************** 1470 /**********************************************************************
3291 * X-Face * 1471 * X-Face *
3292 **********************************************************************/ 1472 **********************************************************************/
4162 2342
4163 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string); 2343 IIFORMAT_VALID_KEYWORD (font, Q_data, check_valid_string);
4164 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string); 2344 IIFORMAT_VALID_KEYWORD (font, Q_foreground, check_valid_string);
4165 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string); 2345 IIFORMAT_VALID_KEYWORD (font, Q_background, check_valid_string);
4166 2346
4167 #ifdef HAVE_JPEG
4168 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
4169
4170 IIFORMAT_HAS_METHOD (jpeg, validate);
4171 IIFORMAT_HAS_METHOD (jpeg, normalize);
4172 IIFORMAT_HAS_METHOD (jpeg, possible_dest_types);
4173 IIFORMAT_HAS_METHOD (jpeg, instantiate);
4174
4175 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
4176 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
4177 #endif
4178
4179 #ifdef HAVE_GIF
4180 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
4181
4182 IIFORMAT_HAS_METHOD (gif, validate);
4183 IIFORMAT_HAS_METHOD (gif, normalize);
4184 IIFORMAT_HAS_METHOD (gif, possible_dest_types);
4185 IIFORMAT_HAS_METHOD (gif, instantiate);
4186
4187 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
4188 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
4189 #endif
4190
4191 #ifdef HAVE_PNG
4192 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
4193
4194 IIFORMAT_HAS_METHOD (png, validate);
4195 IIFORMAT_HAS_METHOD (png, normalize);
4196 IIFORMAT_HAS_METHOD (png, possible_dest_types);
4197 IIFORMAT_HAS_METHOD (png, instantiate);
4198
4199 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
4200 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
4201 #endif
4202
4203 #ifdef HAVE_TIFF
4204 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
4205
4206 IIFORMAT_HAS_METHOD (tiff, validate);
4207 IIFORMAT_HAS_METHOD (tiff, normalize);
4208 IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
4209 IIFORMAT_HAS_METHOD (tiff, instantiate);
4210
4211 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
4212 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
4213 #endif
4214
4215 #ifdef HAVE_XFACE 2347 #ifdef HAVE_XFACE
4216 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface"); 2348 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xface, "xface");
4217 2349
4218 IIFORMAT_HAS_METHOD (xface, validate); 2350 IIFORMAT_HAS_METHOD (xface, validate);
4219 IIFORMAT_HAS_METHOD (xface, normalize); 2351 IIFORMAT_HAS_METHOD (xface, normalize);
4240 } 2372 }
4241 2373
4242 void 2374 void
4243 vars_of_glyphs_x (void) 2375 vars_of_glyphs_x (void)
4244 { 2376 {
4245 #ifdef HAVE_JPEG
4246 Fprovide (Qjpeg);
4247 #endif
4248
4249 #ifdef HAVE_GIF
4250 Fprovide (Qgif);
4251 #endif
4252
4253 #ifdef HAVE_PNG
4254 Fprovide (Qpng);
4255 #endif
4256
4257 #ifdef HAVE_TIFF
4258 Fprovide (Qtiff);
4259 #endif
4260
4261 #ifdef HAVE_XFACE 2377 #ifdef HAVE_XFACE
4262 Fprovide (Qxface); 2378 Fprovide (Qxface);
4263 #endif 2379 #endif
4264 2380
4265 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /* 2381 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path /*