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