3974bc0998326368d9d499cf3a039f08bd8cfaca
[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     png_destroy_read_struct (&(data->png_ptr), &(data->info_ptr), (png_infopp)NULL);
851   if (data->instream)
852     fclose (data->instream);
853
854   if (data->eimage) xfree(data->eimage);
855
856   return Qnil;
857 }
858
859 static void
860 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
861                  Lisp_Object pointer_fg, Lisp_Object pointer_bg,
862                  int dest_mask, Lisp_Object domain)
863 {
864   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
865   struct png_unwind_data unwind;
866   int speccount = specpdl_depth ();
867   int height, width;
868   struct png_memory_storage tbr;  /* Data to be read */
869
870   /* PNG variables */
871   png_structp png_ptr;
872   png_infop info_ptr;
873
874   /* Initialize all PNG structures */
875   png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (void*)&png_err_stct,
876                                     png_error_func, png_warning_func);
877   if (!png_ptr)
878     signal_image_error ("Error obtaining memory for png_read", instantiator);
879   info_ptr = png_create_info_struct (png_ptr);
880   if (!info_ptr)
881     {
882       png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
883       signal_image_error ("Error obtaining memory for png_read", instantiator);
884     }
885
886   xzero (unwind);
887   unwind.png_ptr = png_ptr;
888   unwind.info_ptr = info_ptr;
889
890   record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind));
891
892   /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from
893      this file, example.c from the libpng 0.81 distribution, and the
894      pngtopnm sources. -WMP-
895      */
896   /* It has been further modified to handle the API changes for 0.96,
897      and is no longer usable for previous versions. jh
898   */
899
900   /* Set the jmp_buf return context for png_error ... if this returns !0, then
901      we ran into a problem somewhere, and need to clean up after ourselves. */
902   if (setjmp (png_err_stct.setjmp_buffer))
903     {
904       /* Something blew up: just display the error (cleanup happens in the unwind) */
905       signal_image_error_2 ("Error decoding PNG",
906                              build_string(png_err_stct.err_str),
907                              instantiator);
908     }
909
910   /* Initialize the IO layer and read in header information */
911   {
912     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
913     const Extbyte *bytes;
914     Extcount len;
915
916     assert (!NILP (data));
917
918     /* #### This is a definite problem under Mule due to the amount of
919        stack data it might allocate.  Need to think about using Lstreams */
920     TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary);
921     tbr.bytes = bytes;
922     tbr.len = len;
923     tbr.index = 0;
924     png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory);
925   }
926
927   png_read_info (png_ptr, info_ptr);
928
929   {
930     int y;
931     unsigned char **row_pointers;
932     height = info_ptr->height;
933     width = info_ptr->width;
934
935     /* Wow, allocate all the memory.  Truly, exciting. */
936     unwind.eimage = xnew_array_and_zero (unsigned char, width * height * 3);
937     /* libpng expects that the image buffer passed in contains a
938        picture to draw on top of if the png has any transparencies.
939        This could be a good place to pass that in... */
940
941     row_pointers  = xnew_array (png_byte *, height);
942
943     for (y = 0; y < height; y++)
944       row_pointers[y] = unwind.eimage + (width * 3 * y);
945
946     {
947       /* if the png specifies a background chunk, go ahead and
948          use it, else use what we can get from the default face. */
949       png_color_16 my_background, *image_background;
950       Lisp_Object bkgd = Qnil;
951
952       my_background.red   = 0x7fff;
953       my_background.green = 0x7fff;
954       my_background.blue  = 0x7fff;
955       bkgd = FACE_BACKGROUND (Vdefault_face, domain);
956       if (!COLOR_INSTANCEP (bkgd))
957         {
958           warn_when_safe (Qpng, Qinfo, "Couldn't get background color!");
959         }
960       else
961         {
962           Lisp_Color_Instance *c;
963           Lisp_Object rgblist;
964
965           c = XCOLOR_INSTANCE (bkgd);
966           rgblist = MAYBE_LISP_DEVMETH (XDEVICE (c->device),
967                                         color_instance_rgb_components,
968                                         (c));
969           my_background.red = (unsigned short) XINT (XCAR (rgblist));
970           my_background.green = (unsigned short) XINT (XCAR (XCDR (rgblist)));
971           my_background.blue = (unsigned short) XINT (XCAR (XCDR (XCDR (rgblist))));
972         }
973
974       if (png_get_bKGD (png_ptr, info_ptr, &image_background))
975         png_set_background (png_ptr, image_background,
976                             PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
977       else
978         png_set_background (png_ptr, &my_background,
979                             PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
980     }
981
982     /* Now that we're using EImage, ask for 8bit RGB triples for any type
983        of image*/
984     /* convert palette images to full RGB */
985     if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
986       png_set_expand (png_ptr);
987     /* send grayscale images to RGB too */
988     if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
989         info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
990       png_set_gray_to_rgb (png_ptr);
991     /* we can't handle alpha values */
992     if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
993       png_set_strip_alpha (png_ptr);
994     /* tell libpng to strip 16 bit depth files down to 8 bits */
995     if (info_ptr->bit_depth == 16)
996       png_set_strip_16 (png_ptr);
997     /* if the image is < 8 bits, pad it out */
998     if (info_ptr->bit_depth < 8)
999       {
1000         if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1001           png_set_expand (png_ptr);
1002         else
1003           png_set_packing (png_ptr);
1004       }
1005
1006     png_read_image (png_ptr, row_pointers);
1007     png_read_end (png_ptr, info_ptr);
1008
1009 #ifdef PNG_SHOW_COMMENTS
1010     /* ####
1011      * I turn this off by default now, because the !%^@#!% comments
1012      * show up every time the image is instantiated, which can get
1013      * really really annoying.  There should be some way to pass this
1014      * type of data down into the glyph code, where you can get to it
1015      * from lisp anyway. - WMP
1016      */
1017     {
1018       int i;
1019
1020       for (i = 0 ; i < info_ptr->num_text ; i++)
1021         {
1022           /* How paranoid do I have to be about no trailing NULLs, and
1023              using (int)info_ptr->text[i].text_length, and strncpy and a temp
1024              string somewhere? */
1025
1026           warn_when_safe (Qpng, Qinfo, "%s - %s",
1027                           info_ptr->text[i].key,
1028                           info_ptr->text[i].text);
1029         }
1030     }
1031 #endif
1032
1033     xfree (row_pointers);
1034   }
1035
1036   /* now instantiate */
1037   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
1038                  init_image_instance_from_eimage,
1039                  (ii, width, height, 1, unwind.eimage, dest_mask,
1040                   instantiator, domain));
1041
1042   /* This will clean up everything else. */
1043   unbind_to (speccount, Qnil);
1044 }
1045
1046 #endif /* HAVE_PNG */
1047
1048 \f
1049 #ifdef HAVE_TIFF
1050 #include "tiffio.h"
1051
1052 /**********************************************************************
1053  *                             TIFF                                   *
1054  **********************************************************************/
1055 static void
1056 tiff_validate (Lisp_Object instantiator)
1057 {
1058   file_or_data_must_be_present (instantiator);
1059 }
1060
1061 static Lisp_Object
1062 tiff_normalize (Lisp_Object inst, Lisp_Object console_type,
1063                 Lisp_Object dest_mask)
1064 {
1065   return simple_image_type_normalize (inst, console_type, Qtiff);
1066 }
1067
1068 static int
1069 tiff_possible_dest_types (void)
1070 {
1071   return IMAGE_COLOR_PIXMAP_MASK;
1072 }
1073
1074 struct tiff_unwind_data
1075 {
1076   unsigned char *eimage;
1077   /* Object that holds the decoded data from a TIFF file */
1078   TIFF *tiff;
1079 };
1080
1081 static Lisp_Object
1082 tiff_instantiate_unwind (Lisp_Object unwind_obj)
1083 {
1084   struct tiff_unwind_data *data =
1085     (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj);
1086
1087   free_opaque_ptr (unwind_obj);
1088   if (data->tiff)
1089     {
1090       TIFFClose(data->tiff);
1091     }
1092   if (data->eimage)
1093     xfree (data->eimage);
1094
1095   return Qnil;
1096 }
1097
1098 typedef struct tiff_memory_storage
1099 {
1100   Extbyte *bytes;               /* The data       */
1101   Extcount len;                 /* How big is it? */
1102   int index;                    /* Where are we?  */
1103 } tiff_memory_storage;
1104
1105 static size_t
1106 tiff_memory_read(thandle_t data, tdata_t buf, tsize_t size)
1107 {
1108   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1109
1110   if (size > (mem->len - mem->index))
1111     return (size_t) -1;
1112   memcpy(buf, mem->bytes + mem->index, size);
1113   mem->index = mem->index + size;
1114   return size;
1115 }
1116
1117 static size_t tiff_memory_write(thandle_t data, tdata_t buf, tsize_t size)
1118 {
1119   ABORT();
1120   return 0;                     /* Shut up warnings. */
1121 }
1122
1123 static toff_t tiff_memory_seek(thandle_t data, toff_t off, int whence)
1124 {
1125   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1126   int newidx;
1127   switch(whence) {
1128   case SEEK_SET:
1129     newidx = off;
1130     break;
1131   case SEEK_END:
1132     newidx = mem->len + off;
1133     break;
1134   case SEEK_CUR:
1135     newidx = mem->index + off;
1136     break;
1137   default:
1138     fprintf(stderr,"Eh? invalid seek mode in tiff_memory_seek\n");
1139     return (toff_t) -1;
1140   }
1141
1142   if ((newidx > mem->len) || (newidx < 0))
1143     return (toff_t) -1;
1144
1145   mem->index = newidx;
1146   return newidx;
1147 }
1148
1149 static int
1150 tiff_memory_close(thandle_t data)
1151 {
1152   return 0;
1153 }
1154
1155 static int
1156 tiff_map_noop(thandle_t data, tdata_t* pbase, toff_t* psize)
1157 {
1158   return 0;
1159 }
1160
1161 static void
1162 tiff_unmap_noop(thandle_t data, tdata_t pbase, toff_t psize)
1163 {
1164   return;
1165 }
1166
1167 static toff_t
1168 tiff_memory_size(thandle_t data)
1169 {
1170   tiff_memory_storage *mem = (tiff_memory_storage*)data;
1171   return mem->len;
1172 }
1173
1174 struct tiff_error_struct
1175 {
1176 #ifdef HAVE_VSNPRINTF
1177   char err_str[256];
1178 #else
1179   char err_str[1024];           /* return the error string */
1180 #endif
1181   jmp_buf setjmp_buffer;        /* for return to caller */
1182 };
1183
1184 /* jh 98/03/12 - ###This struct for passing data to the error functions
1185    is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't
1186    have any place to store error func data.  This should be rectified
1187    before XEmacs gets threads! */
1188 static struct tiff_error_struct tiff_err_data;
1189
1190 static void
1191 tiff_error_func(const char *module, const char *fmt, ...)
1192 {
1193   va_list vargs;
1194
1195   va_start (vargs, fmt);
1196 #ifdef HAVE_VSNPRINTF
1197   vsnprintf (tiff_err_data.err_str, 255, fmt, vargs);
1198 #else
1199   /* pray this doesn't overflow... */
1200   vsprintf (tiff_err_data.err_str, fmt, vargs);
1201 #endif
1202   va_end (vargs);
1203   /* return to setjmp point */
1204   longjmp (tiff_err_data.setjmp_buffer, 1);
1205 }
1206
1207 static void
1208 tiff_warning_func(const char *module, const char *fmt, ...)
1209 {
1210   va_list vargs;
1211 #ifdef HAVE_VSNPRINTF
1212   char warn_str[256];
1213 #else
1214   char warn_str[1024];
1215 #endif
1216
1217   va_start (vargs, fmt);
1218 #ifdef HAVE_VSNPRINTF
1219   vsnprintf (warn_str, 255, fmt, vargs);
1220 #else
1221   vsprintf (warn_str, fmt, vargs);
1222 #endif
1223   va_end (vargs);
1224   warn_when_safe (Qtiff, Qinfo, "%s - %s",
1225                   module, warn_str);
1226 }
1227
1228 static void
1229 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
1230                   Lisp_Object pointer_fg, Lisp_Object pointer_bg,
1231                   int dest_mask, Lisp_Object domain)
1232 {
1233   Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
1234   tiff_memory_storage mem_struct;
1235   /* It is OK for the unwind data to be local to this function,
1236      because the unwind-protect is always executed when this
1237      stack frame is still valid. */
1238   struct tiff_unwind_data unwind;
1239   int speccount = specpdl_depth ();
1240   uint32 width, height;
1241
1242   xzero (unwind);
1243   record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind));
1244
1245   /* set up error facilities */
1246   if (setjmp (tiff_err_data.setjmp_buffer))
1247     {
1248       /* An error was signaled. No clean up is needed, as unwind handles that
1249          for us.  Just pass the error along. */
1250       signal_image_error_2 ("TIFF decoding error",
1251                             build_string(tiff_err_data.err_str),
1252                             instantiator);
1253     }
1254   TIFFSetErrorHandler ((TIFFErrorHandler)tiff_error_func);
1255   TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func);
1256   {
1257     Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
1258     Extbyte *bytes;
1259     Extcount len;
1260
1261     uint32 *raster;
1262     unsigned char *ep;
1263
1264     assert (!NILP (data));
1265
1266     /* #### This is a definite problem under Mule due to the amount of
1267        stack data it might allocate.  Think about Lstreams... */
1268     TO_EXTERNAL_FORMAT (LISP_STRING, data,
1269                         ALLOCA, (bytes, len),
1270                         Qbinary);
1271     mem_struct.bytes = bytes;
1272     mem_struct.len = len;
1273     mem_struct.index = 0;
1274
1275     unwind.tiff = TIFFClientOpen ("memfile", "r", (thandle_t) &mem_struct,
1276                                   (TIFFReadWriteProc)tiff_memory_read,
1277                                   (TIFFReadWriteProc)tiff_memory_write,
1278                                   tiff_memory_seek, tiff_memory_close, tiff_memory_size,
1279                                   tiff_map_noop, tiff_unmap_noop);
1280     if (!unwind.tiff)
1281       signal_image_error ("Insufficient memory to instantiate TIFF image", instantiator);
1282
1283     TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width);
1284     TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height);
1285     unwind.eimage = (unsigned char *) xmalloc (width * height * 3);
1286
1287     /* #### This is little more than proof-of-concept/function testing.
1288        It needs to be reimplemented via scanline reads for both memory
1289        compactness. */
1290     raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32));
1291     if (raster != NULL)
1292       {
1293         int i,j;
1294         uint32 *rp;
1295         ep = unwind.eimage;
1296         rp = raster;
1297         if (TIFFReadRGBAImage (unwind.tiff, width, height, raster, 0))
1298           {
1299             for (i = height - 1;  i >= 0; i--)
1300               {
1301                 /* This is to get around weirdness in the libtiff library where properly
1302                    made TIFFs will come out upside down.  libtiff bug or jhod-brainlock? */
1303                 rp = raster + (i * width);
1304                 for (j = 0; (uint32) j < width; j++)
1305                   {
1306                     *ep++ = (unsigned char)TIFFGetR(*rp);
1307                     *ep++ = (unsigned char)TIFFGetG(*rp);
1308                     *ep++ = (unsigned char)TIFFGetB(*rp);
1309                     rp++;
1310                   }
1311               }
1312           }
1313         _TIFFfree (raster);
1314       } else
1315         signal_image_error ("Unable to allocate memory for TIFFReadRGBA", instantiator);
1316
1317   }
1318
1319   /* now instantiate */
1320   MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain),
1321                  init_image_instance_from_eimage,
1322                  (ii, width, height, 1, unwind.eimage, dest_mask,
1323                   instantiator, domain));
1324
1325   unbind_to (speccount, Qnil);
1326 }
1327
1328 #endif /* HAVE_TIFF */
1329
1330 \f
1331 /************************************************************************/
1332 /*                            initialization                            */
1333 /************************************************************************/
1334
1335 void
1336 syms_of_glyphs_eimage (void)
1337 {
1338 }
1339
1340 void
1341 image_instantiator_format_create_glyphs_eimage (void)
1342 {
1343   /* image-instantiator types */
1344 #ifdef HAVE_JPEG
1345   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg");
1346
1347   IIFORMAT_HAS_METHOD (jpeg, validate);
1348   IIFORMAT_HAS_METHOD (jpeg, normalize);
1349   IIFORMAT_HAS_METHOD (jpeg, possible_dest_types);
1350   IIFORMAT_HAS_METHOD (jpeg, instantiate);
1351
1352   IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string);
1353   IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string);
1354 #endif
1355
1356 #ifdef HAVE_GIF
1357   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif");
1358
1359   IIFORMAT_HAS_METHOD (gif, validate);
1360   IIFORMAT_HAS_METHOD (gif, normalize);
1361   IIFORMAT_HAS_METHOD (gif, possible_dest_types);
1362   IIFORMAT_HAS_METHOD (gif, instantiate);
1363
1364   IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string);
1365   IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string);
1366 #endif
1367
1368 #ifdef HAVE_PNG
1369   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png");
1370
1371   IIFORMAT_HAS_METHOD (png, validate);
1372   IIFORMAT_HAS_METHOD (png, normalize);
1373   IIFORMAT_HAS_METHOD (png, possible_dest_types);
1374   IIFORMAT_HAS_METHOD (png, instantiate);
1375
1376   IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string);
1377   IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string);
1378 #endif
1379
1380 #ifdef HAVE_TIFF
1381   INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff");
1382
1383   IIFORMAT_HAS_METHOD (tiff, validate);
1384   IIFORMAT_HAS_METHOD (tiff, normalize);
1385   IIFORMAT_HAS_METHOD (tiff, possible_dest_types);
1386   IIFORMAT_HAS_METHOD (tiff, instantiate);
1387
1388   IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string);
1389   IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string);
1390 #endif
1391
1392 }
1393
1394 void
1395 vars_of_glyphs_eimage (void)
1396 {
1397 #ifdef HAVE_JPEG
1398   Fprovide (Qjpeg);
1399 #endif
1400
1401 #ifdef HAVE_GIF
1402   Fprovide (Qgif);
1403 #endif
1404
1405 #ifdef HAVE_PNG
1406   Fprovide (Qpng);
1407 #endif
1408
1409 #ifdef HAVE_TIFF
1410   Fprovide (Qtiff);
1411 #endif
1412
1413 }