Mercurial > hg > xemacs-beta
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, ¤t_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 |