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