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