Adjust in response to jan.h.d's comments.
[bpt/emacs.git] / src / image.c
CommitLineData
4ef0d4d0 1/* Functions for image support on window system.
73b0cd50 2 Copyright (C) 1989, 1992-2011 Free Software Foundation, Inc.
4ef0d4d0
KS
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
4ef0d4d0 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
4ef0d4d0
KS
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
4ef0d4d0
KS
18
19#include <config.h>
4ef0d4d0
KS
20#include <stdio.h>
21#include <math.h>
be8c4ce4 22#include <ctype.h>
4ef0d4d0 23#include <unistd.h>
4ef0d4d0 24
d7306fe6
DN
25#ifdef HAVE_PNG
26#if defined HAVE_LIBPNG_PNG_H
27# include <libpng/png.h>
28#else
29# include <png.h>
30#endif
285d07e2 31#endif
d7306fe6 32
c3417a74
DN
33#include <setjmp.h>
34
4ef0d4d0
KS
35/* This makes the fields of a Display accessible, in Xlib header files. */
36
37#define XLIB_ILLEGAL_ACCESS
38
39#include "lisp.h"
40#include "frame.h"
41#include "window.h"
42#include "dispextern.h"
43#include "blockinput.h"
44#include "systime.h"
45#include <epaths.h>
3dcc8b84 46#include "character.h"
022af124 47#include "coding.h"
6087292e 48#include "termhooks.h"
3dcc8b84 49#include "font.h"
4ef0d4d0
KS
50
51#ifdef HAVE_X_WINDOWS
52#include "xterm.h"
53#include <sys/types.h>
54#include <sys/stat.h>
55
56#define COLOR_TABLE_SUPPORT 1
57
58typedef struct x_bitmap_record Bitmap_Record;
4ef0d4d0
KS
59#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
60#define NO_PIXMAP None
4ef0d4d0
KS
61
62#define RGB_PIXEL_COLOR unsigned long
63
9ecf6403
YM
64#define PIX_MASK_RETAIN 0
65#define PIX_MASK_DRAW 1
4ef0d4d0
KS
66#endif /* HAVE_X_WINDOWS */
67
68
69#ifdef HAVE_NTGUI
0898ca10 70#include "w32.h"
4ef0d4d0
KS
71#include "w32term.h"
72
73/* W32_TODO : Color tables on W32. */
74#undef COLOR_TABLE_SUPPORT
75
76typedef struct w32_bitmap_record Bitmap_Record;
4ef0d4d0
KS
77#define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
78#define NO_PIXMAP 0
4ef0d4d0
KS
79
80#define RGB_PIXEL_COLOR COLORREF
81
9ecf6403
YM
82#define PIX_MASK_RETAIN 0
83#define PIX_MASK_DRAW 1
4ef0d4d0
KS
84
85#define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
86#define x_defined_color w32_defined_color
87#define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
8b7d0a16
JR
88
89/* Functions from w32term.c that depend on XColor (so can't go in w32term.h
90 without modifying lots of files). */
91extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
92extern void x_query_color (struct frame *f, XColor *color);
5be1c984
EZ
93
94/* Version of libpng that we were compiled with, or -1 if no PNG
95 support was compiled in. This is tested by w32-win.el to correctly
96 set up the alist used to search for PNG libraries. */
97Lisp_Object Qlibpng_version;
4ef0d4d0
KS
98#endif /* HAVE_NTGUI */
99
edfda783
AR
100#ifdef HAVE_NS
101#include "nsterm.h"
102#include <sys/types.h>
103#include <sys/stat.h>
104
105#undef COLOR_TABLE_SUPPORT
106
107typedef struct ns_bitmap_record Bitmap_Record;
108
109#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
110#define NO_PIXMAP 0
111
112#define RGB_PIXEL_COLOR unsigned long
113#define ZPixmap 0
114
115#define PIX_MASK_RETAIN 0
116#define PIX_MASK_DRAW 1
117
118#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
119#define x_defined_color(f, name, color_def, alloc) \
120 ns_defined_color (f, name, color_def, alloc, 0)
121#define FRAME_X_SCREEN(f) 0
9e50ff0c 122#define DefaultDepthOfScreen(screen) x_display_list->n_planes
edfda783
AR
123#endif /* HAVE_NS */
124
125
97ec208f
DN
126/* The symbol `postscript' identifying images of this type. */
127
955cbe7b 128static Lisp_Object Qpostscript;
4ef0d4d0 129
f57e2426
J
130static void x_disable_image (struct frame *, struct image *);
131static void x_edge_detection (struct frame *, struct image *, Lisp_Object,
132 Lisp_Object);
4ef0d4d0 133
f57e2426
J
134static void init_color_table (void);
135static unsigned long lookup_rgb_color (struct frame *f, int r, int g, int b);
4ef0d4d0 136#ifdef COLOR_TABLE_SUPPORT
f57e2426
J
137static void free_color_table (void);
138static unsigned long *colors_in_color_table (int *n);
4ef0d4d0 139#endif
cd64ea1d 140static Lisp_Object Finit_image_library (Lisp_Object, Lisp_Object);
4ef0d4d0
KS
141
142/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
143 id, which is just an int that this section returns. Bitmaps are
144 reference counted so they can be shared among frames.
145
146 Bitmap indices are guaranteed to be > 0, so a negative number can
147 be used to indicate no bitmap.
148
149 If you use x_create_bitmap_from_data, then you must keep track of
150 the bitmaps yourself. That is, creating a bitmap from the same
151 data more than once will not be caught. */
152
edfda783
AR
153#ifdef HAVE_NS
154XImagePtr
155XGetImage (Display *display, Pixmap pixmap, int x, int y,
156 unsigned int width, unsigned int height,
157 unsigned long plane_mask, int format)
158{
6fb5f7da 159 /* TODO: not sure what this function is supposed to do.. */
ed3751c8 160 ns_retain_object (pixmap);
edfda783
AR
161 return pixmap;
162}
163
164/* use with imgs created by ns_image_for_XPM */
165unsigned long
166XGetPixel (XImagePtr ximage, int x, int y)
167{
ed3751c8 168 return ns_get_pixel (ximage, x, y);
edfda783
AR
169}
170
171/* use with imgs created by ns_image_for_XPM; alpha set to 1;
172 pixel is assumed to be in form RGB */
173void
174XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
175{
ed3751c8 176 ns_put_pixel (ximage, x, y, pixel);
edfda783
AR
177}
178#endif /* HAVE_NS */
179
4ef0d4d0
KS
180
181/* Functions to access the contents of a bitmap, given an id. */
182
183int
0766b489 184x_bitmap_height (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0
KS
185{
186 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
187}
188
189int
0766b489 190x_bitmap_width (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0
KS
191{
192 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
193}
194
195#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
196int
0766b489 197x_bitmap_pixmap (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0 198{
13464394 199 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
4ef0d4d0
KS
200}
201#endif
202
203#ifdef HAVE_X_WINDOWS
204int
0766b489 205x_bitmap_mask (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0
KS
206{
207 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
208}
209#endif
210
211/* Allocate a new bitmap record. Returns index of new record. */
212
0766b489 213static ptrdiff_t
d3da34e0 214x_allocate_bitmap_record (FRAME_PTR f)
4ef0d4d0
KS
215{
216 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0766b489 217 ptrdiff_t i;
4ef0d4d0
KS
218
219 if (dpyinfo->bitmaps == NULL)
220 {
4ef0d4d0 221 dpyinfo->bitmaps
ddff3151
PE
222 = (Bitmap_Record *) xmalloc (10 * sizeof (Bitmap_Record));
223 dpyinfo->bitmaps_size = 10;
4ef0d4d0
KS
224 dpyinfo->bitmaps_last = 1;
225 return 1;
226 }
227
228 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
229 return ++dpyinfo->bitmaps_last;
230
231 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
232 if (dpyinfo->bitmaps[i].refcount == 0)
233 return i + 1;
234
0766b489
PE
235 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof (Bitmap_Record) / 2
236 < dpyinfo->bitmaps_size)
237 memory_full (SIZE_MAX);
4ef0d4d0
KS
238 dpyinfo->bitmaps
239 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
ddff3151
PE
240 (dpyinfo->bitmaps_size
241 * (2 * sizeof (Bitmap_Record))));
242 dpyinfo->bitmaps_size *= 2;
4ef0d4d0
KS
243 return ++dpyinfo->bitmaps_last;
244}
245
246/* Add one reference to the reference count of the bitmap with id ID. */
247
248void
13464394 249x_reference_bitmap (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0
KS
250{
251 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
252}
253
254/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
255
0766b489 256ptrdiff_t
d3da34e0 257x_create_bitmap_from_data (struct frame *f, char *bits, unsigned int width, unsigned int height)
4ef0d4d0
KS
258{
259 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0766b489 260 ptrdiff_t id;
4ef0d4d0
KS
261
262#ifdef HAVE_X_WINDOWS
263 Pixmap bitmap;
264 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
265 bits, width, height);
266 if (! bitmap)
267 return -1;
268#endif /* HAVE_X_WINDOWS */
269
270#ifdef HAVE_NTGUI
271 Pixmap bitmap;
272 bitmap = CreateBitmap (width, height,
273 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
274 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
275 bits);
276 if (! bitmap)
277 return -1;
278#endif /* HAVE_NTGUI */
279
edfda783 280#ifdef HAVE_NS
ed3751c8 281 void *bitmap = ns_image_from_XBM (bits, width, height);
edfda783
AR
282 if (!bitmap)
283 return -1;
284#endif
285
4ef0d4d0 286 id = x_allocate_bitmap_record (f);
4ef0d4d0 287
edfda783
AR
288#ifdef HAVE_NS
289 dpyinfo->bitmaps[id - 1].img = bitmap;
290 dpyinfo->bitmaps[id - 1].depth = 1;
291#endif
292
4ef0d4d0
KS
293 dpyinfo->bitmaps[id - 1].file = NULL;
294 dpyinfo->bitmaps[id - 1].height = height;
295 dpyinfo->bitmaps[id - 1].width = width;
296 dpyinfo->bitmaps[id - 1].refcount = 1;
297
298#ifdef HAVE_X_WINDOWS
299 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
300 dpyinfo->bitmaps[id - 1].have_mask = 0;
301 dpyinfo->bitmaps[id - 1].depth = 1;
302#endif /* HAVE_X_WINDOWS */
303
304#ifdef HAVE_NTGUI
305 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
306 dpyinfo->bitmaps[id - 1].hinst = NULL;
307 dpyinfo->bitmaps[id - 1].depth = 1;
308#endif /* HAVE_NTGUI */
309
310 return id;
311}
312
313/* Create bitmap from file FILE for frame F. */
314
0766b489 315ptrdiff_t
d3da34e0 316x_create_bitmap_from_file (struct frame *f, Lisp_Object file)
4ef0d4d0 317{
edfda783
AR
318 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
319
4ef0d4d0
KS
320#ifdef HAVE_NTGUI
321 return -1; /* W32_TODO : bitmap support */
322#endif /* HAVE_NTGUI */
323
edfda783 324#ifdef HAVE_NS
0766b489 325 ptrdiff_t id;
ed3751c8 326 void *bitmap = ns_image_from_file (file);
edfda783
AR
327
328 if (!bitmap)
329 return -1;
330
331
332 id = x_allocate_bitmap_record (f);
333 dpyinfo->bitmaps[id - 1].img = bitmap;
334 dpyinfo->bitmaps[id - 1].refcount = 1;
335 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
336 dpyinfo->bitmaps[id - 1].depth = 1;
ed3751c8
JB
337 dpyinfo->bitmaps[id - 1].height = ns_image_width (bitmap);
338 dpyinfo->bitmaps[id - 1].width = ns_image_height (bitmap);
edfda783
AR
339 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
340 return id;
341#endif
342
4ef0d4d0 343#ifdef HAVE_X_WINDOWS
4ef0d4d0
KS
344 unsigned int width, height;
345 Pixmap bitmap;
0766b489
PE
346 int xhot, yhot, result;
347 ptrdiff_t id;
4ef0d4d0
KS
348 Lisp_Object found;
349 int fd;
350 char *filename;
351
352 /* Look for an existing bitmap with the same name. */
353 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
354 {
355 if (dpyinfo->bitmaps[id].refcount
356 && dpyinfo->bitmaps[id].file
51b59d79 357 && !strcmp (dpyinfo->bitmaps[id].file, SSDATA (file)))
4ef0d4d0
KS
358 {
359 ++dpyinfo->bitmaps[id].refcount;
360 return id + 1;
361 }
362 }
363
364 /* Search bitmap-file-path for the file, if appropriate. */
365 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
366 if (fd < 0)
367 return -1;
368 emacs_close (fd);
369
51b59d79 370 filename = SSDATA (found);
4ef0d4d0
KS
371
372 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
373 filename, &width, &height, &bitmap, &xhot, &yhot);
374 if (result != BitmapSuccess)
375 return -1;
376
377 id = x_allocate_bitmap_record (f);
378 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
379 dpyinfo->bitmaps[id - 1].have_mask = 0;
380 dpyinfo->bitmaps[id - 1].refcount = 1;
381 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
382 dpyinfo->bitmaps[id - 1].depth = 1;
383 dpyinfo->bitmaps[id - 1].height = height;
384 dpyinfo->bitmaps[id - 1].width = width;
42a5b22f 385 strcpy (dpyinfo->bitmaps[id - 1].file, SSDATA (file));
4ef0d4d0
KS
386
387 return id;
388#endif /* HAVE_X_WINDOWS */
389}
390
391/* Free bitmap B. */
392
393static void
d3da34e0 394free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
4ef0d4d0
KS
395{
396#ifdef HAVE_X_WINDOWS
397 XFreePixmap (dpyinfo->display, bm->pixmap);
398 if (bm->have_mask)
399 XFreePixmap (dpyinfo->display, bm->mask);
400#endif /* HAVE_X_WINDOWS */
401
402#ifdef HAVE_NTGUI
403 DeleteObject (bm->pixmap);
404#endif /* HAVE_NTGUI */
405
edfda783 406#ifdef HAVE_NS
ed3751c8 407 ns_release_object (bm->img);
edfda783
AR
408#endif
409
4ef0d4d0
KS
410 if (bm->file)
411 {
412 xfree (bm->file);
413 bm->file = NULL;
414 }
415}
416
417/* Remove reference to bitmap with id number ID. */
418
419void
0766b489 420x_destroy_bitmap (FRAME_PTR f, ptrdiff_t id)
4ef0d4d0
KS
421{
422 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
423
424 if (id > 0)
425 {
426 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
427
428 if (--bm->refcount == 0)
429 {
430 BLOCK_INPUT;
65342ae3 431 free_bitmap_record (dpyinfo, bm);
4ef0d4d0
KS
432 UNBLOCK_INPUT;
433 }
434 }
435}
436
437/* Free all the bitmaps for the display specified by DPYINFO. */
438
439void
d3da34e0 440x_destroy_all_bitmaps (Display_Info *dpyinfo)
4ef0d4d0 441{
0766b489 442 ptrdiff_t i;
4ef0d4d0
KS
443 Bitmap_Record *bm = dpyinfo->bitmaps;
444
445 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
446 if (bm->refcount > 0)
65342ae3 447 free_bitmap_record (dpyinfo, bm);
4ef0d4d0
KS
448
449 dpyinfo->bitmaps_last = 0;
450}
451
452
453#ifdef HAVE_X_WINDOWS
454
455/* Useful functions defined in the section
456 `Image type independent image structures' below. */
457
f57e2426
J
458static unsigned long four_corners_best (XImagePtr ximg,
459 int *corners,
460 unsigned long width,
461 unsigned long height);
4ef0d4d0 462
f57e2426
J
463static int x_create_x_image_and_pixmap (struct frame *f, int width, int height,
464 int depth, XImagePtr *ximg,
465 Pixmap *pixmap);
4ef0d4d0 466
f57e2426 467static void x_destroy_x_image (XImagePtr ximg);
4ef0d4d0
KS
468
469
470/* Create a mask of a bitmap. Note is this not a perfect mask.
471 It's nicer with some borders in this context */
472
473int
0766b489 474x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
4ef0d4d0
KS
475{
476 Pixmap pixmap, mask;
477 XImagePtr ximg, mask_img;
478 unsigned long width, height;
479 int result;
480 unsigned long bg;
481 unsigned long x, y, xp, xm, yp, ym;
482 GC gc;
483
484 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
485
486 if (!(id > 0))
487 return -1;
488
489 pixmap = x_bitmap_pixmap (f, id);
490 width = x_bitmap_width (f, id);
491 height = x_bitmap_height (f, id);
492
493 BLOCK_INPUT;
494 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
495 ~0, ZPixmap);
496
497 if (!ximg)
498 {
499 UNBLOCK_INPUT;
500 return -1;
501 }
502
503 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
504
505 UNBLOCK_INPUT;
506 if (!result)
507 {
508 XDestroyImage (ximg);
509 return -1;
510 }
511
6ac3c7bb 512 bg = four_corners_best (ximg, NULL, width, height);
4ef0d4d0
KS
513
514 for (y = 0; y < ximg->height; ++y)
515 {
516 for (x = 0; x < ximg->width; ++x)
517 {
518 xp = x != ximg->width - 1 ? x + 1 : 0;
519 xm = x != 0 ? x - 1 : ximg->width - 1;
520 yp = y != ximg->height - 1 ? y + 1 : 0;
521 ym = y != 0 ? y - 1 : ximg->height - 1;
522 if (XGetPixel (ximg, x, y) == bg
523 && XGetPixel (ximg, x, yp) == bg
524 && XGetPixel (ximg, x, ym) == bg
525 && XGetPixel (ximg, xp, y) == bg
526 && XGetPixel (ximg, xp, yp) == bg
527 && XGetPixel (ximg, xp, ym) == bg
528 && XGetPixel (ximg, xm, y) == bg
529 && XGetPixel (ximg, xm, yp) == bg
530 && XGetPixel (ximg, xm, ym) == bg)
531 XPutPixel (mask_img, x, y, 0);
532 else
533 XPutPixel (mask_img, x, y, 1);
534 }
535 }
536
537 xassert (interrupt_input_blocked);
538 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
539 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
540 width, height);
541 XFreeGC (FRAME_X_DISPLAY (f), gc);
542
543 dpyinfo->bitmaps[id - 1].have_mask = 1;
544 dpyinfo->bitmaps[id - 1].mask = mask;
545
546 XDestroyImage (ximg);
547 x_destroy_x_image (mask_img);
548
549 return 0;
550}
551
552#endif /* HAVE_X_WINDOWS */
553
554
555/***********************************************************************
556 Image types
557 ***********************************************************************/
558
4ef0d4d0
KS
559/* List of supported image types. Use define_image_type to add new
560 types. Use lookup_image_type to find a type for a given symbol. */
561
562static struct image_type *image_types;
563
564/* The symbol `xbm' which is used as the type symbol for XBM images. */
565
955cbe7b 566static Lisp_Object Qxbm;
4ef0d4d0
KS
567
568/* Keywords. */
569
955cbe7b 570Lisp_Object QCascent, QCmargin, QCrelief;
955cbe7b
PE
571Lisp_Object QCconversion;
572static Lisp_Object QCheuristic_mask;
573static Lisp_Object QCcolor_symbols;
574static Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask, QCgeometry;
575static Lisp_Object QCcrop, QCrotation;
4ef0d4d0
KS
576
577/* Other symbols. */
578
1100a63c 579static Lisp_Object Qcount, Qextension_data, Qdelay;
955cbe7b 580static Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
4ef0d4d0 581
4ef0d4d0
KS
582/* Function prototypes. */
583
f57e2426
J
584static Lisp_Object define_image_type (struct image_type *type, int loaded);
585static struct image_type *lookup_image_type (Lisp_Object symbol);
675e2c69 586static void image_error (const char *format, Lisp_Object, Lisp_Object);
f57e2426
J
587static void x_laplace (struct frame *, struct image *);
588static void x_emboss (struct frame *, struct image *);
589static int x_build_heuristic_mask (struct frame *, struct image *,
590 Lisp_Object);
84d358f0 591#ifdef HAVE_NTGUI
0855eb52 592#define CACHE_IMAGE_TYPE(type, status) \
0898ca10 593 do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
84d358f0
JB
594#else
595#define CACHE_IMAGE_TYPE(type, status)
596#endif
0855eb52
JB
597
598#define ADD_IMAGE_TYPE(type) \
599 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
4ef0d4d0
KS
600
601/* Define a new image type from TYPE. This adds a copy of TYPE to
0855eb52 602 image_types and caches the loading status of TYPE. */
4ef0d4d0 603
0855eb52 604static Lisp_Object
d3da34e0 605define_image_type (struct image_type *type, int loaded)
4ef0d4d0 606{
0855eb52
JB
607 Lisp_Object success;
608
609 if (!loaded)
610 success = Qnil;
611 else
612 {
613 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
614 The initialized data segment is read-only. */
615 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
72af86bd 616 memcpy (p, type, sizeof *p);
0855eb52
JB
617 p->next = image_types;
618 image_types = p;
619 success = Qt;
620 }
621
adac86db 622 CACHE_IMAGE_TYPE (*type->type, success);
0855eb52 623 return success;
4ef0d4d0
KS
624}
625
626
627/* Look up image type SYMBOL, and return a pointer to its image_type
628 structure. Value is null if SYMBOL is not a known image type. */
629
55d4c1b2 630static inline struct image_type *
d3da34e0 631lookup_image_type (Lisp_Object symbol)
4ef0d4d0
KS
632{
633 struct image_type *type;
634
803aac3e 635 /* We must initialize the image-type if it hasn't been already. */
2e288d54 636 if (NILP (Finit_image_library (symbol, Vdynamic_library_alist)))
803aac3e
MB
637 return 0; /* unimplemented */
638
4ef0d4d0
KS
639 for (type = image_types; type; type = type->next)
640 if (EQ (symbol, *type->type))
641 break;
642
643 return type;
644}
645
646
647/* Value is non-zero if OBJECT is a valid Lisp image specification. A
648 valid image specification is a list whose car is the symbol
649 `image', and whose rest is a property list. The property list must
650 contain a value for key `:type'. That value must be the name of a
651 supported image type. The rest of the property list depends on the
652 image type. */
653
654int
d3da34e0 655valid_image_p (Lisp_Object object)
4ef0d4d0
KS
656{
657 int valid_p = 0;
658
659 if (IMAGEP (object))
660 {
661 Lisp_Object tem;
662
663 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
664 if (EQ (XCAR (tem), QCtype))
665 {
666 tem = XCDR (tem);
667 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
668 {
669 struct image_type *type;
670 type = lookup_image_type (XCAR (tem));
671 if (type)
672 valid_p = type->valid_p (object);
673 }
674
675 break;
676 }
677 }
678
679 return valid_p;
680}
681
682
683/* Log error message with format string FORMAT and argument ARG.
684 Signaling an error, e.g. when an image cannot be loaded, is not a
685 good idea because this would interrupt redisplay, and the error
686 message display would lead to another redisplay. This function
687 therefore simply displays a message. */
688
689static void
675e2c69 690image_error (const char *format, Lisp_Object arg1, Lisp_Object arg2)
4ef0d4d0
KS
691{
692 add_to_log (format, arg1, arg2);
693}
694
695
696\f
697/***********************************************************************
698 Image specifications
699 ***********************************************************************/
700
701enum image_value_type
702{
703 IMAGE_DONT_CHECK_VALUE_TYPE,
704 IMAGE_STRING_VALUE,
705 IMAGE_STRING_OR_NIL_VALUE,
706 IMAGE_SYMBOL_VALUE,
707 IMAGE_POSITIVE_INTEGER_VALUE,
708 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
709 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
710 IMAGE_ASCENT_VALUE,
711 IMAGE_INTEGER_VALUE,
712 IMAGE_FUNCTION_VALUE,
713 IMAGE_NUMBER_VALUE,
714 IMAGE_BOOL_VALUE
715};
716
717/* Structure used when parsing image specifications. */
718
719struct image_keyword
720{
721 /* Name of keyword. */
675e2c69 722 const char *name;
4ef0d4d0
KS
723
724 /* The type of value allowed. */
725 enum image_value_type type;
726
727 /* Non-zero means key must be present. */
728 int mandatory_p;
729
730 /* Used to recognize duplicate keywords in a property list. */
731 int count;
732
733 /* The value that was found. */
734 Lisp_Object value;
735};
736
737
f57e2426
J
738static int parse_image_spec (Lisp_Object, struct image_keyword *,
739 int, Lisp_Object);
740static Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, int *);
4ef0d4d0
KS
741
742
743/* Parse image spec SPEC according to KEYWORDS. A valid image spec
744 has the format (image KEYWORD VALUE ...). One of the keyword/
745 value pairs must be `:type TYPE'. KEYWORDS is a vector of
746 image_keywords structures of size NKEYWORDS describing other
747 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
748
749static int
d3da34e0
JB
750parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
751 int nkeywords, Lisp_Object type)
4ef0d4d0
KS
752{
753 int i;
754 Lisp_Object plist;
755
756 if (!IMAGEP (spec))
757 return 0;
758
759 plist = XCDR (spec);
760 while (CONSP (plist))
761 {
762 Lisp_Object key, value;
763
764 /* First element of a pair must be a symbol. */
765 key = XCAR (plist);
766 plist = XCDR (plist);
767 if (!SYMBOLP (key))
768 return 0;
769
770 /* There must follow a value. */
771 if (!CONSP (plist))
772 return 0;
773 value = XCAR (plist);
774 plist = XCDR (plist);
775
776 /* Find key in KEYWORDS. Error if not found. */
777 for (i = 0; i < nkeywords; ++i)
42a5b22f 778 if (strcmp (keywords[i].name, SSDATA (SYMBOL_NAME (key))) == 0)
4ef0d4d0
KS
779 break;
780
781 if (i == nkeywords)
782 continue;
783
784 /* Record that we recognized the keyword. If a keywords
785 was found more than once, it's an error. */
786 keywords[i].value = value;
787 ++keywords[i].count;
788
789 if (keywords[i].count > 1)
790 return 0;
791
792 /* Check type of value against allowed type. */
793 switch (keywords[i].type)
794 {
795 case IMAGE_STRING_VALUE:
796 if (!STRINGP (value))
797 return 0;
798 break;
799
800 case IMAGE_STRING_OR_NIL_VALUE:
801 if (!STRINGP (value) && !NILP (value))
802 return 0;
803 break;
804
805 case IMAGE_SYMBOL_VALUE:
806 if (!SYMBOLP (value))
807 return 0;
808 break;
809
810 case IMAGE_POSITIVE_INTEGER_VALUE:
13464394 811 if (! RANGED_INTEGERP (1, value, INT_MAX))
4ef0d4d0
KS
812 return 0;
813 break;
814
815 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
13464394 816 if (RANGED_INTEGERP (1, value, INT_MAX))
4ef0d4d0
KS
817 break;
818 if (CONSP (value)
13464394
PE
819 && RANGED_INTEGERP (1, XCAR (value), INT_MAX)
820 && RANGED_INTEGERP (1, XCDR (value), INT_MAX))
4ef0d4d0
KS
821 break;
822 return 0;
823
824 case IMAGE_ASCENT_VALUE:
825 if (SYMBOLP (value) && EQ (value, Qcenter))
826 break;
13464394 827 else if (RANGED_INTEGERP (0, value, 100))
4ef0d4d0
KS
828 break;
829 return 0;
830
831 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
13464394
PE
832 /* Unlike the other integer-related cases, this one does not
833 verify that VALUE fits in 'int'. This is because callers
834 want EMACS_INT. */
4ef0d4d0
KS
835 if (!INTEGERP (value) || XINT (value) < 0)
836 return 0;
837 break;
838
839 case IMAGE_DONT_CHECK_VALUE_TYPE:
840 break;
841
842 case IMAGE_FUNCTION_VALUE:
843 value = indirect_function (value);
ca105506 844 if (!NILP (Ffunctionp (value)))
4ef0d4d0
KS
845 break;
846 return 0;
847
848 case IMAGE_NUMBER_VALUE:
849 if (!INTEGERP (value) && !FLOATP (value))
850 return 0;
851 break;
852
853 case IMAGE_INTEGER_VALUE:
13464394 854 if (! TYPE_RANGED_INTEGERP (int, value))
4ef0d4d0
KS
855 return 0;
856 break;
857
858 case IMAGE_BOOL_VALUE:
859 if (!NILP (value) && !EQ (value, Qt))
860 return 0;
861 break;
862
863 default:
864 abort ();
865 break;
866 }
867
868 if (EQ (key, QCtype) && !EQ (type, value))
869 return 0;
870 }
871
872 /* Check that all mandatory fields are present. */
873 for (i = 0; i < nkeywords; ++i)
874 if (keywords[i].mandatory_p && keywords[i].count == 0)
875 return 0;
876
877 return NILP (plist);
878}
879
880
881/* Return the value of KEY in image specification SPEC. Value is nil
882 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
883 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
884
885static Lisp_Object
d3da34e0 886image_spec_value (Lisp_Object spec, Lisp_Object key, int *found)
4ef0d4d0
KS
887{
888 Lisp_Object tail;
889
890 xassert (valid_image_p (spec));
891
892 for (tail = XCDR (spec);
893 CONSP (tail) && CONSP (XCDR (tail));
894 tail = XCDR (XCDR (tail)))
895 {
896 if (EQ (XCAR (tail), key))
897 {
898 if (found)
899 *found = 1;
900 return XCAR (XCDR (tail));
901 }
902 }
903
904 if (found)
905 *found = 0;
906 return Qnil;
907}
908
909
910DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
911 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
912PIXELS non-nil means return the size in pixels, otherwise return the
913size in canonical character units.
914FRAME is the frame on which the image will be displayed. FRAME nil
915or omitted means use the selected frame. */)
5842a27b 916 (Lisp_Object spec, Lisp_Object pixels, Lisp_Object frame)
4ef0d4d0
KS
917{
918 Lisp_Object size;
919
920 size = Qnil;
921 if (valid_image_p (spec))
922 {
923 struct frame *f = check_x_frame (frame);
13464394 924 ptrdiff_t id = lookup_image (f, spec);
4ef0d4d0
KS
925 struct image *img = IMAGE_FROM_ID (f, id);
926 int width = img->width + 2 * img->hmargin;
927 int height = img->height + 2 * img->vmargin;
928
929 if (NILP (pixels))
930 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
931 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
932 else
933 size = Fcons (make_number (width), make_number (height));
934 }
935 else
936 error ("Invalid image specification");
937
938 return size;
939}
940
941
942DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
943 doc: /* Return t if image SPEC has a mask bitmap.
944FRAME is the frame on which the image will be displayed. FRAME nil
945or omitted means use the selected frame. */)
5842a27b 946 (Lisp_Object spec, Lisp_Object frame)
4ef0d4d0
KS
947{
948 Lisp_Object mask;
949
950 mask = Qnil;
951 if (valid_image_p (spec))
952 {
953 struct frame *f = check_x_frame (frame);
13464394 954 ptrdiff_t id = lookup_image (f, spec);
4ef0d4d0
KS
955 struct image *img = IMAGE_FROM_ID (f, id);
956 if (img->mask)
957 mask = Qt;
958 }
959 else
960 error ("Invalid image specification");
961
962 return mask;
963}
964
1546c559
JL
965DEFUN ("image-metadata", Fimage_metadata, Simage_metadata, 1, 2, 0,
966 doc: /* Return metadata for image SPEC.
6ac3c7bb
KS
967FRAME is the frame on which the image will be displayed. FRAME nil
968or omitted means use the selected frame. */)
5842a27b 969 (Lisp_Object spec, Lisp_Object frame)
6ac3c7bb
KS
970{
971 Lisp_Object ext;
972
973 ext = Qnil;
974 if (valid_image_p (spec))
975 {
976 struct frame *f = check_x_frame (frame);
13464394 977 ptrdiff_t id = lookup_image (f, spec);
6ac3c7bb 978 struct image *img = IMAGE_FROM_ID (f, id);
b50691aa 979 ext = img->lisp_data;
6ac3c7bb
KS
980 }
981
982 return ext;
983}
984
4ef0d4d0
KS
985\f
986/***********************************************************************
987 Image type independent image structures
988 ***********************************************************************/
989
f57e2426 990static void free_image (struct frame *f, struct image *img);
4ef0d4d0 991
f1f25b99 992#define MAX_IMAGE_SIZE 6.0
4ef0d4d0
KS
993/* Allocate and return a new image structure for image specification
994 SPEC. SPEC has a hash value of HASH. */
995
996static struct image *
0de4bb68 997make_image (Lisp_Object spec, EMACS_UINT hash)
4ef0d4d0
KS
998{
999 struct image *img = (struct image *) xmalloc (sizeof *img);
a2bc5bdd 1000 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
4ef0d4d0
KS
1001
1002 xassert (valid_image_p (spec));
72af86bd 1003 memset (img, 0, sizeof *img);
a2bc5bdd 1004 img->dependencies = NILP (file) ? Qnil : list1 (file);
4ef0d4d0
KS
1005 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1006 xassert (img->type != NULL);
1007 img->spec = spec;
b50691aa 1008 img->lisp_data = Qnil;
4ef0d4d0
KS
1009 img->ascent = DEFAULT_IMAGE_ASCENT;
1010 img->hash = hash;
6ac3c7bb 1011 img->corners[BOT_CORNER] = -1; /* Full image */
4ef0d4d0
KS
1012 return img;
1013}
1014
1015
1016/* Free image IMG which was used on frame F, including its resources. */
1017
1018static void
d3da34e0 1019free_image (struct frame *f, struct image *img)
4ef0d4d0
KS
1020{
1021 if (img)
1022 {
354884c4 1023 struct image_cache *c = FRAME_IMAGE_CACHE (f);
4ef0d4d0
KS
1024
1025 /* Remove IMG from the hash table of its cache. */
1026 if (img->prev)
1027 img->prev->next = img->next;
1028 else
1029 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1030
1031 if (img->next)
1032 img->next->prev = img->prev;
1033
1034 c->images[img->id] = NULL;
1035
1036 /* Free resources, then free IMG. */
1037 img->type->free (f, img);
1038 xfree (img);
1039 }
1040}
1041
f1f25b99
CY
1042/* Return 1 if the given widths and heights are valid for display;
1043 otherwise, return 0. */
1044
3f791afe 1045static int
d3da34e0 1046check_image_size (struct frame *f, int width, int height)
f1f25b99 1047{
7df4765a 1048 int w, h;
f1f25b99 1049
7df4765a 1050 if (width <= 0 || height <= 0)
f1f25b99
CY
1051 return 0;
1052
7df4765a 1053 if (INTEGERP (Vmax_image_size))
3f791afe
PE
1054 return (width <= XINT (Vmax_image_size)
1055 && height <= XINT (Vmax_image_size));
7df4765a
KS
1056 else if (FLOATP (Vmax_image_size))
1057 {
ca4aa935
PE
1058 xassert (f);
1059 w = FRAME_PIXEL_WIDTH (f);
1060 h = FRAME_PIXEL_HEIGHT (f);
3f791afe
PE
1061 return (width <= XFLOAT_DATA (Vmax_image_size) * w
1062 && height <= XFLOAT_DATA (Vmax_image_size) * h);
7df4765a
KS
1063 }
1064 else
1065 return 1;
f1f25b99 1066}
4ef0d4d0
KS
1067
1068/* Prepare image IMG for display on frame F. Must be called before
1069 drawing an image. */
1070
1071void
d3da34e0 1072prepare_image_for_display (struct frame *f, struct image *img)
4ef0d4d0
KS
1073{
1074 EMACS_TIME t;
1075
1076 /* We're about to display IMG, so set its timestamp to `now'. */
1077 EMACS_GET_TIME (t);
1078 img->timestamp = EMACS_SECS (t);
1079
1080 /* If IMG doesn't have a pixmap yet, load it now, using the image
1081 type dependent loader function. */
1082 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1083 img->load_failed_p = img->type->load (f, img) == 0;
c7fea325 1084
4ef0d4d0
KS
1085}
1086
1087
1088/* Value is the number of pixels for the ascent of image IMG when
1089 drawn in face FACE. */
1090
1091int
d3da34e0 1092image_ascent (struct image *img, struct face *face, struct glyph_slice *slice)
4ef0d4d0 1093{
1938bc36 1094 int height;
4ef0d4d0
KS
1095 int ascent;
1096
1938bc36
KS
1097 if (slice->height == img->height)
1098 height = img->height + img->vmargin;
1099 else if (slice->y == 0)
1100 height = slice->height + img->vmargin;
1101 else
1102 height = slice->height;
1103
4ef0d4d0
KS
1104 if (img->ascent == CENTERED_IMAGE_ASCENT)
1105 {
1106 if (face->font)
1107 {
1108#ifdef HAVE_NTGUI
1109 /* W32 specific version. Why?. ++kfs */
5fc9fdeb
JR
1110 ascent = height / 2 - (FONT_DESCENT (face->font)
1111 - FONT_BASE (face->font)) / 2;
4ef0d4d0
KS
1112#else
1113 /* This expression is arranged so that if the image can't be
1114 exactly centered, it will be moved slightly up. This is
1115 because a typical font is `top-heavy' (due to the presence
1116 uppercase letters), so the image placement should err towards
1117 being top-heavy too. It also just generally looks better. */
edfda783
AR
1118 ascent = (height + FONT_BASE(face->font)
1119 - FONT_DESCENT(face->font) + 1) / 2;
4ef0d4d0
KS
1120#endif /* HAVE_NTGUI */
1121 }
1122 else
1123 ascent = height / 2;
1124 }
1125 else
13464394 1126 ascent = height * (img->ascent / 100.0);
4ef0d4d0
KS
1127
1128 return ascent;
1129}
1130
1131\f
1132/* Image background colors. */
1133
1134/* Find the "best" corner color of a bitmap.
1135 On W32, XIMG is assumed to a device context with the bitmap selected. */
1136
1137static RGB_PIXEL_COLOR
d3da34e0
JB
1138four_corners_best (XImagePtr_or_DC ximg, int *corners,
1139 unsigned long width, unsigned long height)
4ef0d4d0 1140{
f0c77cd1 1141 RGB_PIXEL_COLOR corner_pixels[4], best IF_LINT (= 0);
4ef0d4d0
KS
1142 int i, best_count;
1143
6ac3c7bb
KS
1144 if (corners && corners[BOT_CORNER] >= 0)
1145 {
1146 /* Get the colors at the corner_pixels of ximg. */
1147 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1148 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1149 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1150 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1151 }
1152 else
1153 {
1154 /* Get the colors at the corner_pixels of ximg. */
1155 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1156 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1157 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1158 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1159 }
4ef0d4d0
KS
1160 /* Choose the most frequently found color as background. */
1161 for (i = best_count = 0; i < 4; ++i)
1162 {
1163 int j, n;
1164
1165 for (j = n = 0; j < 4; ++j)
6ac3c7bb 1166 if (corner_pixels[i] == corner_pixels[j])
4ef0d4d0
KS
1167 ++n;
1168
1169 if (n > best_count)
6ac3c7bb 1170 best = corner_pixels[i], best_count = n;
4ef0d4d0
KS
1171 }
1172
1173 return best;
1174}
1175
1176/* Portability macros */
1177
1178#ifdef HAVE_NTGUI
1179
1180#define Destroy_Image(img_dc, prev) \
1181 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1182
1183#define Free_Pixmap(display, pixmap) \
1184 DeleteObject (pixmap)
1185
edfda783
AR
1186#elif defined (HAVE_NS)
1187
1188#define Destroy_Image(ximg, dummy) \
ed3751c8 1189 ns_release_object (ximg)
edfda783
AR
1190
1191#define Free_Pixmap(display, pixmap) \
ed3751c8 1192 ns_release_object (pixmap)
edfda783 1193
4ef0d4d0
KS
1194#else
1195
1196#define Destroy_Image(ximg, dummy) \
1197 XDestroyImage (ximg)
1198
1199#define Free_Pixmap(display, pixmap) \
1200 XFreePixmap (display, pixmap)
1201
edfda783 1202#endif /* !HAVE_NTGUI && !HAVE_NS */
4ef0d4d0
KS
1203
1204
1205/* Return the `background' field of IMG. If IMG doesn't have one yet,
1206 it is guessed heuristically. If non-zero, XIMG is an existing
1207 XImage object (or device context with the image selected on W32) to
1f026899 1208 use for the heuristic. */
4ef0d4d0
KS
1209
1210RGB_PIXEL_COLOR
d3da34e0 1211image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
4ef0d4d0
KS
1212{
1213 if (! img->background_valid)
1214 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1215 {
1216 int free_ximg = !ximg;
1217#ifdef HAVE_NTGUI
1218 HGDIOBJ prev;
1219#endif /* HAVE_NTGUI */
1220
1221 if (free_ximg)
1222 {
1223#ifndef HAVE_NTGUI
1224 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1225 0, 0, img->width, img->height, ~0, ZPixmap);
1226#else
1227 HDC frame_dc = get_frame_dc (f);
1228 ximg = CreateCompatibleDC (frame_dc);
1229 release_frame_dc (f, frame_dc);
1230 prev = SelectObject (ximg, img->pixmap);
1231#endif /* !HAVE_NTGUI */
1232 }
1233
6ac3c7bb 1234 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
4ef0d4d0
KS
1235
1236 if (free_ximg)
1237 Destroy_Image (ximg, prev);
1f026899 1238
4ef0d4d0
KS
1239 img->background_valid = 1;
1240 }
1241
1242 return img->background;
1243}
1244
1245/* Return the `background_transparent' field of IMG. If IMG doesn't
1246 have one yet, it is guessed heuristically. If non-zero, MASK is an
1247 existing XImage object to use for the heuristic. */
1248
1249int
d3da34e0 1250image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_DC mask)
4ef0d4d0
KS
1251{
1252 if (! img->background_transparent_valid)
1253 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1254 {
1255 if (img->mask)
1256 {
1257 int free_mask = !mask;
1258#ifdef HAVE_NTGUI
1259 HGDIOBJ prev;
1260#endif /* HAVE_NTGUI */
1261
1262 if (free_mask)
1263 {
1264#ifndef HAVE_NTGUI
1265 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1266 0, 0, img->width, img->height, ~0, ZPixmap);
1267#else
1268 HDC frame_dc = get_frame_dc (f);
1269 mask = CreateCompatibleDC (frame_dc);
1270 release_frame_dc (f, frame_dc);
1271 prev = SelectObject (mask, img->mask);
1272#endif /* HAVE_NTGUI */
1273 }
1274
1275 img->background_transparent
6ac3c7bb 1276 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
4ef0d4d0
KS
1277
1278 if (free_mask)
1279 Destroy_Image (mask, prev);
1280 }
1281 else
1282 img->background_transparent = 0;
1283
1284 img->background_transparent_valid = 1;
1285 }
1286
1287 return img->background_transparent;
1288}
1289
1290\f
1291/***********************************************************************
1292 Helper functions for X image types
1293 ***********************************************************************/
1294
f57e2426
J
1295static void x_clear_image_1 (struct frame *, struct image *, int,
1296 int, int);
1297static void x_clear_image (struct frame *f, struct image *img);
1298static unsigned long x_alloc_image_color (struct frame *f,
1299 struct image *img,
1300 Lisp_Object color_name,
1301 unsigned long dflt);
4ef0d4d0
KS
1302
1303
1304/* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1305 free the pixmap if any. MASK_P non-zero means clear the mask
1306 pixmap if any. COLORS_P non-zero means free colors allocated for
1307 the image, if any. */
1308
1309static void
d3da34e0
JB
1310x_clear_image_1 (struct frame *f, struct image *img, int pixmap_p, int mask_p,
1311 int colors_p)
4ef0d4d0
KS
1312{
1313 if (pixmap_p && img->pixmap)
1314 {
1315 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1316 img->pixmap = NO_PIXMAP;
5a06864f 1317 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
4ef0d4d0
KS
1318 img->background_valid = 0;
1319 }
1320
1321 if (mask_p && img->mask)
1322 {
1323 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1324 img->mask = NO_PIXMAP;
1325 img->background_transparent_valid = 0;
1326 }
1327
1328 if (colors_p && img->ncolors)
1329 {
4ef0d4d0
KS
1330 /* W32_TODO: color table support. */
1331#ifdef HAVE_X_WINDOWS
1332 x_free_colors (f, img->colors, img->ncolors);
1333#endif /* HAVE_X_WINDOWS */
1334 xfree (img->colors);
1335 img->colors = NULL;
1336 img->ncolors = 0;
1337 }
c7fea325 1338
4ef0d4d0
KS
1339}
1340
1341/* Free X resources of image IMG which is used on frame F. */
1342
1343static void
d3da34e0 1344x_clear_image (struct frame *f, struct image *img)
4ef0d4d0
KS
1345{
1346 BLOCK_INPUT;
1347 x_clear_image_1 (f, img, 1, 1, 1);
1348 UNBLOCK_INPUT;
1349}
1350
1351
1352/* Allocate color COLOR_NAME for image IMG on frame F. If color
1353 cannot be allocated, use DFLT. Add a newly allocated color to
1354 IMG->colors, so that it can be freed again. Value is the pixel
1355 color. */
1356
1357static unsigned long
d3da34e0
JB
1358x_alloc_image_color (struct frame *f, struct image *img, Lisp_Object color_name,
1359 unsigned long dflt)
4ef0d4d0
KS
1360{
1361 XColor color;
1362 unsigned long result;
1363
1364 xassert (STRINGP (color_name));
1365
3f791afe
PE
1366 if (x_defined_color (f, SSDATA (color_name), &color, 1)
1367 && img->ncolors < min (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *img->colors,
1368 INT_MAX))
4ef0d4d0
KS
1369 {
1370 /* This isn't called frequently so we get away with simply
1371 reallocating the color vector to the needed size, here. */
ddff3151 1372 ptrdiff_t ncolors = img->ncolors + 1;
4ef0d4d0
KS
1373 img->colors =
1374 (unsigned long *) xrealloc (img->colors,
ddff3151
PE
1375 ncolors * sizeof *img->colors);
1376 img->colors[ncolors - 1] = color.pixel;
1377 img->ncolors = ncolors;
4ef0d4d0
KS
1378 result = color.pixel;
1379 }
1380 else
1381 result = dflt;
1382
1383 return result;
1384}
1385
1386
1387\f
1388/***********************************************************************
1389 Image Cache
1390 ***********************************************************************/
1391
f57e2426
J
1392static void cache_image (struct frame *f, struct image *img);
1393static void postprocess_image (struct frame *, struct image *);
4ef0d4d0
KS
1394
1395/* Return a new, initialized image cache that is allocated from the
1396 heap. Call free_image_cache to free an image cache. */
1397
1398struct image_cache *
d3da34e0 1399make_image_cache (void)
4ef0d4d0
KS
1400{
1401 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1402 int size;
1403
72af86bd 1404 memset (c, 0, sizeof *c);
ddff3151
PE
1405 size = 50;
1406 c->images = (struct image **) xmalloc (size * sizeof *c->images);
1407 c->size = size;
4ef0d4d0
KS
1408 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1409 c->buckets = (struct image **) xmalloc (size);
72af86bd 1410 memset (c->buckets, 0, size);
4ef0d4d0
KS
1411 return c;
1412}
1413
1414
d3c35d17
CY
1415/* Find an image matching SPEC in the cache, and return it. If no
1416 image is found, return NULL. */
1417static struct image *
0de4bb68 1418search_image_cache (struct frame *f, Lisp_Object spec, EMACS_UINT hash)
483e7ae0 1419{
91be6b66 1420 struct image *img;
354884c4 1421 struct image_cache *c = FRAME_IMAGE_CACHE (f);
483e7ae0
CY
1422 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1423
8198352b
CY
1424 if (!c) return NULL;
1425
d3c35d17
CY
1426 /* If the image spec does not specify a background color, the cached
1427 image must have the same background color as the current frame.
cf26ebe8
CY
1428 The foreground color must also match, for the sake of monochrome
1429 images.
1430
1431 In fact, we could ignore the foreground color matching condition
1432 for color images, or if the image spec specifies :foreground;
1433 similarly we could ignore the background color matching condition
1434 for formats that don't use transparency (such as jpeg), or if the
1435 image spec specifies :background. However, the extra memory
1436 usage is probably negligible in practice, so we don't bother. */
d3c35d17 1437
483e7ae0 1438 for (img = c->buckets[i]; img; img = img->next)
d3c35d17
CY
1439 if (img->hash == hash
1440 && !NILP (Fequal (img->spec, spec))
c5b8e0ea
YM
1441 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1442 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
d3c35d17
CY
1443 break;
1444 return img;
1445}
1446
1447
1448/* Search frame F for an image with spec SPEC, and free it. */
1449
1450static void
d3da34e0 1451uncache_image (struct frame *f, Lisp_Object spec)
d3c35d17
CY
1452{
1453 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1454 if (img)
be3faa80
CY
1455 {
1456 free_image (f, img);
1457 /* As display glyphs may still be referring to the image ID, we
1458 must garbage the frame (Bug#6426). */
1459 SET_FRAME_GARBAGED (f);
1460 }
483e7ae0
CY
1461}
1462
1463
4ef0d4d0
KS
1464/* Free image cache of frame F. Be aware that X frames share images
1465 caches. */
1466
1467void
d3da34e0 1468free_image_cache (struct frame *f)
4ef0d4d0 1469{
354884c4 1470 struct image_cache *c = FRAME_IMAGE_CACHE (f);
4ef0d4d0
KS
1471 if (c)
1472 {
13464394 1473 ptrdiff_t i;
4ef0d4d0
KS
1474
1475 /* Cache should not be referenced by any frame when freed. */
1476 xassert (c->refcount == 0);
1477
1478 for (i = 0; i < c->used; ++i)
1479 free_image (f, c->images[i]);
1480 xfree (c->images);
1481 xfree (c->buckets);
1482 xfree (c);
354884c4 1483 FRAME_IMAGE_CACHE (f) = NULL;
4ef0d4d0
KS
1484 }
1485}
1486
1487
a2bc5bdd
SM
1488/* Clear image cache of frame F. FILTER=t means free all images.
1489 FILTER=nil means clear only images that haven't been
1490 displayed for some time.
1491 Else, only free the images which have FILTER in their `dependencies'.
1492 Should be called from time to time to reduce the number of loaded images.
1493 If image-cache-eviction-delay is non-nil, this frees images in the cache
1494 which weren't displayed for at least that many seconds. */
4ef0d4d0 1495
ce0ad53d 1496static void
a2bc5bdd 1497clear_image_cache (struct frame *f, Lisp_Object filter)
4ef0d4d0 1498{
354884c4 1499 struct image_cache *c = FRAME_IMAGE_CACHE (f);
4ef0d4d0 1500
98fe5161 1501 if (c)
4ef0d4d0 1502 {
13464394 1503 ptrdiff_t i, nfreed = 0;
4ef0d4d0
KS
1504
1505 /* Block input so that we won't be interrupted by a SIGIO
1506 while being in an inconsistent state. */
1507 BLOCK_INPUT;
1508
98fe5161
CY
1509 if (!NILP (filter))
1510 {
1511 /* Filter image cache. */
1512 for (i = 0; i < c->used; ++i)
1513 {
1514 struct image *img = c->images[i];
1515 if (img && (EQ (Qt, filter)
1516 || !NILP (Fmember (filter, img->dependencies))))
1517 {
1518 free_image (f, img);
1519 ++nfreed;
1520 }
1521 }
1522 }
1523 else if (INTEGERP (Vimage_cache_eviction_delay))
4ef0d4d0 1524 {
98fe5161
CY
1525 /* Free cache based on timestamp. */
1526 EMACS_TIME t;
13464394
PE
1527 double old, delay;
1528 ptrdiff_t nimages = 0;
98fe5161
CY
1529
1530 for (i = 0; i < c->used; ++i)
1531 if (c->images[i])
1532 nimages++;
1533
1534 /* If the number of cached images has grown unusually large,
1535 decrease the cache eviction delay (Bug#6230). */
13464394 1536 delay = XINT (Vimage_cache_eviction_delay);
98fe5161 1537 if (nimages > 40)
13464394
PE
1538 delay = 1600 * delay / nimages / nimages;
1539 delay = max (delay, 1);
98fe5161
CY
1540
1541 EMACS_GET_TIME (t);
1542 old = EMACS_SECS (t) - delay;
1543
1544 for (i = 0; i < c->used; ++i)
4ef0d4d0 1545 {
98fe5161
CY
1546 struct image *img = c->images[i];
1547 if (img && img->timestamp < old)
1548 {
1549 free_image (f, img);
1550 ++nfreed;
1551 }
4ef0d4d0
KS
1552 }
1553 }
1554
1555 /* We may be clearing the image cache because, for example,
1556 Emacs was iconified for a longer period of time. In that
1557 case, current matrices may still contain references to
1558 images freed above. So, clear these matrices. */
1559 if (nfreed)
1560 {
1561 Lisp_Object tail, frame;
1562
1563 FOR_EACH_FRAME (tail, frame)
1564 {
6ae141d6
PE
1565 struct frame *fr = XFRAME (frame);
1566 if (FRAME_IMAGE_CACHE (fr) == c)
1567 clear_current_matrices (fr);
4ef0d4d0
KS
1568 }
1569
1570 ++windows_or_buffers_changed;
1571 }
1572
1573 UNBLOCK_INPUT;
1574 }
1575}
1576
354884c4 1577void
a2bc5bdd 1578clear_image_caches (Lisp_Object filter)
354884c4
SM
1579{
1580 /* FIXME: We want to do
1581 * struct terminal *t;
1582 * for (t = terminal_list; t; t = t->next_terminal)
1583 * clear_image_cache (t, filter); */
1584 Lisp_Object tail, frame;
1585 FOR_EACH_FRAME (tail, frame)
1586 if (FRAME_WINDOW_P (XFRAME (frame)))
a2bc5bdd 1587 clear_image_cache (XFRAME (frame), filter);
354884c4 1588}
4ef0d4d0
KS
1589
1590DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1591 0, 1, 0,
a2bc5bdd
SM
1592 doc: /* Clear the image cache.
1593FILTER nil or a frame means clear all images in the selected frame.
1594FILTER t means clear the image caches of all frames.
1595Anything else, means only clear those images which refer to FILTER,
1596which is then usually a filename. */)
5842a27b 1597 (Lisp_Object filter)
4ef0d4d0 1598{
a2bc5bdd
SM
1599 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1600 clear_image_caches (filter);
4ef0d4d0 1601 else
a2bc5bdd 1602 clear_image_cache (check_x_frame (filter), Qt);
4ef0d4d0
KS
1603
1604 return Qnil;
1605}
1606
1607
110683ad 1608DEFUN ("image-flush", Fimage_flush, Simage_flush,
483e7ae0 1609 1, 2, 0,
110683ad
CY
1610 doc: /* Fush the image with specification SPEC on frame FRAME.
1611This removes the image from the Emacs image cache. If SPEC specifies
1612an image file, the next redisplay of this image will read from the
1613current contents of that file.
1614
483e7ae0
CY
1615FRAME nil or omitted means use the selected frame.
1616FRAME t means refresh the image on all frames. */)
5842a27b 1617 (Lisp_Object spec, Lisp_Object frame)
483e7ae0
CY
1618{
1619 if (!valid_image_p (spec))
1620 error ("Invalid image specification");
1621
1622 if (EQ (frame, Qt))
1623 {
1624 Lisp_Object tail;
1625 FOR_EACH_FRAME (tail, frame)
1626 {
1627 struct frame *f = XFRAME (frame);
1628 if (FRAME_WINDOW_P (f))
1629 uncache_image (f, spec);
1630 }
1631 }
1632 else
1633 uncache_image (check_x_frame (frame), spec);
1634
1635 return Qnil;
1636}
1637
1638
4ef0d4d0
KS
1639/* Compute masks and transform image IMG on frame F, as specified
1640 by the image's specification, */
1641
1642static void
d3da34e0 1643postprocess_image (struct frame *f, struct image *img)
4ef0d4d0
KS
1644{
1645 /* Manipulation of the image's mask. */
1646 if (img->pixmap)
1647 {
1648 Lisp_Object conversion, spec;
1649 Lisp_Object mask;
1650
1651 spec = img->spec;
1652
1653 /* `:heuristic-mask t'
1654 `:mask heuristic'
1655 means build a mask heuristically.
1656 `:heuristic-mask (R G B)'
1657 `:mask (heuristic (R G B))'
1658 means build a mask from color (R G B) in the
1659 image.
1660 `:mask nil'
1661 means remove a mask, if any. */
1662
1663 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1664 if (!NILP (mask))
1665 x_build_heuristic_mask (f, img, mask);
1666 else
1667 {
1668 int found_p;
1669
1670 mask = image_spec_value (spec, QCmask, &found_p);
1671
1672 if (EQ (mask, Qheuristic))
1673 x_build_heuristic_mask (f, img, Qt);
1674 else if (CONSP (mask)
1675 && EQ (XCAR (mask), Qheuristic))
1676 {
1677 if (CONSP (XCDR (mask)))
1678 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1679 else
1680 x_build_heuristic_mask (f, img, XCDR (mask));
1681 }
1682 else if (NILP (mask) && found_p && img->mask)
1683 {
1684 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1685 img->mask = NO_PIXMAP;
1686 }
1687 }
1688
1689
1690 /* Should we apply an image transformation algorithm? */
1691 conversion = image_spec_value (spec, QCconversion, NULL);
1692 if (EQ (conversion, Qdisabled))
1693 x_disable_image (f, img);
1694 else if (EQ (conversion, Qlaplace))
1695 x_laplace (f, img);
1696 else if (EQ (conversion, Qemboss))
1697 x_emboss (f, img);
1698 else if (CONSP (conversion)
1699 && EQ (XCAR (conversion), Qedge_detection))
1700 {
1701 Lisp_Object tem;
1702 tem = XCDR (conversion);
1703 if (CONSP (tem))
1704 x_edge_detection (f, img,
1705 Fplist_get (tem, QCmatrix),
1706 Fplist_get (tem, QCcolor_adjustment));
1707 }
1708 }
1709}
1710
1711
1712/* Return the id of image with Lisp specification SPEC on frame F.
1713 SPEC must be a valid Lisp image specification (see valid_image_p). */
1714
13464394 1715ptrdiff_t
d3da34e0 1716lookup_image (struct frame *f, Lisp_Object spec)
4ef0d4d0 1717{
4ef0d4d0 1718 struct image *img;
0de4bb68 1719 EMACS_UINT hash;
4ef0d4d0
KS
1720 EMACS_TIME now;
1721
1722 /* F must be a window-system frame, and SPEC must be a valid image
1723 specification. */
1724 xassert (FRAME_WINDOW_P (f));
1725 xassert (valid_image_p (spec));
1726
4ef0d4d0
KS
1727 /* Look up SPEC in the hash table of the image cache. */
1728 hash = sxhash (spec, 0);
d3c35d17 1729 img = search_image_cache (f, spec, hash);
f1f25b99
CY
1730 if (img && img->load_failed_p)
1731 {
1732 free_image (f, img);
1733 img = NULL;
1734 }
1735
4ef0d4d0
KS
1736 /* If not found, create a new image and cache it. */
1737 if (img == NULL)
1738 {
4ef0d4d0
KS
1739 BLOCK_INPUT;
1740 img = make_image (spec, hash);
1741 cache_image (f, img);
1742 img->load_failed_p = img->type->load (f, img) == 0;
c5b8e0ea
YM
1743 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
1744 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
4ef0d4d0
KS
1745
1746 /* If we can't load the image, and we don't have a width and
1747 height, use some arbitrary width and height so that we can
1748 draw a rectangle for it. */
1749 if (img->load_failed_p)
1750 {
1751 Lisp_Object value;
1752
1753 value = image_spec_value (spec, QCwidth, NULL);
1754 img->width = (INTEGERP (value)
1755 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1756 value = image_spec_value (spec, QCheight, NULL);
1757 img->height = (INTEGERP (value)
1758 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1759 }
1760 else
1761 {
1762 /* Handle image type independent image attributes
1763 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1764 `:background COLOR'. */
1765 Lisp_Object ascent, margin, relief, bg;
1766
1767 ascent = image_spec_value (spec, QCascent, NULL);
1768 if (INTEGERP (ascent))
1769 img->ascent = XFASTINT (ascent);
1770 else if (EQ (ascent, Qcenter))
1771 img->ascent = CENTERED_IMAGE_ASCENT;
1772
1773 margin = image_spec_value (spec, QCmargin, NULL);
13464394 1774 if (INTEGERP (margin))
4ef0d4d0 1775 img->vmargin = img->hmargin = XFASTINT (margin);
13464394 1776 else if (CONSP (margin))
4ef0d4d0 1777 {
13464394
PE
1778 img->hmargin = XFASTINT (XCAR (margin));
1779 img->vmargin = XFASTINT (XCDR (margin));
4ef0d4d0
KS
1780 }
1781
1782 relief = image_spec_value (spec, QCrelief, NULL);
1783 if (INTEGERP (relief))
1784 {
1785 img->relief = XINT (relief);
1ea40aa2
EZ
1786 img->hmargin += eabs (img->relief);
1787 img->vmargin += eabs (img->relief);
4ef0d4d0
KS
1788 }
1789
1790 if (! img->background_valid)
1791 {
1792 bg = image_spec_value (img->spec, QCbackground, NULL);
1793 if (!NILP (bg))
1794 {
1795 img->background
1796 = x_alloc_image_color (f, img, bg,
1797 FRAME_BACKGROUND_PIXEL (f));
1798 img->background_valid = 1;
1799 }
1800 }
1801
1802 /* Do image transformations and compute masks, unless we
1803 don't have the image yet. */
1804 if (!EQ (*img->type->type, Qpostscript))
1805 postprocess_image (f, img);
1806 }
1807
1808 UNBLOCK_INPUT;
1809 }
1810
1811 /* We're using IMG, so set its timestamp to `now'. */
1812 EMACS_GET_TIME (now);
1813 img->timestamp = EMACS_SECS (now);
1814
4ef0d4d0
KS
1815 /* Value is the image id. */
1816 return img->id;
1817}
1818
1819
1820/* Cache image IMG in the image cache of frame F. */
1821
1822static void
d3da34e0 1823cache_image (struct frame *f, struct image *img)
4ef0d4d0 1824{
354884c4 1825 struct image_cache *c = FRAME_IMAGE_CACHE (f);
13464394 1826 ptrdiff_t i;
4ef0d4d0
KS
1827
1828 /* Find a free slot in c->images. */
1829 for (i = 0; i < c->used; ++i)
1830 if (c->images[i] == NULL)
1831 break;
1832
1833 /* If no free slot found, maybe enlarge c->images. */
1834 if (i == c->used && c->used == c->size)
1835 {
7fcccf1e
PE
1836 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *c->images / 2 < c->size)
1837 memory_full (SIZE_MAX);
ddff3151
PE
1838 c->images =
1839 (struct image **) xrealloc (c->images,
1840 c->size * (2 * sizeof *c->images));
4ef0d4d0 1841 c->size *= 2;
4ef0d4d0
KS
1842 }
1843
1844 /* Add IMG to c->images, and assign IMG an id. */
1845 c->images[i] = img;
1846 img->id = i;
1847 if (i == c->used)
1848 ++c->used;
1849
1850 /* Add IMG to the cache's hash table. */
1851 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1852 img->next = c->buckets[i];
1853 if (img->next)
1854 img->next->prev = img;
1855 img->prev = NULL;
1856 c->buckets[i] = img;
1857}
1858
1859
1860/* Call FN on every image in the image cache of frame F. Used to mark
1861 Lisp Objects in the image cache. */
1862
354884c4
SM
1863/* Mark Lisp objects in image IMG. */
1864
1865static void
d3da34e0 1866mark_image (struct image *img)
354884c4
SM
1867{
1868 mark_object (img->spec);
a2bc5bdd 1869 mark_object (img->dependencies);
354884c4 1870
b50691aa
CY
1871 if (!NILP (img->lisp_data))
1872 mark_object (img->lisp_data);
354884c4
SM
1873}
1874
1875
4ef0d4d0 1876void
354884c4 1877mark_image_cache (struct image_cache *c)
4ef0d4d0 1878{
354884c4 1879 if (c)
4ef0d4d0 1880 {
13464394 1881 ptrdiff_t i;
354884c4
SM
1882 for (i = 0; i < c->used; ++i)
1883 if (c->images[i])
1884 mark_image (c->images[i]);
4ef0d4d0
KS
1885 }
1886}
1887
1888
1889\f
1890/***********************************************************************
9e2a2647 1891 X / NS / W32 support code
4ef0d4d0
KS
1892 ***********************************************************************/
1893
1894#ifdef HAVE_NTGUI
1895
1896/* Macro for defining functions that will be loaded from image DLLs. */
dbdb9a7c 1897#define DEF_IMGLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
4ef0d4d0
KS
1898
1899/* Macro for loading those image functions from the library. */
1900#define LOAD_IMGLIB_FN(lib,func) { \
1901 fn_##func = (void *) GetProcAddress (lib, #func); \
1902 if (!fn_##func) return 0; \
1903 }
1904
1905#endif /* HAVE_NTGUI */
1906
f57e2426
J
1907static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
1908 XImagePtr *, Pixmap *);
1909static void x_destroy_x_image (XImagePtr);
1910static void x_put_x_image (struct frame *, XImagePtr, Pixmap, int, int);
4ef0d4d0 1911
476371c4
PE
1912/* Return nonzero if XIMG's size WIDTH x HEIGHT doesn't break the
1913 windowing system.
ca4aa935
PE
1914 WIDTH and HEIGHT must both be positive.
1915 If XIMG is null, assume it is a bitmap. */
1916static int
1917x_check_image_size (XImagePtr ximg, int width, int height)
1918{
476371c4 1919#ifdef HAVE_X_WINDOWS
ca4aa935
PE
1920 /* Respect Xlib's limits: it cannot deal with images that have more
1921 than INT_MAX (and/or UINT_MAX) bytes. And respect Emacs's limits
476371c4 1922 of PTRDIFF_MAX (and/or SIZE_MAX) bytes for any object. */
ca4aa935
PE
1923 enum
1924 {
1925 XLIB_BYTES_MAX = min (INT_MAX, UINT_MAX),
1926 X_IMAGE_BYTES_MAX = min (XLIB_BYTES_MAX, min (PTRDIFF_MAX, SIZE_MAX))
1927 };
1928
1929 int bitmap_pad, depth, bytes_per_line;
1930 if (ximg)
1931 {
1932 bitmap_pad = ximg->bitmap_pad;
1933 depth = ximg->depth;
1934 bytes_per_line = ximg->bytes_per_line;
1935 }
1936 else
1937 {
1938 bitmap_pad = 8;
1939 depth = 1;
1940 bytes_per_line = (width >> 3) + ((width & 7) != 0);
1941 }
1942 return (width <= (INT_MAX - (bitmap_pad - 1)) / depth
1943 && height <= X_IMAGE_BYTES_MAX / bytes_per_line);
476371c4
PE
1944#else
1945 /* FIXME: Implement this check for the HAVE_NS and HAVE_NTGUI cases.
1946 For now, assume that every image size is allowed on these systems. */
1947 return 1;
1948#endif
ca4aa935 1949}
4ef0d4d0
KS
1950
1951/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1952 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1953 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1954 via xmalloc. Print error messages via image_error if an error
1955 occurs. Value is non-zero if successful.
1956
1957 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1958 should indicate the bit depth of the image. */
1959
1960static int
d3da34e0
JB
1961x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
1962 XImagePtr *ximg, Pixmap *pixmap)
4ef0d4d0
KS
1963{
1964#ifdef HAVE_X_WINDOWS
1965 Display *display = FRAME_X_DISPLAY (f);
1966 Window window = FRAME_X_WINDOW (f);
1967 Screen *screen = FRAME_X_SCREEN (f);
1968
1969 xassert (interrupt_input_blocked);
1970
1971 if (depth <= 0)
1972 depth = DefaultDepthOfScreen (screen);
1973 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
1974 depth, ZPixmap, 0, NULL, width, height,
1975 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
1976 if (*ximg == NULL)
1977 {
1978 image_error ("Unable to allocate X image", Qnil, Qnil);
1979 return 0;
1980 }
1981
ca4aa935
PE
1982 if (! x_check_image_size (*ximg, width, height))
1983 {
1984 x_destroy_x_image (*ximg);
1985 *ximg = NULL;
1986 image_error ("Image too large (%dx%d)",
1987 make_number (width), make_number (height));
1988 return 0;
1989 }
1990
4ef0d4d0
KS
1991 /* Allocate image raster. */
1992 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
1993
1994 /* Allocate a pixmap of the same size. */
1995 *pixmap = XCreatePixmap (display, window, width, height, depth);
1996 if (*pixmap == NO_PIXMAP)
1997 {
1998 x_destroy_x_image (*ximg);
1999 *ximg = NULL;
2000 image_error ("Unable to create X pixmap", Qnil, Qnil);
2001 return 0;
2002 }
2003
2004 return 1;
2005#endif /* HAVE_X_WINDOWS */
2006
2007#ifdef HAVE_NTGUI
2008
2009 BITMAPINFOHEADER *header;
2010 HDC hdc;
2011 int scanline_width_bits;
2012 int remainder;
2013 int palette_colors = 0;
2014
2015 if (depth == 0)
2016 depth = 24;
2017
2018 if (depth != 1 && depth != 4 && depth != 8
2019 && depth != 16 && depth != 24 && depth != 32)
2020 {
2021 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2022 return 0;
2023 }
2024
2025 scanline_width_bits = width * depth;
2026 remainder = scanline_width_bits % 32;
2027
2028 if (remainder)
2029 scanline_width_bits += 32 - remainder;
2030
2031 /* Bitmaps with a depth less than 16 need a palette. */
2032 /* BITMAPINFO structure already contains the first RGBQUAD. */
2033 if (depth < 16)
2034 palette_colors = 1 << depth - 1;
2035
2036 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
4ef0d4d0 2037
72af86bd
AS
2038 header = &(*ximg)->info.bmiHeader;
2039 memset (&(*ximg)->info, 0, sizeof (BITMAPINFO));
4ef0d4d0
KS
2040 header->biSize = sizeof (*header);
2041 header->biWidth = width;
2042 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2043 header->biPlanes = 1;
2044 header->biBitCount = depth;
2045 header->biCompression = BI_RGB;
2046 header->biClrUsed = palette_colors;
2047
2048 /* TODO: fill in palette. */
2049 if (depth == 1)
2050 {
2051 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2052 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2053 (*ximg)->info.bmiColors[0].rgbRed = 0;
2054 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2055 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2056 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2057 (*ximg)->info.bmiColors[1].rgbRed = 255;
2058 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2059 }
2060
2061 hdc = get_frame_dc (f);
2062
2063 /* Create a DIBSection and raster array for the bitmap,
2064 and store its handle in *pixmap. */
2065 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2066 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2e09fef1
EZ
2067 /* casting avoids a GCC warning */
2068 (void **)&((*ximg)->data), NULL, 0);
4ef0d4d0
KS
2069
2070 /* Realize display palette and garbage all frames. */
2071 release_frame_dc (f, hdc);
2072
2073 if (*pixmap == NULL)
2074 {
5fc9fdeb 2075 DWORD err = GetLastError ();
4ef0d4d0
KS
2076 Lisp_Object errcode;
2077 /* All system errors are < 10000, so the following is safe. */
13464394 2078 XSETINT (errcode, err);
4ef0d4d0
KS
2079 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2080 x_destroy_x_image (*ximg);
2081 return 0;
2082 }
2083
2084 return 1;
2085
2086#endif /* HAVE_NTGUI */
2087
edfda783 2088#ifdef HAVE_NS
ed3751c8 2089 *pixmap = ns_image_for_XPM (width, height, depth);
edfda783
AR
2090 if (*pixmap == 0)
2091 {
2092 *ximg = NULL;
2093 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2094 return 0;
2095 }
2096 *ximg = *pixmap;
2097 return 1;
2098#endif
4ef0d4d0
KS
2099}
2100
2101
2102/* Destroy XImage XIMG. Free XIMG->data. */
2103
2104static void
d3da34e0 2105x_destroy_x_image (XImagePtr ximg)
4ef0d4d0
KS
2106{
2107 xassert (interrupt_input_blocked);
2108 if (ximg)
2109 {
2110#ifdef HAVE_X_WINDOWS
2111 xfree (ximg->data);
2112 ximg->data = NULL;
2113 XDestroyImage (ximg);
2114#endif /* HAVE_X_WINDOWS */
2115#ifdef HAVE_NTGUI
2116 /* Data will be freed by DestroyObject. */
2117 ximg->data = NULL;
2118 xfree (ximg);
2119#endif /* HAVE_NTGUI */
edfda783 2120#ifdef HAVE_NS
ed3751c8 2121 ns_release_object (ximg);
edfda783 2122#endif /* HAVE_NS */
4ef0d4d0
KS
2123 }
2124}
2125
2126
2127/* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2128 are width and height of both the image and pixmap. */
2129
2130static void
d3da34e0 2131x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int height)
4ef0d4d0
KS
2132{
2133#ifdef HAVE_X_WINDOWS
2134 GC gc;
2135
2136 xassert (interrupt_input_blocked);
2137 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2138 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2139 XFreeGC (FRAME_X_DISPLAY (f), gc);
2140#endif /* HAVE_X_WINDOWS */
2141
2142#ifdef HAVE_NTGUI
2143#if 0 /* I don't think this is necessary looking at where it is used. */
2144 HDC hdc = get_frame_dc (f);
2145 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2146 release_frame_dc (f, hdc);
2147#endif
2148#endif /* HAVE_NTGUI */
2149
edfda783
AR
2150#ifdef HAVE_NS
2151 xassert (ximg == pixmap);
ed3751c8 2152 ns_retain_object (ximg);
edfda783 2153#endif
4ef0d4d0
KS
2154}
2155
2156\f
2157/***********************************************************************
2158 File Handling
2159 ***********************************************************************/
2160
6678dc11 2161/* Find image file FILE. Look in data-directory/images, then
022af124
KH
2162 x-bitmap-file-path. Value is the encoded full name of the file
2163 found, or nil if not found. */
4ef0d4d0 2164
c640aa9b 2165Lisp_Object
d3da34e0 2166x_find_image_file (Lisp_Object file)
4ef0d4d0
KS
2167{
2168 Lisp_Object file_found, search_path;
4ef0d4d0
KS
2169 int fd;
2170
6678dc11
GM
2171 /* TODO I think this should use something like image-load-path
2172 instead. Unfortunately, that can contain non-string elements. */
2173 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2174 Vdata_directory),
2175 Vx_bitmap_file_path);
4ef0d4d0 2176
050b82f6 2177 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
4ef0d4d0
KS
2178 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2179
2180 if (fd == -1)
2181 file_found = Qnil;
2182 else
022af124
KH
2183 {
2184 file_found = ENCODE_FILE (file_found);
2185 close (fd);
2186 }
4ef0d4d0 2187
4ef0d4d0
KS
2188 return file_found;
2189}
2190
2191
2192/* Read FILE into memory. Value is a pointer to a buffer allocated
2193 with xmalloc holding FILE's contents. Value is null if an error
2194 occurred. *SIZE is set to the size of the file. */
2195
2196static unsigned char *
dd52fcea 2197slurp_file (char *file, ptrdiff_t *size)
4ef0d4d0
KS
2198{
2199 FILE *fp = NULL;
2200 unsigned char *buf = NULL;
2201 struct stat st;
2202
2203 if (stat (file, &st) == 0
2204 && (fp = fopen (file, "rb")) != NULL
dd52fcea 2205 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
fa8459a3 2206 && (buf = (unsigned char *) xmalloc (st.st_size),
4ef0d4d0
KS
2207 fread (buf, 1, st.st_size, fp) == st.st_size))
2208 {
2209 *size = st.st_size;
2210 fclose (fp);
2211 }
2212 else
2213 {
2214 if (fp)
2215 fclose (fp);
2216 if (buf)
2217 {
2218 xfree (buf);
2219 buf = NULL;
2220 }
2221 }
2222
2223 return buf;
2224}
2225
2226
2227\f
4ef0d4d0
KS
2228/***********************************************************************
2229 XBM images
2230 ***********************************************************************/
2231
f57e2426
J
2232static int xbm_scan (unsigned char **, unsigned char *, char *, int *);
2233static int xbm_load (struct frame *f, struct image *img);
2234static int xbm_load_image (struct frame *f, struct image *img,
2235 unsigned char *, unsigned char *);
2236static int xbm_image_p (Lisp_Object object);
2237static int xbm_read_bitmap_data (struct frame *f,
2238 unsigned char *, unsigned char *,
b8dc29e9 2239 int *, int *, char **, int);
f57e2426 2240static int xbm_file_p (Lisp_Object);
4ef0d4d0
KS
2241
2242
2243/* Indices of image specification fields in xbm_format, below. */
2244
2245enum xbm_keyword_index
2246{
2247 XBM_TYPE,
2248 XBM_FILE,
2249 XBM_WIDTH,
2250 XBM_HEIGHT,
2251 XBM_DATA,
2252 XBM_FOREGROUND,
2253 XBM_BACKGROUND,
2254 XBM_ASCENT,
2255 XBM_MARGIN,
2256 XBM_RELIEF,
2257 XBM_ALGORITHM,
2258 XBM_HEURISTIC_MASK,
2259 XBM_MASK,
2260 XBM_LAST
2261};
2262
2263/* Vector of image_keyword structures describing the format
2264 of valid XBM image specifications. */
2265
91433552 2266static const struct image_keyword xbm_format[XBM_LAST] =
4ef0d4d0
KS
2267{
2268 {":type", IMAGE_SYMBOL_VALUE, 1},
2269 {":file", IMAGE_STRING_VALUE, 0},
2270 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2271 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2272 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2273 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2274 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2275 {":ascent", IMAGE_ASCENT_VALUE, 0},
2276 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2277 {":relief", IMAGE_INTEGER_VALUE, 0},
2278 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2279 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2280 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2281};
2282
2283/* Structure describing the image type XBM. */
2284
2285static struct image_type xbm_type =
2286{
2287 &Qxbm,
2288 xbm_image_p,
2289 xbm_load,
2290 x_clear_image,
2291 NULL
2292};
2293
2294/* Tokens returned from xbm_scan. */
2295
2296enum xbm_token
2297{
2298 XBM_TK_IDENT = 256,
2299 XBM_TK_NUMBER
2300};
2301
2302
2303/* Return non-zero if OBJECT is a valid XBM-type image specification.
2304 A valid specification is a list starting with the symbol `image'
2305 The rest of the list is a property list which must contain an
2306 entry `:type xbm..
2307
2308 If the specification specifies a file to load, it must contain
2309 an entry `:file FILENAME' where FILENAME is a string.
2310
2311 If the specification is for a bitmap loaded from memory it must
2312 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2313 WIDTH and HEIGHT are integers > 0. DATA may be:
2314
2315 1. a string large enough to hold the bitmap data, i.e. it must
2316 have a size >= (WIDTH + 7) / 8 * HEIGHT
2317
2318 2. a bool-vector of size >= WIDTH * HEIGHT
2319
2320 3. a vector of strings or bool-vectors, one for each line of the
2321 bitmap.
2322
bbe6f2aa 2323 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
4ef0d4d0
KS
2324 may not be specified in this case because they are defined in the
2325 XBM file.
2326
2327 Both the file and data forms may contain the additional entries
2328 `:background COLOR' and `:foreground COLOR'. If not present,
2329 foreground and background of the frame on which the image is
2330 displayed is used. */
2331
2332static int
d3da34e0 2333xbm_image_p (Lisp_Object object)
4ef0d4d0
KS
2334{
2335 struct image_keyword kw[XBM_LAST];
2336
72af86bd 2337 memcpy (kw, xbm_format, sizeof kw);
4ef0d4d0
KS
2338 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2339 return 0;
2340
2341 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2342
2343 if (kw[XBM_FILE].count)
2344 {
2345 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2346 return 0;
2347 }
2348 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2349 {
2350 /* In-memory XBM file. */
2351 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2352 return 0;
2353 }
2354 else
2355 {
2356 Lisp_Object data;
13464394 2357 int width, height;
4ef0d4d0
KS
2358
2359 /* Entries for `:width', `:height' and `:data' must be present. */
2360 if (!kw[XBM_WIDTH].count
2361 || !kw[XBM_HEIGHT].count
2362 || !kw[XBM_DATA].count)
2363 return 0;
2364
2365 data = kw[XBM_DATA].value;
2366 width = XFASTINT (kw[XBM_WIDTH].value);
2367 height = XFASTINT (kw[XBM_HEIGHT].value);
2368
2369 /* Check type of data, and width and height against contents of
2370 data. */
2371 if (VECTORP (data))
2372 {
45aebb64 2373 EMACS_INT i;
4ef0d4d0
KS
2374
2375 /* Number of elements of the vector must be >= height. */
77b37c05 2376 if (ASIZE (data) < height)
4ef0d4d0
KS
2377 return 0;
2378
2379 /* Each string or bool-vector in data must be large enough
2380 for one line of the image. */
2381 for (i = 0; i < height; ++i)
2382 {
2383 Lisp_Object elt = XVECTOR (data)->contents[i];
2384
2385 if (STRINGP (elt))
2386 {
2387 if (SCHARS (elt)
2388 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2389 return 0;
2390 }
2391 else if (BOOL_VECTOR_P (elt))
2392 {
2393 if (XBOOL_VECTOR (elt)->size < width)
2394 return 0;
2395 }
2396 else
2397 return 0;
2398 }
2399 }
2400 else if (STRINGP (data))
2401 {
2402 if (SCHARS (data)
2403 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2404 return 0;
2405 }
2406 else if (BOOL_VECTOR_P (data))
2407 {
ca4aa935 2408 if (XBOOL_VECTOR (data)->size / height < width)
4ef0d4d0
KS
2409 return 0;
2410 }
2411 else
2412 return 0;
2413 }
2414
2415 return 1;
2416}
2417
2418
2419/* Scan a bitmap file. FP is the stream to read from. Value is
2420 either an enumerator from enum xbm_token, or a character for a
2421 single-character token, or 0 at end of file. If scanning an
2422 identifier, store the lexeme of the identifier in SVAL. If
2423 scanning a number, store its value in *IVAL. */
2424
2425static int
d3da34e0 2426xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival)
4ef0d4d0
KS
2427{
2428 unsigned int c;
2429
2430 loop:
2431
2432 /* Skip white space. */
2433 while (*s < end && (c = *(*s)++, isspace (c)))
2434 ;
2435
2436 if (*s >= end)
2437 c = 0;
2438 else if (isdigit (c))
2439 {
2440 int value = 0, digit;
2441
2442 if (c == '0' && *s < end)
2443 {
2444 c = *(*s)++;
2445 if (c == 'x' || c == 'X')
2446 {
2447 while (*s < end)
2448 {
2449 c = *(*s)++;
2450 if (isdigit (c))
2451 digit = c - '0';
2452 else if (c >= 'a' && c <= 'f')
2453 digit = c - 'a' + 10;
2454 else if (c >= 'A' && c <= 'F')
2455 digit = c - 'A' + 10;
2456 else
2457 break;
2458 value = 16 * value + digit;
2459 }
2460 }
2461 else if (isdigit (c))
2462 {
2463 value = c - '0';
2464 while (*s < end
2465 && (c = *(*s)++, isdigit (c)))
2466 value = 8 * value + c - '0';
2467 }
2468 }
2469 else
2470 {
2471 value = c - '0';
2472 while (*s < end
2473 && (c = *(*s)++, isdigit (c)))
2474 value = 10 * value + c - '0';
2475 }
2476
2477 if (*s < end)
2478 *s = *s - 1;
2479 *ival = value;
2480 c = XBM_TK_NUMBER;
2481 }
2482 else if (isalpha (c) || c == '_')
2483 {
2484 *sval++ = c;
2485 while (*s < end
2486 && (c = *(*s)++, (isalnum (c) || c == '_')))
2487 *sval++ = c;
2488 *sval = 0;
2489 if (*s < end)
2490 *s = *s - 1;
2491 c = XBM_TK_IDENT;
2492 }
2493 else if (c == '/' && **s == '*')
2494 {
2495 /* C-style comment. */
2496 ++*s;
2497 while (**s && (**s != '*' || *(*s + 1) != '/'))
2498 ++*s;
2499 if (**s)
2500 {
2501 *s += 2;
2502 goto loop;
2503 }
2504 }
2505
2506 return c;
2507}
2508
2509#ifdef HAVE_NTGUI
2510
2511/* Create a Windows bitmap from X bitmap data. */
2512static HBITMAP
2513w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2514{
2515 static unsigned char swap_nibble[16]
2516 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2517 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2518 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2519 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2520 int i, j, w1, w2;
2521 unsigned char *bits, *p;
2522 HBITMAP bmp;
2523
2524 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2525 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2526 bits = (unsigned char *) alloca (height * w2);
72af86bd 2527 memset (bits, 0, height * w2);
4ef0d4d0
KS
2528 for (i = 0; i < height; i++)
2529 {
2530 p = bits + i*w2;
2531 for (j = 0; j < w1; j++)
2532 {
2533 /* Bitswap XBM bytes to match how Windows does things. */
2534 unsigned char c = *data++;
2535 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2536 | (swap_nibble[(c>>4) & 0xf]));
2537 }
2538 }
2539 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2540
2541 return bmp;
2542}
2543
3046a84b 2544static void
7c3320d8
JB
2545convert_mono_to_color_image (struct frame *f, struct image *img,
2546 COLORREF foreground, COLORREF background)
4ef0d4d0
KS
2547{
2548 HDC hdc, old_img_dc, new_img_dc;
2549 HGDIOBJ old_prev, new_prev;
2550 HBITMAP new_pixmap;
2551
2552 hdc = get_frame_dc (f);
2553 old_img_dc = CreateCompatibleDC (hdc);
2554 new_img_dc = CreateCompatibleDC (hdc);
2555 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2556 release_frame_dc (f, hdc);
2557 old_prev = SelectObject (old_img_dc, img->pixmap);
2558 new_prev = SelectObject (new_img_dc, new_pixmap);
44b1dc2e
JR
2559 /* Windows convention for mono bitmaps is black = background,
2560 white = foreground. */
2386b1f1
JR
2561 SetTextColor (new_img_dc, background);
2562 SetBkColor (new_img_dc, foreground);
4ef0d4d0
KS
2563
2564 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2565 0, 0, SRCCOPY);
2566
2567 SelectObject (old_img_dc, old_prev);
2568 SelectObject (new_img_dc, new_prev);
2569 DeleteDC (old_img_dc);
2570 DeleteDC (new_img_dc);
2571 DeleteObject (img->pixmap);
2572 if (new_pixmap == 0)
2573 fprintf (stderr, "Failed to convert image to color.\n");
2574 else
2575 img->pixmap = new_pixmap;
2576}
2577
2578#define XBM_BIT_SHUFFLE(b) (~(b))
2579
2580#else
2581
2582#define XBM_BIT_SHUFFLE(b) (b)
2583
2584#endif /* HAVE_NTGUI */
2585
2586
2587static void
d3da34e0
JB
2588Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
2589 RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg,
2590 int non_default_colors)
4ef0d4d0
KS
2591{
2592#ifdef HAVE_NTGUI
2593 img->pixmap
2594 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2595
2596 /* If colors were specified, transfer the bitmap to a color one. */
2597 if (non_default_colors)
2598 convert_mono_to_color_image (f, img, fg, bg);
edfda783
AR
2599
2600#elif defined (HAVE_NS)
ed3751c8 2601 img->pixmap = ns_image_from_XBM (data, img->width, img->height);
edfda783 2602
4ef0d4d0 2603#else
ca4aa935
PE
2604 img->pixmap =
2605 (x_check_image_size (0, img->width, img->height)
2606 ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
4ef0d4d0
KS
2607 FRAME_X_WINDOW (f),
2608 data,
2609 img->width, img->height,
2610 fg, bg,
ca4aa935
PE
2611 DefaultDepthOfScreen (FRAME_X_SCREEN (f)))
2612 : NO_PIXMAP);
edfda783 2613#endif /* !HAVE_NTGUI && !HAVE_NS */
4ef0d4d0
KS
2614}
2615
2616
2617
2618/* Replacement for XReadBitmapFileData which isn't available under old
2619 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2620 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2621 the image. Return in *DATA the bitmap data allocated with xmalloc.
2622 Value is non-zero if successful. DATA null means just test if
ce959360
CY
2623 CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR
2624 is non-zero, inhibit the call to image_error when the image size is
2625 invalid (the bitmap remains unread). */
4ef0d4d0
KS
2626
2627static int
d3da34e0 2628xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *end,
b8dc29e9 2629 int *width, int *height, char **data,
d3da34e0 2630 int inhibit_image_error)
4ef0d4d0
KS
2631{
2632 unsigned char *s = contents;
2633 char buffer[BUFSIZ];
2634 int padding_p = 0;
2635 int v10 = 0;
ca4aa935 2636 int bytes_per_line, i, nbytes;
b8dc29e9 2637 char *p;
4ef0d4d0
KS
2638 int value;
2639 int LA1;
2640
2641#define match() \
2642 LA1 = xbm_scan (&s, end, buffer, &value)
2643
2644#define expect(TOKEN) \
2645 if (LA1 != (TOKEN)) \
2646 goto failure; \
2647 else \
2648 match ()
2649
2650#define expect_ident(IDENT) \
2651 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2652 match (); \
2653 else \
2654 goto failure
2655
2656 *width = *height = -1;
2657 if (data)
2658 *data = NULL;
2659 LA1 = xbm_scan (&s, end, buffer, &value);
2660
2661 /* Parse defines for width, height and hot-spots. */
2662 while (LA1 == '#')
2663 {
2664 match ();
2665 expect_ident ("define");
2666 expect (XBM_TK_IDENT);
2667
431feaf6 2668 if (LA1 == XBM_TK_NUMBER)
4ef0d4d0 2669 {
6ae141d6
PE
2670 char *q = strrchr (buffer, '_');
2671 q = q ? q + 1 : buffer;
2672 if (strcmp (q, "width") == 0)
4ef0d4d0 2673 *width = value;
6ae141d6 2674 else if (strcmp (q, "height") == 0)
4ef0d4d0
KS
2675 *height = value;
2676 }
2677 expect (XBM_TK_NUMBER);
2678 }
2679
f1f25b99 2680 if (!check_image_size (f, *width, *height))
10ea2b82 2681 {
ce959360
CY
2682 if (!inhibit_image_error)
2683 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
10ea2b82
JR
2684 goto failure;
2685 }
4ef0d4d0
KS
2686 else if (data == NULL)
2687 goto success;
2688
2689 /* Parse bits. Must start with `static'. */
2690 expect_ident ("static");
2691 if (LA1 == XBM_TK_IDENT)
2692 {
2693 if (strcmp (buffer, "unsigned") == 0)
2694 {
2695 match ();
2696 expect_ident ("char");
2697 }
2698 else if (strcmp (buffer, "short") == 0)
2699 {
2700 match ();
2701 v10 = 1;
2702 if (*width % 16 && *width % 16 < 9)
2703 padding_p = 1;
2704 }
2705 else if (strcmp (buffer, "char") == 0)
2706 match ();
2707 else
2708 goto failure;
2709 }
2710 else
2711 goto failure;
2712
2713 expect (XBM_TK_IDENT);
2714 expect ('[');
2715 expect (']');
2716 expect ('=');
2717 expect ('{');
2718
ca4aa935
PE
2719 if (! x_check_image_size (0, *width, *height))
2720 {
2721 if (!inhibit_image_error)
2722 image_error ("Image too large (%dx%d)",
2723 make_number (*width), make_number (*height));
2724 goto failure;
2725 }
4ef0d4d0
KS
2726 bytes_per_line = (*width + 7) / 8 + padding_p;
2727 nbytes = bytes_per_line * *height;
b8dc29e9 2728 p = *data = (char *) xmalloc (nbytes);
4ef0d4d0
KS
2729
2730 if (v10)
2731 {
2732 for (i = 0; i < nbytes; i += 2)
2733 {
2734 int val = value;
2735 expect (XBM_TK_NUMBER);
2736
2737 *p++ = XBM_BIT_SHUFFLE (val);
2738 if (!padding_p || ((i + 2) % bytes_per_line))
2739 *p++ = XBM_BIT_SHUFFLE (value >> 8);
2740
2741 if (LA1 == ',' || LA1 == '}')
2742 match ();
2743 else
2744 goto failure;
2745 }
2746 }
2747 else
2748 {
2749 for (i = 0; i < nbytes; ++i)
2750 {
2751 int val = value;
2752 expect (XBM_TK_NUMBER);
2753
2754 *p++ = XBM_BIT_SHUFFLE (val);
2755
2756 if (LA1 == ',' || LA1 == '}')
2757 match ();
2758 else
2759 goto failure;
2760 }
2761 }
2762
2763 success:
2764 return 1;
2765
2766 failure:
2767
2768 if (data && *data)
2769 {
2770 xfree (*data);
2771 *data = NULL;
2772 }
2773 return 0;
2774
2775#undef match
2776#undef expect
2777#undef expect_ident
2778}
2779
2780
2781/* Load XBM image IMG which will be displayed on frame F from buffer
2782 CONTENTS. END is the end of the buffer. Value is non-zero if
2783 successful. */
2784
2785static int
d3da34e0
JB
2786xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
2787 unsigned char *end)
4ef0d4d0
KS
2788{
2789 int rc;
b8dc29e9 2790 char *data;
4ef0d4d0
KS
2791 int success_p = 0;
2792
ce959360
CY
2793 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
2794 &data, 0);
4ef0d4d0
KS
2795 if (rc)
2796 {
2797 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2798 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2799 int non_default_colors = 0;
2800 Lisp_Object value;
2801
2802 xassert (img->width > 0 && img->height > 0);
2803
2804 /* Get foreground and background colors, maybe allocate colors. */
2805 value = image_spec_value (img->spec, QCforeground, NULL);
2806 if (!NILP (value))
2807 {
2808 foreground = x_alloc_image_color (f, img, value, foreground);
2809 non_default_colors = 1;
2810 }
2811 value = image_spec_value (img->spec, QCbackground, NULL);
2812 if (!NILP (value))
2813 {
2814 background = x_alloc_image_color (f, img, value, background);
2815 img->background = background;
2816 img->background_valid = 1;
2817 non_default_colors = 1;
2818 }
2819
1f026899 2820 Create_Pixmap_From_Bitmap_Data (f, img, data,
4ef0d4d0
KS
2821 foreground, background,
2822 non_default_colors);
2823 xfree (data);
2824
2825 if (img->pixmap == NO_PIXMAP)
2826 {
2827 x_clear_image (f, img);
2828 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
2829 }
2830 else
2831 success_p = 1;
2832 }
2833 else
2834 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2835
2836 return success_p;
2837}
2838
2839
2840/* Value is non-zero if DATA looks like an in-memory XBM file. */
2841
2842static int
d3da34e0 2843xbm_file_p (Lisp_Object data)
4ef0d4d0
KS
2844{
2845 int w, h;
2846 return (STRINGP (data)
f1f25b99 2847 && xbm_read_bitmap_data (NULL, SDATA (data),
ce959360
CY
2848 (SDATA (data) + SBYTES (data)),
2849 &w, &h, NULL, 1));
4ef0d4d0
KS
2850}
2851
2852
2853/* Fill image IMG which is used on frame F with pixmap data. Value is
2854 non-zero if successful. */
2855
2856static int
d3da34e0 2857xbm_load (struct frame *f, struct image *img)
4ef0d4d0
KS
2858{
2859 int success_p = 0;
2860 Lisp_Object file_name;
2861
2862 xassert (xbm_image_p (img->spec));
2863
2864 /* If IMG->spec specifies a file name, create a non-file spec from it. */
2865 file_name = image_spec_value (img->spec, QCfile, NULL);
2866 if (STRINGP (file_name))
2867 {
2868 Lisp_Object file;
2869 unsigned char *contents;
dd52fcea 2870 ptrdiff_t size;
4ef0d4d0
KS
2871
2872 file = x_find_image_file (file_name);
4ef0d4d0
KS
2873 if (!STRINGP (file))
2874 {
2875 image_error ("Cannot find image file `%s'", file_name, Qnil);
4ef0d4d0
KS
2876 return 0;
2877 }
2878
42a5b22f 2879 contents = slurp_file (SSDATA (file), &size);
4ef0d4d0
KS
2880 if (contents == NULL)
2881 {
2882 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
4ef0d4d0
KS
2883 return 0;
2884 }
2885
2886 success_p = xbm_load_image (f, img, contents, contents + size);
d5a19415 2887 xfree (contents);
4ef0d4d0
KS
2888 }
2889 else
2890 {
2891 struct image_keyword fmt[XBM_LAST];
2892 Lisp_Object data;
2893 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2894 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2895 int non_default_colors = 0;
2896 char *bits;
2897 int parsed_p;
2898 int in_memory_file_p = 0;
2899
2900 /* See if data looks like an in-memory XBM file. */
2901 data = image_spec_value (img->spec, QCdata, NULL);
2902 in_memory_file_p = xbm_file_p (data);
2903
2904 /* Parse the image specification. */
72af86bd 2905 memcpy (fmt, xbm_format, sizeof fmt);
4ef0d4d0 2906 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
35fa624f 2907 (void) parsed_p;
4ef0d4d0
KS
2908 xassert (parsed_p);
2909
2910 /* Get specified width, and height. */
2911 if (!in_memory_file_p)
2912 {
2913 img->width = XFASTINT (fmt[XBM_WIDTH].value);
2914 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
2915 xassert (img->width > 0 && img->height > 0);
ca4aa935
PE
2916 if (!check_image_size (f, img->width, img->height))
2917 {
2918 image_error ("Invalid image size (see `max-image-size')",
2919 Qnil, Qnil);
2920 return 0;
2921 }
4ef0d4d0
KS
2922 }
2923
2924 /* Get foreground and background colors, maybe allocate colors. */
2925 if (fmt[XBM_FOREGROUND].count
2926 && STRINGP (fmt[XBM_FOREGROUND].value))
2927 {
2928 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
2929 foreground);
2930 non_default_colors = 1;
2931 }
2932
2933 if (fmt[XBM_BACKGROUND].count
2934 && STRINGP (fmt[XBM_BACKGROUND].value))
2935 {
2936 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
2937 background);
2938 non_default_colors = 1;
2939 }
2940
2941 if (in_memory_file_p)
2942 success_p = xbm_load_image (f, img, SDATA (data),
2943 (SDATA (data)
2944 + SBYTES (data)));
2945 else
2946 {
2947 if (VECTORP (data))
2948 {
2949 int i;
2950 char *p;
2951 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
2952
2953 p = bits = (char *) alloca (nbytes * img->height);
2954 for (i = 0; i < img->height; ++i, p += nbytes)
2955 {
2956 Lisp_Object line = XVECTOR (data)->contents[i];
2957 if (STRINGP (line))
72af86bd 2958 memcpy (p, SDATA (line), nbytes);
4ef0d4d0 2959 else
72af86bd 2960 memcpy (p, XBOOL_VECTOR (line)->data, nbytes);
4ef0d4d0
KS
2961 }
2962 }
2963 else if (STRINGP (data))
42a5b22f 2964 bits = SSDATA (data);
4ef0d4d0 2965 else
b8dc29e9 2966 bits = (char *) XBOOL_VECTOR (data)->data;
4ef0d4d0 2967
44b1dc2e
JR
2968#ifdef WINDOWSNT
2969 {
2970 char *invertedBits;
2971 int nbytes, i;
2972 /* Windows mono bitmaps are reversed compared with X. */
2973 invertedBits = bits;
285d07e2 2974 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
44b1dc2e 2975 * img->height;
ed3751c8 2976 bits = (char *) alloca (nbytes);
44b1dc2e
JR
2977 for (i = 0; i < nbytes; i++)
2978 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
2979 }
2980#endif
4ef0d4d0
KS
2981 /* Create the pixmap. */
2982
ca4aa935
PE
2983 if (x_check_image_size (0, img->width, img->height))
2984 Create_Pixmap_From_Bitmap_Data (f, img, bits,
2985 foreground, background,
2986 non_default_colors);
2987 else
2988 img->pixmap = NO_PIXMAP;
2989
4ef0d4d0
KS
2990 if (img->pixmap)
2991 success_p = 1;
2992 else
2993 {
2994 image_error ("Unable to create pixmap for XBM image `%s'",
2995 img->spec, Qnil);
2996 x_clear_image (f, img);
2997 }
2998 }
2999 }
3000
3001 return success_p;
3002}
3003
3004
3005\f
3006/***********************************************************************
3007 XPM images
3008 ***********************************************************************/
3009
9e2a2647 3010#if defined (HAVE_XPM) || defined (HAVE_NS)
4ef0d4d0 3011
f57e2426
J
3012static int xpm_image_p (Lisp_Object object);
3013static int xpm_load (struct frame *f, struct image *img);
3014static int xpm_valid_color_symbols_p (Lisp_Object);
4ef0d4d0 3015
9e2a2647 3016#endif /* HAVE_XPM || HAVE_NS */
ea1aaa6f
ST
3017
3018#ifdef HAVE_XPM
4ef0d4d0
KS
3019#ifdef HAVE_NTGUI
3020/* Indicate to xpm.h that we don't have Xlib. */
3021#define FOR_MSW
3022/* simx.h in xpm defines XColor and XImage differently than Emacs. */
279d3293 3023/* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
4ef0d4d0
KS
3024#define XColor xpm_XColor
3025#define XImage xpm_XImage
279d3293 3026#define Display xpm_Display
4ef0d4d0
KS
3027#define PIXEL_ALREADY_TYPEDEFED
3028#include "X11/xpm.h"
3029#undef FOR_MSW
3030#undef XColor
3031#undef XImage
279d3293 3032#undef Display
4ef0d4d0
KS
3033#undef PIXEL_ALREADY_TYPEDEFED
3034#else
3035#include "X11/xpm.h"
3036#endif /* HAVE_NTGUI */
ea1aaa6f 3037#endif /* HAVE_XPM */
4ef0d4d0 3038
9e2a2647 3039#if defined (HAVE_XPM) || defined (HAVE_NS)
4ef0d4d0
KS
3040/* The symbol `xpm' identifying XPM-format images. */
3041
955cbe7b 3042static Lisp_Object Qxpm;
4ef0d4d0
KS
3043
3044/* Indices of image specification fields in xpm_format, below. */
3045
3046enum xpm_keyword_index
3047{
3048 XPM_TYPE,
3049 XPM_FILE,
3050 XPM_DATA,
3051 XPM_ASCENT,
3052 XPM_MARGIN,
3053 XPM_RELIEF,
3054 XPM_ALGORITHM,
3055 XPM_HEURISTIC_MASK,
3056 XPM_MASK,
3057 XPM_COLOR_SYMBOLS,
3058 XPM_BACKGROUND,
3059 XPM_LAST
3060};
3061
3062/* Vector of image_keyword structures describing the format
3063 of valid XPM image specifications. */
3064
91433552 3065static const struct image_keyword xpm_format[XPM_LAST] =
4ef0d4d0
KS
3066{
3067 {":type", IMAGE_SYMBOL_VALUE, 1},
3068 {":file", IMAGE_STRING_VALUE, 0},
3069 {":data", IMAGE_STRING_VALUE, 0},
3070 {":ascent", IMAGE_ASCENT_VALUE, 0},
3071 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3072 {":relief", IMAGE_INTEGER_VALUE, 0},
3073 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3074 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3075 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3076 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3077 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3078};
3079
3080/* Structure describing the image type XPM. */
3081
3082static struct image_type xpm_type =
3083{
3084 &Qxpm,
3085 xpm_image_p,
3086 xpm_load,
3087 x_clear_image,
3088 NULL
3089};
3090
3091#ifdef HAVE_X_WINDOWS
3092
3093/* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3094 functions for allocating image colors. Our own functions handle
3095 color allocation failures more gracefully than the ones on the XPM
3096 lib. */
3097
3098#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3099#define ALLOC_XPM_COLORS
3100#endif
3101#endif /* HAVE_X_WINDOWS */
3102
3103#ifdef ALLOC_XPM_COLORS
3104
f57e2426
J
3105static void xpm_init_color_cache (struct frame *, XpmAttributes *);
3106static void xpm_free_color_cache (void);
3107static int xpm_lookup_color (struct frame *, char *, XColor *);
3108static int xpm_color_bucket (char *);
3109static struct xpm_cached_color *xpm_cache_color (struct frame *, char *,
3110 XColor *, int);
4ef0d4d0
KS
3111
3112/* An entry in a hash table used to cache color definitions of named
3113 colors. This cache is necessary to speed up XPM image loading in
3114 case we do color allocations ourselves. Without it, we would need
3115 a call to XParseColor per pixel in the image. */
3116
3117struct xpm_cached_color
3118{
3119 /* Next in collision chain. */
3120 struct xpm_cached_color *next;
3121
3122 /* Color definition (RGB and pixel color). */
3123 XColor color;
3124
3125 /* Color name. */
3126 char name[1];
3127};
3128
3129/* The hash table used for the color cache, and its bucket vector
3130 size. */
3131
3132#define XPM_COLOR_CACHE_BUCKETS 1001
cd44d2eb 3133static struct xpm_cached_color **xpm_color_cache;
4ef0d4d0
KS
3134
3135/* Initialize the color cache. */
3136
3137static void
d3da34e0 3138xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
4ef0d4d0
KS
3139{
3140 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3141 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3142 memset (xpm_color_cache, 0, nbytes);
3143 init_color_table ();
3144
3145 if (attrs->valuemask & XpmColorSymbols)
3146 {
3147 int i;
3148 XColor color;
3149
3150 for (i = 0; i < attrs->numsymbols; ++i)
3151 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3152 attrs->colorsymbols[i].value, &color))
3153 {
3154 color.pixel = lookup_rgb_color (f, color.red, color.green,
3155 color.blue);
3156 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3157 }
3158 }
3159}
3160
3161/* Free the color cache. */
3162
3163static void
d3da34e0 3164xpm_free_color_cache (void)
4ef0d4d0
KS
3165{
3166 struct xpm_cached_color *p, *next;
3167 int i;
3168
3169 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3170 for (p = xpm_color_cache[i]; p; p = next)
3171 {
3172 next = p->next;
3173 xfree (p);
3174 }
3175
3176 xfree (xpm_color_cache);
3177 xpm_color_cache = NULL;
3178 free_color_table ();
3179}
3180
3181/* Return the bucket index for color named COLOR_NAME in the color
3182 cache. */
3183
3184static int
d3da34e0 3185xpm_color_bucket (char *color_name)
4ef0d4d0 3186{
3f791afe
PE
3187 EMACS_UINT hash = hash_string (color_name, strlen (color_name));
3188 return hash % XPM_COLOR_CACHE_BUCKETS;
4ef0d4d0
KS
3189}
3190
3191
3192/* On frame F, cache values COLOR for color with name COLOR_NAME.
3193 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3194 entry added. */
3195
3196static struct xpm_cached_color *
d3da34e0 3197xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
4ef0d4d0
KS
3198{
3199 size_t nbytes;
3200 struct xpm_cached_color *p;
3201
3202 if (bucket < 0)
3203 bucket = xpm_color_bucket (color_name);
3204
3f791afe 3205 nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1;
4ef0d4d0
KS
3206 p = (struct xpm_cached_color *) xmalloc (nbytes);
3207 strcpy (p->name, color_name);
3208 p->color = *color;
3209 p->next = xpm_color_cache[bucket];
3210 xpm_color_cache[bucket] = p;
3211 return p;
3212}
3213
3214/* Look up color COLOR_NAME for frame F in the color cache. If found,
3215 return the cached definition in *COLOR. Otherwise, make a new
3216 entry in the cache and allocate the color. Value is zero if color
3217 allocation failed. */
3218
3219static int
d3da34e0 3220xpm_lookup_color (struct frame *f, char *color_name, XColor *color)
4ef0d4d0
KS
3221{
3222 struct xpm_cached_color *p;
3223 int h = xpm_color_bucket (color_name);
3224
3225 for (p = xpm_color_cache[h]; p; p = p->next)
3226 if (strcmp (p->name, color_name) == 0)
3227 break;
3228
3229 if (p != NULL)
3230 *color = p->color;
3231 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3232 color_name, color))
3233 {
3234 color->pixel = lookup_rgb_color (f, color->red, color->green,
3235 color->blue);
3236 p = xpm_cache_color (f, color_name, color, h);
3237 }
3238 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3239 with transparency, and it's useful. */
3240 else if (strcmp ("opaque", color_name) == 0)
3241 {
72af86bd 3242 memset (color, 0, sizeof (XColor)); /* Is this necessary/correct? */
4ef0d4d0
KS
3243 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3244 p = xpm_cache_color (f, color_name, color, h);
3245 }
3246
3247 return p != NULL;
3248}
3249
3250
3251/* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3252 CLOSURE is a pointer to the frame on which we allocate the
3253 color. Return in *COLOR the allocated color. Value is non-zero
3254 if successful. */
3255
3256static int
d3da34e0
JB
3257xpm_alloc_color (Display *dpy, Colormap cmap, char *color_name, XColor *color,
3258 void *closure)
4ef0d4d0
KS
3259{
3260 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3261}
3262
3263
3264/* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3265 is a pointer to the frame on which we allocate the color. Value is
3266 non-zero if successful. */
3267
3268static int
d3da34e0 3269xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *closure)
4ef0d4d0
KS
3270{
3271 return 1;
3272}
3273
3274#endif /* ALLOC_XPM_COLORS */
3275
3276
3277#ifdef HAVE_NTGUI
3278
3279/* XPM library details. */
3280
14beddf4
CY
3281DEF_IMGLIB_FN (void, XpmFreeAttributes, (XpmAttributes *));
3282DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer, (Display *, char *, xpm_XImage **,
850690cc 3283 xpm_XImage **, XpmAttributes *));
14beddf4 3284DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
850690cc 3285 xpm_XImage **, XpmAttributes *));
14beddf4 3286DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
4ef0d4d0 3287
4ef0d4d0 3288static int
0855eb52 3289init_xpm_functions (Lisp_Object libraries)
4ef0d4d0
KS
3290{
3291 HMODULE library;
3292
0855eb52 3293 if (!(library = w32_delayed_load (libraries, Qxpm)))
4ef0d4d0
KS
3294 return 0;
3295
3296 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3297 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3298 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3299 LOAD_IMGLIB_FN (library, XImageFree);
3300 return 1;
3301}
3302
3303#endif /* HAVE_NTGUI */
3304
3305
3306/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3307 for XPM images. Such a list must consist of conses whose car and
3308 cdr are strings. */
3309
3310static int
d3da34e0 3311xpm_valid_color_symbols_p (Lisp_Object color_symbols)
4ef0d4d0
KS
3312{
3313 while (CONSP (color_symbols))
3314 {
3315 Lisp_Object sym = XCAR (color_symbols);
3316 if (!CONSP (sym)
3317 || !STRINGP (XCAR (sym))
3318 || !STRINGP (XCDR (sym)))
3319 break;
3320 color_symbols = XCDR (color_symbols);
3321 }
3322
3323 return NILP (color_symbols);
3324}
3325
3326
3327/* Value is non-zero if OBJECT is a valid XPM image specification. */
3328
3329static int
d3da34e0 3330xpm_image_p (Lisp_Object object)
4ef0d4d0
KS
3331{
3332 struct image_keyword fmt[XPM_LAST];
72af86bd 3333 memcpy (fmt, xpm_format, sizeof fmt);
4ef0d4d0
KS
3334 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3335 /* Either `:file' or `:data' must be present. */
3336 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3337 /* Either no `:color-symbols' or it's a list of conses
3338 whose car and cdr are strings. */
3339 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3340 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3341}
3342
9e2a2647 3343#endif /* HAVE_XPM || HAVE_NS */
4ef0d4d0 3344
cd44d2eb 3345#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
0766b489 3346ptrdiff_t
ef1b0ba7 3347x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
786a43d6
CY
3348{
3349 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0766b489
PE
3350 ptrdiff_t id;
3351 int rc;
786a43d6
CY
3352 XpmAttributes attrs;
3353 Pixmap bitmap, mask;
3354
72af86bd 3355 memset (&attrs, 0, sizeof attrs);
786a43d6 3356
54188d8f
CY
3357 attrs.visual = FRAME_X_VISUAL (f);
3358 attrs.colormap = FRAME_X_COLORMAP (f);
3359 attrs.valuemask |= XpmVisual;
3360 attrs.valuemask |= XpmColormap;
3361
786a43d6 3362 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f77fabaf 3363 (char **) bits, &bitmap, &mask, &attrs);
786a43d6 3364 if (rc != XpmSuccess)
fe45ad15
CY
3365 {
3366 XpmFreeAttributes (&attrs);
3367 return -1;
3368 }
786a43d6
CY
3369
3370 id = x_allocate_bitmap_record (f);
786a43d6
CY
3371 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3372 dpyinfo->bitmaps[id - 1].have_mask = 1;
3373 dpyinfo->bitmaps[id - 1].mask = mask;
3374 dpyinfo->bitmaps[id - 1].file = NULL;
3375 dpyinfo->bitmaps[id - 1].height = attrs.height;
3376 dpyinfo->bitmaps[id - 1].width = attrs.width;
3377 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3378 dpyinfo->bitmaps[id - 1].refcount = 1;
3379
3380 XpmFreeAttributes (&attrs);
3381 return id;
3382}
0d876a14 3383#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
786a43d6 3384
4ef0d4d0
KS
3385/* Load image IMG which will be displayed on frame F. Value is
3386 non-zero if successful. */
3387
ea1aaa6f
ST
3388#ifdef HAVE_XPM
3389
4ef0d4d0 3390static int
d3da34e0 3391xpm_load (struct frame *f, struct image *img)
4ef0d4d0
KS
3392{
3393 int rc;
3394 XpmAttributes attrs;
3395 Lisp_Object specified_file, color_symbols;
3396#ifdef HAVE_NTGUI
3397 HDC hdc;
3398 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3399#endif /* HAVE_NTGUI */
3400
3401 /* Configure the XPM lib. Use the visual of frame F. Allocate
3402 close colors. Return colors allocated. */
72af86bd 3403 memset (&attrs, 0, sizeof attrs);
4ef0d4d0
KS
3404
3405#ifndef HAVE_NTGUI
3406 attrs.visual = FRAME_X_VISUAL (f);
3407 attrs.colormap = FRAME_X_COLORMAP (f);
3408 attrs.valuemask |= XpmVisual;
3409 attrs.valuemask |= XpmColormap;
3410#endif /* HAVE_NTGUI */
3411
3412#ifdef ALLOC_XPM_COLORS
3413 /* Allocate colors with our own functions which handle
3414 failing color allocation more gracefully. */
3415 attrs.color_closure = f;
3416 attrs.alloc_color = xpm_alloc_color;
3417 attrs.free_colors = xpm_free_colors;
3418 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3419#else /* not ALLOC_XPM_COLORS */
3420 /* Let the XPM lib allocate colors. */
3421 attrs.valuemask |= XpmReturnAllocPixels;
3422#ifdef XpmAllocCloseColors
3423 attrs.alloc_close_colors = 1;
3424 attrs.valuemask |= XpmAllocCloseColors;
3425#else /* not XpmAllocCloseColors */
3426 attrs.closeness = 600;
3427 attrs.valuemask |= XpmCloseness;
3428#endif /* not XpmAllocCloseColors */
3429#endif /* ALLOC_XPM_COLORS */
3430
3431 /* If image specification contains symbolic color definitions, add
3432 these to `attrs'. */
3433 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3434 if (CONSP (color_symbols))
3435 {
3436 Lisp_Object tail;
3437 XpmColorSymbol *xpm_syms;
3438 int i, size;
3439
3440 attrs.valuemask |= XpmColorSymbols;
3441
3442 /* Count number of symbols. */
3443 attrs.numsymbols = 0;
3444 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3445 ++attrs.numsymbols;
3446
3447 /* Allocate an XpmColorSymbol array. */
3448 size = attrs.numsymbols * sizeof *xpm_syms;
3449 xpm_syms = (XpmColorSymbol *) alloca (size);
72af86bd 3450 memset (xpm_syms, 0, size);
4ef0d4d0
KS
3451 attrs.colorsymbols = xpm_syms;
3452
3453 /* Fill the color symbol array. */
3454 for (tail = color_symbols, i = 0;
3455 CONSP (tail);
3456 ++i, tail = XCDR (tail))
3457 {
7574650a
AS
3458 Lisp_Object name;
3459 Lisp_Object color;
e22cffbc 3460 char *empty_string = (char *) "";
7574650a
AS
3461
3462 if (!CONSP (XCAR (tail)))
3463 {
e22cffbc
PE
3464 xpm_syms[i].name = empty_string;
3465 xpm_syms[i].value = empty_string;
7574650a
AS
3466 continue;
3467 }
3468 name = XCAR (XCAR (tail));
3469 color = XCDR (XCAR (tail));
3470 if (STRINGP (name))
3471 {
3472 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
42a5b22f 3473 strcpy (xpm_syms[i].name, SSDATA (name));
7574650a
AS
3474 }
3475 else
e22cffbc 3476 xpm_syms[i].name = empty_string;
7574650a
AS
3477 if (STRINGP (color))
3478 {
3479 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
42a5b22f 3480 strcpy (xpm_syms[i].value, SSDATA (color));
7574650a
AS
3481 }
3482 else
e22cffbc 3483 xpm_syms[i].value = empty_string;
4ef0d4d0
KS
3484 }
3485 }
3486
3487 /* Create a pixmap for the image, either from a file, or from a
3488 string buffer containing data in the same format as an XPM file. */
3489#ifdef ALLOC_XPM_COLORS
3490 xpm_init_color_cache (f, &attrs);
3491#endif
3492
3493 specified_file = image_spec_value (img->spec, QCfile, NULL);
3494
3495#ifdef HAVE_NTGUI
3496 {
3497 HDC frame_dc = get_frame_dc (f);
3498 hdc = CreateCompatibleDC (frame_dc);
3499 release_frame_dc (f, frame_dc);
3500 }
3501#endif /* HAVE_NTGUI */
3502
3503 if (STRINGP (specified_file))
3504 {
3505 Lisp_Object file = x_find_image_file (specified_file);
3506 if (!STRINGP (file))
3507 {
3508 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7574650a
AS
3509#ifdef ALLOC_XPM_COLORS
3510 xpm_free_color_cache ();
3511#endif
4ef0d4d0
KS
3512 return 0;
3513 }
3514
3515#ifdef HAVE_NTGUI
3516 /* XpmReadFileToPixmap is not available in the Windows port of
3517 libxpm. But XpmReadFileToImage almost does what we want. */
3518 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3519 &xpm_image, &xpm_mask,
3520 &attrs);
3521#else
3522 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
42a5b22f 3523 SSDATA (file), &img->pixmap, &img->mask,
4ef0d4d0
KS
3524 &attrs);
3525#endif /* HAVE_NTGUI */
3526 }
3527 else
3528 {
3529 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
3530 if (!STRINGP (buffer))
3531 {
3532 image_error ("Invalid image data `%s'", buffer, Qnil);
3533#ifdef ALLOC_XPM_COLORS
3534 xpm_free_color_cache ();
3535#endif
3536 return 0;
3537 }
4ef0d4d0
KS
3538#ifdef HAVE_NTGUI
3539 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3540 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3541 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3542 &xpm_image, &xpm_mask,
3543 &attrs);
3544#else
3545 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
42a5b22f 3546 SSDATA (buffer),
4ef0d4d0
KS
3547 &img->pixmap, &img->mask,
3548 &attrs);
3549#endif /* HAVE_NTGUI */
3550 }
3551
3552 if (rc == XpmSuccess)
3553 {
3554#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3555 img->colors = colors_in_color_table (&img->ncolors);
3556#else /* not ALLOC_XPM_COLORS */
3557 int i;
3558
3559#ifdef HAVE_NTGUI
3560 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3561 plus some duplicate attributes. */
3562 if (xpm_image && xpm_image->bitmap)
3563 {
3564 img->pixmap = xpm_image->bitmap;
3565 /* XImageFree in libXpm frees XImage struct without destroying
3566 the bitmap, which is what we want. */
3567 fn_XImageFree (xpm_image);
3568 }
3569 if (xpm_mask && xpm_mask->bitmap)
3570 {
3571 /* The mask appears to be inverted compared with what we expect.
3572 TODO: invert our expectations. See other places where we
3573 have to invert bits because our idea of masks is backwards. */
3574 HGDIOBJ old_obj;
3575 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3576
3577 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3578 SelectObject (hdc, old_obj);
3579
3580 img->mask = xpm_mask->bitmap;
3581 fn_XImageFree (xpm_mask);
3582 DeleteDC (hdc);
3583 }
3584
3585 DeleteDC (hdc);
3586#endif /* HAVE_NTGUI */
3587
3588 /* Remember allocated colors. */
0065d054 3589 img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors);
ddff3151 3590 img->ncolors = attrs.nalloc_pixels;
4ef0d4d0
KS
3591 for (i = 0; i < attrs.nalloc_pixels; ++i)
3592 {
3593 img->colors[i] = attrs.alloc_pixels[i];
3594#ifdef DEBUG_X_COLORS
3595 register_color (img->colors[i]);
3596#endif
3597 }
3598#endif /* not ALLOC_XPM_COLORS */
3599
3600 img->width = attrs.width;
3601 img->height = attrs.height;
3602 xassert (img->width > 0 && img->height > 0);
3603
3604 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3605#ifdef HAVE_NTGUI
3606 fn_XpmFreeAttributes (&attrs);
3607#else
3608 XpmFreeAttributes (&attrs);
3609#endif /* HAVE_NTGUI */
3610 }
3611 else
3612 {
3613#ifdef HAVE_NTGUI
3614 DeleteDC (hdc);
3615#endif /* HAVE_NTGUI */
3616
3617 switch (rc)
3618 {
3619 case XpmOpenFailed:
3620 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3621 break;
3622
3623 case XpmFileInvalid:
3624 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3625 break;
3626
3627 case XpmNoMemory:
3628 image_error ("Out of memory (%s)", img->spec, Qnil);
3629 break;
3630
3631 case XpmColorFailed:
3632 image_error ("Color allocation error (%s)", img->spec, Qnil);
3633 break;
3634
3635 default:
3636 image_error ("Unknown error (%s)", img->spec, Qnil);
3637 break;
3638 }
3639 }
3640
3641#ifdef ALLOC_XPM_COLORS
3642 xpm_free_color_cache ();
3643#endif
3644 return rc == XpmSuccess;
3645}
3646
3647#endif /* HAVE_XPM */
3648
9e2a2647 3649#if defined (HAVE_NS) && !defined (HAVE_XPM)
ea1aaa6f 3650
9e2a2647 3651/* XPM support functions for NS where libxpm is not available.
ea1aaa6f
ST
3652 Only XPM version 3 (without any extensions) is supported. */
3653
f57e2426
J
3654static void xpm_put_color_table_v (Lisp_Object, const unsigned char *,
3655 int, Lisp_Object);
3656static Lisp_Object xpm_get_color_table_v (Lisp_Object,
3657 const unsigned char *, int);
f57e2426
J
3658static void xpm_put_color_table_h (Lisp_Object, const unsigned char *,
3659 int, Lisp_Object);
3660static Lisp_Object xpm_get_color_table_h (Lisp_Object,
3661 const unsigned char *, int);
ea1aaa6f
ST
3662
3663/* Tokens returned from xpm_scan. */
3664
3665enum xpm_token
3666{
3667 XPM_TK_IDENT = 256,
3668 XPM_TK_STRING,
3669 XPM_TK_EOF
3670};
3671
3672/* Scan an XPM data and return a character (< 256) or a token defined
3673 by enum xpm_token above. *S and END are the start (inclusive) and
3674 the end (exclusive) addresses of the data, respectively. Advance
3675 *S while scanning. If token is either XPM_TK_IDENT or
3676 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3677 length of the corresponding token, respectively. */
3678
3679static int
3d608a86
J
3680xpm_scan (const unsigned char **s,
3681 const unsigned char *end,
3682 const unsigned char **beg,
74ca2eb3 3683 ptrdiff_t *len)
ea1aaa6f
ST
3684{
3685 int c;
3686
3687 while (*s < end)
3688 {
3689 /* Skip white-space. */
3690 while (*s < end && (c = *(*s)++, isspace (c)))
9ecf6403 3691 ;
ea1aaa6f
ST
3692
3693 /* gnus-pointer.xpm uses '-' in its identifier.
9ecf6403 3694 sb-dir-plus.xpm uses '+' in its identifier. */
ea1aaa6f 3695 if (isalpha (c) || c == '_' || c == '-' || c == '+')
9ecf6403
YM
3696 {
3697 *beg = *s - 1;
2ff0845e
YM
3698 while (*s < end
3699 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
9ecf6403
YM
3700 ++*s;
3701 *len = *s - *beg;
3702 return XPM_TK_IDENT;
3703 }
ea1aaa6f 3704 else if (c == '"')
9ecf6403
YM
3705 {
3706 *beg = *s;
3707 while (*s < end && **s != '"')
3708 ++*s;
3709 *len = *s - *beg;
3710 if (*s < end)
3711 ++*s;
3712 return XPM_TK_STRING;
3713 }
ea1aaa6f 3714 else if (c == '/')
9ecf6403
YM
3715 {
3716 if (*s < end && **s == '*')
3717 {
3718 /* C-style comment. */
3719 ++*s;
3720 do
3721 {
3722 while (*s < end && *(*s)++ != '*')
3723 ;
3724 }
3725 while (*s < end && **s != '/');
3726 if (*s < end)
3727 ++*s;
3728 }
3729 else
3730 return c;
3731 }
ea1aaa6f 3732 else
9ecf6403 3733 return c;
ea1aaa6f
ST
3734 }
3735
3736 return XPM_TK_EOF;
3737}
3738
bbe6f2aa 3739/* Functions for color table lookup in XPM data. A key is a string
ea1aaa6f
ST
3740 specifying the color of each pixel in XPM data. A value is either
3741 an integer that specifies a pixel color, Qt that specifies
3742 transparency, or Qnil for the unspecified color. If the length of
3743 the key string is one, a vector is used as a table. Otherwise, a
3744 hash table is used. */
3745
3746static Lisp_Object
3d608a86
J
3747xpm_make_color_table_v (void (**put_func) (Lisp_Object,
3748 const unsigned char *,
3749 int,
3750 Lisp_Object),
3751 Lisp_Object (**get_func) (Lisp_Object,
3752 const unsigned char *,
3753 int))
ea1aaa6f
ST
3754{
3755 *put_func = xpm_put_color_table_v;
3756 *get_func = xpm_get_color_table_v;
3757 return Fmake_vector (make_number (256), Qnil);
3758}
3759
3760static void
3d608a86
J
3761xpm_put_color_table_v (Lisp_Object color_table,
3762 const unsigned char *chars_start,
3763 int chars_len,
3764 Lisp_Object color)
ea1aaa6f
ST
3765{
3766 XVECTOR (color_table)->contents[*chars_start] = color;
3767}
3768
3769static Lisp_Object
3d608a86
J
3770xpm_get_color_table_v (Lisp_Object color_table,
3771 const unsigned char *chars_start,
3772 int chars_len)
ea1aaa6f
ST
3773{
3774 return XVECTOR (color_table)->contents[*chars_start];
3775}
3776
3777static Lisp_Object
3d608a86
J
3778xpm_make_color_table_h (void (**put_func) (Lisp_Object,
3779 const unsigned char *,
3780 int,
3781 Lisp_Object),
3782 Lisp_Object (**get_func) (Lisp_Object,
3783 const unsigned char *,
3784 int))
ea1aaa6f
ST
3785{
3786 *put_func = xpm_put_color_table_h;
3787 *get_func = xpm_get_color_table_h;
3788 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
9ecf6403
YM
3789 make_float (DEFAULT_REHASH_SIZE),
3790 make_float (DEFAULT_REHASH_THRESHOLD),
3791 Qnil, Qnil, Qnil);
ea1aaa6f
ST
3792}
3793
3794static void
3d608a86
J
3795xpm_put_color_table_h (Lisp_Object color_table,
3796 const unsigned char *chars_start,
3797 int chars_len,
3798 Lisp_Object color)
ea1aaa6f
ST
3799{
3800 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
0de4bb68 3801 EMACS_UINT hash_code;
ea1aaa6f
ST
3802 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3803
3804 hash_lookup (table, chars, &hash_code);
3805 hash_put (table, chars, color, hash_code);
3806}
3807
3808static Lisp_Object
3d608a86
J
3809xpm_get_color_table_h (Lisp_Object color_table,
3810 const unsigned char *chars_start,
3811 int chars_len)
ea1aaa6f
ST
3812{
3813 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
d3411f89
PE
3814 ptrdiff_t i =
3815 hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
ea1aaa6f
ST
3816
3817 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3818}
3819
3820enum xpm_color_key {
3821 XPM_COLOR_KEY_S,
3822 XPM_COLOR_KEY_M,
3823 XPM_COLOR_KEY_G4,
3824 XPM_COLOR_KEY_G,
3825 XPM_COLOR_KEY_C
3826};
3827
46accb8f 3828static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
ea1aaa6f
ST
3829
3830static int
3d608a86 3831xpm_str_to_color_key (const char *s)
ea1aaa6f
ST
3832{
3833 int i;
3834
3835 for (i = 0;
3836 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3837 i++)
3838 if (strcmp (xpm_color_key_strings[i], s) == 0)
3839 return i;
3840 return -1;
3841}
3842
3843static int
3d608a86
J
3844xpm_load_image (struct frame *f,
3845 struct image *img,
3846 const unsigned char *contents,
3847 const unsigned char *end)
ea1aaa6f 3848{
46accb8f 3849 const unsigned char *s = contents, *beg, *str;
ea1aaa6f
ST
3850 unsigned char buffer[BUFSIZ];
3851 int width, height, x, y;
3852 int num_colors, chars_per_pixel;
74ca2eb3
PE
3853 ptrdiff_t len;
3854 int LA1;
46accb8f
YM
3855 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3856 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
ea1aaa6f
ST
3857 Lisp_Object frame, color_symbols, color_table;
3858 int best_key, have_mask = 0;
3859 XImagePtr ximg = NULL, mask_img = NULL;
3860
3861#define match() \
3862 LA1 = xpm_scan (&s, end, &beg, &len)
3863
9ecf6403
YM
3864#define expect(TOKEN) \
3865 if (LA1 != (TOKEN)) \
3866 goto failure; \
3867 else \
ea1aaa6f
ST
3868 match ()
3869
9ecf6403 3870#define expect_ident(IDENT) \
ea1aaa6f 3871 if (LA1 == XPM_TK_IDENT \
9ecf6403
YM
3872 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
3873 match (); \
3874 else \
ea1aaa6f
ST
3875 goto failure
3876
3877 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
3878 goto failure;
3879 s += 9;
ed3751c8 3880 match ();
ea1aaa6f
ST
3881 expect_ident ("static");
3882 expect_ident ("char");
3883 expect ('*');
3884 expect (XPM_TK_IDENT);
3885 expect ('[');
3886 expect (']');
3887 expect ('=');
3888 expect ('{');
3889 expect (XPM_TK_STRING);
3890 if (len >= BUFSIZ)
3891 goto failure;
3892 memcpy (buffer, beg, len);
3893 buffer[len] = '\0';
3894 if (sscanf (buffer, "%d %d %d %d", &width, &height,
9ecf6403 3895 &num_colors, &chars_per_pixel) != 4
ea1aaa6f
ST
3896 || width <= 0 || height <= 0
3897 || num_colors <= 0 || chars_per_pixel <= 0)
3898 goto failure;
de297941
YM
3899
3900 if (!check_image_size (f, width, height))
3901 {
10ea2b82 3902 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
de297941
YM
3903 goto failure;
3904 }
3905
ca4aa935
PE
3906 if (!x_create_x_image_and_pixmap (f, width, height, 0,
3907 &ximg, &img->pixmap)
3908#ifndef HAVE_NS
3909 || !x_create_x_image_and_pixmap (f, width, height, 1,
3910 &mask_img, &img->mask)
3911#endif
3912 )
3913 {
3914 image_error ("Image too large", Qnil, Qnil);
3915 goto failure;
3916 }
3917
ea1aaa6f
ST
3918 expect (',');
3919
3920 XSETFRAME (frame, f);
3921 if (!NILP (Fxw_display_color_p (frame)))
3922 best_key = XPM_COLOR_KEY_C;
3923 else if (!NILP (Fx_display_grayscale_p (frame)))
3924 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
9ecf6403 3925 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
ea1aaa6f
ST
3926 else
3927 best_key = XPM_COLOR_KEY_M;
3928
3929 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3930 if (chars_per_pixel == 1)
3931 color_table = xpm_make_color_table_v (&put_color_table,
9ecf6403 3932 &get_color_table);
ea1aaa6f
ST
3933 else
3934 color_table = xpm_make_color_table_h (&put_color_table,
9ecf6403 3935 &get_color_table);
ea1aaa6f
ST
3936
3937 while (num_colors-- > 0)
3938 {
25a48bd0 3939 char *color, *max_color;
ea1aaa6f
ST
3940 int key, next_key, max_key = 0;
3941 Lisp_Object symbol_color = Qnil, color_val;
3942 XColor cdef;
3943
3944 expect (XPM_TK_STRING);
3945 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
9ecf6403 3946 goto failure;
ea1aaa6f
ST
3947 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
3948 buffer[len - chars_per_pixel] = '\0';
3949
3950 str = strtok (buffer, " \t");
3951 if (str == NULL)
9ecf6403 3952 goto failure;
ea1aaa6f
ST
3953 key = xpm_str_to_color_key (str);
3954 if (key < 0)
9ecf6403 3955 goto failure;
ea1aaa6f 3956 do
9ecf6403
YM
3957 {
3958 color = strtok (NULL, " \t");
3959 if (color == NULL)
3960 goto failure;
ea1aaa6f 3961
9db94f82 3962 while ((str = strtok (NULL, " \t")) != NULL)
9ecf6403
YM
3963 {
3964 next_key = xpm_str_to_color_key (str);
3965 if (next_key >= 0)
3966 break;
3967 color[strlen (color)] = ' ';
3968 }
ea1aaa6f 3969
9ecf6403
YM
3970 if (key == XPM_COLOR_KEY_S)
3971 {
3972 if (NILP (symbol_color))
3973 symbol_color = build_string (color);
3974 }
3975 else if (max_key < key && key <= best_key)
3976 {
3977 max_key = key;
3978 max_color = color;
3979 }
3980 key = next_key;
3981 }
ea1aaa6f
ST
3982 while (str);
3983
3984 color_val = Qnil;
3985 if (!NILP (color_symbols) && !NILP (symbol_color))
9ecf6403
YM
3986 {
3987 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
3988
3989 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
9db94f82 3990 {
25a48bd0 3991 if (xstrcasecmp (SSDATA (XCDR (specified_color)), "None") == 0)
9db94f82
YM
3992 color_val = Qt;
3993 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
3994 &cdef, 0))
3995 color_val = make_number (cdef.pixel);
3996 }
9ecf6403 3997 }
ea1aaa6f 3998 if (NILP (color_val) && max_key > 0)
9db94f82 3999 {
05131107 4000 if (xstrcasecmp (max_color, "None") == 0)
9db94f82
YM
4001 color_val = Qt;
4002 else if (x_defined_color (f, max_color, &cdef, 0))
4003 color_val = make_number (cdef.pixel);
4004 }
ea1aaa6f 4005 if (!NILP (color_val))
9ecf6403 4006 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
ea1aaa6f
ST
4007
4008 expect (',');
4009 }
4010
ea1aaa6f
ST
4011 for (y = 0; y < height; y++)
4012 {
4013 expect (XPM_TK_STRING);
4014 str = beg;
4015 if (len < width * chars_per_pixel)
9ecf6403 4016 goto failure;
ea1aaa6f 4017 for (x = 0; x < width; x++, str += chars_per_pixel)
9ecf6403
YM
4018 {
4019 Lisp_Object color_val =
4020 (*get_color_table) (color_table, str, chars_per_pixel);
4021
4022 XPutPixel (ximg, x, y,
4023 (INTEGERP (color_val) ? XINT (color_val)
4024 : FRAME_FOREGROUND_PIXEL (f)));
edfda783 4025#ifndef HAVE_NS
9ecf6403
YM
4026 XPutPixel (mask_img, x, y,
4027 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4028 : (have_mask = 1, PIX_MASK_RETAIN)));
edfda783 4029#else
ed3751c8
JB
4030 if (EQ (color_val, Qt))
4031 ns_set_alpha (ximg, x, y, 0);
edfda783 4032#endif
9ecf6403 4033 }
ea1aaa6f 4034 if (y + 1 < height)
9ecf6403 4035 expect (',');
ea1aaa6f
ST
4036 }
4037
4038 img->width = width;
4039 img->height = height;
4040
0b8ac842
YM
4041 /* Maybe fill in the background field while we have ximg handy. */
4042 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4043 IMAGE_BACKGROUND (img, f, ximg);
4044
ea1aaa6f
ST
4045 x_put_x_image (f, ximg, img->pixmap, width, height);
4046 x_destroy_x_image (ximg);
edfda783 4047#ifndef HAVE_NS
ea1aaa6f
ST
4048 if (have_mask)
4049 {
9ecf6403
YM
4050 /* Fill in the background_transparent field while we have the
4051 mask handy. */
4052 image_background_transparent (img, f, mask_img);
4053
ea1aaa6f
ST
4054 x_put_x_image (f, mask_img, img->mask, width, height);
4055 x_destroy_x_image (mask_img);
4056 }
4057 else
4058 {
4059 x_destroy_x_image (mask_img);
4060 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4061 img->mask = NO_PIXMAP;
4062 }
edfda783 4063#endif
ea1aaa6f
ST
4064 return 1;
4065
4066 failure:
4067 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4068 error:
4069 x_destroy_x_image (ximg);
4070 x_destroy_x_image (mask_img);
4071 x_clear_image (f, img);
4072 return 0;
4073
4074#undef match
4075#undef expect
4076#undef expect_ident
4077}
4078
4079static int
3d608a86
J
4080xpm_load (struct frame *f,
4081 struct image *img)
ea1aaa6f
ST
4082{
4083 int success_p = 0;
4084 Lisp_Object file_name;
4085
4086 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4087 file_name = image_spec_value (img->spec, QCfile, NULL);
4088 if (STRINGP (file_name))
4089 {
4090 Lisp_Object file;
4091 unsigned char *contents;
dd52fcea 4092 ptrdiff_t size;
ea1aaa6f
ST
4093
4094 file = x_find_image_file (file_name);
ea1aaa6f 4095 if (!STRINGP (file))
9ecf6403
YM
4096 {
4097 image_error ("Cannot find image file `%s'", file_name, Qnil);
9ecf6403
YM
4098 return 0;
4099 }
ea1aaa6f
ST
4100
4101 contents = slurp_file (SDATA (file), &size);
4102 if (contents == NULL)
9ecf6403
YM
4103 {
4104 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
9ecf6403
YM
4105 return 0;
4106 }
ea1aaa6f
ST
4107
4108 success_p = xpm_load_image (f, img, contents, contents + size);
4109 xfree (contents);
ea1aaa6f
ST
4110 }
4111 else
4112 {
4113 Lisp_Object data;
4114
4115 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
4116 if (!STRINGP (data))
4117 {
4118 image_error ("Invalid image data `%s'", data, Qnil);
4119 return 0;
4120 }
ea1aaa6f 4121 success_p = xpm_load_image (f, img, SDATA (data),
9ecf6403 4122 SDATA (data) + SBYTES (data));
ea1aaa6f
ST
4123 }
4124
4125 return success_p;
4126}
4127
9e2a2647 4128#endif /* HAVE_NS && !HAVE_XPM */
b0da69a7 4129
ea1aaa6f 4130
4ef0d4d0
KS
4131\f
4132/***********************************************************************
4133 Color table
4134 ***********************************************************************/
4135
4136#ifdef COLOR_TABLE_SUPPORT
4137
4138/* An entry in the color table mapping an RGB color to a pixel color. */
4139
4140struct ct_color
4141{
4142 int r, g, b;
4143 unsigned long pixel;
4144
4145 /* Next in color table collision list. */
4146 struct ct_color *next;
4147};
4148
4149/* The bucket vector size to use. Must be prime. */
4150
4151#define CT_SIZE 101
4152
4153/* Value is a hash of the RGB color given by R, G, and B. */
4154
4155#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4156
4157/* The color hash table. */
4158
cd44d2eb 4159static struct ct_color **ct_table;
4ef0d4d0
KS
4160
4161/* Number of entries in the color table. */
4162
cd44d2eb 4163static int ct_colors_allocated;
ddff3151
PE
4164enum
4165{
4166 ct_colors_allocated_max =
4167 min (INT_MAX,
4168 min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long))
4169};
4ef0d4d0
KS
4170
4171/* Initialize the color table. */
4172
4173static void
d3da34e0 4174init_color_table (void)
4ef0d4d0
KS
4175{
4176 int size = CT_SIZE * sizeof (*ct_table);
4177 ct_table = (struct ct_color **) xmalloc (size);
72af86bd 4178 memset (ct_table, 0, size);
4ef0d4d0
KS
4179 ct_colors_allocated = 0;
4180}
4181
4182
4183/* Free memory associated with the color table. */
4184
4185static void
d3da34e0 4186free_color_table (void)
4ef0d4d0
KS
4187{
4188 int i;
4189 struct ct_color *p, *next;
4190
4191 for (i = 0; i < CT_SIZE; ++i)
4192 for (p = ct_table[i]; p; p = next)
4193 {
4194 next = p->next;
4195 xfree (p);
4196 }
4197
4198 xfree (ct_table);
4199 ct_table = NULL;
4200}
4201
4202
4203/* Value is a pixel color for RGB color R, G, B on frame F. If an
4204 entry for that color already is in the color table, return the
4205 pixel color of that entry. Otherwise, allocate a new color for R,
4206 G, B, and make an entry in the color table. */
4207
4208static unsigned long
d3da34e0 4209lookup_rgb_color (struct frame *f, int r, int g, int b)
4ef0d4d0
KS
4210{
4211 unsigned hash = CT_HASH_RGB (r, g, b);
4212 int i = hash % CT_SIZE;
4213 struct ct_color *p;
4214 Display_Info *dpyinfo;
4215
4216 /* Handle TrueColor visuals specially, which improves performance by
4217 two orders of magnitude. Freeing colors on TrueColor visuals is
4218 a nop, and pixel colors specify RGB values directly. See also
4219 the Xlib spec, chapter 3.1. */
4220 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4221 if (dpyinfo->red_bits > 0)
4222 {
4223 unsigned long pr, pg, pb;
4224
4225 /* Apply gamma-correction like normal color allocation does. */
4226 if (f->gamma)
4227 {
4228 XColor color;
4229 color.red = r, color.green = g, color.blue = b;
4230 gamma_correct (f, &color);
4231 r = color.red, g = color.green, b = color.blue;
4232 }
4233
4234 /* Scale down RGB values to the visual's bits per RGB, and shift
4235 them to the right position in the pixel color. Note that the
4236 original RGB values are 16-bit values, as usual in X. */
4237 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4238 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4239 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4240
4241 /* Assemble the pixel color. */
4242 return pr | pg | pb;
4243 }
1f026899 4244
4ef0d4d0
KS
4245 for (p = ct_table[i]; p; p = p->next)
4246 if (p->r == r && p->g == g && p->b == b)
4247 break;
4248
4249 if (p == NULL)
4250 {
4251
4252#ifdef HAVE_X_WINDOWS
4253 XColor color;
4254 Colormap cmap;
4255 int rc;
ddff3151
PE
4256#else
4257 COLORREF color;
4258#endif
4ef0d4d0 4259
ddff3151
PE
4260 if (ct_colors_allocated_max <= ct_colors_allocated)
4261 return FRAME_FOREGROUND_PIXEL (f);
4262
4263#ifdef HAVE_X_WINDOWS
4ef0d4d0
KS
4264 color.red = r;
4265 color.green = g;
4266 color.blue = b;
4267
4268 cmap = FRAME_X_COLORMAP (f);
4269 rc = x_alloc_nearest_color (f, cmap, &color);
4270 if (rc)
4271 {
4272 ++ct_colors_allocated;
4273 p = (struct ct_color *) xmalloc (sizeof *p);
4274 p->r = r;
4275 p->g = g;
4276 p->b = b;
4277 p->pixel = color.pixel;
4278 p->next = ct_table[i];
4279 ct_table[i] = p;
4280 }
4281 else
4282 return FRAME_FOREGROUND_PIXEL (f);
4283
4284#else
4ef0d4d0
KS
4285#ifdef HAVE_NTGUI
4286 color = PALETTERGB (r, g, b);
4287#else
4288 color = RGB_TO_ULONG (r, g, b);
4289#endif /* HAVE_NTGUI */
4290 ++ct_colors_allocated;
4291 p = (struct ct_color *) xmalloc (sizeof *p);
4292 p->r = r;
4293 p->g = g;
4294 p->b = b;
4295 p->pixel = color;
4296 p->next = ct_table[i];
4297 ct_table[i] = p;
4298#endif /* HAVE_X_WINDOWS */
4299
4300 }
4301
4302 return p->pixel;
4303}
4304
4305
4306/* Look up pixel color PIXEL which is used on frame F in the color
4307 table. If not already present, allocate it. Value is PIXEL. */
4308
4309static unsigned long
d3da34e0 4310lookup_pixel_color (struct frame *f, unsigned long pixel)
4ef0d4d0
KS
4311{
4312 int i = pixel % CT_SIZE;
4313 struct ct_color *p;
4314
4315 for (p = ct_table[i]; p; p = p->next)
4316 if (p->pixel == pixel)
4317 break;
4318
4319 if (p == NULL)
4320 {
4321 XColor color;
4322 Colormap cmap;
4323 int rc;
4324
ddff3151
PE
4325 if (ct_colors_allocated_max <= ct_colors_allocated)
4326 return FRAME_FOREGROUND_PIXEL (f);
4327
4ef0d4d0
KS
4328#ifdef HAVE_X_WINDOWS
4329 cmap = FRAME_X_COLORMAP (f);
4330 color.pixel = pixel;
4331 x_query_color (f, &color);
4332 rc = x_alloc_nearest_color (f, cmap, &color);
4333#else
4334 BLOCK_INPUT;
4335 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4336 color.pixel = pixel;
4337 XQueryColor (NULL, cmap, &color);
4338 rc = x_alloc_nearest_color (f, cmap, &color);
4339 UNBLOCK_INPUT;
4340#endif /* HAVE_X_WINDOWS */
4341
4342 if (rc)
4343 {
4344 ++ct_colors_allocated;
4345
4346 p = (struct ct_color *) xmalloc (sizeof *p);
4347 p->r = color.red;
4348 p->g = color.green;
4349 p->b = color.blue;
4350 p->pixel = pixel;
4351 p->next = ct_table[i];
4352 ct_table[i] = p;
4353 }
4354 else
4355 return FRAME_FOREGROUND_PIXEL (f);
4356 }
4357 return p->pixel;
4358}
4359
4360
4361/* Value is a vector of all pixel colors contained in the color table,
4362 allocated via xmalloc. Set *N to the number of colors. */
4363
4364static unsigned long *
d3da34e0 4365colors_in_color_table (int *n)
4ef0d4d0
KS
4366{
4367 int i, j;
4368 struct ct_color *p;
4369 unsigned long *colors;
4370
4371 if (ct_colors_allocated == 0)
4372 {
4373 *n = 0;
4374 colors = NULL;
4375 }
4376 else
4377 {
4378 colors = (unsigned long *) xmalloc (ct_colors_allocated
4379 * sizeof *colors);
4380 *n = ct_colors_allocated;
4381
4382 for (i = j = 0; i < CT_SIZE; ++i)
4383 for (p = ct_table[i]; p; p = p->next)
4384 colors[j++] = p->pixel;
4385 }
4386
4387 return colors;
4388}
4389
4390#else /* COLOR_TABLE_SUPPORT */
4391
4392static unsigned long
7c3320d8 4393lookup_rgb_color (struct frame *f, int r, int g, int b)
4ef0d4d0
KS
4394{
4395 unsigned long pixel;
4396
4ef0d4d0
KS
4397#ifdef HAVE_NTGUI
4398 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4399#endif /* HAVE_NTGUI */
4400
edfda783
AR
4401#ifdef HAVE_NS
4402 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4403#endif /* HAVE_NS */
4ef0d4d0
KS
4404 return pixel;
4405}
4406
4407static void
7c3320d8 4408init_color_table (void)
4ef0d4d0
KS
4409{
4410}
4411#endif /* COLOR_TABLE_SUPPORT */
4412
4413\f
4414/***********************************************************************
4415 Algorithms
4416 ***********************************************************************/
4417
f57e2426
J
4418static XColor *x_to_xcolors (struct frame *, struct image *, int);
4419static void x_from_xcolors (struct frame *, struct image *, XColor *);
4420static void x_detect_edges (struct frame *, struct image *, int[9], int);
4ef0d4d0
KS
4421
4422#ifdef HAVE_NTGUI
4423static void XPutPixel (XImagePtr , int, int, COLORREF);
4424#endif /* HAVE_NTGUI */
4425
4ef0d4d0
KS
4426/* Edge detection matrices for different edge-detection
4427 strategies. */
4428
4429static int emboss_matrix[9] = {
4430 /* x - 1 x x + 1 */
4431 2, -1, 0, /* y - 1 */
4432 -1, 0, 1, /* y */
4433 0, 1, -2 /* y + 1 */
4434};
4435
4436static int laplace_matrix[9] = {
4437 /* x - 1 x x + 1 */
4438 1, 0, 0, /* y - 1 */
4439 0, 0, 0, /* y */
4440 0, 0, -1 /* y + 1 */
4441};
4442
4443/* Value is the intensity of the color whose red/green/blue values
4444 are R, G, and B. */
4445
4446#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4447
4448
4449/* On frame F, return an array of XColor structures describing image
4450 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4451 non-zero means also fill the red/green/blue members of the XColor
4452 structures. Value is a pointer to the array of XColors structures,
4453 allocated with xmalloc; it must be freed by the caller. */
4454
4455static XColor *
d3da34e0 4456x_to_xcolors (struct frame *f, struct image *img, int rgb_p)
4ef0d4d0
KS
4457{
4458 int x, y;
4459 XColor *colors, *p;
4460 XImagePtr_or_DC ximg;
4461#ifdef HAVE_NTGUI
4462 HDC hdc;
4463 HGDIOBJ prev;
4464#endif /* HAVE_NTGUI */
4465
ddff3151
PE
4466 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
4467 memory_full (SIZE_MAX);
4468 colors = (XColor *) xmalloc (sizeof *colors * img->width * img->height);
4ef0d4d0
KS
4469
4470#ifndef HAVE_NTGUI
4471 /* Get the X image IMG->pixmap. */
4472 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4473 0, 0, img->width, img->height, ~0, ZPixmap);
4474#else
4475 /* Load the image into a memory device context. */
4476 hdc = get_frame_dc (f);
4477 ximg = CreateCompatibleDC (hdc);
4478 release_frame_dc (f, hdc);
4479 prev = SelectObject (ximg, img->pixmap);
4480#endif /* HAVE_NTGUI */
4481
4482 /* Fill the `pixel' members of the XColor array. I wished there
4483 were an easy and portable way to circumvent XGetPixel. */
4484 p = colors;
4485 for (y = 0; y < img->height; ++y)
4486 {
4487 XColor *row = p;
4488
8b7d0a16 4489#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4ef0d4d0 4490 for (x = 0; x < img->width; ++x, ++p)
8b7d0a16 4491 p->pixel = GET_PIXEL (ximg, x, y);
4ef0d4d0
KS
4492 if (rgb_p)
4493 x_query_colors (f, row, img->width);
4494
4495#else
4496
4497 for (x = 0; x < img->width; ++x, ++p)
4498 {
4499 /* W32_TODO: palette support needed here? */
4500 p->pixel = GET_PIXEL (ximg, x, y);
4501 if (rgb_p)
4502 {
4ef0d4d0
KS
4503 p->red = RED16_FROM_ULONG (p->pixel);
4504 p->green = GREEN16_FROM_ULONG (p->pixel);
4505 p->blue = BLUE16_FROM_ULONG (p->pixel);
4ef0d4d0
KS
4506 }
4507 }
4508#endif /* HAVE_X_WINDOWS */
4509 }
4510
4511 Destroy_Image (ximg, prev);
4512
4513 return colors;
4514}
4515
4516#ifdef HAVE_NTGUI
4517
4518/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4519 created with CreateDIBSection, with the pointer to the bit values
4520 stored in ximg->data. */
4521
3046a84b 4522static void
7c3320d8 4523XPutPixel (XImagePtr ximg, int x, int y, COLORREF color)
4ef0d4d0
KS
4524{
4525 int width = ximg->info.bmiHeader.biWidth;
4ef0d4d0
KS
4526 unsigned char * pixel;
4527
4528 /* True color images. */
4529 if (ximg->info.bmiHeader.biBitCount == 24)
4530 {
4531 int rowbytes = width * 3;
4532 /* Ensure scanlines are aligned on 4 byte boundaries. */
4533 if (rowbytes % 4)
4534 rowbytes += 4 - (rowbytes % 4);
4535
4536 pixel = ximg->data + y * rowbytes + x * 3;
4537 /* Windows bitmaps are in BGR order. */
4538 *pixel = GetBValue (color);
4539 *(pixel + 1) = GetGValue (color);
4540 *(pixel + 2) = GetRValue (color);
4541 }
4542 /* Monochrome images. */
4543 else if (ximg->info.bmiHeader.biBitCount == 1)
4544 {
4545 int rowbytes = width / 8;
4546 /* Ensure scanlines are aligned on 4 byte boundaries. */
4547 if (rowbytes % 4)
4548 rowbytes += 4 - (rowbytes % 4);
4549 pixel = ximg->data + y * rowbytes + x / 8;
4550 /* Filter out palette info. */
4551 if (color & 0x00ffffff)
4552 *pixel = *pixel | (1 << x % 8);
4553 else
4554 *pixel = *pixel & ~(1 << x % 8);
4555 }
4556 else
4557 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4558}
4559
4560#endif /* HAVE_NTGUI */
4561
4562/* Create IMG->pixmap from an array COLORS of XColor structures, whose
4563 RGB members are set. F is the frame on which this all happens.
4564 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4565
4566static void
d3da34e0 4567x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4ef0d4d0
KS
4568{
4569 int x, y;
edfda783 4570 XImagePtr oimg = NULL;
9d7112ed 4571 Pixmap pixmap;
4ef0d4d0
KS
4572 XColor *p;
4573
4574 init_color_table ();
4575
4576 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4577 &oimg, &pixmap);
4578 p = colors;
4579 for (y = 0; y < img->height; ++y)
4580 for (x = 0; x < img->width; ++x, ++p)
4581 {
4582 unsigned long pixel;
4583 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4584 XPutPixel (oimg, x, y, pixel);
4585 }
4586
4587 xfree (colors);
4588 x_clear_image_1 (f, img, 1, 0, 1);
4589
4590 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4591 x_destroy_x_image (oimg);
4592 img->pixmap = pixmap;
4593#ifdef COLOR_TABLE_SUPPORT
4594 img->colors = colors_in_color_table (&img->ncolors);
4595 free_color_table ();
4596#endif /* COLOR_TABLE_SUPPORT */
4597}
4598
4599
4600/* On frame F, perform edge-detection on image IMG.
4601
4602 MATRIX is a nine-element array specifying the transformation
4603 matrix. See emboss_matrix for an example.
4604
4605 COLOR_ADJUST is a color adjustment added to each pixel of the
4606 outgoing image. */
4607
4608static void
d3da34e0 4609x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjust)
4ef0d4d0
KS
4610{
4611 XColor *colors = x_to_xcolors (f, img, 1);
4612 XColor *new, *p;
4613 int x, y, i, sum;
4614
4615 for (i = sum = 0; i < 9; ++i)
1ea40aa2 4616 sum += eabs (matrix[i]);
4ef0d4d0
KS
4617
4618#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4619
ddff3151
PE
4620 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
4621 memory_full (SIZE_MAX);
4622 new = (XColor *) xmalloc (sizeof *new * img->width * img->height);
4ef0d4d0
KS
4623
4624 for (y = 0; y < img->height; ++y)
4625 {
4626 p = COLOR (new, 0, y);
4627 p->red = p->green = p->blue = 0xffff/2;
4628 p = COLOR (new, img->width - 1, y);
4629 p->red = p->green = p->blue = 0xffff/2;
4630 }
4631
4632 for (x = 1; x < img->width - 1; ++x)
4633 {
4634 p = COLOR (new, x, 0);
4635 p->red = p->green = p->blue = 0xffff/2;
4636 p = COLOR (new, x, img->height - 1);
4637 p->red = p->green = p->blue = 0xffff/2;
4638 }
4639
4640 for (y = 1; y < img->height - 1; ++y)
4641 {
4642 p = COLOR (new, 1, y);
4643
4644 for (x = 1; x < img->width - 1; ++x, ++p)
4645 {
6ae141d6 4646 int r, g, b, yy, xx;
4ef0d4d0
KS
4647
4648 r = g = b = i = 0;
6ae141d6
PE
4649 for (yy = y - 1; yy < y + 2; ++yy)
4650 for (xx = x - 1; xx < x + 2; ++xx, ++i)
4ef0d4d0
KS
4651 if (matrix[i])
4652 {
6ae141d6 4653 XColor *t = COLOR (colors, xx, yy);
4ef0d4d0
KS
4654 r += matrix[i] * t->red;
4655 g += matrix[i] * t->green;
4656 b += matrix[i] * t->blue;
4657 }
4658
4659 r = (r / sum + color_adjust) & 0xffff;
4660 g = (g / sum + color_adjust) & 0xffff;
4661 b = (b / sum + color_adjust) & 0xffff;
4662 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4663 }
4664 }
4665
4666 xfree (colors);
4667 x_from_xcolors (f, img, new);
4668
4669#undef COLOR
4670}
4671
4672
4673/* Perform the pre-defined `emboss' edge-detection on image IMG
4674 on frame F. */
4675
4676static void
d3da34e0 4677x_emboss (struct frame *f, struct image *img)
4ef0d4d0
KS
4678{
4679 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4680}
4681
4682
4683/* Transform image IMG which is used on frame F with a Laplace
4684 edge-detection algorithm. The result is an image that can be used
4685 to draw disabled buttons, for example. */
4686
4687static void
d3da34e0 4688x_laplace (struct frame *f, struct image *img)
4ef0d4d0
KS
4689{
4690 x_detect_edges (f, img, laplace_matrix, 45000);
4691}
4692
4693
4694/* Perform edge-detection on image IMG on frame F, with specified
4695 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4696
4697 MATRIX must be either
4698
4699 - a list of at least 9 numbers in row-major form
4700 - a vector of at least 9 numbers
4701
4702 COLOR_ADJUST nil means use a default; otherwise it must be a
4703 number. */
4704
4705static void
d3da34e0
JB
4706x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix,
4707 Lisp_Object color_adjust)
4ef0d4d0
KS
4708{
4709 int i = 0;
4710 int trans[9];
4711
4712 if (CONSP (matrix))
4713 {
4714 for (i = 0;
4715 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
4716 ++i, matrix = XCDR (matrix))
4717 trans[i] = XFLOATINT (XCAR (matrix));
4718 }
4719 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
4720 {
4721 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
4722 trans[i] = XFLOATINT (AREF (matrix, i));
4723 }
4724
4725 if (NILP (color_adjust))
4726 color_adjust = make_number (0xffff / 2);
4727
4728 if (i == 9 && NUMBERP (color_adjust))
77a765fd 4729 x_detect_edges (f, img, trans, XFLOATINT (color_adjust));
4ef0d4d0
KS
4730}
4731
4732
4733/* Transform image IMG on frame F so that it looks disabled. */
4734
4735static void
d3da34e0 4736x_disable_image (struct frame *f, struct image *img)
4ef0d4d0
KS
4737{
4738 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4739#ifdef HAVE_NTGUI
4740 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
4741#else
4742 int n_planes = dpyinfo->n_planes;
4743#endif /* HAVE_NTGUI */
4744
4745 if (n_planes >= 2)
4746 {
4747 /* Color (or grayscale). Convert to gray, and equalize. Just
4748 drawing such images with a stipple can look very odd, so
4749 we're using this method instead. */
4750 XColor *colors = x_to_xcolors (f, img, 1);
4751 XColor *p, *end;
4752 const int h = 15000;
4753 const int l = 30000;
4754
4755 for (p = colors, end = colors + img->width * img->height;
4756 p < end;
4757 ++p)
4758 {
4759 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
4760 int i2 = (0xffff - h - l) * i / 0xffff + l;
4761 p->red = p->green = p->blue = i2;
4762 }
4763
4764 x_from_xcolors (f, img, colors);
4765 }
4766
4767 /* Draw a cross over the disabled image, if we must or if we
4768 should. */
4769 if (n_planes < 2 || cross_disabled_images)
4770 {
4771#ifndef HAVE_NTGUI
4772 Display *dpy = FRAME_X_DISPLAY (f);
4773 GC gc;
4774
5afa3a81 4775#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
edfda783 4776
4ef0d4d0 4777#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4ef0d4d0 4778
ae8279db 4779 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4ef0d4d0
KS
4780 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4781 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4782 img->width - 1, img->height - 1);
4783 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
4784 img->width - 1, 0);
4785 XFreeGC (dpy, gc);
4786
4787 if (img->mask)
4788 {
ae8279db 4789 gc = XCreateGC (dpy, img->mask, 0, NULL);
4ef0d4d0
KS
4790 XSetForeground (dpy, gc, MaskForeground (f));
4791 XDrawLine (dpy, img->mask, gc, 0, 0,
4792 img->width - 1, img->height - 1);
4793 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
4794 img->width - 1, 0);
4795 XFreeGC (dpy, gc);
4796 }
edfda783 4797#endif /* !HAVE_NS */
4ef0d4d0
KS
4798#else
4799 HDC hdc, bmpdc;
4800 HGDIOBJ prev;
4801
4802 hdc = get_frame_dc (f);
4803 bmpdc = CreateCompatibleDC (hdc);
4804 release_frame_dc (f, hdc);
4805
4806 prev = SelectObject (bmpdc, img->pixmap);
4807
4808 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
4809 MoveToEx (bmpdc, 0, 0, NULL);
4810 LineTo (bmpdc, img->width - 1, img->height - 1);
4811 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4812 LineTo (bmpdc, img->width - 1, 0);
4813
4814 if (img->mask)
4815 {
4816 SelectObject (bmpdc, img->mask);
4817 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
4818 MoveToEx (bmpdc, 0, 0, NULL);
4819 LineTo (bmpdc, img->width - 1, img->height - 1);
4820 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4821 LineTo (bmpdc, img->width - 1, 0);
4822 }
4823 SelectObject (bmpdc, prev);
4824 DeleteDC (bmpdc);
4825#endif /* HAVE_NTGUI */
4826 }
4827}
4828
4829
4830/* Build a mask for image IMG which is used on frame F. FILE is the
4831 name of an image file, for error messages. HOW determines how to
4832 determine the background color of IMG. If it is a list '(R G B)',
4833 with R, G, and B being integers >= 0, take that as the color of the
4834 background. Otherwise, determine the background color of IMG
4835 heuristically. Value is non-zero if successful. */
4836
4837static int
d3da34e0 4838x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4ef0d4d0
KS
4839{
4840 XImagePtr_or_DC ximg;
4841#ifndef HAVE_NTGUI
4842 XImagePtr mask_img;
4843#else
4844 HDC frame_dc;
4845 HGDIOBJ prev;
4846 char *mask_img;
4847 int row_width;
4848#endif /* HAVE_NTGUI */
4849 int x, y, rc, use_img_background;
4850 unsigned long bg = 0;
4851
4852 if (img->mask)
4853 {
4854 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4855 img->mask = NO_PIXMAP;
4856 img->background_transparent_valid = 0;
4857 }
4858
4859#ifndef HAVE_NTGUI
edfda783 4860#ifndef HAVE_NS
4ef0d4d0
KS
4861 /* Create an image and pixmap serving as mask. */
4862 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
4863 &mask_img, &img->mask);
4864 if (!rc)
4865 return 0;
edfda783 4866#endif /* !HAVE_NS */
4ef0d4d0
KS
4867
4868 /* Get the X image of IMG->pixmap. */
4869 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4870 img->width, img->height,
4871 ~0, ZPixmap);
4872#else
4873 /* Create the bit array serving as mask. */
4874 row_width = (img->width + 7) / 8;
4875 mask_img = xmalloc (row_width * img->height);
72af86bd 4876 memset (mask_img, 0, row_width * img->height);
4ef0d4d0
KS
4877
4878 /* Create a memory device context for IMG->pixmap. */
4879 frame_dc = get_frame_dc (f);
4880 ximg = CreateCompatibleDC (frame_dc);
4881 release_frame_dc (f, frame_dc);
4882 prev = SelectObject (ximg, img->pixmap);
4883#endif /* HAVE_NTGUI */
4884
4885 /* Determine the background color of ximg. If HOW is `(R G B)'
4886 take that as color. Otherwise, use the image's background color. */
4887 use_img_background = 1;
4888
4889 if (CONSP (how))
4890 {
4891 int rgb[3], i;
4892
4893 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
4894 {
4895 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
4896 how = XCDR (how);
4897 }
4898
4899 if (i == 3 && NILP (how))
4900 {
4901 char color_name[30];
4902 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
4903 bg = (
4904#ifdef HAVE_NTGUI
4905 0x00ffffff & /* Filter out palette info. */
4906#endif /* HAVE_NTGUI */
4907 x_alloc_image_color (f, img, build_string (color_name), 0));
4908 use_img_background = 0;
4909 }
4910 }
4911
4912 if (use_img_background)
6ac3c7bb 4913 bg = four_corners_best (ximg, img->corners, img->width, img->height);
4ef0d4d0
KS
4914
4915 /* Set all bits in mask_img to 1 whose color in ximg is different
4916 from the background color bg. */
4917#ifndef HAVE_NTGUI
4918 for (y = 0; y < img->height; ++y)
4919 for (x = 0; x < img->width; ++x)
edfda783 4920#ifndef HAVE_NS
4ef0d4d0 4921 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
9ecf6403 4922 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
edfda783
AR
4923#else
4924 if (XGetPixel (ximg, x, y) == bg)
ed3751c8 4925 ns_set_alpha (ximg, x, y, 0);
edfda783
AR
4926#endif /* HAVE_NS */
4927#ifndef HAVE_NS
4ef0d4d0
KS
4928 /* Fill in the background_transparent field while we have the mask handy. */
4929 image_background_transparent (img, f, mask_img);
4930
4931 /* Put mask_img into img->mask. */
4932 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
4933 x_destroy_x_image (mask_img);
edfda783 4934#endif /* !HAVE_NS */
4ef0d4d0
KS
4935#else
4936 for (y = 0; y < img->height; ++y)
4937 for (x = 0; x < img->width; ++x)
4938 {
4939 COLORREF p = GetPixel (ximg, x, y);
4940 if (p != bg)
4941 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
4942 }
4943
4944 /* Create the mask image. */
4945 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
4946 mask_img);
4947 /* Fill in the background_transparent field while we have the mask handy. */
4948 SelectObject (ximg, img->mask);
4949 image_background_transparent (img, f, ximg);
4950
4951 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4952 xfree (mask_img);
4953#endif /* HAVE_NTGUI */
4954
4955 Destroy_Image (ximg, prev);
4956
4957 return 1;
4958}
4959
4960\f
4961/***********************************************************************
4962 PBM (mono, gray, color)
4963 ***********************************************************************/
4964
f57e2426
J
4965static int pbm_image_p (Lisp_Object object);
4966static int pbm_load (struct frame *f, struct image *img);
4967static int pbm_scan_number (unsigned char **, unsigned char *);
4ef0d4d0
KS
4968
4969/* The symbol `pbm' identifying images of this type. */
4970
955cbe7b 4971static Lisp_Object Qpbm;
4ef0d4d0
KS
4972
4973/* Indices of image specification fields in gs_format, below. */
4974
4975enum pbm_keyword_index
4976{
4977 PBM_TYPE,
4978 PBM_FILE,
4979 PBM_DATA,
4980 PBM_ASCENT,
4981 PBM_MARGIN,
4982 PBM_RELIEF,
4983 PBM_ALGORITHM,
4984 PBM_HEURISTIC_MASK,
4985 PBM_MASK,
4986 PBM_FOREGROUND,
4987 PBM_BACKGROUND,
4988 PBM_LAST
4989};
4990
4991/* Vector of image_keyword structures describing the format
4992 of valid user-defined image specifications. */
4993
91433552 4994static const struct image_keyword pbm_format[PBM_LAST] =
4ef0d4d0
KS
4995{
4996 {":type", IMAGE_SYMBOL_VALUE, 1},
4997 {":file", IMAGE_STRING_VALUE, 0},
4998 {":data", IMAGE_STRING_VALUE, 0},
4999 {":ascent", IMAGE_ASCENT_VALUE, 0},
5000 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5001 {":relief", IMAGE_INTEGER_VALUE, 0},
5002 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5003 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5004 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5005 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5006 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5007};
5008
5009/* Structure describing the image type `pbm'. */
5010
5011static struct image_type pbm_type =
5012{
5013 &Qpbm,
5014 pbm_image_p,
5015 pbm_load,
5016 x_clear_image,
5017 NULL
5018};
5019
5020
5021/* Return non-zero if OBJECT is a valid PBM image specification. */
5022
5023static int
d3da34e0 5024pbm_image_p (Lisp_Object object)
4ef0d4d0
KS
5025{
5026 struct image_keyword fmt[PBM_LAST];
5027
72af86bd 5028 memcpy (fmt, pbm_format, sizeof fmt);
4ef0d4d0
KS
5029
5030 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5031 return 0;
5032
5033 /* Must specify either :data or :file. */
5034 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5035}
5036
5037
5038/* Scan a decimal number from *S and return it. Advance *S while
5039 reading the number. END is the end of the string. Value is -1 at
5040 end of input. */
5041
5042static int
d3da34e0 5043pbm_scan_number (unsigned char **s, unsigned char *end)
4ef0d4d0
KS
5044{
5045 int c = 0, val = -1;
5046
5047 while (*s < end)
5048 {
5049 /* Skip white-space. */
5050 while (*s < end && (c = *(*s)++, isspace (c)))
5051 ;
5052
5053 if (c == '#')
5054 {
5055 /* Skip comment to end of line. */
5056 while (*s < end && (c = *(*s)++, c != '\n'))
5057 ;
5058 }
5059 else if (isdigit (c))
5060 {
5061 /* Read decimal number. */
5062 val = c - '0';
5063 while (*s < end && (c = *(*s)++, isdigit (c)))
5064 val = 10 * val + c - '0';
5065 break;
5066 }
5067 else
5068 break;
5069 }
5070
5071 return val;
5072}
5073
5074
5075#ifdef HAVE_NTGUI
5076#if 0 /* Unused. ++kfs */
5077
5078/* Read FILE into memory. Value is a pointer to a buffer allocated
5079 with xmalloc holding FILE's contents. Value is null if an error
5080 occurred. *SIZE is set to the size of the file. */
5081
5082static char *
1dae0f0a 5083pbm_read_file (Lisp_Object file, int *size)
4ef0d4d0
KS
5084{
5085 FILE *fp = NULL;
5086 char *buf = NULL;
5087 struct stat st;
5088
5089 if (stat (SDATA (file), &st) == 0
5090 && (fp = fopen (SDATA (file), "rb")) != NULL
dd52fcea 5091 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
4ef0d4d0
KS
5092 && (buf = (char *) xmalloc (st.st_size),
5093 fread (buf, 1, st.st_size, fp) == st.st_size))
5094 {
5095 *size = st.st_size;
5096 fclose (fp);
5097 }
5098 else
5099 {
5100 if (fp)
5101 fclose (fp);
5102 if (buf)
5103 {
5104 xfree (buf);
5105 buf = NULL;
5106 }
5107 }
5108
5109 return buf;
5110}
5111#endif
5112#endif /* HAVE_NTGUI */
5113
5114/* Load PBM image IMG for use on frame F. */
5115
5116static int
d3da34e0 5117pbm_load (struct frame *f, struct image *img)
4ef0d4d0
KS
5118{
5119 int raw_p, x, y;
5120 int width, height, max_color_idx = 0;
5121 XImagePtr ximg;
5122 Lisp_Object file, specified_file;
5123 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
4ef0d4d0
KS
5124 unsigned char *contents = NULL;
5125 unsigned char *end, *p;
dd52fcea 5126 ptrdiff_t size;
4ef0d4d0
KS
5127
5128 specified_file = image_spec_value (img->spec, QCfile, NULL);
4ef0d4d0
KS
5129
5130 if (STRINGP (specified_file))
5131 {
5132 file = x_find_image_file (specified_file);
5133 if (!STRINGP (file))
5134 {
5135 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
5136 return 0;
5137 }
5138
42a5b22f 5139 contents = slurp_file (SSDATA (file), &size);
4ef0d4d0
KS
5140 if (contents == NULL)
5141 {
5142 image_error ("Error reading `%s'", file, Qnil);
4ef0d4d0
KS
5143 return 0;
5144 }
5145
5146 p = contents;
5147 end = contents + size;
5148 }
5149 else
5150 {
5151 Lisp_Object data;
5152 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
5153 if (!STRINGP (data))
5154 {
5155 image_error ("Invalid image data `%s'", data, Qnil);
5156 return 0;
5157 }
4ef0d4d0
KS
5158 p = SDATA (data);
5159 end = p + SBYTES (data);
5160 }
5161
5162 /* Check magic number. */
5163 if (end - p < 2 || *p++ != 'P')
5164 {
5165 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5166 error:
5167 xfree (contents);
4ef0d4d0
KS
5168 return 0;
5169 }
5170
5171 switch (*p++)
5172 {
5173 case '1':
5174 raw_p = 0, type = PBM_MONO;
5175 break;
5176
5177 case '2':
5178 raw_p = 0, type = PBM_GRAY;
5179 break;
5180
5181 case '3':
5182 raw_p = 0, type = PBM_COLOR;
5183 break;
5184
5185 case '4':
5186 raw_p = 1, type = PBM_MONO;
5187 break;
5188
5189 case '5':
5190 raw_p = 1, type = PBM_GRAY;
5191 break;
5192
5193 case '6':
5194 raw_p = 1, type = PBM_COLOR;
5195 break;
5196
5197 default:
5198 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5199 goto error;
5200 }
5201
5202 /* Read width, height, maximum color-component. Characters
5203 starting with `#' up to the end of a line are ignored. */
5204 width = pbm_scan_number (&p, end);
5205 height = pbm_scan_number (&p, end);
5206
5207 if (type != PBM_MONO)
5208 {
5209 max_color_idx = pbm_scan_number (&p, end);
b9c89e11
JR
5210 if (max_color_idx > 65535 || max_color_idx < 0)
5211 {
5212 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
5213 goto error;
5214 }
4ef0d4d0
KS
5215 }
5216
b9c89e11
JR
5217 if (!check_image_size (f, width, height))
5218 {
10ea2b82 5219 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
b9c89e11
JR
5220 goto error;
5221 }
4ef0d4d0
KS
5222
5223 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5224 &ximg, &img->pixmap))
5225 goto error;
5226
5227 /* Initialize the color hash table. */
5228 init_color_table ();
5229
5230 if (type == PBM_MONO)
5231 {
5232 int c = 0, g;
5233 struct image_keyword fmt[PBM_LAST];
5234 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5235 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5236
5237 /* Parse the image specification. */
72af86bd 5238 memcpy (fmt, pbm_format, sizeof fmt);
4ef0d4d0
KS
5239 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5240
5241 /* Get foreground and background colors, maybe allocate colors. */
5242 if (fmt[PBM_FOREGROUND].count
5243 && STRINGP (fmt[PBM_FOREGROUND].value))
5244 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5245 if (fmt[PBM_BACKGROUND].count
5246 && STRINGP (fmt[PBM_BACKGROUND].value))
5247 {
5248 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5249 img->background = bg;
5250 img->background_valid = 1;
5251 }
5252
5253 for (y = 0; y < height; ++y)
5254 for (x = 0; x < width; ++x)
5255 {
5256 if (raw_p)
5257 {
5258 if ((x & 7) == 0)
c295e710
CY
5259 {
5260 if (p >= end)
5261 {
5262 x_destroy_x_image (ximg);
5263 x_clear_image (f, img);
5264 image_error ("Invalid image size in image `%s'",
5265 img->spec, Qnil);
5266 goto error;
5267 }
5268 c = *p++;
5269 }
4ef0d4d0
KS
5270 g = c & 0x80;
5271 c <<= 1;
5272 }
5273 else
5274 g = pbm_scan_number (&p, end);
5275
5276 XPutPixel (ximg, x, y, g ? fg : bg);
5277 }
5278 }
5279 else
5280 {
b9c89e11
JR
5281 int expected_size = height * width;
5282 if (max_color_idx > 255)
5283 expected_size *= 2;
5284 if (type == PBM_COLOR)
5285 expected_size *= 3;
5286
5287 if (raw_p && p + expected_size > end)
39e653ea
CY
5288 {
5289 x_destroy_x_image (ximg);
fb0b0862 5290 x_clear_image (f, img);
39e653ea
CY
5291 image_error ("Invalid image size in image `%s'",
5292 img->spec, Qnil);
5293 goto error;
5294 }
5295
4ef0d4d0
KS
5296 for (y = 0; y < height; ++y)
5297 for (x = 0; x < width; ++x)
5298 {
5299 int r, g, b;
5300
b9c89e11
JR
5301 if (type == PBM_GRAY && raw_p)
5302 {
5303 r = g = b = *p++;
5304 if (max_color_idx > 255)
5305 r = g = b = r * 256 + *p++;
5306 }
5307 else if (type == PBM_GRAY)
5308 r = g = b = pbm_scan_number (&p, end);
4ef0d4d0
KS
5309 else if (raw_p)
5310 {
5311 r = *p++;
b9c89e11
JR
5312 if (max_color_idx > 255)
5313 r = r * 256 + *p++;
4ef0d4d0 5314 g = *p++;
b9c89e11
JR
5315 if (max_color_idx > 255)
5316 g = g * 256 + *p++;
4ef0d4d0 5317 b = *p++;
b9c89e11
JR
5318 if (max_color_idx > 255)
5319 b = b * 256 + *p++;
4ef0d4d0
KS
5320 }
5321 else
5322 {
5323 r = pbm_scan_number (&p, end);
5324 g = pbm_scan_number (&p, end);
5325 b = pbm_scan_number (&p, end);
5326 }
5327
5328 if (r < 0 || g < 0 || b < 0)
5329 {
5330 x_destroy_x_image (ximg);
5331 image_error ("Invalid pixel value in image `%s'",
5332 img->spec, Qnil);
5333 goto error;
5334 }
5335
5336 /* RGB values are now in the range 0..max_color_idx.
5337 Scale this to the range 0..0xffff supported by X. */
5338 r = (double) r * 65535 / max_color_idx;
5339 g = (double) g * 65535 / max_color_idx;
5340 b = (double) b * 65535 / max_color_idx;
5341 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5342 }
5343 }
5344
5345#ifdef COLOR_TABLE_SUPPORT
5346 /* Store in IMG->colors the colors allocated for the image, and
5347 free the color table. */
5348 img->colors = colors_in_color_table (&img->ncolors);
5349 free_color_table ();
5350#endif /* COLOR_TABLE_SUPPORT */
5351
5352 img->width = width;
5353 img->height = height;
5354
5355 /* Maybe fill in the background field while we have ximg handy. */
5356
5357 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
5358 /* Casting avoids a GCC warning. */
5359 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
5360
5361 /* Put the image into a pixmap. */
5362 x_put_x_image (f, ximg, img->pixmap, width, height);
5363 x_destroy_x_image (ximg);
5364
5365 /* X and W32 versions did it here, MAC version above. ++kfs
1f026899 5366 img->width = width;
4ef0d4d0
KS
5367 img->height = height; */
5368
4ef0d4d0
KS
5369 xfree (contents);
5370 return 1;
5371}
5372
5373\f
5374/***********************************************************************
5375 PNG
5376 ***********************************************************************/
5377
9e2a2647 5378#if defined (HAVE_PNG) || defined (HAVE_NS)
4ef0d4d0
KS
5379
5380/* Function prototypes. */
5381
f57e2426
J
5382static int png_image_p (Lisp_Object object);
5383static int png_load (struct frame *f, struct image *img);
4ef0d4d0
KS
5384
5385/* The symbol `png' identifying images of this type. */
5386
955cbe7b 5387static Lisp_Object Qpng;
4ef0d4d0
KS
5388
5389/* Indices of image specification fields in png_format, below. */
5390
5391enum png_keyword_index
5392{
5393 PNG_TYPE,
5394 PNG_DATA,
5395 PNG_FILE,
5396 PNG_ASCENT,
5397 PNG_MARGIN,
5398 PNG_RELIEF,
5399 PNG_ALGORITHM,
5400 PNG_HEURISTIC_MASK,
5401 PNG_MASK,
5402 PNG_BACKGROUND,
5403 PNG_LAST
5404};
5405
5406/* Vector of image_keyword structures describing the format
5407 of valid user-defined image specifications. */
5408
91433552 5409static const struct image_keyword png_format[PNG_LAST] =
4ef0d4d0
KS
5410{
5411 {":type", IMAGE_SYMBOL_VALUE, 1},
5412 {":data", IMAGE_STRING_VALUE, 0},
5413 {":file", IMAGE_STRING_VALUE, 0},
5414 {":ascent", IMAGE_ASCENT_VALUE, 0},
5415 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5416 {":relief", IMAGE_INTEGER_VALUE, 0},
5417 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5418 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5419 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5420 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5421};
5422
5423/* Structure describing the image type `png'. */
5424
5425static struct image_type png_type =
5426{
5427 &Qpng,
5428 png_image_p,
5429 png_load,
5430 x_clear_image,
5431 NULL
5432};
5433
5434/* Return non-zero if OBJECT is a valid PNG image specification. */
5435
5436static int
d3da34e0 5437png_image_p (Lisp_Object object)
4ef0d4d0
KS
5438{
5439 struct image_keyword fmt[PNG_LAST];
72af86bd 5440 memcpy (fmt, png_format, sizeof fmt);
4ef0d4d0
KS
5441
5442 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5443 return 0;
5444
5445 /* Must specify either the :data or :file keyword. */
5446 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5447}
5448
9e2a2647 5449#endif /* HAVE_PNG || HAVE_NS */
4ef0d4d0
KS
5450
5451
5452#ifdef HAVE_PNG
5453
4ef0d4d0
KS
5454#ifdef HAVE_NTGUI
5455/* PNG library details. */
5456
14beddf4
CY
5457DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
5458DEF_IMGLIB_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
5459DEF_IMGLIB_FN (png_structp, png_create_read_struct, (png_const_charp, png_voidp,
5460 png_error_ptr, png_error_ptr));
5461DEF_IMGLIB_FN (png_infop, png_create_info_struct, (png_structp));
5462DEF_IMGLIB_FN (void, png_destroy_read_struct, (png_structpp, png_infopp, png_infopp));
5463DEF_IMGLIB_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
5464DEF_IMGLIB_FN (void, png_set_sig_bytes, (png_structp, int));
5465DEF_IMGLIB_FN (void, png_read_info, (png_structp, png_infop));
5466DEF_IMGLIB_FN (png_uint_32, png_get_IHDR, (png_structp, png_infop,
850690cc
JB
5467 png_uint_32 *, png_uint_32 *,
5468 int *, int *, int *, int *, int *));
14beddf4
CY
5469DEF_IMGLIB_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
5470DEF_IMGLIB_FN (void, png_set_strip_16, (png_structp));
5471DEF_IMGLIB_FN (void, png_set_expand, (png_structp));
5472DEF_IMGLIB_FN (void, png_set_gray_to_rgb, (png_structp));
5473DEF_IMGLIB_FN (void, png_set_background, (png_structp, png_color_16p,
850690cc 5474 int, int, double));
14beddf4
CY
5475DEF_IMGLIB_FN (png_uint_32, png_get_bKGD, (png_structp, png_infop, png_color_16p *));
5476DEF_IMGLIB_FN (void, png_read_update_info, (png_structp, png_infop));
5477DEF_IMGLIB_FN (png_byte, png_get_channels, (png_structp, png_infop));
5478DEF_IMGLIB_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
5479DEF_IMGLIB_FN (void, png_read_image, (png_structp, png_bytepp));
5480DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop));
5481DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp));
4ef0d4d0 5482
7f9c5df9 5483#if (PNG_LIBPNG_VER >= 10500)
14beddf4
CY
5484DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int));
5485DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
7f9c5df9 5486#endif /* libpng version >= 1.5 */
4ef0d4d0
KS
5487
5488static int
0855eb52 5489init_png_functions (Lisp_Object libraries)
4ef0d4d0
KS
5490{
5491 HMODULE library;
5492
0855eb52 5493 if (!(library = w32_delayed_load (libraries, Qpng)))
4ef0d4d0
KS
5494 return 0;
5495
5496 LOAD_IMGLIB_FN (library, png_get_io_ptr);
285d07e2 5497 LOAD_IMGLIB_FN (library, png_sig_cmp);
4ef0d4d0
KS
5498 LOAD_IMGLIB_FN (library, png_create_read_struct);
5499 LOAD_IMGLIB_FN (library, png_create_info_struct);
5500 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5501 LOAD_IMGLIB_FN (library, png_set_read_fn);
4ef0d4d0
KS
5502 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5503 LOAD_IMGLIB_FN (library, png_read_info);
5504 LOAD_IMGLIB_FN (library, png_get_IHDR);
5505 LOAD_IMGLIB_FN (library, png_get_valid);
5506 LOAD_IMGLIB_FN (library, png_set_strip_16);
5507 LOAD_IMGLIB_FN (library, png_set_expand);
5508 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5509 LOAD_IMGLIB_FN (library, png_set_background);
5510 LOAD_IMGLIB_FN (library, png_get_bKGD);
5511 LOAD_IMGLIB_FN (library, png_read_update_info);
5512 LOAD_IMGLIB_FN (library, png_get_channels);
5513 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5514 LOAD_IMGLIB_FN (library, png_read_image);
5515 LOAD_IMGLIB_FN (library, png_read_end);
5516 LOAD_IMGLIB_FN (library, png_error);
7f9c5df9
CY
5517
5518#if (PNG_LIBPNG_VER >= 10500)
5519 LOAD_IMGLIB_FN (library, png_longjmp);
5520 LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
5521#endif /* libpng version >= 1.5 */
5522
4ef0d4d0
KS
5523 return 1;
5524}
5525#else
5526
5527#define fn_png_get_io_ptr png_get_io_ptr
285d07e2 5528#define fn_png_sig_cmp png_sig_cmp
4ef0d4d0
KS
5529#define fn_png_create_read_struct png_create_read_struct
5530#define fn_png_create_info_struct png_create_info_struct
5531#define fn_png_destroy_read_struct png_destroy_read_struct
5532#define fn_png_set_read_fn png_set_read_fn
4ef0d4d0
KS
5533#define fn_png_set_sig_bytes png_set_sig_bytes
5534#define fn_png_read_info png_read_info
5535#define fn_png_get_IHDR png_get_IHDR
5536#define fn_png_get_valid png_get_valid
5537#define fn_png_set_strip_16 png_set_strip_16
5538#define fn_png_set_expand png_set_expand
5539#define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5540#define fn_png_set_background png_set_background
5541#define fn_png_get_bKGD png_get_bKGD
5542#define fn_png_read_update_info png_read_update_info
5543#define fn_png_get_channels png_get_channels
5544#define fn_png_get_rowbytes png_get_rowbytes
5545#define fn_png_read_image png_read_image
5546#define fn_png_read_end png_read_end
5547#define fn_png_error png_error
5548
7f9c5df9
CY
5549#if (PNG_LIBPNG_VER >= 10500)
5550#define fn_png_longjmp png_longjmp
5551#define fn_png_set_longjmp_fn png_set_longjmp_fn
5552#endif /* libpng version >= 1.5 */
5553
4ef0d4d0
KS
5554#endif /* HAVE_NTGUI */
5555
7f9c5df9
CY
5556
5557#if (PNG_LIBPNG_VER < 10500)
c2e79cb4 5558#define PNG_LONGJMP(ptr) (longjmp ((ptr)->jmpbuf, 1))
7f9c5df9
CY
5559#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
5560#else
df61c790 5561/* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */
c2e79cb4 5562#define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
7f9c5df9 5563#define PNG_JMPBUF(ptr) \
df61c790 5564 (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf)))
7f9c5df9
CY
5565#endif
5566
4ef0d4d0
KS
5567/* Error and warning handlers installed when the PNG library
5568 is initialized. */
5569
ec6cf4c6 5570static void my_png_error (png_struct *, const char *) NO_RETURN;
4ef0d4d0 5571static void
d3da34e0 5572my_png_error (png_struct *png_ptr, const char *msg)
4ef0d4d0
KS
5573{
5574 xassert (png_ptr != NULL);
5be1c984
EZ
5575 /* Avoid compiler warning about deprecated direct access to
5576 png_ptr's fields in libpng versions 1.4.x. */
4ef0d4d0 5577 image_error ("PNG error: %s", build_string (msg), Qnil);
7f9c5df9 5578 PNG_LONGJMP (png_ptr);
4ef0d4d0
KS
5579}
5580
5581
5582static void
d3da34e0 5583my_png_warning (png_struct *png_ptr, const char *msg)
4ef0d4d0
KS
5584{
5585 xassert (png_ptr != NULL);
5586 image_error ("PNG warning: %s", build_string (msg), Qnil);
5587}
5588
5589/* Memory source for PNG decoding. */
5590
5591struct png_memory_storage
5592{
5593 unsigned char *bytes; /* The data */
3f791afe
PE
5594 ptrdiff_t len; /* How big is it? */
5595 ptrdiff_t index; /* Where are we? */
4ef0d4d0
KS
5596};
5597
5598
5599/* Function set as reader function when reading PNG image from memory.
5600 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5601 bytes from the input to DATA. */
5602
5603static void
d3da34e0 5604png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
4ef0d4d0
KS
5605{
5606 struct png_memory_storage *tbr
5607 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5608
5609 if (length > tbr->len - tbr->index)
5610 fn_png_error (png_ptr, "Read error");
5611
72af86bd 5612 memcpy (data, tbr->bytes + tbr->index, length);
4ef0d4d0
KS
5613 tbr->index = tbr->index + length;
5614}
5615
b0da69a7 5616
9a22a004
JB
5617/* Function set as reader function when reading PNG image from a file.
5618 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5619 bytes from the input to DATA. */
5620
5621static void
d3da34e0 5622png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
9a22a004
JB
5623{
5624 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
5625
5626 if (fread (data, 1, length, fp) < length)
5627 fn_png_error (png_ptr, "Read error");
5628}
5629
5630
4ef0d4d0
KS
5631/* Load PNG image IMG for use on frame F. Value is non-zero if
5632 successful. */
5633
5634static int
d3da34e0 5635png_load (struct frame *f, struct image *img)
4ef0d4d0
KS
5636{
5637 Lisp_Object file, specified_file;
5638 Lisp_Object specified_data;
5adf60bc
PE
5639 int x, y;
5640 ptrdiff_t i;
4ef0d4d0 5641 XImagePtr ximg, mask_img = NULL;
4ef0d4d0
KS
5642 png_struct *png_ptr = NULL;
5643 png_info *info_ptr = NULL, *end_info = NULL;
5644 FILE *volatile fp = NULL;
5645 png_byte sig[8];
5646 png_byte * volatile pixels = NULL;
5647 png_byte ** volatile rows = NULL;
5648 png_uint_32 width, height;
5649 int bit_depth, color_type, interlace_type;
5650 png_byte channels;
5651 png_uint_32 row_bytes;
5652 int transparent_p;
4ef0d4d0
KS
5653 struct png_memory_storage tbr; /* Data to be read */
5654
5655 /* Find out what file to load. */
5656 specified_file = image_spec_value (img->spec, QCfile, NULL);
5657 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0
KS
5658
5659 if (NILP (specified_data))
5660 {
5661 file = x_find_image_file (specified_file);
5662 if (!STRINGP (file))
5663 {
5664 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
5665 return 0;
5666 }
5667
5668 /* Open the image file. */
42a5b22f 5669 fp = fopen (SSDATA (file), "rb");
4ef0d4d0
KS
5670 if (!fp)
5671 {
5672 image_error ("Cannot open image file `%s'", file, Qnil);
4ef0d4d0
KS
5673 return 0;
5674 }
5675
5676 /* Check PNG signature. */
5677 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
285d07e2 5678 || fn_png_sig_cmp (sig, 0, sizeof sig))
4ef0d4d0
KS
5679 {
5680 image_error ("Not a PNG file: `%s'", file, Qnil);
4ef0d4d0
KS
5681 fclose (fp);
5682 return 0;
5683 }
5684 }
5685 else
5686 {
7574650a
AS
5687 if (!STRINGP (specified_data))
5688 {
5689 image_error ("Invalid image data `%s'", specified_data, Qnil);
5690 return 0;
5691 }
5692
4ef0d4d0
KS
5693 /* Read from memory. */
5694 tbr.bytes = SDATA (specified_data);
5695 tbr.len = SBYTES (specified_data);
5696 tbr.index = 0;
5697
5698 /* Check PNG signature. */
5699 if (tbr.len < sizeof sig
285d07e2 5700 || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
4ef0d4d0
KS
5701 {
5702 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
4ef0d4d0
KS
5703 return 0;
5704 }
5705
5706 /* Need to skip past the signature. */
5707 tbr.bytes += sizeof (sig);
5708 }
5709
df61c790
AS
5710 /* Initialize read and info structs for PNG lib. */
5711 png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
5712 NULL, my_png_error,
5713 my_png_warning);
4ef0d4d0
KS
5714 if (!png_ptr)
5715 {
5716 if (fp) fclose (fp);
4ef0d4d0
KS
5717 return 0;
5718 }
5719
df61c790 5720 info_ptr = fn_png_create_info_struct (png_ptr);
4ef0d4d0
KS
5721 if (!info_ptr)
5722 {
5723 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
5724 if (fp) fclose (fp);
4ef0d4d0
KS
5725 return 0;
5726 }
5727
df61c790 5728 end_info = fn_png_create_info_struct (png_ptr);
4ef0d4d0
KS
5729 if (!end_info)
5730 {
5731 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
5732 if (fp) fclose (fp);
4ef0d4d0
KS
5733 return 0;
5734 }
5735
5736 /* Set error jump-back. We come back here when the PNG library
5737 detects an error. */
7f9c5df9 5738 if (setjmp (PNG_JMPBUF (png_ptr)))
4ef0d4d0
KS
5739 {
5740 error:
5741 if (png_ptr)
5742 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5743 xfree (pixels);
5744 xfree (rows);
5745 if (fp) fclose (fp);
4ef0d4d0
KS
5746 return 0;
5747 }
5748
5749 /* Read image info. */
5750 if (!NILP (specified_data))
5751 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
5752 else
9a22a004 5753 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
4ef0d4d0
KS
5754
5755 fn_png_set_sig_bytes (png_ptr, sizeof sig);
5756 fn_png_read_info (png_ptr, info_ptr);
5757 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
5758 &interlace_type, NULL, NULL);
5759
3f791afe
PE
5760 if (! (width <= INT_MAX && height <= INT_MAX
5761 && check_image_size (f, width, height)))
10ea2b82
JR
5762 {
5763 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5764 goto error;
5765 }
ca4aa935
PE
5766
5767 /* Create the X image and pixmap now, so that the work below can be
5768 omitted if the image is too large for X. */
5769 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5770 &img->pixmap))
5771 goto error;
5772
4ef0d4d0
KS
5773 /* If image contains simply transparency data, we prefer to
5774 construct a clipping mask. */
5775 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
5776 transparent_p = 1;
5777 else
5778 transparent_p = 0;
5779
5780 /* This function is easier to write if we only have to handle
5781 one data format: RGB or RGBA with 8 bits per channel. Let's
5782 transform other formats into that format. */
5783
5784 /* Strip more than 8 bits per channel. */
5785 if (bit_depth == 16)
5786 fn_png_set_strip_16 (png_ptr);
5787
5788 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5789 if available. */
5790 fn_png_set_expand (png_ptr);
5791
5792 /* Convert grayscale images to RGB. */
5793 if (color_type == PNG_COLOR_TYPE_GRAY
5794 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5795 fn_png_set_gray_to_rgb (png_ptr);
5796
4ef0d4d0
KS
5797 /* Handle alpha channel by combining the image with a background
5798 color. Do this only if a real alpha channel is supplied. For
5799 simple transparency, we prefer a clipping mask. */
5800 if (!transparent_p)
5801 {
917ac1a9 5802 /* png_color_16 *image_bg; */
4ef0d4d0
KS
5803 Lisp_Object specified_bg
5804 = image_spec_value (img->spec, QCbackground, NULL);
c4f13f44 5805 int shift = (bit_depth == 16) ? 0 : 8;
4ef0d4d0
KS
5806
5807 if (STRINGP (specified_bg))
5808 /* The user specified `:background', use that. */
5809 {
4ef0d4d0 5810 XColor color;
42a5b22f 5811 if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
4ef0d4d0
KS
5812 {
5813 png_color_16 user_bg;
5814
72af86bd 5815 memset (&user_bg, 0, sizeof user_bg);
c4f13f44
CY
5816 user_bg.red = color.red >> shift;
5817 user_bg.green = color.green >> shift;
5818 user_bg.blue = color.blue >> shift;
4ef0d4d0
KS
5819
5820 fn_png_set_background (png_ptr, &user_bg,
5821 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5822 }
5823 }
4ef0d4d0
KS
5824 else
5825 {
c4f13f44
CY
5826 /* We use the current frame background, ignoring any default
5827 background color set by the image. */
8b7d0a16 5828#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4ef0d4d0
KS
5829 XColor color;
5830 png_color_16 frame_background;
5831
5832 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5833 x_query_color (f, &color);
5834
72af86bd 5835 memset (&frame_background, 0, sizeof frame_background);
c4f13f44
CY
5836 frame_background.red = color.red >> shift;
5837 frame_background.green = color.green >> shift;
5838 frame_background.blue = color.blue >> shift;
4ef0d4d0
KS
5839#endif /* HAVE_X_WINDOWS */
5840
4ef0d4d0
KS
5841 fn_png_set_background (png_ptr, &frame_background,
5842 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5843 }
5844 }
5845
5846 /* Update info structure. */
5847 fn_png_read_update_info (png_ptr, info_ptr);
5848
5849 /* Get number of channels. Valid values are 1 for grayscale images
5850 and images with a palette, 2 for grayscale images with transparency
5851 information (alpha channel), 3 for RGB images, and 4 for RGB
5852 images with alpha channel, i.e. RGBA. If conversions above were
5853 sufficient we should only have 3 or 4 channels here. */
5854 channels = fn_png_get_channels (png_ptr, info_ptr);
5855 xassert (channels == 3 || channels == 4);
5856
5857 /* Number of bytes needed for one row of the image. */
5858 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
5859
5860 /* Allocate memory for the image. */
3f791afe
PE
5861 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
5862 || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
5863 memory_full (SIZE_MAX);
5864 pixels = (png_byte *) xmalloc (sizeof *pixels * row_bytes * height);
4ef0d4d0
KS
5865 rows = (png_byte **) xmalloc (height * sizeof *rows);
5866 for (i = 0; i < height; ++i)
5867 rows[i] = pixels + i * row_bytes;
5868
5869 /* Read the entire image. */
5870 fn_png_read_image (png_ptr, rows);
5871 fn_png_read_end (png_ptr, info_ptr);
5872 if (fp)
5873 {
5874 fclose (fp);
5875 fp = NULL;
5876 }
5877
4ef0d4d0
KS
5878 /* Create an image and pixmap serving as mask if the PNG image
5879 contains an alpha channel. */
5880 if (channels == 4
5881 && !transparent_p
5882 && !x_create_x_image_and_pixmap (f, width, height, 1,
5883 &mask_img, &img->mask))
5884 {
5885 x_destroy_x_image (ximg);
5886 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
5887 img->pixmap = NO_PIXMAP;
5888 goto error;
5889 }
5890
5891 /* Fill the X image and mask from PNG data. */
5892 init_color_table ();
5893
5894 for (y = 0; y < height; ++y)
5895 {
5896 png_byte *p = rows[y];
5897
5898 for (x = 0; x < width; ++x)
5899 {
13464394 5900 int r, g, b;
4ef0d4d0
KS
5901
5902 r = *p++ << 8;
5903 g = *p++ << 8;
5904 b = *p++ << 8;
5905 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5906 /* An alpha channel, aka mask channel, associates variable
5907 transparency with an image. Where other image formats
5908 support binary transparency---fully transparent or fully
5909 opaque---PNG allows up to 254 levels of partial transparency.
5910 The PNG library implements partial transparency by combining
5911 the image with a specified background color.
5912
5913 I'm not sure how to handle this here nicely: because the
5914 background on which the image is displayed may change, for
5915 real alpha channel support, it would be necessary to create
5916 a new image for each possible background.
5917
5918 What I'm doing now is that a mask is created if we have
5919 boolean transparency information. Otherwise I'm using
5920 the frame's background color to combine the image with. */
5921
5922 if (channels == 4)
5923 {
5924 if (mask_img)
9ecf6403 5925 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
4ef0d4d0
KS
5926 ++p;
5927 }
5928 }
5929 }
5930
5931 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5932 /* Set IMG's background color from the PNG image, unless the user
5933 overrode it. */
5934 {
5935 png_color_16 *bg;
5936 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
5937 {
5938 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
5939 img->background_valid = 1;
5940 }
5941 }
5942
5943#ifdef COLOR_TABLE_SUPPORT
5944 /* Remember colors allocated for this image. */
5945 img->colors = colors_in_color_table (&img->ncolors);
5946 free_color_table ();
5947#endif /* COLOR_TABLE_SUPPORT */
5948
5949 /* Clean up. */
5950 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5951 xfree (rows);
5952 xfree (pixels);
5953
5954 img->width = width;
5955 img->height = height;
5956
2e09fef1
EZ
5957 /* Maybe fill in the background field while we have ximg handy.
5958 Casting avoids a GCC warning. */
5959 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
5960
5961 /* Put the image into the pixmap, then free the X image and its buffer. */
5962 x_put_x_image (f, ximg, img->pixmap, width, height);
5963 x_destroy_x_image (ximg);
5964
5965 /* Same for the mask. */
5966 if (mask_img)
5967 {
2e09fef1
EZ
5968 /* Fill in the background_transparent field while we have the
5969 mask handy. Casting avoids a GCC warning. */
5970 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
4ef0d4d0
KS
5971
5972 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5973 x_destroy_x_image (mask_img);
5974 }
5975
4ef0d4d0
KS
5976 return 1;
5977}
5978
5979#else /* HAVE_PNG */
5980
edfda783
AR
5981#ifdef HAVE_NS
5982static int
5983png_load (struct frame *f, struct image *img)
5984{
5985 return ns_load_image(f, img,
5986 image_spec_value (img->spec, QCfile, NULL),
5987 image_spec_value (img->spec, QCdata, NULL));
5988}
5989#endif /* HAVE_NS */
5990
5991
4ef0d4d0
KS
5992#endif /* !HAVE_PNG */
5993
5994
5995\f
5996/***********************************************************************
5997 JPEG
5998 ***********************************************************************/
5999
9e2a2647 6000#if defined (HAVE_JPEG) || defined (HAVE_NS)
4ef0d4d0 6001
f57e2426
J
6002static int jpeg_image_p (Lisp_Object object);
6003static int jpeg_load (struct frame *f, struct image *img);
4ef0d4d0
KS
6004
6005/* The symbol `jpeg' identifying images of this type. */
6006
955cbe7b 6007static Lisp_Object Qjpeg;
4ef0d4d0
KS
6008
6009/* Indices of image specification fields in gs_format, below. */
6010
6011enum jpeg_keyword_index
6012{
6013 JPEG_TYPE,
6014 JPEG_DATA,
6015 JPEG_FILE,
6016 JPEG_ASCENT,
6017 JPEG_MARGIN,
6018 JPEG_RELIEF,
6019 JPEG_ALGORITHM,
6020 JPEG_HEURISTIC_MASK,
6021 JPEG_MASK,
6022 JPEG_BACKGROUND,
6023 JPEG_LAST
6024};
6025
6026/* Vector of image_keyword structures describing the format
6027 of valid user-defined image specifications. */
6028
91433552 6029static const struct image_keyword jpeg_format[JPEG_LAST] =
4ef0d4d0
KS
6030{
6031 {":type", IMAGE_SYMBOL_VALUE, 1},
6032 {":data", IMAGE_STRING_VALUE, 0},
6033 {":file", IMAGE_STRING_VALUE, 0},
6034 {":ascent", IMAGE_ASCENT_VALUE, 0},
6035 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6036 {":relief", IMAGE_INTEGER_VALUE, 0},
6037 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6038 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6039 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6040 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6041};
6042
6043/* Structure describing the image type `jpeg'. */
6044
6045static struct image_type jpeg_type =
6046{
6047 &Qjpeg,
6048 jpeg_image_p,
6049 jpeg_load,
6050 x_clear_image,
6051 NULL
6052};
6053
6054/* Return non-zero if OBJECT is a valid JPEG image specification. */
6055
6056static int
d3da34e0 6057jpeg_image_p (Lisp_Object object)
4ef0d4d0
KS
6058{
6059 struct image_keyword fmt[JPEG_LAST];
6060
72af86bd 6061 memcpy (fmt, jpeg_format, sizeof fmt);
4ef0d4d0
KS
6062
6063 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6064 return 0;
6065
6066 /* Must specify either the :data or :file keyword. */
6067 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6068}
6069
9e2a2647 6070#endif /* HAVE_JPEG || HAVE_NS */
4ef0d4d0
KS
6071
6072#ifdef HAVE_JPEG
6073
6074/* Work around a warning about HAVE_STDLIB_H being redefined in
6075 jconfig.h. */
6076#ifdef HAVE_STDLIB_H
4ef0d4d0
KS
6077#undef HAVE_STDLIB_H
6078#endif /* HAVE_STLIB_H */
6079
66354420 6080#if defined (HAVE_NTGUI) && !defined (__WIN32__)
28893db2
JB
6081/* In older releases of the jpeg library, jpeglib.h will define boolean
6082 differently depending on __WIN32__, so make sure it is defined. */
66354420
JR
6083#define __WIN32__ 1
6084#endif
6085
4ef0d4d0
KS
6086#include <jpeglib.h>
6087#include <jerror.h>
4ef0d4d0
KS
6088
6089#ifdef HAVE_STLIB_H_1
6090#define HAVE_STDLIB_H 1
6091#endif
6092
6093#ifdef HAVE_NTGUI
6094
6095/* JPEG library details. */
14beddf4
CY
6096DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
6097DEF_IMGLIB_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
6098DEF_IMGLIB_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
6099DEF_IMGLIB_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
6100DEF_IMGLIB_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
6101DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
6102DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr *));
6103DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
4ef0d4d0
KS
6104
6105static int
0855eb52 6106init_jpeg_functions (Lisp_Object libraries)
4ef0d4d0
KS
6107{
6108 HMODULE library;
6109
0855eb52 6110 if (!(library = w32_delayed_load (libraries, Qjpeg)))
4ef0d4d0
KS
6111 return 0;
6112
6113 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6114 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6115 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6116 LOAD_IMGLIB_FN (library, jpeg_read_header);
4ef0d4d0
KS
6117 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6118 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6119 LOAD_IMGLIB_FN (library, jpeg_std_error);
6120 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6121 return 1;
6122}
6123
6124/* Wrapper since we can't directly assign the function pointer
6125 to another function pointer that was declared more completely easily. */
6126static boolean
7c3320d8 6127jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
4ef0d4d0
KS
6128{
6129 return fn_jpeg_resync_to_restart (cinfo, desired);
6130}
6131
6132#else
6133
6134#define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6135#define fn_jpeg_start_decompress jpeg_start_decompress
6136#define fn_jpeg_finish_decompress jpeg_finish_decompress
6137#define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6138#define fn_jpeg_read_header jpeg_read_header
6139#define fn_jpeg_read_scanlines jpeg_read_scanlines
4ef0d4d0
KS
6140#define fn_jpeg_std_error jpeg_std_error
6141#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6142
6143#endif /* HAVE_NTGUI */
6144
6145struct my_jpeg_error_mgr
6146{
6147 struct jpeg_error_mgr pub;
6148 jmp_buf setjmp_buffer;
6149};
6150
6151
ec6cf4c6 6152static void my_error_exit (j_common_ptr) NO_RETURN;
4ef0d4d0 6153static void
d3da34e0 6154my_error_exit (j_common_ptr cinfo)
4ef0d4d0
KS
6155{
6156 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6157 longjmp (mgr->setjmp_buffer, 1);
6158}
6159
6160
6161/* Init source method for JPEG data source manager. Called by
6162 jpeg_read_header() before any data is actually read. See
6163 libjpeg.doc from the JPEG lib distribution. */
6164
6165static void
d3da34e0 6166our_common_init_source (j_decompress_ptr cinfo)
b25a72ab
JB
6167{
6168}
6169
6170
6171/* Method to terminate data source. Called by
6172 jpeg_finish_decompress() after all data has been processed. */
6173
6174static void
d3da34e0 6175our_common_term_source (j_decompress_ptr cinfo)
4ef0d4d0
KS
6176{
6177}
6178
6179
6180/* Fill input buffer method for JPEG data source manager. Called
6181 whenever more data is needed. We read the whole image in one step,
6182 so this only adds a fake end of input marker at the end. */
6183
5a1539f3 6184static JOCTET our_memory_buffer[2];
aca946f3 6185
4ef0d4d0 6186static boolean
d3da34e0 6187our_memory_fill_input_buffer (j_decompress_ptr cinfo)
4ef0d4d0
KS
6188{
6189 /* Insert a fake EOI marker. */
6190 struct jpeg_source_mgr *src = cinfo->src;
4ef0d4d0 6191
5a1539f3
MB
6192 our_memory_buffer[0] = (JOCTET) 0xFF;
6193 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
4ef0d4d0 6194
5a1539f3 6195 src->next_input_byte = our_memory_buffer;
4ef0d4d0 6196 src->bytes_in_buffer = 2;
e0e30823 6197 return 1;
4ef0d4d0
KS
6198}
6199
6200
6201/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6202 is the JPEG data source manager. */
6203
6204static void
d3da34e0 6205our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
4ef0d4d0
KS
6206{
6207 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6208
6209 if (src)
6210 {
6211 if (num_bytes > src->bytes_in_buffer)
6212 ERREXIT (cinfo, JERR_INPUT_EOF);
6213
6214 src->bytes_in_buffer -= num_bytes;
6215 src->next_input_byte += num_bytes;
6216 }
6217}
6218
6219
4ef0d4d0
KS
6220/* Set up the JPEG lib for reading an image from DATA which contains
6221 LEN bytes. CINFO is the decompression info structure created for
6222 reading the image. */
6223
6224static void
d3da34e0 6225jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, unsigned int len)
4ef0d4d0
KS
6226{
6227 struct jpeg_source_mgr *src;
6228
6229 if (cinfo->src == NULL)
6230 {
6231 /* First time for this JPEG object? */
6232 cinfo->src = (struct jpeg_source_mgr *)
6233 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6234 sizeof (struct jpeg_source_mgr));
6235 src = (struct jpeg_source_mgr *) cinfo->src;
6236 src->next_input_byte = data;
6237 }
6238
6239 src = (struct jpeg_source_mgr *) cinfo->src;
b25a72ab
JB
6240 src->init_source = our_common_init_source;
6241 src->fill_input_buffer = our_memory_fill_input_buffer;
6242 src->skip_input_data = our_memory_skip_input_data;
4ef0d4d0 6243 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
b25a72ab 6244 src->term_source = our_common_term_source;
4ef0d4d0
KS
6245 src->bytes_in_buffer = len;
6246 src->next_input_byte = data;
6247}
6248
6249
b25a72ab
JB
6250struct jpeg_stdio_mgr
6251{
6252 struct jpeg_source_mgr mgr;
6253 boolean finished;
6254 FILE *file;
6255 JOCTET *buffer;
6256};
6257
6258
6259/* Size of buffer to read JPEG from file.
6260 Not too big, as we want to use alloc_small. */
6261#define JPEG_STDIO_BUFFER_SIZE 8192
6262
6263
6264/* Fill input buffer method for JPEG data source manager. Called
6265 whenever more data is needed. The data is read from a FILE *. */
6266
6267static boolean
d3da34e0 6268our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
b25a72ab
JB
6269{
6270 struct jpeg_stdio_mgr *src;
6271
6272 src = (struct jpeg_stdio_mgr *) cinfo->src;
6273 if (!src->finished)
6274 {
3f791afe 6275 ptrdiff_t bytes;
b25a72ab
JB
6276
6277 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6278 if (bytes > 0)
6279 src->mgr.bytes_in_buffer = bytes;
6280 else
6281 {
6282 WARNMS (cinfo, JWRN_JPEG_EOF);
6283 src->finished = 1;
6284 src->buffer[0] = (JOCTET) 0xFF;
6285 src->buffer[1] = (JOCTET) JPEG_EOI;
6286 src->mgr.bytes_in_buffer = 2;
6287 }
6288 src->mgr.next_input_byte = src->buffer;
6289 }
6290
6291 return 1;
6292}
6293
6294
6295/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6296 is the JPEG data source manager. */
6297
6298static void
d3da34e0 6299our_stdio_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
b25a72ab
JB
6300{
6301 struct jpeg_stdio_mgr *src;
6302 src = (struct jpeg_stdio_mgr *) cinfo->src;
6303
6304 while (num_bytes > 0 && !src->finished)
6305 {
6306 if (num_bytes <= src->mgr.bytes_in_buffer)
6307 {
6308 src->mgr.bytes_in_buffer -= num_bytes;
6309 src->mgr.next_input_byte += num_bytes;
6310 break;
6311 }
6312 else
6313 {
6314 num_bytes -= src->mgr.bytes_in_buffer;
6315 src->mgr.bytes_in_buffer = 0;
6316 src->mgr.next_input_byte = NULL;
6317
6318 our_stdio_fill_input_buffer (cinfo);
6319 }
6320 }
6321}
6322
6323
6324/* Set up the JPEG lib for reading an image from a FILE *.
6325 CINFO is the decompression info structure created for
6326 reading the image. */
6327
6328static void
d3da34e0 6329jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
b25a72ab
JB
6330{
6331 struct jpeg_stdio_mgr *src;
6332
6333 if (cinfo->src != NULL)
6334 src = (struct jpeg_stdio_mgr *) cinfo->src;
6335 else
6336 {
6337 /* First time for this JPEG object? */
6338 cinfo->src = (struct jpeg_source_mgr *)
6339 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6340 sizeof (struct jpeg_stdio_mgr));
6341 src = (struct jpeg_stdio_mgr *) cinfo->src;
6342 src->buffer = (JOCTET *)
6343 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6344 JPEG_STDIO_BUFFER_SIZE);
6345 }
6346
6347 src->file = fp;
6348 src->finished = 0;
6349 src->mgr.init_source = our_common_init_source;
6350 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6351 src->mgr.skip_input_data = our_stdio_skip_input_data;
6352 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6353 src->mgr.term_source = our_common_term_source;
6354 src->mgr.bytes_in_buffer = 0;
6355 src->mgr.next_input_byte = NULL;
6356}
6357
6358
4ef0d4d0
KS
6359/* Load image IMG for use on frame F. Patterned after example.c
6360 from the JPEG lib. */
6361
6362static int
d3da34e0 6363jpeg_load (struct frame *f, struct image *img)
4ef0d4d0
KS
6364{
6365 struct jpeg_decompress_struct cinfo;
6366 struct my_jpeg_error_mgr mgr;
6367 Lisp_Object file, specified_file;
6368 Lisp_Object specified_data;
6369 FILE * volatile fp = NULL;
6370 JSAMPARRAY buffer;
6371 int row_stride, x, y;
6372 XImagePtr ximg = NULL;
6373 int rc;
6374 unsigned long *colors;
6375 int width, height;
4ef0d4d0
KS
6376
6377 /* Open the JPEG file. */
6378 specified_file = image_spec_value (img->spec, QCfile, NULL);
6379 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0
KS
6380
6381 if (NILP (specified_data))
6382 {
6383 file = x_find_image_file (specified_file);
6384 if (!STRINGP (file))
6385 {
6386 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
6387 return 0;
6388 }
6389
42a5b22f 6390 fp = fopen (SSDATA (file), "rb");
4ef0d4d0
KS
6391 if (fp == NULL)
6392 {
6393 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
6394 return 0;
6395 }
6396 }
7574650a
AS
6397 else if (!STRINGP (specified_data))
6398 {
6399 image_error ("Invalid image data `%s'", specified_data, Qnil);
6400 return 0;
6401 }
4ef0d4d0
KS
6402
6403 /* Customize libjpeg's error handling to call my_error_exit when an
df61c790
AS
6404 error is detected. This function will perform a longjmp. */
6405 cinfo.err = fn_jpeg_std_error (&mgr.pub);
4ef0d4d0
KS
6406 mgr.pub.error_exit = my_error_exit;
6407
6408 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6409 {
6410 if (rc == 1)
6411 {
6412 /* Called from my_error_exit. Display a JPEG error. */
6ae141d6
PE
6413 char buf[JMSG_LENGTH_MAX];
6414 cinfo.err->format_message ((j_common_ptr) &cinfo, buf);
4ef0d4d0 6415 image_error ("Error reading JPEG image `%s': %s", img->spec,
6ae141d6 6416 build_string (buf));
4ef0d4d0
KS
6417 }
6418
6419 /* Close the input file and destroy the JPEG object. */
6420 if (fp)
6421 fclose ((FILE *) fp);
6422 fn_jpeg_destroy_decompress (&cinfo);
6423
6424 /* If we already have an XImage, free that. */
6425 x_destroy_x_image (ximg);
6426
6427 /* Free pixmap and colors. */
6428 x_clear_image (f, img);
4ef0d4d0
KS
6429 return 0;
6430 }
6431
6432 /* Create the JPEG decompression object. Let it read from fp.
6433 Read the JPEG image header. */
6434 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6435
6436 if (NILP (specified_data))
b25a72ab 6437 jpeg_file_src (&cinfo, (FILE *) fp);
4ef0d4d0
KS
6438 else
6439 jpeg_memory_src (&cinfo, SDATA (specified_data),
6440 SBYTES (specified_data));
6441
e0e30823 6442 fn_jpeg_read_header (&cinfo, 1);
4ef0d4d0
KS
6443
6444 /* Customize decompression so that color quantization will be used.
6445 Start decompression. */
e0e30823 6446 cinfo.quantize_colors = 1;
4ef0d4d0
KS
6447 fn_jpeg_start_decompress (&cinfo);
6448 width = img->width = cinfo.output_width;
6449 height = img->height = cinfo.output_height;
6450
f1f25b99
CY
6451 if (!check_image_size (f, width, height))
6452 {
10ea2b82 6453 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99
CY
6454 longjmp (mgr.setjmp_buffer, 2);
6455 }
6456
4ef0d4d0
KS
6457 /* Create X image and pixmap. */
6458 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6459 longjmp (mgr.setjmp_buffer, 2);
6460
6461 /* Allocate colors. When color quantization is used,
6462 cinfo.actual_number_of_colors has been set with the number of
6463 colors generated, and cinfo.colormap is a two-dimensional array
6464 of color indices in the range 0..cinfo.actual_number_of_colors.
6465 No more than 255 colors will be generated. */
6466 {
6467 int i, ir, ig, ib;
6468
6469 if (cinfo.out_color_components > 2)
6470 ir = 0, ig = 1, ib = 2;
6471 else if (cinfo.out_color_components > 1)
6472 ir = 0, ig = 1, ib = 0;
6473 else
6474 ir = 0, ig = 0, ib = 0;
6475
6476 /* Use the color table mechanism because it handles colors that
6477 cannot be allocated nicely. Such colors will be replaced with
6478 a default color, and we don't have to care about which colors
6479 can be freed safely, and which can't. */
6480 init_color_table ();
6481 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6482 * sizeof *colors);
6483
6484 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6485 {
6486 /* Multiply RGB values with 255 because X expects RGB values
6487 in the range 0..0xffff. */
6488 int r = cinfo.colormap[ir][i] << 8;
6489 int g = cinfo.colormap[ig][i] << 8;
6490 int b = cinfo.colormap[ib][i] << 8;
6491 colors[i] = lookup_rgb_color (f, r, g, b);
6492 }
6493
6494#ifdef COLOR_TABLE_SUPPORT
6495 /* Remember those colors actually allocated. */
6496 img->colors = colors_in_color_table (&img->ncolors);
6497 free_color_table ();
6498#endif /* COLOR_TABLE_SUPPORT */
6499 }
6500
6501 /* Read pixels. */
6502 row_stride = width * cinfo.output_components;
6503 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6504 row_stride, 1);
6505 for (y = 0; y < height; ++y)
6506 {
6507 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6508 for (x = 0; x < cinfo.output_width; ++x)
6509 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6510 }
6511
6512 /* Clean up. */
6513 fn_jpeg_finish_decompress (&cinfo);
6514 fn_jpeg_destroy_decompress (&cinfo);
6515 if (fp)
6516 fclose ((FILE *) fp);
6517
6518 /* Maybe fill in the background field while we have ximg handy. */
6519 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
6520 /* Casting avoids a GCC warning. */
6521 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
6522
6523 /* Put the image into the pixmap. */
6524 x_put_x_image (f, ximg, img->pixmap, width, height);
6525 x_destroy_x_image (ximg);
4ef0d4d0
KS
6526 return 1;
6527}
6528
6529#else /* HAVE_JPEG */
6530
edfda783
AR
6531#ifdef HAVE_NS
6532static int
6533jpeg_load (struct frame *f, struct image *img)
6534{
ed3751c8
JB
6535 return ns_load_image (f, img,
6536 image_spec_value (img->spec, QCfile, NULL),
6537 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
6538}
6539#endif /* HAVE_NS */
6540
4ef0d4d0
KS
6541#endif /* !HAVE_JPEG */
6542
6543
6544\f
6545/***********************************************************************
6546 TIFF
6547 ***********************************************************************/
6548
9e2a2647 6549#if defined (HAVE_TIFF) || defined (HAVE_NS)
4ef0d4d0 6550
f57e2426
J
6551static int tiff_image_p (Lisp_Object object);
6552static int tiff_load (struct frame *f, struct image *img);
4ef0d4d0
KS
6553
6554/* The symbol `tiff' identifying images of this type. */
6555
955cbe7b 6556static Lisp_Object Qtiff;
4ef0d4d0
KS
6557
6558/* Indices of image specification fields in tiff_format, below. */
6559
6560enum tiff_keyword_index
6561{
6562 TIFF_TYPE,
6563 TIFF_DATA,
6564 TIFF_FILE,
6565 TIFF_ASCENT,
6566 TIFF_MARGIN,
6567 TIFF_RELIEF,
6568 TIFF_ALGORITHM,
6569 TIFF_HEURISTIC_MASK,
6570 TIFF_MASK,
6571 TIFF_BACKGROUND,
58279503 6572 TIFF_INDEX,
4ef0d4d0
KS
6573 TIFF_LAST
6574};
6575
6576/* Vector of image_keyword structures describing the format
6577 of valid user-defined image specifications. */
6578
91433552 6579static const struct image_keyword tiff_format[TIFF_LAST] =
4ef0d4d0
KS
6580{
6581 {":type", IMAGE_SYMBOL_VALUE, 1},
6582 {":data", IMAGE_STRING_VALUE, 0},
6583 {":file", IMAGE_STRING_VALUE, 0},
6584 {":ascent", IMAGE_ASCENT_VALUE, 0},
6585 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6586 {":relief", IMAGE_INTEGER_VALUE, 0},
6587 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6588 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6589 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
58279503
JR
6590 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6591 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
4ef0d4d0
KS
6592};
6593
6594/* Structure describing the image type `tiff'. */
6595
6596static struct image_type tiff_type =
6597{
6598 &Qtiff,
6599 tiff_image_p,
6600 tiff_load,
6601 x_clear_image,
6602 NULL
6603};
6604
6605/* Return non-zero if OBJECT is a valid TIFF image specification. */
6606
6607static int
d3da34e0 6608tiff_image_p (Lisp_Object object)
4ef0d4d0
KS
6609{
6610 struct image_keyword fmt[TIFF_LAST];
72af86bd 6611 memcpy (fmt, tiff_format, sizeof fmt);
4ef0d4d0
KS
6612
6613 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6614 return 0;
6615
6616 /* Must specify either the :data or :file keyword. */
6617 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6618}
6619
9e2a2647 6620#endif /* HAVE_TIFF || HAVE_NS */
4ef0d4d0
KS
6621
6622#ifdef HAVE_TIFF
6623
6624#include <tiffio.h>
6625
6626#ifdef HAVE_NTGUI
6627
6628/* TIFF library details. */
14beddf4
CY
6629DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
6630DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
6631DEF_IMGLIB_FN (TIFF *, TIFFOpen, (const char *, const char *));
6632DEF_IMGLIB_FN (TIFF *, TIFFClientOpen, (const char *, const char *, thandle_t,
850690cc
JB
6633 TIFFReadWriteProc, TIFFReadWriteProc,
6634 TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
6635 TIFFMapFileProc, TIFFUnmapFileProc));
14beddf4
CY
6636DEF_IMGLIB_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
6637DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
6638DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
6639DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
4ef0d4d0
KS
6640
6641static int
0855eb52 6642init_tiff_functions (Lisp_Object libraries)
4ef0d4d0
KS
6643{
6644 HMODULE library;
6645
0855eb52 6646 if (!(library = w32_delayed_load (libraries, Qtiff)))
4ef0d4d0
KS
6647 return 0;
6648
6649 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6650 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6651 LOAD_IMGLIB_FN (library, TIFFOpen);
6652 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6653 LOAD_IMGLIB_FN (library, TIFFGetField);
6654 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6655 LOAD_IMGLIB_FN (library, TIFFClose);
58279503 6656 LOAD_IMGLIB_FN (library, TIFFSetDirectory);
4ef0d4d0
KS
6657 return 1;
6658}
6659
6660#else
6661
6662#define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6663#define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6664#define fn_TIFFOpen TIFFOpen
6665#define fn_TIFFClientOpen TIFFClientOpen
6666#define fn_TIFFGetField TIFFGetField
6667#define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6668#define fn_TIFFClose TIFFClose
58279503 6669#define fn_TIFFSetDirectory TIFFSetDirectory
4ef0d4d0
KS
6670#endif /* HAVE_NTGUI */
6671
6672
6673/* Reading from a memory buffer for TIFF images Based on the PNG
6674 memory source, but we have to provide a lot of extra functions.
6675 Blah.
6676
6677 We really only need to implement read and seek, but I am not
6678 convinced that the TIFF library is smart enough not to destroy
6679 itself if we only hand it the function pointers we need to
6680 override. */
6681
6682typedef struct
6683{
6684 unsigned char *bytes;
3f791afe
PE
6685 ptrdiff_t len;
6686 ptrdiff_t index;
4ef0d4d0
KS
6687}
6688tiff_memory_source;
6689
3f791afe 6690static tsize_t
d3da34e0 6691tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
4ef0d4d0
KS
6692{
6693 tiff_memory_source *src = (tiff_memory_source *) data;
6694
3f791afe 6695 size = min (size, src->len - src->index);
72af86bd 6696 memcpy (buf, src->bytes + src->index, size);
4ef0d4d0
KS
6697 src->index += size;
6698 return size;
6699}
6700
3f791afe 6701static tsize_t
d3da34e0 6702tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size)
4ef0d4d0 6703{
3f791afe 6704 return -1;
4ef0d4d0
KS
6705}
6706
6707static toff_t
d3da34e0 6708tiff_seek_in_memory (thandle_t data, toff_t off, int whence)
4ef0d4d0
KS
6709{
6710 tiff_memory_source *src = (tiff_memory_source *) data;
3f791afe 6711 ptrdiff_t idx;
4ef0d4d0
KS
6712
6713 switch (whence)
6714 {
6715 case SEEK_SET: /* Go from beginning of source. */
6716 idx = off;
6717 break;
6718
6719 case SEEK_END: /* Go from end of source. */
6720 idx = src->len + off;
6721 break;
6722
6723 case SEEK_CUR: /* Go from current position. */
6724 idx = src->index + off;
6725 break;
6726
6727 default: /* Invalid `whence'. */
6728 return -1;
6729 }
6730
6731 if (idx > src->len || idx < 0)
6732 return -1;
6733
6734 src->index = idx;
6735 return src->index;
6736}
6737
6738static int
d3da34e0 6739tiff_close_memory (thandle_t data)
4ef0d4d0
KS
6740{
6741 /* NOOP */
6742 return 0;
6743}
6744
6745static int
d3da34e0 6746tiff_mmap_memory (thandle_t data, tdata_t *pbase, toff_t *psize)
4ef0d4d0
KS
6747{
6748 /* It is already _IN_ memory. */
6749 return 0;
6750}
6751
6752static void
d3da34e0 6753tiff_unmap_memory (thandle_t data, tdata_t base, toff_t size)
4ef0d4d0
KS
6754{
6755 /* We don't need to do this. */
6756}
6757
6758static toff_t
d3da34e0 6759tiff_size_of_memory (thandle_t data)
4ef0d4d0
KS
6760{
6761 return ((tiff_memory_source *) data)->len;
6762}
6763
6764
13464394
PE
6765static void tiff_handler (const char *, const char *, const char *, va_list)
6766 ATTRIBUTE_FORMAT_PRINTF (3, 0);
6767static void
6768tiff_handler (const char *log_format, const char *title,
6769 const char *format, va_list ap)
6770{
6771 /* doprnt is not suitable here, as TIFF handlers are called from
6772 libtiff and are passed arbitrary printf directives. Instead, use
6773 vsnprintf, taking care to be portable to nonstandard environments
6774 where vsnprintf returns -1 on buffer overflow. Since it's just a
6775 log entry, it's OK to truncate it. */
6776 char buf[4000];
6777 int len = vsnprintf (buf, sizeof buf, format, ap);
6778 add_to_log (log_format, build_string (title),
6779 make_string (buf, max (0, min (len, sizeof buf - 1))));
6780}
6781
5e2d4a30
PE
6782static void tiff_error_handler (const char *, const char *, va_list)
6783 ATTRIBUTE_FORMAT_PRINTF (2, 0);
4ef0d4d0 6784static void
d3da34e0 6785tiff_error_handler (const char *title, const char *format, va_list ap)
4ef0d4d0 6786{
13464394 6787 tiff_handler ("TIFF error: %s %s", title, format, ap);
4ef0d4d0
KS
6788}
6789
6790
5e2d4a30
PE
6791static void tiff_warning_handler (const char *, const char *, va_list)
6792 ATTRIBUTE_FORMAT_PRINTF (2, 0);
4ef0d4d0 6793static void
d3da34e0 6794tiff_warning_handler (const char *title, const char *format, va_list ap)
4ef0d4d0 6795{
13464394 6796 tiff_handler ("TIFF warning: %s %s", title, format, ap);
4ef0d4d0
KS
6797}
6798
6799
6800/* Load TIFF image IMG for use on frame F. Value is non-zero if
6801 successful. */
6802
6803static int
d3da34e0 6804tiff_load (struct frame *f, struct image *img)
4ef0d4d0
KS
6805{
6806 Lisp_Object file, specified_file;
6807 Lisp_Object specified_data;
6808 TIFF *tiff;
58279503 6809 int width, height, x, y, count;
4ef0d4d0 6810 uint32 *buf;
03d0a109 6811 int rc;
4ef0d4d0 6812 XImagePtr ximg;
4ef0d4d0 6813 tiff_memory_source memsrc;
58279503 6814 Lisp_Object image;
4ef0d4d0
KS
6815
6816 specified_file = image_spec_value (img->spec, QCfile, NULL);
6817 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0 6818
5e2d4a30
PE
6819 fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
6820 fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
4ef0d4d0
KS
6821
6822 if (NILP (specified_data))
6823 {
6824 /* Read from a file */
6825 file = x_find_image_file (specified_file);
6826 if (!STRINGP (file))
6827 {
6828 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
6829 return 0;
6830 }
6831
df61c790 6832 /* Try to open the image file. */
b19beacc 6833 tiff = fn_TIFFOpen (SSDATA (file), "r");
4ef0d4d0
KS
6834 if (tiff == NULL)
6835 {
6836 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
6837 return 0;
6838 }
6839 }
6840 else
6841 {
7574650a
AS
6842 if (!STRINGP (specified_data))
6843 {
6844 image_error ("Invalid image data `%s'", specified_data, Qnil);
6845 return 0;
6846 }
6847
4ef0d4d0
KS
6848 /* Memory source! */
6849 memsrc.bytes = SDATA (specified_data);
6850 memsrc.len = SBYTES (specified_data);
6851 memsrc.index = 0;
6852
3082f617 6853 tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
3f791afe
PE
6854 tiff_read_from_memory,
6855 tiff_write_from_memory,
df61c790
AS
6856 tiff_seek_in_memory,
6857 tiff_close_memory,
6858 tiff_size_of_memory,
6859 tiff_mmap_memory,
6860 tiff_unmap_memory);
4ef0d4d0
KS
6861
6862 if (!tiff)
6863 {
6864 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
4ef0d4d0
KS
6865 return 0;
6866 }
6867 }
6868
58279503
JR
6869 image = image_spec_value (img->spec, QCindex, NULL);
6870 if (INTEGERP (image))
6871 {
13464394
PE
6872 EMACS_INT ino = XFASTINT (image);
6873 if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
6874 && fn_TIFFSetDirectory (tiff, ino)))
58279503
JR
6875 {
6876 image_error ("Invalid image number `%s' in image `%s'",
6877 image, img->spec);
6878 fn_TIFFClose (tiff);
58279503
JR
6879 return 0;
6880 }
6881 }
6882
4ef0d4d0
KS
6883 /* Get width and height of the image, and allocate a raster buffer
6884 of width x height 32-bit values. */
6885 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
6886 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
f1f25b99
CY
6887
6888 if (!check_image_size (f, width, height))
6889 {
10ea2b82 6890 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
58279503 6891 fn_TIFFClose (tiff);
f1f25b99
CY
6892 return 0;
6893 }
6894
ca4aa935
PE
6895 /* Create the X image and pixmap. */
6896 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
6897 && x_create_x_image_and_pixmap (f, width, height, 0,
6898 &ximg, &img->pixmap)))
6899 {
6900 fn_TIFFClose (tiff);
6901 return 0;
6902 }
6903
3f791afe 6904 buf = (uint32 *) xmalloc (sizeof *buf * width * height);
4ef0d4d0
KS
6905
6906 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
58279503
JR
6907
6908 /* Count the number of images in the file. */
03d0a109
PE
6909 for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
6910 continue;
58279503
JR
6911
6912 if (count > 1)
b50691aa
CY
6913 img->lisp_data = Fcons (Qcount,
6914 Fcons (make_number (count),
6915 img->lisp_data));
58279503 6916
4ef0d4d0
KS
6917 fn_TIFFClose (tiff);
6918 if (!rc)
6919 {
6920 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
6921 xfree (buf);
4ef0d4d0
KS
6922 return 0;
6923 }
6924
4ef0d4d0
KS
6925 /* Initialize the color table. */
6926 init_color_table ();
6927
6928 /* Process the pixel raster. Origin is in the lower-left corner. */
6929 for (y = 0; y < height; ++y)
6930 {
6931 uint32 *row = buf + y * width;
6932
6933 for (x = 0; x < width; ++x)
6934 {
6935 uint32 abgr = row[x];
6936 int r = TIFFGetR (abgr) << 8;
6937 int g = TIFFGetG (abgr) << 8;
6938 int b = TIFFGetB (abgr) << 8;
6939 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
6940 }
6941 }
6942
6943#ifdef COLOR_TABLE_SUPPORT
6944 /* Remember the colors allocated for the image. Free the color table. */
6945 img->colors = colors_in_color_table (&img->ncolors);
6946 free_color_table ();
6947#endif /* COLOR_TABLE_SUPPORT */
6948
6949 img->width = width;
6950 img->height = height;
6951
6952 /* Maybe fill in the background field while we have ximg handy. */
6953 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
6954 /* Casting avoids a GCC warning on W32. */
6955 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
6956
6957 /* Put the image into the pixmap, then free the X image and its buffer. */
6958 x_put_x_image (f, ximg, img->pixmap, width, height);
6959 x_destroy_x_image (ximg);
6960 xfree (buf);
6961
4ef0d4d0
KS
6962 return 1;
6963}
6964
6965#else /* HAVE_TIFF */
6966
edfda783
AR
6967#ifdef HAVE_NS
6968static int
6969tiff_load (struct frame *f, struct image *img)
6970{
ed3751c8
JB
6971 return ns_load_image (f, img,
6972 image_spec_value (img->spec, QCfile, NULL),
6973 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
6974}
6975#endif /* HAVE_NS */
6976
4ef0d4d0
KS
6977#endif /* !HAVE_TIFF */
6978
6979
6980\f
6981/***********************************************************************
6982 GIF
6983 ***********************************************************************/
6984
9e2a2647 6985#if defined (HAVE_GIF) || defined (HAVE_NS)
4ef0d4d0 6986
f57e2426
J
6987static int gif_image_p (Lisp_Object object);
6988static int gif_load (struct frame *f, struct image *img);
6989static void gif_clear_image (struct frame *f, struct image *img);
4ef0d4d0
KS
6990
6991/* The symbol `gif' identifying images of this type. */
6992
955cbe7b 6993static Lisp_Object Qgif;
4ef0d4d0
KS
6994
6995/* Indices of image specification fields in gif_format, below. */
6996
6997enum gif_keyword_index
6998{
6999 GIF_TYPE,
7000 GIF_DATA,
7001 GIF_FILE,
7002 GIF_ASCENT,
7003 GIF_MARGIN,
7004 GIF_RELIEF,
7005 GIF_ALGORITHM,
7006 GIF_HEURISTIC_MASK,
7007 GIF_MASK,
7008 GIF_IMAGE,
7009 GIF_BACKGROUND,
7010 GIF_LAST
7011};
7012
7013/* Vector of image_keyword structures describing the format
7014 of valid user-defined image specifications. */
7015
91433552 7016static const struct image_keyword gif_format[GIF_LAST] =
4ef0d4d0
KS
7017{
7018 {":type", IMAGE_SYMBOL_VALUE, 1},
7019 {":data", IMAGE_STRING_VALUE, 0},
7020 {":file", IMAGE_STRING_VALUE, 0},
7021 {":ascent", IMAGE_ASCENT_VALUE, 0},
7022 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7023 {":relief", IMAGE_INTEGER_VALUE, 0},
7024 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7025 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7026 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
58279503 7027 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
4ef0d4d0
KS
7028 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7029};
7030
7031/* Structure describing the image type `gif'. */
7032
7033static struct image_type gif_type =
7034{
7035 &Qgif,
7036 gif_image_p,
7037 gif_load,
6ac3c7bb 7038 gif_clear_image,
4ef0d4d0
KS
7039 NULL
7040};
7041
6ac3c7bb
KS
7042/* Free X resources of GIF image IMG which is used on frame F. */
7043
7044static void
d3da34e0 7045gif_clear_image (struct frame *f, struct image *img)
6ac3c7bb 7046{
b50691aa 7047 img->lisp_data = Qnil;
6ac3c7bb
KS
7048 x_clear_image (f, img);
7049}
7050
4ef0d4d0
KS
7051/* Return non-zero if OBJECT is a valid GIF image specification. */
7052
7053static int
d3da34e0 7054gif_image_p (Lisp_Object object)
4ef0d4d0
KS
7055{
7056 struct image_keyword fmt[GIF_LAST];
72af86bd 7057 memcpy (fmt, gif_format, sizeof fmt);
4ef0d4d0
KS
7058
7059 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7060 return 0;
7061
7062 /* Must specify either the :data or :file keyword. */
7063 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7064}
7065
9e2a2647 7066#endif /* HAVE_GIF */
4ef0d4d0
KS
7067
7068#ifdef HAVE_GIF
7069
9e2a2647 7070#if defined (HAVE_NTGUI)
2e09fef1
EZ
7071/* winuser.h might define DrawText to DrawTextA or DrawTextW.
7072 Undefine before redefining to avoid a preprocessor warning. */
7073#ifdef DrawText
7074#undef DrawText
7075#endif
4ef0d4d0
KS
7076/* avoid conflict with QuickdrawText.h */
7077#define DrawText gif_DrawText
7078#include <gif_lib.h>
7079#undef DrawText
7080
9e2a2647 7081#else /* HAVE_NTGUI */
4ef0d4d0
KS
7082
7083#include <gif_lib.h>
7084
9e2a2647 7085#endif /* HAVE_NTGUI */
4ef0d4d0
KS
7086
7087
7088#ifdef HAVE_NTGUI
7089
7090/* GIF library details. */
14beddf4
CY
7091DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
7092DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
7093DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
7094DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
4ef0d4d0
KS
7095
7096static int
0855eb52 7097init_gif_functions (Lisp_Object libraries)
4ef0d4d0
KS
7098{
7099 HMODULE library;
7100
0855eb52 7101 if (!(library = w32_delayed_load (libraries, Qgif)))
4ef0d4d0
KS
7102 return 0;
7103
7104 LOAD_IMGLIB_FN (library, DGifCloseFile);
7105 LOAD_IMGLIB_FN (library, DGifSlurp);
7106 LOAD_IMGLIB_FN (library, DGifOpen);
7107 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7108 return 1;
7109}
7110
7111#else
7112
7113#define fn_DGifCloseFile DGifCloseFile
7114#define fn_DGifSlurp DGifSlurp
7115#define fn_DGifOpen DGifOpen
7116#define fn_DGifOpenFileName DGifOpenFileName
7117
7118#endif /* HAVE_NTGUI */
7119
7120/* Reading a GIF image from memory
7121 Based on the PNG memory stuff to a certain extent. */
7122
7123typedef struct
7124{
7125 unsigned char *bytes;
3f791afe
PE
7126 ptrdiff_t len;
7127 ptrdiff_t index;
4ef0d4d0
KS
7128}
7129gif_memory_source;
7130
7131/* Make the current memory source available to gif_read_from_memory.
7132 It's done this way because not all versions of libungif support
7133 a UserData field in the GifFileType structure. */
7134static gif_memory_source *current_gif_memory_src;
7135
7136static int
d3da34e0 7137gif_read_from_memory (GifFileType *file, GifByteType *buf, int len)
4ef0d4d0
KS
7138{
7139 gif_memory_source *src = current_gif_memory_src;
7140
7141 if (len > src->len - src->index)
7142 return -1;
7143
72af86bd 7144 memcpy (buf, src->bytes + src->index, len);
4ef0d4d0
KS
7145 src->index += len;
7146 return len;
7147}
7148
7149
7150/* Load GIF image IMG for use on frame F. Value is non-zero if
7151 successful. */
7152
91433552
DN
7153static const int interlace_start[] = {0, 4, 2, 1};
7154static const int interlace_increment[] = {8, 8, 4, 2};
aca946f3 7155
17c0c952
JD
7156#define GIF_LOCAL_DESCRIPTOR_EXTENSION 249
7157
4ef0d4d0 7158static int
d3da34e0 7159gif_load (struct frame *f, struct image *img)
4ef0d4d0 7160{
60002bf5
CY
7161 Lisp_Object file;
7162 int rc, width, height, x, y, i, j;
4ef0d4d0
KS
7163 XImagePtr ximg;
7164 ColorMapObject *gif_color_map;
7165 unsigned long pixel_colors[256];
7166 GifFileType *gif;
60002bf5 7167 int image_height, image_width;
4ef0d4d0 7168 gif_memory_source memsrc;
60002bf5
CY
7169 Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7170 Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
7171 Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
7172 unsigned long bgcolor = 0;
13464394 7173 EMACS_INT idx;
4ef0d4d0
KS
7174
7175 if (NILP (specified_data))
7176 {
7177 file = x_find_image_file (specified_file);
7178 if (!STRINGP (file))
7179 {
7180 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
7181 return 0;
7182 }
7183
df61c790 7184 /* Open the GIF file. */
2037898d 7185 gif = fn_DGifOpenFileName (SSDATA (file));
4ef0d4d0
KS
7186 if (gif == NULL)
7187 {
7188 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
7189 return 0;
7190 }
7191 }
7192 else
7193 {
7574650a
AS
7194 if (!STRINGP (specified_data))
7195 {
7196 image_error ("Invalid image data `%s'", specified_data, Qnil);
7197 return 0;
7198 }
7199
4ef0d4d0
KS
7200 /* Read from memory! */
7201 current_gif_memory_src = &memsrc;
7202 memsrc.bytes = SDATA (specified_data);
7203 memsrc.len = SBYTES (specified_data);
7204 memsrc.index = 0;
7205
df61c790 7206 gif = fn_DGifOpen (&memsrc, gif_read_from_memory);
4ef0d4d0
KS
7207 if (!gif)
7208 {
7209 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
4ef0d4d0
KS
7210 return 0;
7211 }
7212 }
7213
f1f25b99
CY
7214 /* Before reading entire contents, check the declared image size. */
7215 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7216 {
10ea2b82 7217 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99 7218 fn_DGifCloseFile (gif);
f1f25b99
CY
7219 return 0;
7220 }
7221
4ef0d4d0
KS
7222 /* Read entire contents. */
7223 rc = fn_DGifSlurp (gif);
60002bf5 7224 if (rc == GIF_ERROR || gif->ImageCount <= 0)
4ef0d4d0
KS
7225 {
7226 image_error ("Error reading `%s'", img->spec, Qnil);
7227 fn_DGifCloseFile (gif);
4ef0d4d0
KS
7228 return 0;
7229 }
7230
60002bf5
CY
7231 /* Which sub-image are we to display? */
7232 {
33290528
PE
7233 Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
7234 idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
60002bf5 7235 if (idx < 0 || idx >= gif->ImageCount)
17c0c952 7236 {
60002bf5 7237 image_error ("Invalid image number `%s' in image `%s'",
33290528 7238 image_number, img->spec);
60002bf5
CY
7239 fn_DGifCloseFile (gif);
7240 return 0;
17c0c952 7241 }
60002bf5 7242 }
17c0c952 7243
60002bf5
CY
7244 img->corners[TOP_CORNER] = gif->SavedImages[idx].ImageDesc.Top;
7245 img->corners[LEFT_CORNER] = gif->SavedImages[idx].ImageDesc.Left;
7246 image_height = gif->SavedImages[idx].ImageDesc.Height;
6ac3c7bb 7247 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
60002bf5 7248 image_width = gif->SavedImages[idx].ImageDesc.Width;
6ac3c7bb 7249 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
0f4aca46
KS
7250
7251 width = img->width = max (gif->SWidth,
7252 max (gif->Image.Left + gif->Image.Width,
6ac3c7bb 7253 img->corners[RIGHT_CORNER]));
0f4aca46
KS
7254 height = img->height = max (gif->SHeight,
7255 max (gif->Image.Top + gif->Image.Height,
6ac3c7bb 7256 img->corners[BOT_CORNER]));
4ef0d4d0 7257
f1f25b99
CY
7258 if (!check_image_size (f, width, height))
7259 {
10ea2b82 7260 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99 7261 fn_DGifCloseFile (gif);
f1f25b99
CY
7262 return 0;
7263 }
7264
4ef0d4d0
KS
7265 /* Create the X image and pixmap. */
7266 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7267 {
7268 fn_DGifCloseFile (gif);
4ef0d4d0
KS
7269 return 0;
7270 }
7271
60002bf5
CY
7272 /* Clear the part of the screen image not covered by the image.
7273 Full animated GIF support requires more here (see the gif89 spec,
7274 disposal methods). Let's simply assume that the part not covered
7275 by a sub-image is in the frame's background color. */
6ac3c7bb 7276 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
4ef0d4d0
KS
7277 for (x = 0; x < width; ++x)
7278 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7279
6ac3c7bb 7280 for (y = img->corners[BOT_CORNER]; y < height; ++y)
4ef0d4d0
KS
7281 for (x = 0; x < width; ++x)
7282 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7283
6ac3c7bb 7284 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
4ef0d4d0 7285 {
6ac3c7bb 7286 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
4ef0d4d0 7287 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6ac3c7bb 7288 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
4ef0d4d0
KS
7289 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7290 }
7291
60002bf5 7292 /* Read the GIF image into the X image. */
4ef0d4d0 7293
60002bf5
CY
7294 /* FIXME: With the current implementation, loading an animated gif
7295 is quadratic in the number of animation frames, since each frame
7296 is a separate struct image. We must provide a way for a single
7297 gif_load call to construct and save all animation frames. */
4ef0d4d0 7298
60002bf5
CY
7299 init_color_table ();
7300 if (STRINGP (specified_bg))
7301 bgcolor = x_alloc_image_color (f, img, specified_bg,
7302 FRAME_BACKGROUND_PIXEL (f));
7303 for (j = 0; j <= idx; ++j)
7304 {
7305 /* We use a local variable `raster' here because RasterBits is a
7306 char *, which invites problems with bytes >= 0x80. */
7307 struct SavedImage *subimage = gif->SavedImages + j;
7308 unsigned char *raster = (unsigned char *) subimage->RasterBits;
7309 int transparency_color_index = -1;
7310 int disposal = 0;
7311
7312 /* Find the Graphic Control Extension block for this sub-image.
7313 Extract the disposal method and transparency color. */
7314 for (i = 0; i < subimage->ExtensionBlockCount; i++)
4ef0d4d0 7315 {
60002bf5 7316 ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
4ef0d4d0 7317
60002bf5
CY
7318 if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
7319 && extblock->ByteCount == 4
7320 && extblock->Bytes[0] & 1)
4ef0d4d0 7321 {
60002bf5
CY
7322 /* From gif89a spec: 1 = "keep in place", 2 = "restore
7323 to background". Treat any other value like 2. */
7324 disposal = (extblock->Bytes[0] >> 2) & 7;
2547adb1 7325 transparency_color_index = (unsigned char) extblock->Bytes[3];
60002bf5 7326 break;
4ef0d4d0 7327 }
4ef0d4d0 7328 }
60002bf5
CY
7329
7330 /* We can't "keep in place" the first subimage. */
7331 if (j == 0)
7332 disposal = 2;
7333
7334 /* Allocate subimage colors. */
7335 memset (pixel_colors, 0, sizeof pixel_colors);
7336 gif_color_map = subimage->ImageDesc.ColorMap;
7337 if (!gif_color_map)
7338 gif_color_map = gif->SColorMap;
7339
7340 if (gif_color_map)
7341 for (i = 0; i < gif_color_map->ColorCount; ++i)
4ef0d4d0 7342 {
60002bf5
CY
7343 if (transparency_color_index == i)
7344 pixel_colors[i] = STRINGP (specified_bg)
7345 ? bgcolor : FRAME_BACKGROUND_PIXEL (f);
7346 else
7347 {
7348 int r = gif_color_map->Colors[i].Red << 8;
7349 int g = gif_color_map->Colors[i].Green << 8;
7350 int b = gif_color_map->Colors[i].Blue << 8;
7351 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7352 }
4ef0d4d0 7353 }
60002bf5
CY
7354
7355 /* Apply the pixel values. */
7356 if (gif->SavedImages[j].ImageDesc.Interlace)
7357 {
7358 int row, pass;
7359
7360 for (y = 0, row = interlace_start[0], pass = 0;
7361 y < image_height;
7362 y++, row += interlace_increment[pass])
7363 {
7364 if (row >= image_height)
7365 {
7366 row = interlace_start[++pass];
7367 while (row >= image_height)
7368 row = interlace_start[++pass];
7369 }
7370
7371 for (x = 0; x < image_width; x++)
7372 {
7373 int c = raster[y * image_width + x];
7374 if (transparency_color_index != c || disposal != 1)
7375 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7376 row + img->corners[TOP_CORNER], pixel_colors[c]);
7377 }
7378 }
7379 }
7380 else
7381 {
7382 for (y = 0; y < image_height; ++y)
7383 for (x = 0; x < image_width; ++x)
7384 {
7385 int c = raster[y * image_width + x];
7386 if (transparency_color_index != c || disposal != 1)
7387 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7388 y + img->corners[TOP_CORNER], pixel_colors[c]);
7389 }
7390 }
4ef0d4d0
KS
7391 }
7392
60002bf5
CY
7393#ifdef COLOR_TABLE_SUPPORT
7394 img->colors = colors_in_color_table (&img->ncolors);
7395 free_color_table ();
7396#endif /* COLOR_TABLE_SUPPORT */
7397
1546c559
JL
7398 /* Save GIF image extension data for `image-metadata'.
7399 Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)). */
b50691aa 7400 img->lisp_data = Qnil;
60002bf5 7401 if (gif->SavedImages[idx].ExtensionBlockCount > 0)
6ac3c7bb 7402 {
13464394 7403 int delay = 0;
60002bf5
CY
7404 ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
7405 for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
6ac3c7bb 7406 /* Append (... FUNCTION "BYTES") */
1100a63c
CY
7407 {
7408 img->lisp_data
7409 = Fcons (make_number (ext->Function),
7410 Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7411 img->lisp_data));
7412 if (ext->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION
7413 && ext->ByteCount == 4)
7414 {
7415 delay = ext->Bytes[2] << CHAR_BIT;
7416 delay |= ext->Bytes[1];
7417 }
7418 }
b50691aa 7419 img->lisp_data = Fcons (Qextension_data,
1100a63c
CY
7420 Fcons (img->lisp_data, Qnil));
7421 if (delay)
7422 img->lisp_data
7423 = Fcons (Qdelay,
13464394 7424 Fcons (make_float (delay / 100.0),
1100a63c 7425 img->lisp_data));
6ac3c7bb 7426 }
1100a63c 7427
6ac3c7bb 7428 if (gif->ImageCount > 1)
b50691aa
CY
7429 img->lisp_data = Fcons (Qcount,
7430 Fcons (make_number (gif->ImageCount),
7431 img->lisp_data));
6ac3c7bb 7432
4ef0d4d0
KS
7433 fn_DGifCloseFile (gif);
7434
7435 /* Maybe fill in the background field while we have ximg handy. */
7436 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
7437 /* Casting avoids a GCC warning. */
7438 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
7439
7440 /* Put the image into the pixmap, then free the X image and its buffer. */
7441 x_put_x_image (f, ximg, img->pixmap, width, height);
7442 x_destroy_x_image (ximg);
7443
4ef0d4d0
KS
7444 return 1;
7445}
7446
2e09fef1 7447#else /* !HAVE_GIF */
4ef0d4d0 7448
edfda783
AR
7449#ifdef HAVE_NS
7450static int
7451gif_load (struct frame *f, struct image *img)
7452{
ed3751c8
JB
7453 return ns_load_image (f, img,
7454 image_spec_value (img->spec, QCfile, NULL),
7455 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
7456}
7457#endif /* HAVE_NS */
7458
4ef0d4d0
KS
7459#endif /* HAVE_GIF */
7460
7461
3de25479 7462/***********************************************************************
a32d4040 7463 ImageMagick
4917006b 7464***********************************************************************/
3de25479 7465#if defined (HAVE_IMAGEMAGICK)
3de25479 7466
4b66faf3 7467static Lisp_Object Qimagemagick;
a32d4040 7468
d66c4c7c
CY
7469static int imagemagick_image_p (Lisp_Object);
7470static int imagemagick_load (struct frame *, struct image *);
7471static void imagemagick_clear_image (struct frame *, struct image *);
7472
a32d4040 7473/* Indices of image specification fields in imagemagick_format. */
3de25479
JV
7474
7475enum imagemagick_keyword_index
4917006b
JV
7476 {
7477 IMAGEMAGICK_TYPE,
7478 IMAGEMAGICK_DATA,
7479 IMAGEMAGICK_FILE,
7480 IMAGEMAGICK_ASCENT,
7481 IMAGEMAGICK_MARGIN,
7482 IMAGEMAGICK_RELIEF,
7483 IMAGEMAGICK_ALGORITHM,
7484 IMAGEMAGICK_HEURISTIC_MASK,
7485 IMAGEMAGICK_MASK,
7486 IMAGEMAGICK_BACKGROUND,
c7f514b5
JV
7487 IMAGEMAGICK_HEIGHT,
7488 IMAGEMAGICK_WIDTH,
7489 IMAGEMAGICK_ROTATION,
7490 IMAGEMAGICK_CROP,
4917006b
JV
7491 IMAGEMAGICK_LAST
7492 };
3de25479
JV
7493
7494/* Vector of image_keyword structures describing the format
7495 of valid user-defined image specifications. */
7496
7497static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
4917006b
JV
7498 {
7499 {":type", IMAGE_SYMBOL_VALUE, 1},
7500 {":data", IMAGE_STRING_VALUE, 0},
7501 {":file", IMAGE_STRING_VALUE, 0},
7502 {":ascent", IMAGE_ASCENT_VALUE, 0},
7503 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7504 {":relief", IMAGE_INTEGER_VALUE, 0},
7505 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7506 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7507 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
c7f514b5 7508 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
7574650a
AS
7509 {":height", IMAGE_INTEGER_VALUE, 0},
7510 {":width", IMAGE_INTEGER_VALUE, 0},
7511 {":rotation", IMAGE_NUMBER_VALUE, 0},
c7f514b5 7512 {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
4917006b 7513 };
a32d4040 7514
d66c4c7c
CY
7515/* Structure describing the image type for any image handled via
7516 ImageMagick. */
7517
7518static struct image_type imagemagick_type =
7519 {
7520 &Qimagemagick,
7521 imagemagick_image_p,
7522 imagemagick_load,
7523 imagemagick_clear_image,
7524 NULL
7525 };
7526
3de25479
JV
7527/* Free X resources of imagemagick image IMG which is used on frame F. */
7528
7529static void
4917006b
JV
7530imagemagick_clear_image (struct frame *f,
7531 struct image *img)
3de25479 7532{
3de25479
JV
7533 x_clear_image (f, img);
7534}
7535
3de25479
JV
7536/* Return non-zero if OBJECT is a valid IMAGEMAGICK image specification. Do
7537 this by calling parse_image_spec and supplying the keywords that
7538 identify the IMAGEMAGICK format. */
7539
7540static int
4917006b 7541imagemagick_image_p (Lisp_Object object)
3de25479
JV
7542{
7543 struct image_keyword fmt[IMAGEMAGICK_LAST];
dbfe4532 7544 memcpy (fmt, imagemagick_format, sizeof fmt);
3de25479
JV
7545
7546 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
7547 return 0;
7548
7549 /* Must specify either the :data or :file keyword. */
7550 return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
7551}
7552
7553/* The GIF library also defines DrawRectangle, but its never used in Emacs.
7554 Therefore rename the function so it doesnt collide with ImageMagick. */
7555#define DrawRectangle DrawRectangleGif
7556#include <wand/MagickWand.h>
7557
60737f02
PE
7558/* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
7559 Emacs seems to work fine with the hidden version, so unhide it. */
7560#include <magick/version.h>
7561#if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
7562extern WandExport void PixelGetMagickColor (const PixelWand *,
7563 MagickPixelPacket *);
7564#endif
7565
d66c4c7c
CY
7566/* Helper function for imagemagick_load, which does the actual loading
7567 given contents and size, apart from frame and image structures,
7568 passed from imagemagick_load. Uses librimagemagick to do most of
7569 the image processing.
3de25479 7570
d66c4c7c
CY
7571 F is a pointer to the Emacs frame; IMG to the image structure to
7572 prepare; CONTENTS is the string containing the IMAGEMAGICK data to
7573 be parsed; SIZE is the number of bytes of data; and FILENAME is
7574 either the file name or the image data.
3de25479 7575
d66c4c7c 7576 Return non-zero if successful. */
3de25479
JV
7577
7578static int
d66c4c7c
CY
7579imagemagick_load_image (struct frame *f, struct image *img,
7580 unsigned char *contents, unsigned int size,
33290528 7581 char *filename)
3de25479 7582{
1ab0dee5
AS
7583 size_t width;
7584 size_t height;
3de25479 7585
d66c4c7c 7586 MagickBooleanType status;
3de25479
JV
7587
7588 XImagePtr ximg;
3de25479
JV
7589 int x;
7590 int y;
7591
7592 MagickWand *image_wand;
7574650a 7593 MagickWand *ping_wand;
3de25479
JV
7594 PixelIterator *iterator;
7595 PixelWand **pixels;
7596 MagickPixelPacket pixel;
4917006b 7597 Lisp_Object image;
7574650a 7598 Lisp_Object value;
33290528 7599 Lisp_Object crop;
13464394 7600 EMACS_INT ino;
4917006b
JV
7601 int desired_width, desired_height;
7602 double rotation;
13464394 7603 EMACS_INT imagemagick_rendermethod;
7574650a 7604 int pixelwidth;
f3700365
JV
7605 ImageInfo *image_info;
7606 ExceptionInfo *exception;
7607 Image * im_image;
3de25479 7608
7574650a 7609
a32d4040
CY
7610 /* Handle image index for image types who can contain more than one image.
7611 Interface :index is same as for GIF. First we "ping" the image to see how
7612 many sub-images it contains. Pinging is faster than loading the image to
7613 find out things about it. */
f853f599 7614
a32d4040 7615 /* Initialize the imagemagick environment. */
f853f599 7616 MagickWandGenesis ();
3de25479
JV
7617 image = image_spec_value (img->spec, QCindex, NULL);
7618 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7574650a
AS
7619 ping_wand = NewMagickWand ();
7620 MagickSetResolution (ping_wand, 2, 2);
f3700365
JV
7621 if (filename != NULL)
7622 {
7574650a 7623 status = MagickPingImage (ping_wand, filename);
f3700365
JV
7624 }
7625 else
7626 {
7574650a
AS
7627 status = MagickPingImageBlob (ping_wand, contents, size);
7628 }
7629
13464394 7630 if (! (0 <= ino && ino < MagickGetNumberImages (ping_wand)))
7574650a
AS
7631 {
7632 image_error ("Invalid image number `%s' in image `%s'",
7633 image, img->spec);
7634 DestroyMagickWand (ping_wand);
7635 return 0;
f3700365 7636 }
431dab04 7637
f3700365 7638 if (MagickGetNumberImages(ping_wand) > 1)
b50691aa 7639 img->lisp_data =
d2a2d277 7640 Fcons (Qcount,
7574650a 7641 Fcons (make_number (MagickGetNumberImages (ping_wand)),
b50691aa 7642 img->lisp_data));
f3700365
JV
7643
7644 DestroyMagickWand (ping_wand);
f853f599 7645
d66c4c7c
CY
7646 /* Now we know how many images are inside the file. If it's not a
7647 bundle, the number is one. */
f3700365
JV
7648
7649 if (filename != NULL)
7650 {
7574650a
AS
7651 image_info = CloneImageInfo ((ImageInfo *) NULL);
7652 (void) strcpy (image_info->filename, filename);
7653 image_info->number_scenes = 1;
7654 image_info->scene = ino;
7655 exception = AcquireExceptionInfo ();
f3700365 7656
7574650a 7657 im_image = ReadImage (image_info, exception);
466cbae9 7658 DestroyExceptionInfo (exception);
f3700365 7659
f7e13da3
PE
7660 if (im_image == NULL)
7661 goto imagemagick_no_wand;
7662 image_wand = NewMagickWandFromImage (im_image);
7663 DestroyImage(im_image);
f3700365 7664 }
3de25479 7665 else
f3700365 7666 {
7574650a 7667 image_wand = NewMagickWand ();
f7e13da3
PE
7668 if (MagickReadImageBlob (image_wand, contents, size) == MagickFalse)
7669 goto imagemagick_error;
f3700365 7670 }
f853f599 7671
d2a2d277 7672 /* If width and/or height is set in the display spec assume we want
a32d4040 7673 to scale to those values. If either h or w is unspecified, the
f3700365 7674 unspecified should be calculated from the specified to preserve
549a73b9 7675 aspect ratio. */
3de25479 7676
3de25479
JV
7677 value = image_spec_value (img->spec, QCwidth, NULL);
7678 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
7679 value = image_spec_value (img->spec, QCheight, NULL);
7680 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
c7f514b5 7681
bdf6a35d
JV
7682 height = MagickGetImageHeight (image_wand);
7683 width = MagickGetImageWidth (image_wand);
7684
a32d4040
CY
7685 if (desired_width != -1 && desired_height == -1)
7686 /* w known, calculate h. */
7687 desired_height = (double) desired_width / width * height;
7688 if (desired_width == -1 && desired_height != -1)
7689 /* h known, calculate w. */
7690 desired_width = (double) desired_height / height * width;
7691 if (desired_width != -1 && desired_height != -1)
4917006b 7692 {
7574650a
AS
7693 status = MagickScaleImage (image_wand, desired_width, desired_height);
7694 if (status == MagickFalse)
7695 {
7696 image_error ("Imagemagick scale failed", Qnil, Qnil);
7697 goto imagemagick_error;
7698 }
3de25479 7699 }
3de25479 7700
f3700365 7701 /* crop behaves similar to image slicing in Emacs but is more memory
7574650a
AS
7702 efficient. */
7703 crop = image_spec_value (img->spec, QCcrop, NULL);
7704
13464394 7705 if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
7574650a 7706 {
a32d4040
CY
7707 /* After some testing, it seems MagickCropImage is the fastest crop
7708 function in ImageMagick. This crop function seems to do less copying
7709 than the alternatives, but it still reads the entire image into memory
13464394 7710 before cropping, which is apparently difficult to avoid when using
a32d4040 7711 imagemagick. */
13464394 7712 size_t crop_width = XINT (XCAR (crop));
7574650a 7713 crop = XCDR (crop);
13464394 7714 if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
7574650a 7715 {
13464394 7716 size_t crop_height = XINT (XCAR (crop));
7574650a 7717 crop = XCDR (crop);
13464394 7718 if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
7574650a 7719 {
13464394 7720 ssize_t crop_x = XINT (XCAR (crop));
7574650a 7721 crop = XCDR (crop);
13464394 7722 if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
7574650a 7723 {
13464394
PE
7724 ssize_t crop_y = XINT (XCAR (crop));
7725 MagickCropImage (image_wand, crop_width, crop_height,
7726 crop_x, crop_y);
7574650a
AS
7727 }
7728 }
7729 }
7730 }
7731
d2a2d277
JV
7732 /* Furthermore :rotation. we need background color and angle for
7733 rotation. */
3de25479 7734 /*
d2a2d277
JV
7735 TODO background handling for rotation specified_bg =
7736 image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP
549a73b9 7737 (specified_bg). */
4917006b
JV
7738 value = image_spec_value (img->spec, QCrotation, NULL);
7739 if (FLOATP (value))
7740 {
7574650a 7741 PixelWand* background = NewPixelWand ();
3de25479 7742 PixelSetColor (background, "#ffffff");/*TODO remove hardcode*/
7574650a 7743
3de25479 7744 rotation = extract_float (value);
7574650a 7745
4917006b 7746 status = MagickRotateImage (image_wand, background, rotation);
3de25479 7747 DestroyPixelWand (background);
4917006b
JV
7748 if (status == MagickFalse)
7749 {
7750 image_error ("Imagemagick image rotate failed", Qnil, Qnil);
7751 goto imagemagick_error;
7752 }
3de25479 7753 }
7574650a 7754
d66c4c7c
CY
7755 /* Finally we are done manipulating the image. Figure out the
7756 resulting width/height and transfer ownerwship to Emacs. */
4917006b
JV
7757 height = MagickGetImageHeight (image_wand);
7758 width = MagickGetImageWidth (image_wand);
7574650a 7759
3f791afe
PE
7760 if (! (width <= INT_MAX && height <= INT_MAX
7761 && check_image_size (f, width, height)))
3de25479
JV
7762 {
7763 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7764 goto imagemagick_error;
7765 }
7574650a 7766
3de25479
JV
7767 /* We can now get a valid pixel buffer from the imagemagick file, if all
7768 went ok. */
3de25479
JV
7769
7770 init_color_table ();
d2a2d277 7771 imagemagick_rendermethod = (INTEGERP (Vimagemagick_render_type)
13464394 7772 ? XINT (Vimagemagick_render_type) : 0);
4917006b
JV
7773 if (imagemagick_rendermethod == 0)
7774 {
13464394
PE
7775 size_t image_height;
7776
4917006b 7777 /* Try to create a x pixmap to hold the imagemagick pixmap. */
d2a2d277
JV
7778 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7779 &ximg, &img->pixmap))
4917006b 7780 {
466cbae9
AS
7781#ifdef COLOR_TABLE_SUPPORT
7782 free_color_table ();
7783#endif
4917006b
JV
7784 image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
7785 goto imagemagick_error;
7786 }
7574650a 7787
4917006b
JV
7788 /* Copy imagegmagick image to x with primitive yet robust pixel
7789 pusher loop. This has been tested a lot with many different
549a73b9 7790 images. */
7574650a 7791
4917006b
JV
7792 /* Copy pixels from the imagemagick image structure to the x image map. */
7793 iterator = NewPixelIterator (image_wand);
7574650a 7794 if (iterator == (PixelIterator *) NULL)
4917006b 7795 {
466cbae9
AS
7796#ifdef COLOR_TABLE_SUPPORT
7797 free_color_table ();
7798#endif
7799 x_destroy_x_image (ximg);
d2a2d277
JV
7800 image_error ("Imagemagick pixel iterator creation failed",
7801 Qnil, Qnil);
3de25479 7802 goto imagemagick_error;
4917006b
JV
7803 }
7804
13464394
PE
7805 image_height = MagickGetImageHeight (image_wand);
7806 for (y = 0; y < image_height; y++)
4917006b
JV
7807 {
7808 pixels = PixelGetNextIteratorRow (iterator, &width);
7574650a 7809 if (pixels == (PixelWand **) NULL)
4917006b
JV
7810 break;
7811 for (x = 0; x < (long) width; x++)
7812 {
7813 PixelGetMagickColor (pixels[x], &pixel);
d2a2d277
JV
7814 XPutPixel (ximg, x, y,
7815 lookup_rgb_color (f,
7816 pixel.red,
7817 pixel.green,
7818 pixel.blue));
4917006b
JV
7819 }
7820 }
7821 DestroyPixelIterator (iterator);
3de25479
JV
7822 }
7823
4917006b
JV
7824 if (imagemagick_rendermethod == 1)
7825 {
3234a340
JV
7826 /* Magicexportimage is normaly faster than pixelpushing. This
7827 method is also well tested. Some aspects of this method are
7828 ad-hoc and needs to be more researched. */
4917006b 7829 int imagedepth = 24;/*MagickGetImageDepth(image_wand);*/
33290528 7830 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP";/*"RGBP";*/
4917006b 7831 /* Try to create a x pixmap to hold the imagemagick pixmap. */
d2a2d277 7832 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
7574650a
AS
7833 &ximg, &img->pixmap))
7834 {
466cbae9
AS
7835#ifdef COLOR_TABLE_SUPPORT
7836 free_color_table ();
7837#endif
7574650a
AS
7838 image_error("Imagemagick X bitmap allocation failure", Qnil, Qnil);
7839 goto imagemagick_error;
7840 }
7841
3de25479 7842
4917006b
JV
7843 /* Oddly, the below code doesnt seem to work:*/
7844 /* switch(ximg->bitmap_unit){ */
7845 /* case 8: */
7846 /* pixelwidth=CharPixel; */
7847 /* break; */
7848 /* case 16: */
7849 /* pixelwidth=ShortPixel; */
7850 /* break; */
7851 /* case 32: */
7852 /* pixelwidth=LongPixel; */
7853 /* break; */
7854 /* } */
7855 /*
7856 Here im just guessing the format of the bitmap.
7857 happens to work fine for:
7858 - bw djvu images
7859 on rgb display.
7860 seems about 3 times as fast as pixel pushing(not carefully measured)
4917006b
JV
7861 */
7862 pixelwidth = CharPixel;/*??? TODO figure out*/
7574650a
AS
7863#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
7864 MagickExportImagePixels (image_wand,
7865 0, 0,
7866 width, height,
7867 exportdepth,
7868 pixelwidth,
7869 /*&(img->pixmap));*/
7870 ximg->data);
431dab04 7871#else
7574650a
AS
7872 image_error ("You dont have MagickExportImagePixels, upgrade ImageMagick!",
7873 Qnil, Qnil);
7874#endif
4917006b 7875 }
7574650a 7876
3ed42149 7877
3de25479
JV
7878#ifdef COLOR_TABLE_SUPPORT
7879 /* Remember colors allocated for this image. */
7880 img->colors = colors_in_color_table (&img->ncolors);
7881 free_color_table ();
7882#endif /* COLOR_TABLE_SUPPORT */
7883
7884
7885 img->width = width;
7886 img->height = height;
7887
3de25479
JV
7888 /* Put the image into the pixmap, then free the X image and its
7889 buffer. */
7890 x_put_x_image (f, ximg, img->pixmap, width, height);
3de25479
JV
7891 x_destroy_x_image (ximg);
7892
7893
f3700365 7894 /* Final cleanup. image_wand should be the only resource left. */
3de25479 7895 DestroyMagickWand (image_wand);
03d32f1b 7896 /* `MagickWandTerminus' terminates the imagemagick environment. */
f853f599 7897 MagickWandTerminus ();
3de25479
JV
7898
7899 return 1;
7900
7901 imagemagick_error:
466cbae9 7902 DestroyMagickWand (image_wand);
f7e13da3 7903 imagemagick_no_wand:
f853f599 7904 MagickWandTerminus ();
3de25479
JV
7905 /* TODO more cleanup. */
7906 image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
3de25479
JV
7907 return 0;
7908}
7909
4917006b
JV
7910
7911/* Load IMAGEMAGICK image IMG for use on frame F. Value is non-zero if
7912 successful. this function will go into the imagemagick_type structure, and
7913 the prototype thus needs to be compatible with that structure. */
7914
7915static int
d66c4c7c 7916imagemagick_load (struct frame *f, struct image *img)
4917006b
JV
7917{
7918 int success_p = 0;
7919 Lisp_Object file_name;
7920
7921 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7922 file_name = image_spec_value (img->spec, QCfile, NULL);
7923 if (STRINGP (file_name))
7924 {
7925 Lisp_Object file;
4917006b
JV
7926
7927 file = x_find_image_file (file_name);
4917006b
JV
7928 if (!STRINGP (file))
7929 {
7930 image_error ("Cannot find image file `%s'", file_name, Qnil);
4917006b
JV
7931 return 0;
7932 }
33290528 7933 success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
4917006b
JV
7934 }
7935 /* Else its not a file, its a lisp object. Load the image from a
7936 lisp object rather than a file. */
7937 else
7938 {
7939 Lisp_Object data;
7940
7941 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
7942 if (!STRINGP (data))
7943 {
7944 image_error ("Invalid image data `%s'", data, Qnil);
7945 return 0;
7946 }
d2a2d277
JV
7947 success_p = imagemagick_load_image (f, img, SDATA (data),
7948 SBYTES (data), NULL);
4917006b
JV
7949 }
7950
7951 return success_p;
7952}
7953
a7ca3326 7954DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
d66c4c7c
CY
7955 doc: /* Return a list of image types supported by ImageMagick.
7956Each entry in this list is a symbol named after an ImageMagick format
7957tag. See the ImageMagick manual for a list of ImageMagick formats and
7958their descriptions (http://www.imagemagick.org/script/formats.php).
7959
7960Note that ImageMagick recognizes many file-types that Emacs does not
7961recognize as images, such as C. See `imagemagick-types-inhibit'. */)
a8101f66 7962 (void)
3de25479
JV
7963{
7964 Lisp_Object typelist = Qnil;
1ab0dee5 7965 size_t numf = 0;
3de25479 7966 ExceptionInfo ex;
7574650a 7967 char **imtypes = GetMagickList ("*", &numf, &ex);
3f791afe 7968 size_t i;
3de25479 7969 Lisp_Object Qimagemagicktype;
4917006b
JV
7970 for (i = 0; i < numf; i++)
7971 {
7972 Qimagemagicktype = intern (imtypes[i]);
f3700365
JV
7973 typelist = Fcons (Qimagemagicktype, typelist);
7974 }
7975 return typelist;
3de25479 7976}
7574650a 7977
3de25479
JV
7978#endif /* defined (HAVE_IMAGEMAGICK) */
7979
7980
4ef0d4d0 7981\f
4ab27a43
GM
7982/***********************************************************************
7983 SVG
7984 ***********************************************************************/
7985
7986#if defined (HAVE_RSVG)
7987
7988/* Function prototypes. */
7989
f57e2426
J
7990static int svg_image_p (Lisp_Object object);
7991static int svg_load (struct frame *f, struct image *img);
4ab27a43 7992
f57e2426 7993static int svg_load_image (struct frame *, struct image *,
dd52fcea 7994 unsigned char *, ptrdiff_t);
4ab27a43
GM
7995
7996/* The symbol `svg' identifying images of this type. */
7997
4b66faf3 7998static Lisp_Object Qsvg;
4ab27a43
GM
7999
8000/* Indices of image specification fields in svg_format, below. */
8001
8002enum svg_keyword_index
8003{
8004 SVG_TYPE,
8005 SVG_DATA,
8006 SVG_FILE,
8007 SVG_ASCENT,
8008 SVG_MARGIN,
8009 SVG_RELIEF,
8010 SVG_ALGORITHM,
8011 SVG_HEURISTIC_MASK,
8012 SVG_MASK,
8013 SVG_BACKGROUND,
8014 SVG_LAST
8015};
8016
8017/* Vector of image_keyword structures describing the format
8018 of valid user-defined image specifications. */
8019
91433552 8020static const struct image_keyword svg_format[SVG_LAST] =
4ab27a43
GM
8021{
8022 {":type", IMAGE_SYMBOL_VALUE, 1},
8023 {":data", IMAGE_STRING_VALUE, 0},
8024 {":file", IMAGE_STRING_VALUE, 0},
8025 {":ascent", IMAGE_ASCENT_VALUE, 0},
8026 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8027 {":relief", IMAGE_INTEGER_VALUE, 0},
8028 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8029 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8030 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8031 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8032};
8033
8034/* Structure describing the image type `svg'. Its the same type of
8035 structure defined for all image formats, handled by emacs image
8036 functions. See struct image_type in dispextern.h. */
8037
8038static struct image_type svg_type =
8039{
8040 /* An identifier showing that this is an image structure for the SVG format. */
8041 &Qsvg,
8042 /* Handle to a function that can be used to identify a SVG file. */
8043 svg_image_p,
8044 /* Handle to function used to load a SVG file. */
8045 svg_load,
8046 /* Handle to function to free sresources for SVG. */
8047 x_clear_image,
8048 /* An internal field to link to the next image type in a list of
8049 image types, will be filled in when registering the format. */
c21e6151 8050 NULL
4ab27a43
GM
8051};
8052
8053
8054/* Return non-zero if OBJECT is a valid SVG image specification. Do
8055 this by calling parse_image_spec and supplying the keywords that
8056 identify the SVG format. */
8057
8058static int
d3da34e0 8059svg_image_p (Lisp_Object object)
4ab27a43
GM
8060{
8061 struct image_keyword fmt[SVG_LAST];
72af86bd 8062 memcpy (fmt, svg_format, sizeof fmt);
4ab27a43
GM
8063
8064 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
8065 return 0;
8066
8067 /* Must specify either the :data or :file keyword. */
8068 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
8069}
8070
8071#include <librsvg/rsvg.h>
8072
5fc9fdeb
JR
8073#ifdef HAVE_NTGUI
8074
8075/* SVG library functions. */
df61c790
AS
8076DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new);
8077DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
8078DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
8079DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
8080DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
df61c790
AS
8081
8082DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
8083DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
8084DEF_IMGLIB_FN (guchar *, gdk_pixbuf_get_pixels);
8085DEF_IMGLIB_FN (int, gdk_pixbuf_get_rowstride);
8086DEF_IMGLIB_FN (GdkColorspace, gdk_pixbuf_get_colorspace);
8087DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels);
8088DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha);
8089DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample);
8090
8091DEF_IMGLIB_FN (void, g_type_init);
8092DEF_IMGLIB_FN (void, g_object_unref);
8093DEF_IMGLIB_FN (void, g_error_free);
5fc9fdeb 8094
df23bf08 8095Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
5fc9fdeb
JR
8096
8097static int
8098init_svg_functions (Lisp_Object libraries)
8099{
df23bf08 8100 HMODULE library, gdklib, glib, gobject;
5fc9fdeb
JR
8101
8102 if (!(glib = w32_delayed_load (libraries, Qglib))
df23bf08 8103 || !(gobject = w32_delayed_load (libraries, Qgobject))
5fc9fdeb
JR
8104 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
8105 || !(library = w32_delayed_load (libraries, Qsvg)))
8106 return 0;
8107
8108 LOAD_IMGLIB_FN (library, rsvg_handle_new);
e025c9c2 8109 LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
5fc9fdeb
JR
8110 LOAD_IMGLIB_FN (library, rsvg_handle_write);
8111 LOAD_IMGLIB_FN (library, rsvg_handle_close);
8112 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
5fc9fdeb
JR
8113
8114 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
8115 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
8116 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
8117 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
8118 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
8119 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
8120 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
8121 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
8122
df23bf08
JR
8123 LOAD_IMGLIB_FN (gobject, g_type_init);
8124 LOAD_IMGLIB_FN (gobject, g_object_unref);
5fc9fdeb 8125 LOAD_IMGLIB_FN (glib, g_error_free);
df23bf08 8126
5fc9fdeb
JR
8127 return 1;
8128}
4ab27a43 8129
5fc9fdeb
JR
8130#else
8131/* The following aliases for library functions allow dynamic loading
8132 to be used on some platforms. */
4ab27a43 8133#define fn_rsvg_handle_new rsvg_handle_new
e025c9c2 8134#define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
4ab27a43
GM
8135#define fn_rsvg_handle_write rsvg_handle_write
8136#define fn_rsvg_handle_close rsvg_handle_close
8137#define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
4ab27a43 8138
5fc9fdeb
JR
8139#define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8140#define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8141#define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8142#define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8143#define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8144#define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8145#define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
4ab27a43
GM
8146#define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8147
5fc9fdeb
JR
8148#define fn_g_type_init g_type_init
8149#define fn_g_object_unref g_object_unref
8150#define fn_g_error_free g_error_free
8151#endif /* !HAVE_NTGUI */
4ab27a43
GM
8152
8153/* Load SVG image IMG for use on frame F. Value is non-zero if
8154 successful. this function will go into the svg_type structure, and
8155 the prototype thus needs to be compatible with that structure. */
8156
8157static int
d3da34e0 8158svg_load (struct frame *f, struct image *img)
4ab27a43
GM
8159{
8160 int success_p = 0;
8161 Lisp_Object file_name;
8162
8163 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8164 file_name = image_spec_value (img->spec, QCfile, NULL);
8165 if (STRINGP (file_name))
8166 {
8167 Lisp_Object file;
8168 unsigned char *contents;
dd52fcea 8169 ptrdiff_t size;
4ab27a43
GM
8170
8171 file = x_find_image_file (file_name);
4ab27a43 8172 if (!STRINGP (file))
c21e6151
YM
8173 {
8174 image_error ("Cannot find image file `%s'", file_name, Qnil);
c21e6151
YM
8175 return 0;
8176 }
8177
4ab27a43 8178 /* Read the entire file into memory. */
33290528 8179 contents = slurp_file (SSDATA (file), &size);
4ab27a43 8180 if (contents == NULL)
c21e6151
YM
8181 {
8182 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
c21e6151
YM
8183 return 0;
8184 }
4ab27a43 8185 /* If the file was slurped into memory properly, parse it. */
c21e6151 8186 success_p = svg_load_image (f, img, contents, size);
4ab27a43 8187 xfree (contents);
4ab27a43
GM
8188 }
8189 /* Else its not a file, its a lisp object. Load the image from a
8190 lisp object rather than a file. */
8191 else
8192 {
8193 Lisp_Object data;
8194
8195 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
8196 if (!STRINGP (data))
8197 {
8198 image_error ("Invalid image data `%s'", data, Qnil);
8199 return 0;
8200 }
4ab27a43
GM
8201 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
8202 }
8203
8204 return success_p;
8205}
8206
bbe6f2aa
JB
8207/* svg_load_image is a helper function for svg_load, which does the
8208 actual loading given contents and size, apart from frame and image
8209 structures, passed from svg_load.
4ab27a43 8210
bbe6f2aa 8211 Uses librsvg to do most of the image processing.
c21e6151 8212
bbe6f2aa 8213 Returns non-zero when successful. */
4ab27a43 8214static int
d3da34e0
JB
8215svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
8216 struct image *img, /* Pointer to emacs image structure. */
8217 unsigned char *contents, /* String containing the SVG XML data to be parsed. */
dd52fcea 8218 ptrdiff_t size) /* Size of data in bytes. */
4ab27a43
GM
8219{
8220 RsvgHandle *rsvg_handle;
e025c9c2 8221 RsvgDimensionData dimension_data;
33290528 8222 GError *err = NULL;
4ab27a43
GM
8223 GdkPixbuf *pixbuf;
8224 int width;
8225 int height;
8226 const guint8 *pixels;
8227 int rowstride;
8228 XImagePtr ximg;
c21e6151 8229 Lisp_Object specified_bg;
4ab27a43
GM
8230 XColor background;
8231 int x;
8232 int y;
8233
8234 /* g_type_init is a glib function that must be called prior to using
8235 gnome type library functions. */
5fc9fdeb 8236 fn_g_type_init ();
4ab27a43 8237 /* Make a handle to a new rsvg object. */
df61c790 8238 rsvg_handle = fn_rsvg_handle_new ();
4ab27a43
GM
8239
8240 /* Parse the contents argument and fill in the rsvg_handle. */
33290528
PE
8241 fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
8242 if (err) goto rsvg_error;
4ab27a43
GM
8243
8244 /* The parsing is complete, rsvg_handle is ready to used, close it
8245 for further writes. */
33290528
PE
8246 fn_rsvg_handle_close (rsvg_handle, &err);
8247 if (err) goto rsvg_error;
e025c9c2
CY
8248
8249 fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
8250 if (! check_image_size (f, dimension_data.width, dimension_data.height))
10ea2b82
JR
8251 {
8252 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
8253 goto rsvg_error;
8254 }
b2996e57 8255
4ab27a43
GM
8256 /* We can now get a valid pixel buffer from the svg file, if all
8257 went ok. */
df61c790 8258 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
e025c9c2
CY
8259 if (!pixbuf) goto rsvg_error;
8260 fn_g_object_unref (rsvg_handle);
4ab27a43
GM
8261
8262 /* Extract some meta data from the svg handle. */
8263 width = fn_gdk_pixbuf_get_width (pixbuf);
8264 height = fn_gdk_pixbuf_get_height (pixbuf);
df61c790 8265 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
4ab27a43
GM
8266 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
8267
8268 /* Validate the svg meta data. */
8269 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
8270 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
8271 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
8272 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8273
8274 /* Try to create a x pixmap to hold the svg pixmap. */
c21e6151
YM
8275 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8276 {
5fc9fdeb 8277 fn_g_object_unref (pixbuf);
c21e6151
YM
8278 return 0;
8279 }
4ab27a43
GM
8280
8281 init_color_table ();
8282
c21e6151
YM
8283 /* Handle alpha channel by combining the image with a background
8284 color. */
8285 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8d3c4e79 8286 if (!STRINGP (specified_bg)
33290528 8287 || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
c21e6151 8288 {
d7e008d0 8289#ifndef HAVE_NS
c21e6151
YM
8290 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8291 x_query_color (f, &background);
d7e008d0 8292#else
ed3751c8 8293 ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1);
d7e008d0 8294#endif
c21e6151 8295 }
4ab27a43 8296
8d3c4e79
CY
8297 /* SVG pixmaps specify transparency in the last byte, so right
8298 shift 8 bits to get rid of it, since emacs doesn't support
8299 transparency. */
8300 background.red >>= 8;
8301 background.green >>= 8;
8302 background.blue >>= 8;
8303
4ab27a43
GM
8304 /* This loop handles opacity values, since Emacs assumes
8305 non-transparent images. Each pixel must be "flattened" by
bbe6f2aa
JB
8306 calculating the resulting color, given the transparency of the
8307 pixel, and the image background color. */
4ab27a43
GM
8308 for (y = 0; y < height; ++y)
8309 {
8310 for (x = 0; x < width; ++x)
8311 {
13464394
PE
8312 int red;
8313 int green;
8314 int blue;
8315 int opacity;
4ab27a43
GM
8316
8317 red = *pixels++;
8318 green = *pixels++;
8319 blue = *pixels++;
8320 opacity = *pixels++;
8321
8322 red = ((red * opacity)
8323 + (background.red * ((1 << 8) - opacity)));
8324 green = ((green * opacity)
8325 + (background.green * ((1 << 8) - opacity)));
8326 blue = ((blue * opacity)
8327 + (background.blue * ((1 << 8) - opacity)));
8328
8329 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
8330 }
8331
8332 pixels += rowstride - 4 * width;
8333 }
8334
8335#ifdef COLOR_TABLE_SUPPORT
8336 /* Remember colors allocated for this image. */
8337 img->colors = colors_in_color_table (&img->ncolors);
8338 free_color_table ();
8339#endif /* COLOR_TABLE_SUPPORT */
8340
5fc9fdeb 8341 fn_g_object_unref (pixbuf);
4ab27a43 8342
c21e6151
YM
8343 img->width = width;
8344 img->height = height;
8345
8346 /* Maybe fill in the background field while we have ximg handy.
8347 Casting avoids a GCC warning. */
8348 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8349
4ab27a43
GM
8350 /* Put the image into the pixmap, then free the X image and its
8351 buffer. */
8352 x_put_x_image (f, ximg, img->pixmap, width, height);
8353 x_destroy_x_image (ximg);
8354
4ab27a43
GM
8355 return 1;
8356
8357 rsvg_error:
e025c9c2 8358 fn_g_object_unref (rsvg_handle);
4ab27a43
GM
8359 /* FIXME: Use error->message so the user knows what is the actual
8360 problem with the image. */
8361 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
33290528 8362 fn_g_error_free (err);
4ab27a43
GM
8363 return 0;
8364}
8365
8366#endif /* defined (HAVE_RSVG) */
8367
8368
8369
4ef0d4d0
KS
8370\f
8371/***********************************************************************
8372 Ghostscript
8373 ***********************************************************************/
8374
8375#ifdef HAVE_X_WINDOWS
8376#define HAVE_GHOSTSCRIPT 1
8377#endif /* HAVE_X_WINDOWS */
8378
4ef0d4d0
KS
8379#ifdef HAVE_GHOSTSCRIPT
8380
f57e2426
J
8381static int gs_image_p (Lisp_Object object);
8382static int gs_load (struct frame *f, struct image *img);
8383static void gs_clear_image (struct frame *f, struct image *img);
4ef0d4d0
KS
8384
8385/* Keyword symbols. */
8386
955cbe7b 8387static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
4ef0d4d0
KS
8388
8389/* Indices of image specification fields in gs_format, below. */
8390
8391enum gs_keyword_index
8392{
8393 GS_TYPE,
8394 GS_PT_WIDTH,
8395 GS_PT_HEIGHT,
8396 GS_FILE,
8397 GS_LOADER,
8398 GS_BOUNDING_BOX,
8399 GS_ASCENT,
8400 GS_MARGIN,
8401 GS_RELIEF,
8402 GS_ALGORITHM,
8403 GS_HEURISTIC_MASK,
8404 GS_MASK,
8405 GS_BACKGROUND,
8406 GS_LAST
8407};
8408
8409/* Vector of image_keyword structures describing the format
8410 of valid user-defined image specifications. */
8411
91433552 8412static const struct image_keyword gs_format[GS_LAST] =
4ef0d4d0
KS
8413{
8414 {":type", IMAGE_SYMBOL_VALUE, 1},
8415 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8416 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8417 {":file", IMAGE_STRING_VALUE, 1},
8418 {":loader", IMAGE_FUNCTION_VALUE, 0},
8419 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8420 {":ascent", IMAGE_ASCENT_VALUE, 0},
8421 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8422 {":relief", IMAGE_INTEGER_VALUE, 0},
8423 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8424 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8425 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8426 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8427};
8428
8429/* Structure describing the image type `ghostscript'. */
8430
8431static struct image_type gs_type =
8432{
8433 &Qpostscript,
8434 gs_image_p,
8435 gs_load,
8436 gs_clear_image,
8437 NULL
8438};
8439
8440
8441/* Free X resources of Ghostscript image IMG which is used on frame F. */
8442
8443static void
d3da34e0 8444gs_clear_image (struct frame *f, struct image *img)
4ef0d4d0 8445{
4ef0d4d0
KS
8446 x_clear_image (f, img);
8447}
8448
8449
8450/* Return non-zero if OBJECT is a valid Ghostscript image
8451 specification. */
8452
8453static int
d3da34e0 8454gs_image_p (Lisp_Object object)
4ef0d4d0
KS
8455{
8456 struct image_keyword fmt[GS_LAST];
8457 Lisp_Object tem;
8458 int i;
8459
72af86bd 8460 memcpy (fmt, gs_format, sizeof fmt);
4ef0d4d0
KS
8461
8462 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8463 return 0;
8464
8465 /* Bounding box must be a list or vector containing 4 integers. */
8466 tem = fmt[GS_BOUNDING_BOX].value;
8467 if (CONSP (tem))
8468 {
8469 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8470 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8471 return 0;
8472 if (!NILP (tem))
8473 return 0;
8474 }
8475 else if (VECTORP (tem))
8476 {
77b37c05 8477 if (ASIZE (tem) != 4)
4ef0d4d0
KS
8478 return 0;
8479 for (i = 0; i < 4; ++i)
8480 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8481 return 0;
8482 }
8483 else
8484 return 0;
8485
8486 return 1;
8487}
8488
8489
8490/* Load Ghostscript image IMG for use on frame F. Value is non-zero
8491 if successful. */
8492
8493static int
d3da34e0 8494gs_load (struct frame *f, struct image *img)
4ef0d4d0 8495{
13464394
PE
8496 uprintmax_t printnum1, printnum2;
8497 char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
4ef0d4d0 8498 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
4ef0d4d0
KS
8499 Lisp_Object frame;
8500 double in_width, in_height;
8501 Lisp_Object pixel_colors = Qnil;
8502
8503 /* Compute pixel size of pixmap needed from the given size in the
8504 image specification. Sizes in the specification are in pt. 1 pt
8505 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8506 info. */
8507 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7574650a 8508 in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
13464394 8509 in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
4ef0d4d0 8510 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7574650a 8511 in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
13464394 8512 in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
4ef0d4d0 8513
13464394
PE
8514 if (! (in_width <= INT_MAX && in_height <= INT_MAX
8515 && check_image_size (f, in_width, in_height)))
f1f25b99 8516 {
10ea2b82 8517 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99
CY
8518 return 0;
8519 }
13464394
PE
8520 img->width = in_width;
8521 img->height = in_height;
f1f25b99 8522
4ef0d4d0
KS
8523 /* Create the pixmap. */
8524 xassert (img->pixmap == NO_PIXMAP);
8525
ca4aa935
PE
8526 if (x_check_image_size (0, img->width, img->height))
8527 {
8528 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8529 BLOCK_INPUT;
8530 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8531 img->width, img->height,
8532 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8533 UNBLOCK_INPUT;
8534 }
4ef0d4d0
KS
8535
8536 if (!img->pixmap)
8537 {
8538 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8539 return 0;
8540 }
8541
8542 /* Call the loader to fill the pixmap. It returns a process object
8543 if successful. We do not record_unwind_protect here because
8544 other places in redisplay like calling window scroll functions
8545 don't either. Let the Lisp loader use `unwind-protect' instead. */
13464394
PE
8546 printnum1 = FRAME_X_WINDOW (f);
8547 printnum2 = img->pixmap;
8548 sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
4ef0d4d0
KS
8549 window_and_pixmap_id = build_string (buffer);
8550
13464394
PE
8551 printnum1 = FRAME_FOREGROUND_PIXEL (f);
8552 printnum2 = FRAME_BACKGROUND_PIXEL (f);
8553 sprintf (buffer, "%"pMu" %"pMu, printnum1, printnum2);
4ef0d4d0
KS
8554 pixel_colors = build_string (buffer);
8555
8556 XSETFRAME (frame, f);
8557 loader = image_spec_value (img->spec, QCloader, NULL);
8558 if (NILP (loader))
8559 loader = intern ("gs-load-image");
8560
b50691aa
CY
8561 img->lisp_data = call6 (loader, frame, img->spec,
8562 make_number (img->width),
8563 make_number (img->height),
8564 window_and_pixmap_id,
8565 pixel_colors);
8566 return PROCESSP (img->lisp_data);
4ef0d4d0
KS
8567}
8568
8569
8570/* Kill the Ghostscript process that was started to fill PIXMAP on
8571 frame F. Called from XTread_socket when receiving an event
8572 telling Emacs that Ghostscript has finished drawing. */
8573
8574void
d3da34e0 8575x_kill_gs_process (Pixmap pixmap, struct frame *f)
4ef0d4d0 8576{
354884c4 8577 struct image_cache *c = FRAME_IMAGE_CACHE (f);
13464394
PE
8578 int class;
8579 ptrdiff_t i;
4ef0d4d0
KS
8580 struct image *img;
8581
8582 /* Find the image containing PIXMAP. */
8583 for (i = 0; i < c->used; ++i)
8584 if (c->images[i]->pixmap == pixmap)
8585 break;
8586
8587 /* Should someone in between have cleared the image cache, for
8588 instance, give up. */
8589 if (i == c->used)
8590 return;
8591
8592 /* Kill the GS process. We should have found PIXMAP in the image
8593 cache and its image should contain a process object. */
8594 img = c->images[i];
b50691aa
CY
8595 xassert (PROCESSP (img->lisp_data));
8596 Fkill_process (img->lisp_data, Qnil);
8597 img->lisp_data = Qnil;
4ef0d4d0
KS
8598
8599#if defined (HAVE_X_WINDOWS)
8600
8601 /* On displays with a mutable colormap, figure out the colors
8602 allocated for the image by looking at the pixels of an XImage for
8603 img->pixmap. */
8604 class = FRAME_X_VISUAL (f)->class;
8605 if (class != StaticColor && class != StaticGray && class != TrueColor)
8606 {
8607 XImagePtr ximg;
8608
8609 BLOCK_INPUT;
8610
8611 /* Try to get an XImage for img->pixmep. */
8612 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8613 0, 0, img->width, img->height, ~0, ZPixmap);
8614 if (ximg)
8615 {
8616 int x, y;
8617
8618 /* Initialize the color table. */
8619 init_color_table ();
8620
8621 /* For each pixel of the image, look its color up in the
8622 color table. After having done so, the color table will
8623 contain an entry for each color used by the image. */
8624 for (y = 0; y < img->height; ++y)
8625 for (x = 0; x < img->width; ++x)
8626 {
8627 unsigned long pixel = XGetPixel (ximg, x, y);
8628 lookup_pixel_color (f, pixel);
8629 }
8630
8631 /* Record colors in the image. Free color table and XImage. */
8632#ifdef COLOR_TABLE_SUPPORT
8633 img->colors = colors_in_color_table (&img->ncolors);
8634 free_color_table ();
8635#endif
8636 XDestroyImage (ximg);
8637
8638#if 0 /* This doesn't seem to be the case. If we free the colors
8639 here, we get a BadAccess later in x_clear_image when
8640 freeing the colors. */
8641 /* We have allocated colors once, but Ghostscript has also
8642 allocated colors on behalf of us. So, to get the
8643 reference counts right, free them once. */
8644 if (img->ncolors)
8645 x_free_colors (f, img->colors, img->ncolors);
8646#endif
8647 }
8648 else
8649 image_error ("Cannot get X image of `%s'; colors will not be freed",
8650 img->spec, Qnil);
8651
8652 UNBLOCK_INPUT;
8653 }
8654#endif /* HAVE_X_WINDOWS */
8655
8656 /* Now that we have the pixmap, compute mask and transform the
8657 image if requested. */
8658 BLOCK_INPUT;
8659 postprocess_image (f, img);
8660 UNBLOCK_INPUT;
8661}
8662
8663#endif /* HAVE_GHOSTSCRIPT */
8664
8665\f
8666/***********************************************************************
8667 Tests
8668 ***********************************************************************/
8669
8670#if GLYPH_DEBUG
8671
a7ca3326 8672DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
4ef0d4d0 8673 doc: /* Value is non-nil if SPEC is a valid image specification. */)
5842a27b 8674 (Lisp_Object spec)
4ef0d4d0
KS
8675{
8676 return valid_image_p (spec) ? Qt : Qnil;
8677}
8678
8679
a7ca3326 8680DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
5842a27b 8681 (Lisp_Object spec)
4ef0d4d0 8682{
13464394 8683 ptrdiff_t id = -1;
4ef0d4d0
KS
8684
8685 if (valid_image_p (spec))
8686 id = lookup_image (SELECTED_FRAME (), spec);
8687
8688 debug_print (spec);
8689 return make_number (id);
8690}
8691
8692#endif /* GLYPH_DEBUG != 0 */
8693
8694
8695/***********************************************************************
8696 Initialization
8697 ***********************************************************************/
8698
0855eb52
JB
8699#ifdef HAVE_NTGUI
8700/* Image types that rely on external libraries are loaded dynamically
8701 if the library is available. */
adac86db 8702#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
0855eb52
JB
8703 define_image_type (image_type, init_lib_fn (libraries))
8704#else
adac86db 8705#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
e0e30823 8706 define_image_type (image_type, 1)
0855eb52
JB
8707#endif /* HAVE_NTGUI */
8708
8709DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8710 doc: /* Initialize image library implementing image type TYPE.
8711Return non-nil if TYPE is a supported image type.
8712
8713Image types pbm and xbm are prebuilt; other types are loaded here.
8714Libraries to load are specified in alist LIBRARIES (usually, the value
2e288d54 8715of `dynamic-library-alist', which see). */)
5842a27b 8716 (Lisp_Object type, Lisp_Object libraries)
0855eb52 8717{
84d358f0 8718#ifdef HAVE_NTGUI
0855eb52 8719 /* Don't try to reload the library. */
4c4b566b 8720 Lisp_Object tested = Fassq (type, Vlibrary_cache);
0855eb52
JB
8721 if (CONSP (tested))
8722 return XCDR (tested);
84d358f0 8723#endif
0855eb52 8724
2f142cc5
JB
8725 /* Types pbm and xbm are built-in and always available. */
8726 if (EQ (type, Qpbm) || EQ (type, Qxbm))
8727 return Qt;
8728
9e2a2647 8729#if defined (HAVE_XPM) || defined (HAVE_NS)
0855eb52 8730 if (EQ (type, Qxpm))
adac86db 8731 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
0855eb52
JB
8732#endif
8733
9e2a2647 8734#if defined (HAVE_JPEG) || defined (HAVE_NS)
0855eb52 8735 if (EQ (type, Qjpeg))
adac86db 8736 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
0855eb52
JB
8737#endif
8738
9e2a2647 8739#if defined (HAVE_TIFF) || defined (HAVE_NS)
0855eb52 8740 if (EQ (type, Qtiff))
adac86db 8741 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
0855eb52
JB
8742#endif
8743
9e2a2647 8744#if defined (HAVE_GIF) || defined (HAVE_NS)
0855eb52 8745 if (EQ (type, Qgif))
adac86db 8746 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
0855eb52
JB
8747#endif
8748
9e2a2647 8749#if defined (HAVE_PNG) || defined (HAVE_NS)
0855eb52 8750 if (EQ (type, Qpng))
adac86db 8751 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
0855eb52
JB
8752#endif
8753
4ab27a43
GM
8754#if defined (HAVE_RSVG)
8755 if (EQ (type, Qsvg))
8756 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
8757#endif
c21e6151 8758
3de25479 8759#if defined (HAVE_IMAGEMAGICK)
7574650a 8760 if (EQ (type, Qimagemagick))
2f142cc5
JB
8761 return CHECK_LIB_AVAILABLE (&imagemagick_type, init_imagemagick_functions,
8762 libraries);
3de25479
JV
8763#endif
8764
0855eb52
JB
8765#ifdef HAVE_GHOSTSCRIPT
8766 if (EQ (type, Qpostscript))
adac86db 8767 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
0855eb52
JB
8768#endif
8769
8770 /* If the type is not recognized, avoid testing it ever again. */
adac86db 8771 CACHE_IMAGE_TYPE (type, Qnil);
0855eb52
JB
8772 return Qnil;
8773}
8774
4ef0d4d0 8775void
d3da34e0 8776syms_of_image (void)
4ef0d4d0 8777{
6e6fc3fd
RS
8778 /* Initialize this only once, since that's what we do with Vimage_types
8779 and they are supposed to be in sync. Initializing here gives correct
8780 operation on GNU/Linux of calling dump-emacs after loading some images. */
8781 image_types = NULL;
8782
0855eb52
JB
8783 /* Must be defined now becase we're going to update it below, while
8784 defining the supported image types. */
29208e82 8785 DEFVAR_LISP ("image-types", Vimage_types,
0855eb52 8786 doc: /* List of potentially supported image types.
bbe6f2aa 8787Each element of the list is a symbol for an image type, like 'jpeg or 'png.
0855eb52
JB
8788To check whether it is really supported, use `image-type-available-p'. */);
8789 Vimage_types = Qnil;
8790
29208e82 8791 DEFVAR_LISP ("max-image-size", Vmax_image_size,
7df4765a
KS
8792 doc: /* Maximum size of images.
8793Emacs will not load an image into memory if its pixel width or
8794pixel height exceeds this limit.
8795
8796If the value is an integer, it directly specifies the maximum
8797image height and width, measured in pixels. If it is a floating
8798point number, it specifies the maximum image height and width
8799as a ratio to the frame height and width. If the value is
8800non-numeric, there is no explicit limit on the size of images. */);
f1f25b99
CY
8801 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8802
1100a63c 8803 DEFSYM (Qpbm, "pbm");
5fc9fdeb 8804 ADD_IMAGE_TYPE (Qpbm);
7c4e3a32 8805
1100a63c 8806 DEFSYM (Qxbm, "xbm");
5fc9fdeb 8807 ADD_IMAGE_TYPE (Qxbm);
7c4e3a32
RS
8808
8809 define_image_type (&xbm_type, 1);
8810 define_image_type (&pbm_type, 1);
8811
1100a63c
CY
8812 DEFSYM (Qcount, "count");
8813 DEFSYM (Qextension_data, "extension-data");
8814 DEFSYM (Qdelay, "delay");
8815
8816 DEFSYM (QCascent, ":ascent");
8817 DEFSYM (QCmargin, ":margin");
8818 DEFSYM (QCrelief, ":relief");
8819 DEFSYM (QCconversion, ":conversion");
8820 DEFSYM (QCcolor_symbols, ":color-symbols");
8821 DEFSYM (QCheuristic_mask, ":heuristic-mask");
8822 DEFSYM (QCindex, ":index");
8823 DEFSYM (QCgeometry, ":geometry");
8824 DEFSYM (QCcrop, ":crop");
8825 DEFSYM (QCrotation, ":rotation");
8826 DEFSYM (QCmatrix, ":matrix");
8827 DEFSYM (QCcolor_adjustment, ":color-adjustment");
8828 DEFSYM (QCmask, ":mask");
8829
8830 DEFSYM (Qlaplace, "laplace");
8831 DEFSYM (Qemboss, "emboss");
8832 DEFSYM (Qedge_detection, "edge-detection");
8833 DEFSYM (Qheuristic, "heuristic");
8834
8835 DEFSYM (Qpostscript, "postscript");
4ef0d4d0 8836#ifdef HAVE_GHOSTSCRIPT
5fc9fdeb 8837 ADD_IMAGE_TYPE (Qpostscript);
1100a63c
CY
8838 DEFSYM (QCloader, ":loader");
8839 DEFSYM (QCbounding_box, ":bounding-box");
8840 DEFSYM (QCpt_width, ":pt-width");
8841 DEFSYM (QCpt_height, ":pt-height");
4ef0d4d0
KS
8842#endif /* HAVE_GHOSTSCRIPT */
8843
5be1c984 8844#ifdef HAVE_NTGUI
1100a63c 8845 DEFSYM (Qlibpng_version, "libpng-version");
0514b4be 8846 Fset (Qlibpng_version,
5be1c984 8847#if HAVE_PNG
0514b4be 8848 make_number (PNG_LIBPNG_VER)
5be1c984 8849#else
0514b4be 8850 make_number (-1)
5be1c984 8851#endif
0514b4be 8852 );
5be1c984
EZ
8853#endif
8854
9e2a2647 8855#if defined (HAVE_XPM) || defined (HAVE_NS)
1100a63c 8856 DEFSYM (Qxpm, "xpm");
5fc9fdeb 8857 ADD_IMAGE_TYPE (Qxpm);
4ef0d4d0
KS
8858#endif
8859
9e2a2647 8860#if defined (HAVE_JPEG) || defined (HAVE_NS)
1100a63c 8861 DEFSYM (Qjpeg, "jpeg");
5fc9fdeb 8862 ADD_IMAGE_TYPE (Qjpeg);
4ef0d4d0
KS
8863#endif
8864
9e2a2647 8865#if defined (HAVE_TIFF) || defined (HAVE_NS)
1100a63c 8866 DEFSYM (Qtiff, "tiff");
5fc9fdeb 8867 ADD_IMAGE_TYPE (Qtiff);
4ef0d4d0
KS
8868#endif
8869
9e2a2647 8870#if defined (HAVE_GIF) || defined (HAVE_NS)
1100a63c 8871 DEFSYM (Qgif, "gif");
5fc9fdeb 8872 ADD_IMAGE_TYPE (Qgif);
4ef0d4d0
KS
8873#endif
8874
9e2a2647 8875#if defined (HAVE_PNG) || defined (HAVE_NS)
1100a63c 8876 DEFSYM (Qpng, "png");
5fc9fdeb 8877 ADD_IMAGE_TYPE (Qpng);
4ef0d4d0
KS
8878#endif
8879
3de25479 8880#if defined (HAVE_IMAGEMAGICK)
1100a63c 8881 DEFSYM (Qimagemagick, "imagemagick");
3de25479
JV
8882 ADD_IMAGE_TYPE (Qimagemagick);
8883#endif
7574650a 8884
4ab27a43 8885#if defined (HAVE_RSVG)
1100a63c 8886 DEFSYM (Qsvg, "svg");
5fc9fdeb
JR
8887 ADD_IMAGE_TYPE (Qsvg);
8888#ifdef HAVE_NTGUI
df23bf08 8889 /* Other libraries used directly by svg code. */
1100a63c
CY
8890 DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
8891 DEFSYM (Qglib, "glib");
8892 DEFSYM (Qgobject, "gobject");
5fc9fdeb
JR
8893#endif /* HAVE_NTGUI */
8894#endif /* HAVE_RSVG */
4ab27a43 8895
0855eb52 8896 defsubr (&Sinit_image_library);
7574650a 8897#ifdef HAVE_IMAGEMAGICK
3de25479 8898 defsubr (&Simagemagick_types);
7574650a 8899#endif
4ef0d4d0 8900 defsubr (&Sclear_image_cache);
110683ad 8901 defsubr (&Simage_flush);
4ef0d4d0
KS
8902 defsubr (&Simage_size);
8903 defsubr (&Simage_mask_p);
1546c559 8904 defsubr (&Simage_metadata);
4ef0d4d0
KS
8905
8906#if GLYPH_DEBUG
8907 defsubr (&Simagep);
8908 defsubr (&Slookup_image);
8909#endif
8910
29208e82 8911 DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
4ef0d4d0 8912 doc: /* Non-nil means always draw a cross over disabled images.
3046a84b 8913Disabled images are those having a `:conversion disabled' property.
4ef0d4d0
KS
8914A cross is always drawn on black & white displays. */);
8915 cross_disabled_images = 0;
8916
29208e82 8917 DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path,
4ef0d4d0
KS
8918 doc: /* List of directories to search for window system bitmap files. */);
8919 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8920
29208e82 8921 DEFVAR_LISP ("image-cache-eviction-delay", Vimage_cache_eviction_delay,
98fe5161
CY
8922 doc: /* Maximum time after which images are removed from the cache.
8923When an image has not been displayed this many seconds, Emacs
8924automatically removes it from the image cache. If the cache contains
8925a large number of images, the actual eviction time may be shorter.
8926The value can also be nil, meaning the cache is never cleared.
8927
8928The function `clear-image-cache' disregards this variable. */);
8929 Vimage_cache_eviction_delay = make_number (300);
7574650a 8930#ifdef HAVE_IMAGEMAGICK
29208e82 8931 DEFVAR_LISP ("imagemagick-render-type", Vimagemagick_render_type,
4917006b 8932 doc: /* Choose between ImageMagick render methods. */);
7574650a 8933#endif
4ef0d4d0 8934
4ef0d4d0
KS
8935}
8936
4ef0d4d0 8937void
d3da34e0 8938init_image (void)
4ef0d4d0 8939{
4ef0d4d0 8940}