comparison src/glyphs-eimage.c @ 428:3ecd8885ac67 r21-2-22

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