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