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