(U+37FD): Apply new conventions for glyph granularity for components
[chise/xemacs-chise.git.1] / src / glyphs-eimage.c
1 /* EImage-specific Lisp objects.
2    Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc.
3    Copyright (C) 1995 Board of Trustees, University of Illinois.
4    Copyright (C) 1995 Tinker Systems
5    Copyright (C) 1995, 1996, 2005 Ben Wing
6    Copyright (C) 1995 Sun Microsystems
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING.  If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.  */
24
25 /* Synched up with: Not in FSF. */
26
27 /* Original author: Jamie Zawinski for 19.8
28    font-truename stuff added by Jamie Zawinski for 19.10
29    subwindow support added by Chuck Thompson
30    additional XPM support added by Chuck Thompson
31    initial X-Face support added by Stig
32    rewritten/restructured by Ben Wing for 19.12/19.13
33    GIF/JPEG support added by Ben Wing for 19.14
34    PNG 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
37    Pointer/icon overhaul, more restructuring by Ben Wing for 19.14
38    GIF support changed to external Gifreader lib by Jareth Hein for 21.0
39    Many changes for color work and optimizations by Jareth Hein for 21.0
40    Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
41    TIFF code by Jareth Hein for 21.0
42    Generalization for ms-windows by Andy Piper for 21.0
43    TODO:
44    Convert images.el to C and stick it in here?
45  */
46
47 #include <config.h>
48 #include "lisp.h"
49 #include "lstream.h"
50 #include "console.h"
51 #include "device.h"
52 #include "faces.h"
53 #include "glyphs.h"
54 #include "objects.h"
55
56 #include "buffer.h"
57 #include "frame.h"
58 #include "opaque.h"
59 #include "window.h"
60
61 #include "sysfile.h"
62
63 #ifdef HAVE_PNG
64 #ifdef __cplusplus
65 extern "C" {
66 #endif
67 #include <png.h>
68 #ifdef __cplusplus
69 }
70 #endif
71 #else
72 #include <setjmp.h>
73 #endif
74 #ifdef FILE_CODING
75 #include "file-coding.h"
76 #endif
77
78 #ifdef HAVE_TIFF
79 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff);
80 Lisp_Object Qtiff;
81 #endif
82
83 #ifdef HAVE_JPEG
84 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg);
85 Lisp_Object Qjpeg;
86 #endif
87
88 #ifdef HAVE_GIF
89 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif);
90 Lisp_Object Qgif;
91 #endif
92
93 #ifdef HAVE_PNG
94 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png);
95 Lisp_Object Qpng;
96 #endif
97
98 \f
99 #ifdef HAVE_JPEG
100
101 /**********************************************************************
102  *                             JPEG                                   *
103  **********************************************************************/
104
105 #ifdef __cplusplus
106 extern "C" {
107 #endif
108
109 #ifdef WIN32_NATIVE
110 /* #### Yuck!  More horrifitude.  tiffio.h, below, includes <windows.h>,
111    which defines INT32 and INT16, the former differently and incompatibly
112    from jmorecfg.h, included by jpeglib.h.  We can disable the stuff in
113    jmorecfg.h by defining XMD_H (clever, huh?); then we define these
114    typedefs the way that <windows.h> wants them (which is more correct,
115    anyway; jmorecfg.h defines INT32 as `long'). */
116 #define XMD_H
117 typedef signed int INT32;
118 typedef signed short INT16;
119 #endif
120
121 #include <jpeglib.h>
122 #include <jerror.h>
123 #ifdef __cplusplus
124 }
125 #endif
126
127 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/
128 static void
129 jpeg_validate (Lisp_Object instantiator)
130 {
131   file_or_data_must_be_present (instantiator);
132 }
133
134 static Lisp_Object
135 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type,
136                 Lisp_Object dest_mask)
137 {
138   return simple_image_type_normalize (inst, console_type, Qjpeg);
139 }
140
141 static int
142 jpeg_possible_dest_types (void)
143 {
144   return IMAGE_COLOR_PIXMAP_MASK;
145 }
146
147 /* To survive the otherwise baffling complexity of making sure
148    everything gets cleaned up in the presence of an error, we
149    use an unwind_protect(). */
150
151 struct jpeg_unwind_data
152 {
153   /* Stream that we need to close */
154   FILE *instream;
155   /* Object that holds state info for JPEG decoding */
156   struct jpeg_decompress_struct *cinfo_ptr;
157   /* EImage data */
158   unsigned char *eimage;
159 };
160
161 static Lisp_Object
162 jpeg_instantiate_unwind (Lisp_Object unwind_obj)
163 {
164   struct jpeg_unwind_data *data =
165     (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj);
166
167   free_opaque_ptr (unwind_obj);
168   if (data->cinfo_ptr)
169     jpeg_destroy_decompress (data->cinfo_ptr);
170
171   if (data->instream)
172     fclose (data->instream);
173
174   if (data->eimage) xfree (data->eimage);
175
176   return Qnil;
177 }
178
179 /*
180  * ERROR HANDLING:
181  *
182  * The JPEG library's standard error handler (jerror.c) is divided into
183  * several "methods" which you can override individually.  This lets you
184  * adjust the behavior without duplicating a lot of code, which you might
185  * have to update with each future release.
186  *
187  * Our example here shows how to override the "error_exit" method so that
188  * control is returned to the library's caller when a fatal error occurs,
189  * rather than calling exit() as the standard error_exit method does.
190  *
191  * We use C's setjmp/longjmp facility to return control.  This means that the
192  * routine which calls the JPEG library must first execute a setjmp() call to
193  * establish the return point.  We want the replacement error_exit to do a
194  * longjmp().  But we need to make the setjmp buffer accessible to the
195  * error_exit routine.  To do this, we make a private extension of the
196  * standard JPEG error handler object.  (If we were using C++, we'd say we
197  * were making a subclass of the regular error handler.)
198  *
199  * Here's the extended error handler struct:
200  */
201
202 struct my_jpeg_error_mgr
203 {
204   struct jpeg_error_mgr pub;    /* "public" fields */
205   jmp_buf setjmp_buffer;        /* for return to caller */
206 };
207
208 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
209 METHODDEF(void)
210 #else
211 METHODDEF void
212 #endif
213 our_init_source (j_decompress_ptr cinfo)
214 {
215 }
216
217 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
218 METHODDEF(boolean)
219 #else
220 METHODDEF boolean
221 #endif
222 our_fill_input_buffer (j_decompress_ptr cinfo)
223 {
224   /* Insert a fake EOI marker */
225   struct jpeg_source_mgr *src = cinfo->src;
226   static JOCTET buffer[2];
227
228   buffer[0] = (JOCTET) 0xFF;
229   buffer[1] = (JOCTET) JPEG_EOI;
230
231   src->next_input_byte = buffer;
232   src->bytes_in_buffer = 2;
233   return TRUE;
234 }
235
236 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
237 METHODDEF(void)
238 #else
239 METHODDEF void
240 #endif
241 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
242 {
243   struct jpeg_source_mgr *src = NULL;
244
245   src = (struct jpeg_source_mgr *) cinfo->src;
246
247   if (!src)
248     {
249       return;
250     } else if (num_bytes > (long) src->bytes_in_buffer)
251       {
252         ERREXIT(cinfo, JERR_INPUT_EOF);
253         /*NOTREACHED*/
254       }
255
256   src->bytes_in_buffer -= num_bytes;
257   src->next_input_byte += num_bytes;
258 }
259
260 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
261 METHODDEF(void)
262 #else
263 METHODDEF void
264 #endif
265 our_term_source (j_decompress_ptr cinfo)
266 {
267 }
268
269 typedef struct
270 {
271   struct jpeg_source_mgr pub;
272 } our_jpeg_source_mgr;
273
274 static void
275 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
276 {
277   struct jpeg_source_mgr *src;
278
279   if (cinfo->src == NULL)
280     {   /* first time for this JPEG object? */
281       cinfo->src = (struct jpeg_source_mgr *)
282         (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
283                                     sizeof(our_jpeg_source_mgr));
284       src = (struct jpeg_source_mgr *) cinfo->src;
285       src->next_input_byte = data;
286     }
287   src = (struct jpeg_source_mgr *) cinfo->src;
288   src->init_source = our_init_source;
289   src->fill_input_buffer = our_fill_input_buffer;
290   src->skip_input_data = our_skip_input_data;
291   src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
292   src->term_source = our_term_source;
293   src->bytes_in_buffer = len;
294   src->next_input_byte = data;
295 }
296
297 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
298 METHODDEF(void)
299 #else
300 METHODDEF void
301 #endif
302 my_jpeg_error_exit (j_common_ptr cinfo)
303 {
304   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
305   struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err;
306
307   /* Return control to the setjmp point */
308   longjmp (myerr->setjmp_buffer, 1);
309 }
310
311 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61)
312 METHODDEF(void)
313 #else
314 METHODDEF void
315 #endif
316 my_jpeg_output_message (j_common_ptr cinfo)
317 {
318   char buffer[JMSG_LENGTH_MAX];
319
320   /* Create the message */
321   (*cinfo->err->format_message) (cinfo, buffer);
322   warn_when_safe (Qjpeg, Qinfo, "%s", buffer);
323 }
324
325 /* The code in this routine is based on example.c from the JPEG library
326    source code and from gif_instantiate() */
327 static void
328 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
329                   Lisp_Object pointer_fg, Lisp_Object pointer_bg,
330                   int dest_mask, Lisp_Object domain)
331 {
332   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
333   /* It is OK for the unwind data to be local to this function,
334      because the unwind-protect is always executed when this
335      stack frame is still valid. */
336   struct jpeg_unwind_data unwind;
337   int speccount = specpdl_depth ();
338
339   /* This struct contains the JPEG decompression parameters and pointers to
340    * working space (which is allocated as needed by the JPEG library).
341    */
342   struct jpeg_decompress_struct cinfo;
343   /* We use our private extension JPEG error handler.
344    * Note that this struct must live as long as the main JPEG parameter
345    * struct, to avoid dangling-pointer problems.
346    */
347   struct my_jpeg_error_mgr jerr;
348
349   /* Step -1: First record our unwind-protect, which will clean up after
350      any exit, normal or not */
351
352   xzero (unwind);
353   record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind));
354
355   /* Step 1: allocate and initialize JPEG decompression object */
356
357   /* We set up the normal JPEG error routines, then override error_exit. */
358   cinfo.err = jpeg_std_error (&jerr.pub);
359   jerr.pub.error_exit = my_jpeg_error_exit;
360   jerr.pub.output_message = my_jpeg_output_message;
361
362   /* Establish the setjmp return context for my_error_exit to use. */
363   if (setjmp (jerr.setjmp_buffer))
364     {
365       /* If we get here, the JPEG code has signaled an error.
366        * We need to clean up the JPEG object, close the input file, and return.
367        */
368
369       {
370         Lisp_Object errstring;
371         char buffer[JMSG_LENGTH_MAX];
372
373         /* Create the message */
374         (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer);
375         errstring = build_string (buffer);
376
377         signal_image_error_2 ("JPEG decoding error",
378                               errstring, instantiator);
379       }
380     }
381
382   /* Now we can initialize the JPEG decompression object. */
383   jpeg_create_decompress (&cinfo);
384   unwind.cinfo_ptr = &cinfo;
385
386   /* Step 2: specify data source (eg, a file) */
387
388   {
389     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
390     const Extbyte *bytes;
391     Extcount len;
392
393     /* #### This is a definite problem under Mule due to the amount of
394        stack data it might allocate.  Need to be able to convert and
395        write out to a file. */
396     TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary);
397     jpeg_memory_src (&cinfo, (JOCTET *) bytes, len);
398   }
399
400   /* Step 3: read file parameters with jpeg_read_header() */
401
402   jpeg_read_header (&cinfo, TRUE);
403   /* We can ignore the return value from jpeg_read_header since
404    *   (a) suspension is not possible with the stdio data source, and
405    *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
406    * See libjpeg.doc for more info.
407    */
408
409   {
410     int jpeg_gray = 0;          /* if we're dealing with a grayscale */
411     /* Step 4: set parameters for decompression.   */
412
413     /* Now that we're using EImages, send all data as 24bit color.
414        The backend routine will take care of any necessary reductions.
415        We do have to handle the grayscale case ourselves, however. */
416     if (cinfo.jpeg_color_space == JCS_GRAYSCALE)
417       {
418         cinfo.out_color_space = JCS_GRAYSCALE;
419         jpeg_gray = 1;
420       }
421     else
422       {
423         /* we're relying on the jpeg driver to do any other conversions,
424            or signal an error if the conversion isn't supported. */
425         cinfo.out_color_space = JCS_RGB;
426       }
427
428     /* Step 5: Start decompressor */
429     jpeg_start_decompress (&cinfo);
430
431     /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/
432
433     unwind.eimage = (unsigned char*) xmalloc (cinfo.output_width * cinfo.output_height * 3);
434     if (!unwind.eimage)
435       signal_image_error("Unable to allocate enough memory for image", instantiator);
436
437     {
438       JSAMPARRAY row_buffer;    /* Output row buffer */
439       JSAMPLE *jp;
440       int row_stride;           /* physical row width in output buffer */
441       unsigned char *op = unwind.eimage;
442
443       /* We may need to do some setup of our own at this point before reading
444        * the data.  After jpeg_start_decompress() we have the correct scaled
445        * output image dimensions available
446        * We need to make an output work buffer of the right size.
447        */
448       /* JSAMPLEs per row in output buffer. */
449       row_stride = cinfo.output_width * cinfo.output_components;
450       /* Make a one-row-high sample array that will go away when done
451          with image */
452       row_buffer = ((*cinfo.mem->alloc_sarray)
453                     ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1));
454
455       /* Here we use the library's state variable cinfo.output_scanline as the
456        * loop counter, so that we don't have to keep track ourselves.
457        */
458       while (cinfo.output_scanline < cinfo.output_height)
459         {
460           unsigned int i;
461
462           /* jpeg_read_scanlines expects an array of pointers to scanlines.
463            * Here the array is only one element long, but you could ask for
464            * more than one scanline at a time if that's more convenient.
465            */
466           (void) jpeg_read_scanlines (&cinfo, row_buffer, 1);
467           jp = row_buffer[0];
468           for (i = 0; i < cinfo.output_width; i++)
469             {
470               int clr;
471               if (jpeg_gray)
472                 {
473                   unsigned char val;
474 #if (BITS_IN_JSAMPLE == 8)
475                   val = (unsigned char)*jp++;
476 #else /* other option is 12 */
477                   val = (unsigned char)(*jp++ >> 4);
478 #endif
479                   for (clr = 0; clr < 3; clr++) /* copy the same value into RGB */
480                       *op++ = val;
481                 }
482               else
483                 {
484                   for (clr = 0; clr < 3; clr++)
485 #if (BITS_IN_JSAMPLE == 8)
486                     *op++ = (unsigned char)*jp++;
487 #else /* other option is 12 */
488                     *op++ = (unsigned char)(*jp++ >> 4);
489 #endif
490                 }
491             }
492         }
493     }
494   }
495
496   /* Step 6.5: Create the pixmap and set up the image instance */
497   /* now instantiate */
498   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
499                  init_image_instance_from_eimage,
500                  (ii, cinfo.output_width, cinfo.output_height, 1,
501                   unwind.eimage, dest_mask,
502                   instantiator, domain));
503
504   /* Step 7: Finish decompression */
505
506   jpeg_finish_decompress (&cinfo);
507   /* We can ignore the return value since suspension is not possible
508    * with the stdio data source.
509    */
510
511   /* And we're done! */
512   /* This will clean up everything else. */
513   unbind_to (speccount, Qnil);
514 }
515
516 #endif /* HAVE_JPEG */
517 \f
518 #ifdef HAVE_GIF
519 /**********************************************************************
520  *                               GIF                                  *
521  **********************************************************************/
522
523 #include "gifrlib.h"
524
525 static void
526 gif_validate (Lisp_Object instantiator)
527 {
528   file_or_data_must_be_present (instantiator);
529 }
530
531 static Lisp_Object
532 gif_normalize (Lisp_Object inst, Lisp_Object console_type,
533                Lisp_Object dest_mask)
534 {
535   return simple_image_type_normalize (inst, console_type, Qgif);
536 }
537
538 static int
539 gif_possible_dest_types (void)
540 {
541   return IMAGE_COLOR_PIXMAP_MASK;
542 }
543
544 /* To survive the otherwise baffling complexity of making sure
545    everything gets cleaned up in the presence of an error, we
546    use an unwind_protect(). */
547
548 struct gif_unwind_data
549 {
550   unsigned char *eimage;
551   /* Object that holds the decoded data from a GIF file */
552   GifFileType *giffile;
553 };
554
555 static Lisp_Object
556 gif_instantiate_unwind (Lisp_Object unwind_obj)
557 {
558   struct gif_unwind_data *data =
559     (struct gif_unwind_data *) get_opaque_ptr (unwind_obj);
560
561   free_opaque_ptr (unwind_obj);
562   if (data->giffile)
563     {
564       DGifCloseFile (data->giffile);
565       GifFree(data->giffile);
566     }
567   if (data->eimage) xfree(data->eimage);
568
569   return Qnil;
570 }
571
572 typedef struct gif_memory_storage
573 {
574   Extbyte *bytes;               /* The data       */
575   Extcount len;                 /* How big is it? */
576   int index;                    /* Where are we?  */
577 } gif_memory_storage;
578
579 static size_t
580 gif_read_from_memory(GifByteType *buf, size_t size, VoidPtr data)
581 {
582   gif_memory_storage *mem = (gif_memory_storage*)data;
583
584   if ((ssize_t) size > (mem->len - mem->index))
585     return (size_t) -1;
586   memcpy(buf, mem->bytes + mem->index, size);
587   mem->index = mem->index + size;
588   return size;
589 }
590
591 static int
592 gif_memory_close(VoidPtr data)
593 {
594   return 0;
595 }
596
597 struct gif_error_struct
598 {
599   const char *err_str;          /* return the error string */
600   jmp_buf setjmp_buffer;        /* for return to caller */
601 };
602
603 static void
604 gif_error_func(const char *err_str, VoidPtr error_ptr)
605 {
606   struct gif_error_struct *error_data = (struct gif_error_struct*)error_ptr;
607
608   /* return to setjmp point */
609   error_data->err_str = err_str;
610   longjmp (error_data->setjmp_buffer, 1);
611 }
612
613 static void
614 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
615                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
616                  int dest_mask, Lisp_Object domain)
617 {
618   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
619   /* It is OK for the unwind data to be local to this function,
620      because the unwind-protect is always executed when this
621      stack frame is still valid. */
622   struct gif_unwind_data unwind;
623   int speccount = specpdl_depth ();
624   gif_memory_storage mem_struct;
625   struct gif_error_struct gif_err;
626   Extbyte *bytes;
627   Extcount len;
628   int height = 0;
629   int width = 0;
630
631   xzero (unwind);
632   record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind));
633
634   /* 1. Now decode the data. */
635
636   {
637     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
638
639     assert (!NILP (data));
640
641     if (!(unwind.giffile = GifSetup()))
642       signal_image_error ("Insufficient memory to instantiate GIF image", instantiator);
643
644     /* set up error facilities */
645     if (setjmp(gif_err.setjmp_buffer))
646       {
647         /* An error was signaled. No clean up is needed, as unwind handles that
648            for us.  Just pass the error along. */
649         Lisp_Object errstring;
650         errstring = build_string (gif_err.err_str);
651         signal_image_error_2 ("GIF decoding error", errstring, instantiator);
652       }
653     GifSetErrorFunc(unwind.giffile, (Gif_error_func)gif_error_func, (VoidPtr)&gif_err);
654
655     TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary);
656     mem_struct.bytes = bytes;
657     mem_struct.len = len;
658     mem_struct.index = 0;
659     GifSetReadFunc(unwind.giffile, gif_read_from_memory, (VoidPtr)&mem_struct);
660     GifSetCloseFunc(unwind.giffile, gif_memory_close, (VoidPtr)&mem_struct);
661     DGifInitRead(unwind.giffile);
662
663     /* Then slurp the image into memory, decoding along the way.
664        The result is the image in a simple one-byte-per-pixel
665        format (#### the GIF routines only support 8-bit GIFs,
666        it appears). */
667     DGifSlurp (unwind.giffile);
668   }
669
670   /* 3. Now create the EImage(s) */
671   {
672     ColorMapObject *cmo = unwind.giffile->SColorMap;
673     int i, j, row, pass, interlace, slice;
674     unsigned char *eip;
675     /* interlaced gifs have rows in this order:
676        0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ...  */
677     static int InterlacedOffset[] = { 0, 4, 2, 1 };
678     static int InterlacedJumps[] = { 8, 8, 4, 2 };
679
680     height = unwind.giffile->SHeight;
681     width = unwind.giffile->SWidth;
682     unwind.eimage = (unsigned char*)
683       xmalloc (width * height * 3 * unwind.giffile->ImageCount);
684     if (!unwind.eimage)
685       signal_image_error("Unable to allocate enough memory for image", instantiator);
686
687     /* write the data in EImage format (8bit RGB triples) */
688
689     for (slice = 0; slice < unwind.giffile->ImageCount; slice++)
690       {
691         /* We check here that the current image covers the full "screen" size. */
692         if (unwind.giffile->SavedImages[slice].ImageDesc.Height != height
693             || unwind.giffile->SavedImages[slice].ImageDesc.Width != width
694             || unwind.giffile->SavedImages[slice].ImageDesc.Left != 0
695             || unwind.giffile->SavedImages[slice].ImageDesc.Top != 0)
696           signal_image_error ("Image in GIF file is not full size",
697                               instantiator);
698
699         interlace = unwind.giffile->SavedImages[slice].ImageDesc.Interlace;
700         pass = 0;
701         row = interlace ? InterlacedOffset[pass] : 0;
702         eip = unwind.eimage + (width * height * 3 * slice);
703         for (i = 0; i < height; i++)
704           {
705             if (interlace)
706               if (row >= height) {
707                 row = InterlacedOffset[++pass];
708                 while (row >= height)
709                   row = InterlacedOffset[++pass];
710               }
711             eip = unwind.eimage + (width * height * 3 * slice) + (row * width * 3);
712             for (j = 0; j < width; j++)
713               {
714                 unsigned char pixel =
715                   unwind.giffile->SavedImages[slice].RasterBits[(i * width) + j];
716                 *eip++ = cmo->Colors[pixel].Red;
717                 *eip++ = cmo->Colors[pixel].Green;
718                 *eip++ = cmo->Colors[pixel].Blue;
719               }
720             row += interlace ? InterlacedJumps[pass] : 1;
721           }
722       }
723
724     /* now instantiate */
725     MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
726                    init_image_instance_from_eimage,
727                    (ii, width, height, unwind.giffile->ImageCount, unwind.eimage, dest_mask,
728                     instantiator, domain));
729   }
730
731   /* We read the gif successfully. If we have more than one slice then
732      animate the gif. */
733   if (unwind.giffile->ImageCount > 1)
734     {
735     /* See if there is a timeout value. In theory there could be one
736        for every image - but that makes the implementation way to
737        complicated for now so we just take the first. */
738       unsigned short timeout = 0;
739       Lisp_Object tid;
740
741       if (unwind.giffile->SavedImages[0].Function == GRAPHICS_EXT_FUNC_CODE
742           &&
743           unwind.giffile->SavedImages[0].ExtensionBlockCount)
744         {
745           timeout = (unsigned short)
746             ((unwind.giffile->SavedImages[0].ExtensionBlocks[0].Bytes[2] << 8) +
747              unwind.giffile-> SavedImages[0].ExtensionBlocks[0].Bytes[1]) * 10;
748         }
749
750       /* Too short a timeout will crucify us performance-wise. */
751       tid = add_glyph_animated_timeout (timeout > 10 ? timeout : 10, image_instance);
752
753       if (!NILP (tid))
754         IMAGE_INSTANCE_PIXMAP_TIMEOUT (ii) = XINT (tid);
755     }
756
757   unbind_to (speccount, Qnil);
758 }
759
760 #endif /* HAVE_GIF */
761
762 \f
763 #ifdef HAVE_PNG
764
765 /**********************************************************************
766  *                             PNG                                    *
767  **********************************************************************/
768 static void
769 png_validate (Lisp_Object instantiator)
770 {
771   file_or_data_must_be_present (instantiator);
772 }
773
774 static Lisp_Object
775 png_normalize (Lisp_Object inst, Lisp_Object console_type,
776                Lisp_Object dest_mask)
777 {
778   return simple_image_type_normalize (inst, console_type, Qpng);
779 }
780
781 static int
782 png_possible_dest_types (void)
783 {
784   return IMAGE_COLOR_PIXMAP_MASK;
785 }
786
787 struct png_memory_storage
788 {
789   const Extbyte *bytes;         /* The data       */
790   Extcount len;                 /* How big is it? */
791   int index;                    /* Where are we?  */
792 };
793
794 static void
795 png_read_from_memory(png_structp png_ptr, png_bytep data,
796                      png_size_t length)
797 {
798    struct png_memory_storage *tbr =
799      (struct png_memory_storage *) png_get_io_ptr (png_ptr);
800
801    if ((ssize_t) length > (tbr->len - tbr->index))
802      png_error (png_ptr, (png_const_charp) "Read Error");
803    memcpy (data,tbr->bytes + tbr->index,length);
804    tbr->index = tbr->index + length;
805 }
806
807 struct png_error_struct
808 {
809   const char *err_str;
810   jmp_buf setjmp_buffer;        /* for return to caller */
811 };
812
813 /* jh 98/03/12 - #### AARRRGH! libpng includes jmp_buf inside its own
814    structure, and there are cases where the size can be different from
815    between inside the library, and inside the code!  To do an end run
816    around this, use our own error functions, and don't rely on things
817    passed in the png_ptr to them.  This is an ugly hack and must
818    go away when the lisp engine is threaded! */
819 static struct png_error_struct png_err_stct;
820
821 static void
822 png_error_func (png_structp png_ptr, png_const_charp msg)
823 {
824   png_err_stct.err_str = msg;
825   longjmp (png_err_stct.setjmp_buffer, 1);
826 }
827
828 static void
829 png_warning_func (png_structp png_ptr, png_const_charp msg)
830 {
831   warn_when_safe (Qpng, Qinfo, "%s", msg);
832 }
833
834 struct png_unwind_data
835 {
836   FILE *instream;
837   unsigned char *eimage;
838   png_structp png_ptr;
839   png_infop info_ptr;
840 };
841
842 static Lisp_Object
843 png_instantiate_unwind (Lisp_Object unwind_obj)
844 {
845   struct png_unwind_data *data =
846     (struct png_unwind_data *) get_opaque_ptr (unwind_obj);
847
848   free_opaque_ptr (unwind_obj);
849   if (data->png_ptr)
850     {
851       /* ensure we can't get here again */
852       png_structp tmp = data->png_ptr;
853       data->png_ptr = NULL;
854       png_destroy_read_struct (&tmp, &(data->info_ptr), (png_infopp)NULL);
855     }
856
857   if (data->instream)
858     fclose (data->instream);
859
860   if (data->eimage) xfree(data->eimage);
861
862   return Qnil;
863 }
864
865 static void
866 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
867                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
868                  int dest_mask, Lisp_Object domain)
869 {
870   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
871   struct png_unwind_data unwind;
872   int speccount = specpdl_depth ();
873   int height, width;
874   struct png_memory_storage tbr;  /* Data to be read */
875
876   /* PNG variables */
877   png_structp png_ptr;
878   png_infop info_ptr;
879
880   xzero (unwind);
881   record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
882
883   if (setjmp (png_err_stct.setjmp_buffer))
884     {
885       /* Something blew up:
886          just display the error (cleanup happens in the unwind) */
887       signal_image_error_2 ("Error decoding PNG",
888                              build_string(png_err_stct.err_str),
889                              instantiator);
890     }
891
892   /* Initialize all PNG structures */
893   png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
894                                     (void *) &png_err_stct,
895                                     png_error_func, png_warning_func);
896   if (!png_ptr)
897     signal_image_error ("Error obtaining memory for png_read", instantiator);
898   unwind.png_ptr = png_ptr;
899
900   info_ptr = png_create_info_struct (png_ptr);
901   if (!info_ptr)
902     {
903       unwind.png_ptr = NULL;    /* avoid re-calling png_destroy_read_struct
904                                    when unwinding */
905       png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
906       signal_image_error ("Error obtaining memory for png_read", instantiator);
907     }
908   unwind.info_ptr = info_ptr;
909
910   /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
911      this file, example.c from the libpng 0.81 distribution, and the
912      pngtopnm sources. -WMP-
913      */
914   /* It has been further modified to handle the API changes for 0.96,
915      and is no longer usable for previous versions. jh
916   */
917
918   /* Initialize the IO layer and read in header information */
919   {
920     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
921     const Extbyte *bytes;
922     Extcount len;
923
924     assert (!NILP (data));
925
926     /* #### This is a definite problem under Mule due to the amount of
927        stack data it might allocate.  Need to think about using Lstreams */
928     TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary);
929     tbr.bytes = bytes;
930     tbr.len = len;
931     tbr.index = 0;
932     png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory);
933   }
934
935   png_read_info (png_ptr, info_ptr);
936
937   {
938     int y;
939     unsigned char **row_pointers;
940     height = png_get_image_height (png_ptr, info_ptr) /* info_ptr->height */;
941     width = png_get_image_width (png_ptr, info_ptr) /* info_ptr->width */;
942
943     /* Wow, allocate all the memory.  Truly, exciting. */
944     unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 3);
945     /* libpng expects that the image buffer passed in contains a
946        picture to draw on top of if the png has any transparencies.
947        This could be a good place to pass that in... */
948
949     row_pointers  = xnew_array (png_byte *, height);
950
951     for (y = 0; y < height; y++)
952       row_pointers[y] = unwind.eimage + (width * 3 * y);
953
954     {
955       /* if the png specifies a background chunk, go ahead and
956          use it, else use what we can get from the default face. */
957       png_color_16 my_background, *image_background;
958       Lisp_Object bkgd = Qnil;
959
960       my_background.red   = 0x7fff;
961       my_background.green = 0x7fff;
962       my_background.blue  = 0x7fff;
963       bkgd = FACE_BACKGROUND (Vdefault_face, domain);
964       if (!COLOR_INSTANCEP (bkgd))
965         {
966           warn_when_safe (Qpng, Qinfo, "Couldn't get background color!");
967         }
968       else
969         {
970           Lisp_Color_Instance *c;
971           Lisp_Object rgblist;
972
973           c = XCOLOR_INSTANCE (bkgd);
974           rgblist = MAYBE_LISP_DEVMETH (XDEVICE (c->device),
975                                         color_instance_rgb_components,
976                                         (c));
977           my_background.red = (unsigned short) XINT (XCAR (rgblist));
978           my_background.green = (unsigned short) XINT (XCAR (XCDR (rgblist)));
979           my_background.blue = (unsigned short) XINT (XCAR (XCDR (XCDR (rgblist))));
980         }
981
982       if (png_get_bKGD (png_ptr, info_ptr, &image_background))
983         png_set_background (png_ptr, image_background,
984                             PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
985       else
986         png_set_background (png_ptr, &my_background,
987                             PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
988     }
989
990     /* Now that we're using EImage, ask for 8bit RGB triples for any type
991        of image*/
992     /* convert palette images to full RGB */
993     if (png_get_color_type(png_ptr, info_ptr) /* info_ptr->color_type */ == PNG_COLOR_TYPE_PALETTE)
994       png_set_expand (png_ptr);
995     /* send grayscale images to RGB too */
996     if (png_get_color_type(png_ptr, info_ptr) /* info_ptr->color_type */ == PNG_COLOR_TYPE_GRAY ||
997         png_get_color_type(png_ptr, info_ptr) /* info_ptr->color_type */ == PNG_COLOR_TYPE_GRAY_ALPHA)
998       png_set_gray_to_rgb (png_ptr);
999     /* we can't handle alpha values */
1000     if (png_get_color_type(png_ptr, info_ptr) /* info_ptr->color_type */ & PNG_COLOR_MASK_ALPHA)
1001       png_set_strip_alpha (png_ptr);
1002     /* tell libpng to strip 16 bit depth files down to 8 bits */
1003     if (png_get_bit_depth(png_ptr, info_ptr) /* info_ptr->bit_depth */ == 16)
1004       png_set_strip_16 (png_ptr);
1005     /* if the image is < 8 bits, pad it out */
1006     if (png_get_bit_depth(png_ptr, info_ptr) /* info_ptr->bit_depth */ < 8)
1007       {
1008         if (png_get_color_type(png_ptr, info_ptr) /* info_ptr->color_type */ == PNG_COLOR_TYPE_GRAY)
1009           png_set_expand (png_ptr);
1010         else
1011           png_set_packing (png_ptr);
1012       }
1013
1014     png_read_image (png_ptr, row_pointers);
1015     png_read_end (png_ptr, info_ptr);
1016
1017 #ifdef PNG_SHOW_COMMENTS
1018     /* ####
1019      * I turn this off by default now, because the !%^@#!% comments
1020      * show up every time the image is instantiated, which can get
1021      * really really annoying.  There should be some way to pass this
1022      * type of data down into the glyph code, where you can get to it
1023      * from lisp anyway. - WMP
1024      */
1025     {
1026       int i;
1027
1028       for (i = 0 ; i < info_ptr->num_text ; i++)
1029         {
1030           /* How paranoid do I have to be about no trailing NULLs, and
1031              using (int)info_ptr->text[i].text_length, and strncpy and a temp
1032              string somewhere? */
1033
1034           warn_when_safe (Qpng, Qinfo, "%s - %s",
1035                           info_ptr->text[i].key,
1036                           info_ptr->text[i].text);
1037         }
1038     }
1039 #endif
1040
1041     xfree (row_pointers);
1042   }
1043
1044   /* now instantiate */
1045   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
1046                  init_image_instance_from_eimage,
1047                  (ii, width, height, 1, unwind.eimage, dest_mask,
1048                   instantiator, domain));
1049
1050   /* This will clean up everything else. */
1051   unbind_to (speccount, Qnil);
1052 }
1053
1054 #endif /* HAVE_PNG */
1055
1056 \f
1057 #ifdef HAVE_TIFF
1058 #include "tiffio.h"
1059
1060 /**********************************************************************
1061  *                             TIFF                                   *
1062  **********************************************************************/
1063 static void
1064 tiff_validate (Lisp_Object instantiator)
1065 {
1066   file_or_data_must_be_present (instantiator);
1067 }
1068
1069 static Lisp_Object
1070 tiff_normalize (Lisp_Object inst, Lisp_Object console_type,
1071                 Lisp_Object dest_mask)
1072 {
1073   return simple_image_type_normalize (inst, console_type, Qtiff);
1074 }
1075
1076 static int
1077 tiff_possible_dest_types (void)
1078 {
1079   return IMAGE_COLOR_PIXMAP_MASK;
1080 }
1081
1082 struct tiff_unwind_data
1083 {
1084   unsigned char *eimage;
1085   /* Object that holds the decoded data from a TIFF file */
1086   TIFF *tiff;
1087 };
1088
1089 static Lisp_Object
1090 tiff_instantiate_unwind (Lisp_Object unwind_obj)
1091 {
1092   struct tiff_unwind_data *data =
1093     (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj);
1094
1095   free_opaque_ptr (unwind_obj);
1096   if (data->tiff)
1097     {
1098       TIFFClose(data->tiff);
1099     }
1100   if (data->eimage)
1101     xfree (data->eimage);
1102
1103   return Qnil;
1104 }
1105
1106 typedef struct tiff_memory_storage
1107 {
1108   Extbyte *bytes;               /* The data       */
1109   Extcount len;                 /* How big is it? */
1110   int index;                    /* Where are we?  */
1111 } tiff_memory_storage;
1112
1113 static size_t
1114 tiff_memory_read(thandle_t data, tdata_t buf, tsize_t size)
1115 {
1116   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1117
1118   if (size > (mem->len - mem->index))
1119     return (size_t) -1;
1120   memcpy(buf, mem->bytes + mem->index, size);
1121   mem->index = mem->index + size;
1122   return size;
1123 }
1124
1125 static size_t tiff_memory_write(thandle_t data, tdata_t buf, tsize_t size)
1126 {
1127   ABORT();
1128   return 0;                     /* Shut up warnings. */
1129 }
1130
1131 static toff_t tiff_memory_seek(thandle_t data, toff_t off, int whence)
1132 {
1133   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1134   int newidx;
1135   switch(whence) {
1136   case SEEK_SET:
1137     newidx = off;
1138     break;
1139   case SEEK_END:
1140     newidx = mem->len + off;
1141     break;
1142   case SEEK_CUR:
1143     newidx = mem->index + off;
1144     break;
1145   default:
1146     fprintf(stderr,"Eh? invalid seek mode in tiff_memory_seek\n");
1147     return (toff_t) -1;
1148   }
1149
1150   if ((newidx > mem->len) || (newidx < 0))
1151     return (toff_t) -1;
1152
1153   mem->index = newidx;
1154   return newidx;
1155 }
1156
1157 static int
1158 tiff_memory_close(thandle_t data)
1159 {
1160   return 0;
1161 }
1162
1163 static int
1164 tiff_map_noop(thandle_t data, tdata_t* pbase, toff_t* psize)
1165 {
1166   return 0;
1167 }
1168
1169 static void
1170 tiff_unmap_noop(thandle_t data, tdata_t pbase, toff_t psize)
1171 {
1172   return;
1173 }
1174
1175 static toff_t
1176 tiff_memory_size(thandle_t data)
1177 {
1178   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1179   return mem->len;
1180 }
1181
1182 struct tiff_error_struct
1183 {
1184 #ifdef HAVE_VSNPRINTF
1185   char err_str[256];
1186 #else
1187   char err_str[1024];           /* return the error string */
1188 #endif
1189   jmp_buf setjmp_buffer;        /* for return to caller */
1190 };
1191
1192 /* jh 98/03/12 - ###This struct for passing data to the error functions
1193    is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't
1194    have any place to store error func data.  This should be rectified
1195    before XEmacs gets threads! */
1196 static struct tiff_error_struct tiff_err_data;
1197
1198 static void
1199 tiff_error_func(const char *module, const char *fmt, ...)
1200 {
1201   va_list vargs;
1202
1203   va_start (vargs, fmt);
1204 #ifdef HAVE_VSNPRINTF
1205   vsnprintf (tiff_err_data.err_str, 255, fmt, vargs);
1206 #else
1207   /* pray this doesn't overflow... */
1208   vsprintf (tiff_err_data.err_str, fmt, vargs);
1209 #endif
1210   va_end (vargs);
1211   /* return to setjmp point */
1212   longjmp (tiff_err_data.setjmp_buffer, 1);
1213 }
1214
1215 static void
1216 tiff_warning_func(const char *module, const char *fmt, ...)
1217 {
1218   va_list vargs;
1219 #ifdef HAVE_VSNPRINTF
1220   char warn_str[256];
1221 #else
1222   char warn_str[1024];
1223 #endif
1224
1225   va_start (vargs, fmt);
1226 #ifdef HAVE_VSNPRINTF
1227   vsnprintf (warn_str, 255, fmt, vargs);
1228 #else
1229   vsprintf (warn_str, fmt, vargs);
1230 #endif
1231   va_end (vargs);
1232   warn_when_safe (Qtiff, Qinfo, "%s - %s",
1233                   module, warn_str);
1234 }
1235
1236 static void
1237 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1238                   Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1239                   int dest_mask, Lisp_Object domain)
1240 {
1241   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1242   tiff_memory_storage mem_struct;
1243   /* It is OK for the unwind data to be local to this function,
1244      because the unwind-protect is always executed when this
1245      stack frame is still valid. */
1246   struct tiff_unwind_data unwind;
1247   int speccount = specpdl_depth ();
1248   uint32 width, height;
1249
1250   xzero (unwind);
1251   record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind));
1252
1253   /* set up error facilities */
1254   if (setjmp (tiff_err_data.setjmp_buffer))
1255     {
1256       /* An error was signaled. No clean up is needed, as unwind handles that
1257          for us.  Just pass the error along. */
1258       signal_image_error_2 ("TIFF decoding error",
1259                             build_string(tiff_err_data.err_str),
1260                             instantiator);
1261     }
1262   TIFFSetErrorHandler ((TIFFErrorHandler)tiff_error_func);
1263   TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func);
1264   {
1265     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1266     Extbyte *bytes;
1267     Extcount len;
1268
1269     uint32 *raster;
1270     unsigned char *ep;
1271
1272     assert (!NILP (data));
1273
1274     /* #### This is a definite problem under Mule due to the amount of
1275        stack data it might allocate.  Think about Lstreams... */
1276     TO_EXTERNAL_FORMAT (LISP_STRING, data,
1277                         ALLOCA, (bytes, len),
1278                         Qbinary);
1279     mem_struct.bytes = bytes;
1280     mem_struct.len = len;
1281     mem_struct.index = 0;
1282
1283     unwind.tiff = TIFFClientOpen ("memfile", "r", (thandle_t) &mem_struct,
1284                                   (TIFFReadWriteProc)tiff_memory_read,
1285                                   (TIFFReadWriteProc)tiff_memory_write,
1286                                   tiff_memory_seek, tiff_memory_close, tiff_memory_size,
1287                                   tiff_map_noop, tiff_unmap_noop);
1288     if (!unwind.tiff)
1289       signal_image_error ("Insufficient memory to instantiate TIFF image", instantiator);
1290
1291     TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
1292     TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
1293     unwind.eimage = (unsigned char *) xmalloc (width * height * 3);
1294
1295     /* #### This is little more than proof-of-concept/function testing.
1296        It needs to be reimplemented via scanline reads for both memory
1297        compactness. */
1298     raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32));
1299     if (raster != NULL)
1300       {
1301         int i,j;
1302         uint32 *rp;
1303         ep = unwind.eimage;
1304         rp = raster;
1305         if (TIFFReadRGBAImage (unwind.tiff, width, height, raster, 0))
1306           {
1307             for (i = height - 1;  i >= 0; i--)
1308               {
1309                 /* This is to get around weirdness in the libtiff library where properly
1310                    made TIFFs will come out upside down.  libtiff bug or jhod-brainlock? */
1311                 rp = raster + (i * width);
1312                 for (j = 0; (uint32) j < width; j++)
1313                   {
1314                     *ep++ = (unsigned char)TIFFGetR(*rp);
1315                     *ep++ = (unsigned char)TIFFGetG(*rp);
1316                     *ep++ = (unsigned char)TIFFGetB(*rp);
1317                     rp++;
1318                   }
1319               }
1320           }
1321         _TIFFfree (raster);
1322       } else
1323         signal_image_error ("Unable to allocate memory for TIFFReadRGBA", instantiator);
1324
1325   }
1326
1327   /* now instantiate */
1328   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
1329                  init_image_instance_from_eimage,
1330                  (ii, width, height, 1, unwind.eimage, dest_mask,
1331                   instantiator, domain));
1332
1333   unbind_to (speccount, Qnil);
1334 }
1335
1336 #endif /* HAVE_TIFF */
1337
1338 \f
1339 /************************************************************************/
1340 /*                            initialization                            */
1341 /************************************************************************/
1342
1343 void
1344 syms_of_glyphs_eimage (void)
1345 {
1346 }
1347
1348 void
1349 image_instantiator_format_create_glyphs_eimage (void)
1350 {
1351   /* image-instantiator types */
1352 #ifdef HAVE_JPEG
1353   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
1354
1355   IIFORMAT_HAS_METHOD (jpeg, validate);
1356   IIFORMAT_HAS_METHOD (jpeg, normalize);
1357   IIFORMAT_HAS_METHOD (jpeg, possible_dest_types);
1358   IIFORMAT_HAS_METHOD (jpeg, instantiate);
1359
1360   IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
1361   IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
1362 #endif
1363
1364 #ifdef HAVE_GIF
1365   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
1366
1367   IIFORMAT_HAS_METHOD (gif, validate);
1368   IIFORMAT_HAS_METHOD (gif, normalize);
1369   IIFORMAT_HAS_METHOD (gif, possible_dest_types);
1370   IIFORMAT_HAS_METHOD (gif, instantiate);
1371
1372   IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
1373   IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
1374 #endif
1375
1376 #ifdef HAVE_PNG
1377   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
1378
1379   IIFORMAT_HAS_METHOD (png, validate);
1380   IIFORMAT_HAS_METHOD (png, normalize);
1381   IIFORMAT_HAS_METHOD (png, possible_dest_types);
1382   IIFORMAT_HAS_METHOD (png, instantiate);
1383
1384   IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
1385   IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
1386 #endif
1387
1388 #ifdef HAVE_TIFF
1389   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
1390
1391   IIFORMAT_HAS_METHOD (tiff, validate);
1392   IIFORMAT_HAS_METHOD (tiff, normalize);
1393   IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
1394   IIFORMAT_HAS_METHOD (tiff, instantiate);
1395
1396   IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
1397   IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
1398 #endif
1399
1400 }
1401
1402 void
1403 vars_of_glyphs_eimage (void)
1404 {
1405 #ifdef HAVE_JPEG
1406   Fprovide (Qjpeg);
1407 #endif
1408
1409 #ifdef HAVE_GIF
1410   Fprovide (Qgif);
1411 #endif
1412
1413 #ifdef HAVE_PNG
1414   Fprovide (Qpng);
1415 #endif
1416
1417 #ifdef HAVE_TIFF
1418   Fprovide (Qtiff);
1419 #endif
1420
1421 }