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