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