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