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