* src/doc.c (get_doc_string): Don't signal an error if the file is missing.
[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
KS
2142{
2143 FILE *fp = NULL;
2144 unsigned char *buf = NULL;
2145 struct stat st;
2146
2147 if (stat (file, &st) == 0
2148 && (fp = fopen (file, "rb")) != NULL
dd52fcea 2149 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
23f86fce 2150 && (buf = xmalloc (st.st_size),
4ef0d4d0
KS
2151 fread (buf, 1, st.st_size, fp) == st.st_size))
2152 {
2153 *size = st.st_size;
2154 fclose (fp);
2155 }
2156 else
2157 {
2158 if (fp)
2159 fclose (fp);
2160 if (buf)
2161 {
2162 xfree (buf);
2163 buf = NULL;
2164 }
2165 }
2166
2167 return buf;
2168}
2169
2170
2171\f
4ef0d4d0
KS
2172/***********************************************************************
2173 XBM images
2174 ***********************************************************************/
2175
578098f3
PE
2176static bool xbm_load (struct frame *f, struct image *img);
2177static bool xbm_image_p (Lisp_Object object);
2178static bool xbm_file_p (Lisp_Object);
4ef0d4d0
KS
2179
2180
2181/* Indices of image specification fields in xbm_format, below. */
2182
2183enum xbm_keyword_index
2184{
2185 XBM_TYPE,
2186 XBM_FILE,
2187 XBM_WIDTH,
2188 XBM_HEIGHT,
2189 XBM_DATA,
2190 XBM_FOREGROUND,
2191 XBM_BACKGROUND,
2192 XBM_ASCENT,
2193 XBM_MARGIN,
2194 XBM_RELIEF,
2195 XBM_ALGORITHM,
2196 XBM_HEURISTIC_MASK,
2197 XBM_MASK,
2198 XBM_LAST
2199};
2200
2201/* Vector of image_keyword structures describing the format
2202 of valid XBM image specifications. */
2203
91433552 2204static const struct image_keyword xbm_format[XBM_LAST] =
4ef0d4d0
KS
2205{
2206 {":type", IMAGE_SYMBOL_VALUE, 1},
2207 {":file", IMAGE_STRING_VALUE, 0},
2208 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2209 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2210 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2211 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2212 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2213 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 2214 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
2215 {":relief", IMAGE_INTEGER_VALUE, 0},
2216 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2217 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2218 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2219};
2220
2221/* Structure describing the image type XBM. */
2222
2223static struct image_type xbm_type =
2224{
2225 &Qxbm,
2226 xbm_image_p,
2227 xbm_load,
2228 x_clear_image,
bb4d86b4 2229 NULL,
4ef0d4d0
KS
2230 NULL
2231};
2232
2233/* Tokens returned from xbm_scan. */
2234
2235enum xbm_token
2236{
2237 XBM_TK_IDENT = 256,
2238 XBM_TK_NUMBER
2239};
2240
2241
578098f3 2242/* Return true if OBJECT is a valid XBM-type image specification.
4ef0d4d0
KS
2243 A valid specification is a list starting with the symbol `image'
2244 The rest of the list is a property list which must contain an
578098f3 2245 entry `:type xbm'.
4ef0d4d0
KS
2246
2247 If the specification specifies a file to load, it must contain
2248 an entry `:file FILENAME' where FILENAME is a string.
2249
2250 If the specification is for a bitmap loaded from memory it must
2251 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2252 WIDTH and HEIGHT are integers > 0. DATA may be:
2253
2254 1. a string large enough to hold the bitmap data, i.e. it must
2255 have a size >= (WIDTH + 7) / 8 * HEIGHT
2256
2257 2. a bool-vector of size >= WIDTH * HEIGHT
2258
2259 3. a vector of strings or bool-vectors, one for each line of the
2260 bitmap.
2261
bbe6f2aa 2262 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
4ef0d4d0
KS
2263 may not be specified in this case because they are defined in the
2264 XBM file.
2265
2266 Both the file and data forms may contain the additional entries
2267 `:background COLOR' and `:foreground COLOR'. If not present,
2268 foreground and background of the frame on which the image is
2269 displayed is used. */
2270
578098f3 2271static bool
d3da34e0 2272xbm_image_p (Lisp_Object object)
4ef0d4d0
KS
2273{
2274 struct image_keyword kw[XBM_LAST];
2275
72af86bd 2276 memcpy (kw, xbm_format, sizeof kw);
4ef0d4d0
KS
2277 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2278 return 0;
2279
a54e2c05 2280 eassert (EQ (kw[XBM_TYPE].value, Qxbm));
4ef0d4d0
KS
2281
2282 if (kw[XBM_FILE].count)
2283 {
2284 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2285 return 0;
2286 }
2287 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2288 {
2289 /* In-memory XBM file. */
2290 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2291 return 0;
2292 }
2293 else
2294 {
2295 Lisp_Object data;
13464394 2296 int width, height;
4ef0d4d0
KS
2297
2298 /* Entries for `:width', `:height' and `:data' must be present. */
2299 if (!kw[XBM_WIDTH].count
2300 || !kw[XBM_HEIGHT].count
2301 || !kw[XBM_DATA].count)
2302 return 0;
2303
2304 data = kw[XBM_DATA].value;
2305 width = XFASTINT (kw[XBM_WIDTH].value);
2306 height = XFASTINT (kw[XBM_HEIGHT].value);
2307
2308 /* Check type of data, and width and height against contents of
2309 data. */
2310 if (VECTORP (data))
2311 {
45aebb64 2312 EMACS_INT i;
4ef0d4d0
KS
2313
2314 /* Number of elements of the vector must be >= height. */
77b37c05 2315 if (ASIZE (data) < height)
4ef0d4d0
KS
2316 return 0;
2317
2318 /* Each string or bool-vector in data must be large enough
2319 for one line of the image. */
2320 for (i = 0; i < height; ++i)
2321 {
28be1ada 2322 Lisp_Object elt = AREF (data, i);
4ef0d4d0
KS
2323
2324 if (STRINGP (elt))
2325 {
2326 if (SCHARS (elt)
2327 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2328 return 0;
2329 }
2330 else if (BOOL_VECTOR_P (elt))
2331 {
2332 if (XBOOL_VECTOR (elt)->size < width)
2333 return 0;
2334 }
2335 else
2336 return 0;
2337 }
2338 }
2339 else if (STRINGP (data))
2340 {
2341 if (SCHARS (data)
2342 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2343 return 0;
2344 }
2345 else if (BOOL_VECTOR_P (data))
2346 {
ca4aa935 2347 if (XBOOL_VECTOR (data)->size / height < width)
4ef0d4d0
KS
2348 return 0;
2349 }
2350 else
2351 return 0;
2352 }
2353
2354 return 1;
2355}
2356
2357
2358/* Scan a bitmap file. FP is the stream to read from. Value is
2359 either an enumerator from enum xbm_token, or a character for a
2360 single-character token, or 0 at end of file. If scanning an
2361 identifier, store the lexeme of the identifier in SVAL. If
2362 scanning a number, store its value in *IVAL. */
2363
2364static int
d3da34e0 2365xbm_scan (unsigned char **s, unsigned char *end, char *sval, int *ival)
4ef0d4d0
KS
2366{
2367 unsigned int c;
2368
2369 loop:
2370
2371 /* Skip white space. */
620f13b0 2372 while (*s < end && (c = *(*s)++, c_isspace (c)))
4ef0d4d0
KS
2373 ;
2374
2375 if (*s >= end)
2376 c = 0;
620f13b0 2377 else if (c_isdigit (c))
4ef0d4d0
KS
2378 {
2379 int value = 0, digit;
2380
2381 if (c == '0' && *s < end)
2382 {
2383 c = *(*s)++;
2384 if (c == 'x' || c == 'X')
2385 {
2386 while (*s < end)
2387 {
2388 c = *(*s)++;
620f13b0 2389 if (c_isdigit (c))
4ef0d4d0
KS
2390 digit = c - '0';
2391 else if (c >= 'a' && c <= 'f')
2392 digit = c - 'a' + 10;
2393 else if (c >= 'A' && c <= 'F')
2394 digit = c - 'A' + 10;
2395 else
2396 break;
2397 value = 16 * value + digit;
2398 }
2399 }
620f13b0 2400 else if (c_isdigit (c))
4ef0d4d0
KS
2401 {
2402 value = c - '0';
2403 while (*s < end
620f13b0 2404 && (c = *(*s)++, c_isdigit (c)))
4ef0d4d0
KS
2405 value = 8 * value + c - '0';
2406 }
2407 }
2408 else
2409 {
2410 value = c - '0';
2411 while (*s < end
620f13b0 2412 && (c = *(*s)++, c_isdigit (c)))
4ef0d4d0
KS
2413 value = 10 * value + c - '0';
2414 }
2415
2416 if (*s < end)
2417 *s = *s - 1;
2418 *ival = value;
2419 c = XBM_TK_NUMBER;
2420 }
620f13b0 2421 else if (c_isalpha (c) || c == '_')
4ef0d4d0
KS
2422 {
2423 *sval++ = c;
2424 while (*s < end
620f13b0 2425 && (c = *(*s)++, (c_isalnum (c) || c == '_')))
4ef0d4d0
KS
2426 *sval++ = c;
2427 *sval = 0;
2428 if (*s < end)
2429 *s = *s - 1;
2430 c = XBM_TK_IDENT;
2431 }
2432 else if (c == '/' && **s == '*')
2433 {
2434 /* C-style comment. */
2435 ++*s;
2436 while (**s && (**s != '*' || *(*s + 1) != '/'))
2437 ++*s;
2438 if (**s)
2439 {
2440 *s += 2;
2441 goto loop;
2442 }
2443 }
2444
2445 return c;
2446}
2447
2448#ifdef HAVE_NTGUI
2449
2450/* Create a Windows bitmap from X bitmap data. */
2451static HBITMAP
2452w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2453{
2454 static unsigned char swap_nibble[16]
2455 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2456 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2457 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2458 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2459 int i, j, w1, w2;
2460 unsigned char *bits, *p;
2461 HBITMAP bmp;
2462
2463 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2464 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
38182d90 2465 bits = alloca (height * w2);
72af86bd 2466 memset (bits, 0, height * w2);
4ef0d4d0
KS
2467 for (i = 0; i < height; i++)
2468 {
2469 p = bits + i*w2;
2470 for (j = 0; j < w1; j++)
2471 {
2472 /* Bitswap XBM bytes to match how Windows does things. */
2473 unsigned char c = *data++;
2474 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2475 | (swap_nibble[(c>>4) & 0xf]));
2476 }
2477 }
2478 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2479
2480 return bmp;
2481}
2482
3046a84b 2483static void
7c3320d8
JB
2484convert_mono_to_color_image (struct frame *f, struct image *img,
2485 COLORREF foreground, COLORREF background)
4ef0d4d0
KS
2486{
2487 HDC hdc, old_img_dc, new_img_dc;
2488 HGDIOBJ old_prev, new_prev;
2489 HBITMAP new_pixmap;
2490
2491 hdc = get_frame_dc (f);
2492 old_img_dc = CreateCompatibleDC (hdc);
2493 new_img_dc = CreateCompatibleDC (hdc);
2494 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2495 release_frame_dc (f, hdc);
2496 old_prev = SelectObject (old_img_dc, img->pixmap);
2497 new_prev = SelectObject (new_img_dc, new_pixmap);
44b1dc2e
JR
2498 /* Windows convention for mono bitmaps is black = background,
2499 white = foreground. */
2386b1f1
JR
2500 SetTextColor (new_img_dc, background);
2501 SetBkColor (new_img_dc, foreground);
4ef0d4d0
KS
2502
2503 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2504 0, 0, SRCCOPY);
2505
2506 SelectObject (old_img_dc, old_prev);
2507 SelectObject (new_img_dc, new_prev);
2508 DeleteDC (old_img_dc);
2509 DeleteDC (new_img_dc);
2510 DeleteObject (img->pixmap);
2511 if (new_pixmap == 0)
2512 fprintf (stderr, "Failed to convert image to color.\n");
2513 else
2514 img->pixmap = new_pixmap;
2515}
2516
2517#define XBM_BIT_SHUFFLE(b) (~(b))
2518
2519#else
2520
2521#define XBM_BIT_SHUFFLE(b) (b)
2522
2523#endif /* HAVE_NTGUI */
2524
2525
2526static void
d3da34e0
JB
2527Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
2528 RGB_PIXEL_COLOR fg, RGB_PIXEL_COLOR bg,
578098f3 2529 bool non_default_colors)
4ef0d4d0
KS
2530{
2531#ifdef HAVE_NTGUI
2532 img->pixmap
2533 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2534
2535 /* If colors were specified, transfer the bitmap to a color one. */
2536 if (non_default_colors)
2537 convert_mono_to_color_image (f, img, fg, bg);
edfda783
AR
2538
2539#elif defined (HAVE_NS)
ed3751c8 2540 img->pixmap = ns_image_from_XBM (data, img->width, img->height);
edfda783 2541
4ef0d4d0 2542#else
ca4aa935
PE
2543 img->pixmap =
2544 (x_check_image_size (0, img->width, img->height)
2545 ? XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
4ef0d4d0
KS
2546 FRAME_X_WINDOW (f),
2547 data,
2548 img->width, img->height,
2549 fg, bg,
ca4aa935
PE
2550 DefaultDepthOfScreen (FRAME_X_SCREEN (f)))
2551 : NO_PIXMAP);
edfda783 2552#endif /* !HAVE_NTGUI && !HAVE_NS */
4ef0d4d0
KS
2553}
2554
2555
2556
2557/* Replacement for XReadBitmapFileData which isn't available under old
2558 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2559 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2560 the image. Return in *DATA the bitmap data allocated with xmalloc.
578098f3
PE
2561 Value is true if successful. DATA null means just test if
2562 CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR,
2563 inhibit the call to image_error when the image size is invalid (the
2564 bitmap remains unread). */
4ef0d4d0 2565
578098f3 2566static bool
d3da34e0 2567xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *end,
b8dc29e9 2568 int *width, int *height, char **data,
578098f3 2569 bool inhibit_image_error)
4ef0d4d0
KS
2570{
2571 unsigned char *s = contents;
2572 char buffer[BUFSIZ];
578098f3
PE
2573 bool padding_p = 0;
2574 bool v10 = 0;
ca4aa935 2575 int bytes_per_line, i, nbytes;
b8dc29e9 2576 char *p;
4ef0d4d0
KS
2577 int value;
2578 int LA1;
2579
2580#define match() \
2581 LA1 = xbm_scan (&s, end, buffer, &value)
2582
2583#define expect(TOKEN) \
2584 if (LA1 != (TOKEN)) \
2585 goto failure; \
2586 else \
2587 match ()
2588
2589#define expect_ident(IDENT) \
2590 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2591 match (); \
2592 else \
2593 goto failure
2594
2595 *width = *height = -1;
2596 if (data)
2597 *data = NULL;
2598 LA1 = xbm_scan (&s, end, buffer, &value);
2599
2600 /* Parse defines for width, height and hot-spots. */
2601 while (LA1 == '#')
2602 {
2603 match ();
2604 expect_ident ("define");
2605 expect (XBM_TK_IDENT);
2606
431feaf6 2607 if (LA1 == XBM_TK_NUMBER)
4ef0d4d0 2608 {
6ae141d6
PE
2609 char *q = strrchr (buffer, '_');
2610 q = q ? q + 1 : buffer;
2611 if (strcmp (q, "width") == 0)
4ef0d4d0 2612 *width = value;
6ae141d6 2613 else if (strcmp (q, "height") == 0)
4ef0d4d0
KS
2614 *height = value;
2615 }
2616 expect (XBM_TK_NUMBER);
2617 }
2618
f1f25b99 2619 if (!check_image_size (f, *width, *height))
10ea2b82 2620 {
ce959360
CY
2621 if (!inhibit_image_error)
2622 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
10ea2b82
JR
2623 goto failure;
2624 }
4ef0d4d0
KS
2625 else if (data == NULL)
2626 goto success;
2627
2628 /* Parse bits. Must start with `static'. */
2629 expect_ident ("static");
2630 if (LA1 == XBM_TK_IDENT)
2631 {
2632 if (strcmp (buffer, "unsigned") == 0)
2633 {
2634 match ();
2635 expect_ident ("char");
2636 }
2637 else if (strcmp (buffer, "short") == 0)
2638 {
2639 match ();
2640 v10 = 1;
2641 if (*width % 16 && *width % 16 < 9)
2642 padding_p = 1;
2643 }
2644 else if (strcmp (buffer, "char") == 0)
2645 match ();
2646 else
2647 goto failure;
2648 }
2649 else
2650 goto failure;
2651
2652 expect (XBM_TK_IDENT);
2653 expect ('[');
2654 expect (']');
2655 expect ('=');
2656 expect ('{');
2657
ca4aa935
PE
2658 if (! x_check_image_size (0, *width, *height))
2659 {
2660 if (!inhibit_image_error)
2661 image_error ("Image too large (%dx%d)",
2662 make_number (*width), make_number (*height));
2663 goto failure;
2664 }
4ef0d4d0
KS
2665 bytes_per_line = (*width + 7) / 8 + padding_p;
2666 nbytes = bytes_per_line * *height;
23f86fce 2667 p = *data = xmalloc (nbytes);
4ef0d4d0
KS
2668
2669 if (v10)
2670 {
2671 for (i = 0; i < nbytes; i += 2)
2672 {
2673 int val = value;
2674 expect (XBM_TK_NUMBER);
2675
2676 *p++ = XBM_BIT_SHUFFLE (val);
2677 if (!padding_p || ((i + 2) % bytes_per_line))
2678 *p++ = XBM_BIT_SHUFFLE (value >> 8);
2679
2680 if (LA1 == ',' || LA1 == '}')
2681 match ();
2682 else
2683 goto failure;
2684 }
2685 }
2686 else
2687 {
2688 for (i = 0; i < nbytes; ++i)
2689 {
2690 int val = value;
2691 expect (XBM_TK_NUMBER);
2692
2693 *p++ = XBM_BIT_SHUFFLE (val);
2694
2695 if (LA1 == ',' || LA1 == '}')
2696 match ();
2697 else
2698 goto failure;
2699 }
2700 }
2701
2702 success:
2703 return 1;
2704
2705 failure:
2706
2707 if (data && *data)
2708 {
2709 xfree (*data);
2710 *data = NULL;
2711 }
2712 return 0;
2713
2714#undef match
2715#undef expect
2716#undef expect_ident
2717}
2718
2719
2720/* Load XBM image IMG which will be displayed on frame F from buffer
578098f3 2721 CONTENTS. END is the end of the buffer. Value is true if
4ef0d4d0
KS
2722 successful. */
2723
578098f3 2724static bool
d3da34e0
JB
2725xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
2726 unsigned char *end)
4ef0d4d0 2727{
578098f3 2728 bool rc;
b8dc29e9 2729 char *data;
578098f3 2730 bool success_p = 0;
4ef0d4d0 2731
ce959360
CY
2732 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
2733 &data, 0);
4ef0d4d0
KS
2734 if (rc)
2735 {
2736 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2737 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
578098f3 2738 bool non_default_colors = 0;
4ef0d4d0
KS
2739 Lisp_Object value;
2740
a54e2c05 2741 eassert (img->width > 0 && img->height > 0);
4ef0d4d0
KS
2742
2743 /* Get foreground and background colors, maybe allocate colors. */
2744 value = image_spec_value (img->spec, QCforeground, NULL);
2745 if (!NILP (value))
2746 {
2747 foreground = x_alloc_image_color (f, img, value, foreground);
2748 non_default_colors = 1;
2749 }
2750 value = image_spec_value (img->spec, QCbackground, NULL);
2751 if (!NILP (value))
2752 {
2753 background = x_alloc_image_color (f, img, value, background);
2754 img->background = background;
2755 img->background_valid = 1;
2756 non_default_colors = 1;
2757 }
2758
1f026899 2759 Create_Pixmap_From_Bitmap_Data (f, img, data,
4ef0d4d0
KS
2760 foreground, background,
2761 non_default_colors);
2762 xfree (data);
2763
2764 if (img->pixmap == NO_PIXMAP)
2765 {
2766 x_clear_image (f, img);
2767 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
2768 }
2769 else
2770 success_p = 1;
2771 }
2772 else
2773 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2774
2775 return success_p;
2776}
2777
2778
578098f3 2779/* Value is true if DATA looks like an in-memory XBM file. */
4ef0d4d0 2780
578098f3 2781static bool
d3da34e0 2782xbm_file_p (Lisp_Object data)
4ef0d4d0
KS
2783{
2784 int w, h;
2785 return (STRINGP (data)
f1f25b99 2786 && xbm_read_bitmap_data (NULL, SDATA (data),
ce959360
CY
2787 (SDATA (data) + SBYTES (data)),
2788 &w, &h, NULL, 1));
4ef0d4d0
KS
2789}
2790
2791
2792/* Fill image IMG which is used on frame F with pixmap data. Value is
578098f3 2793 true if successful. */
4ef0d4d0 2794
578098f3 2795static bool
d3da34e0 2796xbm_load (struct frame *f, struct image *img)
4ef0d4d0 2797{
578098f3 2798 bool success_p = 0;
4ef0d4d0
KS
2799 Lisp_Object file_name;
2800
a54e2c05 2801 eassert (xbm_image_p (img->spec));
4ef0d4d0
KS
2802
2803 /* If IMG->spec specifies a file name, create a non-file spec from it. */
2804 file_name = image_spec_value (img->spec, QCfile, NULL);
2805 if (STRINGP (file_name))
2806 {
2807 Lisp_Object file;
2808 unsigned char *contents;
dd52fcea 2809 ptrdiff_t size;
4ef0d4d0
KS
2810
2811 file = x_find_image_file (file_name);
4ef0d4d0
KS
2812 if (!STRINGP (file))
2813 {
2814 image_error ("Cannot find image file `%s'", file_name, Qnil);
4ef0d4d0
KS
2815 return 0;
2816 }
2817
42a5b22f 2818 contents = slurp_file (SSDATA (file), &size);
4ef0d4d0
KS
2819 if (contents == NULL)
2820 {
2821 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
4ef0d4d0
KS
2822 return 0;
2823 }
2824
2825 success_p = xbm_load_image (f, img, contents, contents + size);
d5a19415 2826 xfree (contents);
4ef0d4d0
KS
2827 }
2828 else
2829 {
2830 struct image_keyword fmt[XBM_LAST];
2831 Lisp_Object data;
2832 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2833 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
578098f3 2834 bool non_default_colors = 0;
4ef0d4d0 2835 char *bits;
578098f3
PE
2836 bool parsed_p;
2837 bool in_memory_file_p = 0;
4ef0d4d0
KS
2838
2839 /* See if data looks like an in-memory XBM file. */
2840 data = image_spec_value (img->spec, QCdata, NULL);
2841 in_memory_file_p = xbm_file_p (data);
2842
2843 /* Parse the image specification. */
72af86bd 2844 memcpy (fmt, xbm_format, sizeof fmt);
4ef0d4d0 2845 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
a54e2c05 2846 eassert (parsed_p);
4ef0d4d0
KS
2847
2848 /* Get specified width, and height. */
2849 if (!in_memory_file_p)
2850 {
2851 img->width = XFASTINT (fmt[XBM_WIDTH].value);
2852 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
a54e2c05 2853 eassert (img->width > 0 && img->height > 0);
ca4aa935
PE
2854 if (!check_image_size (f, img->width, img->height))
2855 {
2856 image_error ("Invalid image size (see `max-image-size')",
2857 Qnil, Qnil);
2858 return 0;
2859 }
4ef0d4d0
KS
2860 }
2861
2862 /* Get foreground and background colors, maybe allocate colors. */
2863 if (fmt[XBM_FOREGROUND].count
2864 && STRINGP (fmt[XBM_FOREGROUND].value))
2865 {
2866 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
2867 foreground);
2868 non_default_colors = 1;
2869 }
2870
2871 if (fmt[XBM_BACKGROUND].count
2872 && STRINGP (fmt[XBM_BACKGROUND].value))
2873 {
2874 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
2875 background);
2876 non_default_colors = 1;
2877 }
2878
2879 if (in_memory_file_p)
2880 success_p = xbm_load_image (f, img, SDATA (data),
2881 (SDATA (data)
2882 + SBYTES (data)));
2883 else
2884 {
2885 if (VECTORP (data))
2886 {
2887 int i;
2888 char *p;
2889 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
2890
38182d90 2891 p = bits = alloca (nbytes * img->height);
4ef0d4d0
KS
2892 for (i = 0; i < img->height; ++i, p += nbytes)
2893 {
28be1ada 2894 Lisp_Object line = AREF (data, i);
4ef0d4d0 2895 if (STRINGP (line))
72af86bd 2896 memcpy (p, SDATA (line), nbytes);
4ef0d4d0 2897 else
72af86bd 2898 memcpy (p, XBOOL_VECTOR (line)->data, nbytes);
4ef0d4d0
KS
2899 }
2900 }
2901 else if (STRINGP (data))
42a5b22f 2902 bits = SSDATA (data);
4ef0d4d0 2903 else
b8dc29e9 2904 bits = (char *) XBOOL_VECTOR (data)->data;
4ef0d4d0 2905
0fda9b75 2906#ifdef HAVE_NTGUI
44b1dc2e
JR
2907 {
2908 char *invertedBits;
2909 int nbytes, i;
2910 /* Windows mono bitmaps are reversed compared with X. */
2911 invertedBits = bits;
285d07e2 2912 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
44b1dc2e 2913 * img->height;
38182d90 2914 bits = alloca (nbytes);
44b1dc2e
JR
2915 for (i = 0; i < nbytes; i++)
2916 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
2917 }
2918#endif
4ef0d4d0
KS
2919 /* Create the pixmap. */
2920
ca4aa935
PE
2921 if (x_check_image_size (0, img->width, img->height))
2922 Create_Pixmap_From_Bitmap_Data (f, img, bits,
2923 foreground, background,
2924 non_default_colors);
2925 else
2926 img->pixmap = NO_PIXMAP;
2927
4ef0d4d0
KS
2928 if (img->pixmap)
2929 success_p = 1;
2930 else
2931 {
2932 image_error ("Unable to create pixmap for XBM image `%s'",
2933 img->spec, Qnil);
2934 x_clear_image (f, img);
2935 }
2936 }
2937 }
2938
2939 return success_p;
2940}
2941
2942
2943\f
2944/***********************************************************************
2945 XPM images
2946 ***********************************************************************/
2947
9e2a2647 2948#if defined (HAVE_XPM) || defined (HAVE_NS)
4ef0d4d0 2949
578098f3
PE
2950static bool xpm_image_p (Lisp_Object object);
2951static bool xpm_load (struct frame *f, struct image *img);
4ef0d4d0 2952
9e2a2647 2953#endif /* HAVE_XPM || HAVE_NS */
ea1aaa6f
ST
2954
2955#ifdef HAVE_XPM
4ef0d4d0
KS
2956#ifdef HAVE_NTGUI
2957/* Indicate to xpm.h that we don't have Xlib. */
2958#define FOR_MSW
2959/* simx.h in xpm defines XColor and XImage differently than Emacs. */
279d3293 2960/* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
4ef0d4d0
KS
2961#define XColor xpm_XColor
2962#define XImage xpm_XImage
279d3293 2963#define Display xpm_Display
4ef0d4d0
KS
2964#define PIXEL_ALREADY_TYPEDEFED
2965#include "X11/xpm.h"
2966#undef FOR_MSW
2967#undef XColor
2968#undef XImage
279d3293 2969#undef Display
4ef0d4d0
KS
2970#undef PIXEL_ALREADY_TYPEDEFED
2971#else
2972#include "X11/xpm.h"
2973#endif /* HAVE_NTGUI */
ea1aaa6f 2974#endif /* HAVE_XPM */
4ef0d4d0 2975
9e2a2647 2976#if defined (HAVE_XPM) || defined (HAVE_NS)
4ef0d4d0
KS
2977/* The symbol `xpm' identifying XPM-format images. */
2978
955cbe7b 2979static Lisp_Object Qxpm;
4ef0d4d0
KS
2980
2981/* Indices of image specification fields in xpm_format, below. */
2982
2983enum xpm_keyword_index
2984{
2985 XPM_TYPE,
2986 XPM_FILE,
2987 XPM_DATA,
2988 XPM_ASCENT,
2989 XPM_MARGIN,
2990 XPM_RELIEF,
2991 XPM_ALGORITHM,
2992 XPM_HEURISTIC_MASK,
2993 XPM_MASK,
2994 XPM_COLOR_SYMBOLS,
2995 XPM_BACKGROUND,
2996 XPM_LAST
2997};
2998
2999/* Vector of image_keyword structures describing the format
3000 of valid XPM image specifications. */
3001
91433552 3002static const struct image_keyword xpm_format[XPM_LAST] =
4ef0d4d0
KS
3003{
3004 {":type", IMAGE_SYMBOL_VALUE, 1},
3005 {":file", IMAGE_STRING_VALUE, 0},
3006 {":data", IMAGE_STRING_VALUE, 0},
3007 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 3008 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
3009 {":relief", IMAGE_INTEGER_VALUE, 0},
3010 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3011 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3012 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3013 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3014 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3015};
3016
a9e7a9d5 3017#if defined HAVE_NTGUI && defined WINDOWSNT
578098f3 3018static bool init_xpm_functions (void);
bb4d86b4
CY
3019#else
3020#define init_xpm_functions NULL
3021#endif
3022
4ef0d4d0
KS
3023/* Structure describing the image type XPM. */
3024
3025static struct image_type xpm_type =
3026{
3027 &Qxpm,
3028 xpm_image_p,
3029 xpm_load,
3030 x_clear_image,
bb4d86b4 3031 init_xpm_functions,
4ef0d4d0
KS
3032 NULL
3033};
3034
3035#ifdef HAVE_X_WINDOWS
3036
3037/* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3038 functions for allocating image colors. Our own functions handle
3039 color allocation failures more gracefully than the ones on the XPM
3040 lib. */
3041
3042#if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3043#define ALLOC_XPM_COLORS
3044#endif
3045#endif /* HAVE_X_WINDOWS */
3046
3047#ifdef ALLOC_XPM_COLORS
3048
f57e2426
J
3049static struct xpm_cached_color *xpm_cache_color (struct frame *, char *,
3050 XColor *, int);
4ef0d4d0
KS
3051
3052/* An entry in a hash table used to cache color definitions of named
3053 colors. This cache is necessary to speed up XPM image loading in
3054 case we do color allocations ourselves. Without it, we would need
3055 a call to XParseColor per pixel in the image. */
3056
3057struct xpm_cached_color
3058{
3059 /* Next in collision chain. */
3060 struct xpm_cached_color *next;
3061
3062 /* Color definition (RGB and pixel color). */
3063 XColor color;
3064
3065 /* Color name. */
3066 char name[1];
3067};
3068
3069/* The hash table used for the color cache, and its bucket vector
3070 size. */
3071
3072#define XPM_COLOR_CACHE_BUCKETS 1001
cd44d2eb 3073static struct xpm_cached_color **xpm_color_cache;
4ef0d4d0
KS
3074
3075/* Initialize the color cache. */
3076
3077static void
d3da34e0 3078xpm_init_color_cache (struct frame *f, XpmAttributes *attrs)
4ef0d4d0
KS
3079{
3080 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
23f86fce 3081 xpm_color_cache = xzalloc (nbytes);
4ef0d4d0
KS
3082 init_color_table ();
3083
3084 if (attrs->valuemask & XpmColorSymbols)
3085 {
3086 int i;
3087 XColor color;
3088
3089 for (i = 0; i < attrs->numsymbols; ++i)
3090 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3091 attrs->colorsymbols[i].value, &color))
3092 {
3093 color.pixel = lookup_rgb_color (f, color.red, color.green,
3094 color.blue);
3095 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3096 }
3097 }
3098}
3099
3100/* Free the color cache. */
3101
3102static void
d3da34e0 3103xpm_free_color_cache (void)
4ef0d4d0
KS
3104{
3105 struct xpm_cached_color *p, *next;
3106 int i;
3107
3108 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3109 for (p = xpm_color_cache[i]; p; p = next)
3110 {
3111 next = p->next;
3112 xfree (p);
3113 }
3114
3115 xfree (xpm_color_cache);
3116 xpm_color_cache = NULL;
3117 free_color_table ();
3118}
3119
3120/* Return the bucket index for color named COLOR_NAME in the color
3121 cache. */
3122
3123static int
d3da34e0 3124xpm_color_bucket (char *color_name)
4ef0d4d0 3125{
3f791afe
PE
3126 EMACS_UINT hash = hash_string (color_name, strlen (color_name));
3127 return hash % XPM_COLOR_CACHE_BUCKETS;
4ef0d4d0
KS
3128}
3129
3130
3131/* On frame F, cache values COLOR for color with name COLOR_NAME.
3132 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3133 entry added. */
3134
3135static struct xpm_cached_color *
d3da34e0 3136xpm_cache_color (struct frame *f, char *color_name, XColor *color, int bucket)
4ef0d4d0
KS
3137{
3138 size_t nbytes;
3139 struct xpm_cached_color *p;
3140
3141 if (bucket < 0)
3142 bucket = xpm_color_bucket (color_name);
3143
3f791afe 3144 nbytes = offsetof (struct xpm_cached_color, name) + strlen (color_name) + 1;
23f86fce 3145 p = xmalloc (nbytes);
4ef0d4d0
KS
3146 strcpy (p->name, color_name);
3147 p->color = *color;
3148 p->next = xpm_color_cache[bucket];
3149 xpm_color_cache[bucket] = p;
3150 return p;
3151}
3152
3153/* Look up color COLOR_NAME for frame F in the color cache. If found,
3154 return the cached definition in *COLOR. Otherwise, make a new
578098f3 3155 entry in the cache and allocate the color. Value is false if color
4ef0d4d0
KS
3156 allocation failed. */
3157
578098f3 3158static bool
d3da34e0 3159xpm_lookup_color (struct frame *f, char *color_name, XColor *color)
4ef0d4d0
KS
3160{
3161 struct xpm_cached_color *p;
3162 int h = xpm_color_bucket (color_name);
3163
3164 for (p = xpm_color_cache[h]; p; p = p->next)
3165 if (strcmp (p->name, color_name) == 0)
3166 break;
3167
3168 if (p != NULL)
3169 *color = p->color;
3170 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3171 color_name, color))
3172 {
3173 color->pixel = lookup_rgb_color (f, color->red, color->green,
3174 color->blue);
3175 p = xpm_cache_color (f, color_name, color, h);
3176 }
3177 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3178 with transparency, and it's useful. */
3179 else if (strcmp ("opaque", color_name) == 0)
3180 {
72af86bd 3181 memset (color, 0, sizeof (XColor)); /* Is this necessary/correct? */
4ef0d4d0
KS
3182 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3183 p = xpm_cache_color (f, color_name, color, h);
3184 }
3185
3186 return p != NULL;
3187}
3188
3189
3190/* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3191 CLOSURE is a pointer to the frame on which we allocate the
3192 color. Return in *COLOR the allocated color. Value is non-zero
3193 if successful. */
3194
3195static int
d3da34e0
JB
3196xpm_alloc_color (Display *dpy, Colormap cmap, char *color_name, XColor *color,
3197 void *closure)
4ef0d4d0
KS
3198{
3199 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3200}
3201
3202
3203/* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3204 is a pointer to the frame on which we allocate the color. Value is
3205 non-zero if successful. */
3206
3207static int
d3da34e0 3208xpm_free_colors (Display *dpy, Colormap cmap, Pixel *pixels, int npixels, void *closure)
4ef0d4d0
KS
3209{
3210 return 1;
3211}
3212
3213#endif /* ALLOC_XPM_COLORS */
3214
3215
0fda9b75 3216#ifdef WINDOWSNT
4ef0d4d0
KS
3217
3218/* XPM library details. */
3219
14beddf4
CY
3220DEF_IMGLIB_FN (void, XpmFreeAttributes, (XpmAttributes *));
3221DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer, (Display *, char *, xpm_XImage **,
850690cc 3222 xpm_XImage **, XpmAttributes *));
14beddf4 3223DEF_IMGLIB_FN (int, XpmReadFileToImage, (Display *, char *, xpm_XImage **,
850690cc 3224 xpm_XImage **, XpmAttributes *));
14beddf4 3225DEF_IMGLIB_FN (void, XImageFree, (xpm_XImage *));
4ef0d4d0 3226
578098f3 3227static bool
d07ff9db 3228init_xpm_functions (void)
4ef0d4d0
KS
3229{
3230 HMODULE library;
3231
d07ff9db 3232 if (!(library = w32_delayed_load (Qxpm)))
4ef0d4d0
KS
3233 return 0;
3234
3235 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3236 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3237 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3238 LOAD_IMGLIB_FN (library, XImageFree);
3239 return 1;
3240}
3241
0fda9b75 3242#endif /* WINDOWSNT */
4ef0d4d0 3243
a9e7a9d5 3244#if defined HAVE_NTGUI && !defined WINDOWSNT
0fda9b75
DC
3245/* Glue for code below */
3246#define fn_XpmReadFileToImage XpmReadFileToImage
3247#define fn_XpmCreateImageFromBuffer XpmCreateImageFromBuffer
3248#define fn_XImageFree XImageFree
3249#define fn_XpmFreeAttributes XpmFreeAttributes
2ae3a8a7 3250#endif /* HAVE_NTGUI && !WINDOWSNT */
4ef0d4d0 3251
578098f3 3252/* Value is true if COLOR_SYMBOLS is a valid color symbols list
4ef0d4d0
KS
3253 for XPM images. Such a list must consist of conses whose car and
3254 cdr are strings. */
3255
578098f3 3256static bool
d3da34e0 3257xpm_valid_color_symbols_p (Lisp_Object color_symbols)
4ef0d4d0
KS
3258{
3259 while (CONSP (color_symbols))
3260 {
3261 Lisp_Object sym = XCAR (color_symbols);
3262 if (!CONSP (sym)
3263 || !STRINGP (XCAR (sym))
3264 || !STRINGP (XCDR (sym)))
3265 break;
3266 color_symbols = XCDR (color_symbols);
3267 }
3268
3269 return NILP (color_symbols);
3270}
3271
3272
578098f3 3273/* Value is true if OBJECT is a valid XPM image specification. */
4ef0d4d0 3274
578098f3 3275static bool
d3da34e0 3276xpm_image_p (Lisp_Object object)
4ef0d4d0
KS
3277{
3278 struct image_keyword fmt[XPM_LAST];
72af86bd 3279 memcpy (fmt, xpm_format, sizeof fmt);
4ef0d4d0
KS
3280 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3281 /* Either `:file' or `:data' must be present. */
3282 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3283 /* Either no `:color-symbols' or it's a list of conses
3284 whose car and cdr are strings. */
3285 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3286 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3287}
3288
9e2a2647 3289#endif /* HAVE_XPM || HAVE_NS */
4ef0d4d0 3290
cd44d2eb 3291#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
0766b489 3292ptrdiff_t
ef1b0ba7 3293x_create_bitmap_from_xpm_data (struct frame *f, const char **bits)
786a43d6
CY
3294{
3295 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
0766b489
PE
3296 ptrdiff_t id;
3297 int rc;
786a43d6
CY
3298 XpmAttributes attrs;
3299 Pixmap bitmap, mask;
3300
72af86bd 3301 memset (&attrs, 0, sizeof attrs);
786a43d6 3302
54188d8f
CY
3303 attrs.visual = FRAME_X_VISUAL (f);
3304 attrs.colormap = FRAME_X_COLORMAP (f);
3305 attrs.valuemask |= XpmVisual;
3306 attrs.valuemask |= XpmColormap;
3307
786a43d6 3308 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f77fabaf 3309 (char **) bits, &bitmap, &mask, &attrs);
786a43d6 3310 if (rc != XpmSuccess)
fe45ad15
CY
3311 {
3312 XpmFreeAttributes (&attrs);
3313 return -1;
3314 }
786a43d6
CY
3315
3316 id = x_allocate_bitmap_record (f);
786a43d6
CY
3317 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3318 dpyinfo->bitmaps[id - 1].have_mask = 1;
3319 dpyinfo->bitmaps[id - 1].mask = mask;
3320 dpyinfo->bitmaps[id - 1].file = NULL;
3321 dpyinfo->bitmaps[id - 1].height = attrs.height;
3322 dpyinfo->bitmaps[id - 1].width = attrs.width;
3323 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3324 dpyinfo->bitmaps[id - 1].refcount = 1;
3325
3326 XpmFreeAttributes (&attrs);
3327 return id;
3328}
0d876a14 3329#endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
786a43d6 3330
4ef0d4d0 3331/* Load image IMG which will be displayed on frame F. Value is
578098f3 3332 true if successful. */
4ef0d4d0 3333
ea1aaa6f
ST
3334#ifdef HAVE_XPM
3335
578098f3 3336static bool
d3da34e0 3337xpm_load (struct frame *f, struct image *img)
4ef0d4d0
KS
3338{
3339 int rc;
3340 XpmAttributes attrs;
3341 Lisp_Object specified_file, color_symbols;
3342#ifdef HAVE_NTGUI
3343 HDC hdc;
3344 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3345#endif /* HAVE_NTGUI */
3346
3347 /* Configure the XPM lib. Use the visual of frame F. Allocate
3348 close colors. Return colors allocated. */
72af86bd 3349 memset (&attrs, 0, sizeof attrs);
4ef0d4d0
KS
3350
3351#ifndef HAVE_NTGUI
3352 attrs.visual = FRAME_X_VISUAL (f);
3353 attrs.colormap = FRAME_X_COLORMAP (f);
3354 attrs.valuemask |= XpmVisual;
3355 attrs.valuemask |= XpmColormap;
3356#endif /* HAVE_NTGUI */
3357
3358#ifdef ALLOC_XPM_COLORS
3359 /* Allocate colors with our own functions which handle
3360 failing color allocation more gracefully. */
3361 attrs.color_closure = f;
3362 attrs.alloc_color = xpm_alloc_color;
3363 attrs.free_colors = xpm_free_colors;
3364 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3365#else /* not ALLOC_XPM_COLORS */
3366 /* Let the XPM lib allocate colors. */
3367 attrs.valuemask |= XpmReturnAllocPixels;
3368#ifdef XpmAllocCloseColors
3369 attrs.alloc_close_colors = 1;
3370 attrs.valuemask |= XpmAllocCloseColors;
3371#else /* not XpmAllocCloseColors */
3372 attrs.closeness = 600;
3373 attrs.valuemask |= XpmCloseness;
3374#endif /* not XpmAllocCloseColors */
3375#endif /* ALLOC_XPM_COLORS */
3376
3377 /* If image specification contains symbolic color definitions, add
3378 these to `attrs'. */
3379 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3380 if (CONSP (color_symbols))
3381 {
3382 Lisp_Object tail;
3383 XpmColorSymbol *xpm_syms;
3384 int i, size;
3385
3386 attrs.valuemask |= XpmColorSymbols;
3387
3388 /* Count number of symbols. */
3389 attrs.numsymbols = 0;
3390 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3391 ++attrs.numsymbols;
3392
3393 /* Allocate an XpmColorSymbol array. */
3394 size = attrs.numsymbols * sizeof *xpm_syms;
38182d90 3395 xpm_syms = alloca (size);
72af86bd 3396 memset (xpm_syms, 0, size);
4ef0d4d0
KS
3397 attrs.colorsymbols = xpm_syms;
3398
3399 /* Fill the color symbol array. */
3400 for (tail = color_symbols, i = 0;
3401 CONSP (tail);
3402 ++i, tail = XCDR (tail))
3403 {
7574650a
AS
3404 Lisp_Object name;
3405 Lisp_Object color;
e22cffbc 3406 char *empty_string = (char *) "";
7574650a
AS
3407
3408 if (!CONSP (XCAR (tail)))
3409 {
e22cffbc
PE
3410 xpm_syms[i].name = empty_string;
3411 xpm_syms[i].value = empty_string;
7574650a
AS
3412 continue;
3413 }
3414 name = XCAR (XCAR (tail));
3415 color = XCDR (XCAR (tail));
3416 if (STRINGP (name))
3417 {
38182d90 3418 xpm_syms[i].name = alloca (SCHARS (name) + 1);
42a5b22f 3419 strcpy (xpm_syms[i].name, SSDATA (name));
7574650a
AS
3420 }
3421 else
e22cffbc 3422 xpm_syms[i].name = empty_string;
7574650a
AS
3423 if (STRINGP (color))
3424 {
38182d90 3425 xpm_syms[i].value = alloca (SCHARS (color) + 1);
42a5b22f 3426 strcpy (xpm_syms[i].value, SSDATA (color));
7574650a
AS
3427 }
3428 else
e22cffbc 3429 xpm_syms[i].value = empty_string;
4ef0d4d0
KS
3430 }
3431 }
3432
3433 /* Create a pixmap for the image, either from a file, or from a
3434 string buffer containing data in the same format as an XPM file. */
3435#ifdef ALLOC_XPM_COLORS
3436 xpm_init_color_cache (f, &attrs);
3437#endif
3438
3439 specified_file = image_spec_value (img->spec, QCfile, NULL);
3440
3441#ifdef HAVE_NTGUI
3442 {
3443 HDC frame_dc = get_frame_dc (f);
3444 hdc = CreateCompatibleDC (frame_dc);
3445 release_frame_dc (f, frame_dc);
3446 }
3447#endif /* HAVE_NTGUI */
3448
3449 if (STRINGP (specified_file))
3450 {
3451 Lisp_Object file = x_find_image_file (specified_file);
3452 if (!STRINGP (file))
3453 {
3454 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7574650a
AS
3455#ifdef ALLOC_XPM_COLORS
3456 xpm_free_color_cache ();
3457#endif
4ef0d4d0
KS
3458 return 0;
3459 }
3460
3461#ifdef HAVE_NTGUI
3462 /* XpmReadFileToPixmap is not available in the Windows port of
3463 libxpm. But XpmReadFileToImage almost does what we want. */
3464 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3465 &xpm_image, &xpm_mask,
3466 &attrs);
3467#else
3468 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
42a5b22f 3469 SSDATA (file), &img->pixmap, &img->mask,
4ef0d4d0
KS
3470 &attrs);
3471#endif /* HAVE_NTGUI */
3472 }
3473 else
3474 {
3475 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
3476 if (!STRINGP (buffer))
3477 {
3478 image_error ("Invalid image data `%s'", buffer, Qnil);
3479#ifdef ALLOC_XPM_COLORS
3480 xpm_free_color_cache ();
3481#endif
3482 return 0;
3483 }
4ef0d4d0
KS
3484#ifdef HAVE_NTGUI
3485 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3486 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3487 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3488 &xpm_image, &xpm_mask,
3489 &attrs);
3490#else
3491 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
42a5b22f 3492 SSDATA (buffer),
4ef0d4d0
KS
3493 &img->pixmap, &img->mask,
3494 &attrs);
3495#endif /* HAVE_NTGUI */
3496 }
3497
3498 if (rc == XpmSuccess)
3499 {
3500#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3501 img->colors = colors_in_color_table (&img->ncolors);
3502#else /* not ALLOC_XPM_COLORS */
3503 int i;
3504
3505#ifdef HAVE_NTGUI
3506 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3507 plus some duplicate attributes. */
3508 if (xpm_image && xpm_image->bitmap)
3509 {
3510 img->pixmap = xpm_image->bitmap;
3511 /* XImageFree in libXpm frees XImage struct without destroying
3512 the bitmap, which is what we want. */
3513 fn_XImageFree (xpm_image);
3514 }
3515 if (xpm_mask && xpm_mask->bitmap)
3516 {
3517 /* The mask appears to be inverted compared with what we expect.
3518 TODO: invert our expectations. See other places where we
3519 have to invert bits because our idea of masks is backwards. */
3520 HGDIOBJ old_obj;
3521 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3522
3523 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3524 SelectObject (hdc, old_obj);
3525
3526 img->mask = xpm_mask->bitmap;
3527 fn_XImageFree (xpm_mask);
3528 DeleteDC (hdc);
3529 }
3530
3531 DeleteDC (hdc);
3532#endif /* HAVE_NTGUI */
3533
3534 /* Remember allocated colors. */
0065d054 3535 img->colors = xnmalloc (attrs.nalloc_pixels, sizeof *img->colors);
ddff3151 3536 img->ncolors = attrs.nalloc_pixels;
4ef0d4d0
KS
3537 for (i = 0; i < attrs.nalloc_pixels; ++i)
3538 {
3539 img->colors[i] = attrs.alloc_pixels[i];
3540#ifdef DEBUG_X_COLORS
3541 register_color (img->colors[i]);
3542#endif
3543 }
3544#endif /* not ALLOC_XPM_COLORS */
3545
3546 img->width = attrs.width;
3547 img->height = attrs.height;
a54e2c05 3548 eassert (img->width > 0 && img->height > 0);
4ef0d4d0
KS
3549
3550 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3551#ifdef HAVE_NTGUI
3552 fn_XpmFreeAttributes (&attrs);
3553#else
3554 XpmFreeAttributes (&attrs);
3555#endif /* HAVE_NTGUI */
3556 }
3557 else
3558 {
3559#ifdef HAVE_NTGUI
3560 DeleteDC (hdc);
3561#endif /* HAVE_NTGUI */
3562
3563 switch (rc)
3564 {
3565 case XpmOpenFailed:
3566 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3567 break;
3568
3569 case XpmFileInvalid:
3570 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3571 break;
3572
3573 case XpmNoMemory:
3574 image_error ("Out of memory (%s)", img->spec, Qnil);
3575 break;
3576
3577 case XpmColorFailed:
3578 image_error ("Color allocation error (%s)", img->spec, Qnil);
3579 break;
3580
3581 default:
3582 image_error ("Unknown error (%s)", img->spec, Qnil);
3583 break;
3584 }
3585 }
3586
3587#ifdef ALLOC_XPM_COLORS
3588 xpm_free_color_cache ();
3589#endif
3590 return rc == XpmSuccess;
3591}
3592
3593#endif /* HAVE_XPM */
3594
9e2a2647 3595#if defined (HAVE_NS) && !defined (HAVE_XPM)
ea1aaa6f 3596
9e2a2647 3597/* XPM support functions for NS where libxpm is not available.
ea1aaa6f
ST
3598 Only XPM version 3 (without any extensions) is supported. */
3599
f57e2426
J
3600static void xpm_put_color_table_v (Lisp_Object, const unsigned char *,
3601 int, Lisp_Object);
3602static Lisp_Object xpm_get_color_table_v (Lisp_Object,
3603 const unsigned char *, int);
f57e2426
J
3604static void xpm_put_color_table_h (Lisp_Object, const unsigned char *,
3605 int, Lisp_Object);
3606static Lisp_Object xpm_get_color_table_h (Lisp_Object,
3607 const unsigned char *, int);
ea1aaa6f
ST
3608
3609/* Tokens returned from xpm_scan. */
3610
3611enum xpm_token
3612{
3613 XPM_TK_IDENT = 256,
3614 XPM_TK_STRING,
3615 XPM_TK_EOF
3616};
3617
3618/* Scan an XPM data and return a character (< 256) or a token defined
3619 by enum xpm_token above. *S and END are the start (inclusive) and
3620 the end (exclusive) addresses of the data, respectively. Advance
3621 *S while scanning. If token is either XPM_TK_IDENT or
3622 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3623 length of the corresponding token, respectively. */
3624
3625static int
3d608a86
J
3626xpm_scan (const unsigned char **s,
3627 const unsigned char *end,
3628 const unsigned char **beg,
74ca2eb3 3629 ptrdiff_t *len)
ea1aaa6f
ST
3630{
3631 int c;
3632
3633 while (*s < end)
3634 {
3635 /* Skip white-space. */
620f13b0 3636 while (*s < end && (c = *(*s)++, c_isspace (c)))
9ecf6403 3637 ;
ea1aaa6f
ST
3638
3639 /* gnus-pointer.xpm uses '-' in its identifier.
9ecf6403 3640 sb-dir-plus.xpm uses '+' in its identifier. */
620f13b0 3641 if (c_isalpha (c) || c == '_' || c == '-' || c == '+')
9ecf6403
YM
3642 {
3643 *beg = *s - 1;
2ff0845e 3644 while (*s < end
620f13b0
PE
3645 && (c = **s, c_isalnum (c)
3646 || c == '_' || c == '-' || c == '+'))
9ecf6403
YM
3647 ++*s;
3648 *len = *s - *beg;
3649 return XPM_TK_IDENT;
3650 }
ea1aaa6f 3651 else if (c == '"')
9ecf6403
YM
3652 {
3653 *beg = *s;
3654 while (*s < end && **s != '"')
3655 ++*s;
3656 *len = *s - *beg;
3657 if (*s < end)
3658 ++*s;
3659 return XPM_TK_STRING;
3660 }
ea1aaa6f 3661 else if (c == '/')
9ecf6403
YM
3662 {
3663 if (*s < end && **s == '*')
3664 {
3665 /* C-style comment. */
3666 ++*s;
3667 do
3668 {
3669 while (*s < end && *(*s)++ != '*')
3670 ;
3671 }
3672 while (*s < end && **s != '/');
3673 if (*s < end)
3674 ++*s;
3675 }
3676 else
3677 return c;
3678 }
ea1aaa6f 3679 else
9ecf6403 3680 return c;
ea1aaa6f
ST
3681 }
3682
3683 return XPM_TK_EOF;
3684}
3685
bbe6f2aa 3686/* Functions for color table lookup in XPM data. A key is a string
ea1aaa6f
ST
3687 specifying the color of each pixel in XPM data. A value is either
3688 an integer that specifies a pixel color, Qt that specifies
3689 transparency, or Qnil for the unspecified color. If the length of
3690 the key string is one, a vector is used as a table. Otherwise, a
3691 hash table is used. */
3692
3693static Lisp_Object
3d608a86
J
3694xpm_make_color_table_v (void (**put_func) (Lisp_Object,
3695 const unsigned char *,
3696 int,
3697 Lisp_Object),
3698 Lisp_Object (**get_func) (Lisp_Object,
3699 const unsigned char *,
3700 int))
ea1aaa6f
ST
3701{
3702 *put_func = xpm_put_color_table_v;
3703 *get_func = xpm_get_color_table_v;
3704 return Fmake_vector (make_number (256), Qnil);
3705}
3706
3707static void
3d608a86
J
3708xpm_put_color_table_v (Lisp_Object color_table,
3709 const unsigned char *chars_start,
3710 int chars_len,
3711 Lisp_Object color)
ea1aaa6f 3712{
28be1ada 3713 ASET (color_table, *chars_start, color);
ea1aaa6f
ST
3714}
3715
3716static Lisp_Object
3d608a86
J
3717xpm_get_color_table_v (Lisp_Object color_table,
3718 const unsigned char *chars_start,
3719 int chars_len)
ea1aaa6f 3720{
28be1ada 3721 return AREF (color_table, *chars_start);
ea1aaa6f
ST
3722}
3723
3724static Lisp_Object
3d608a86
J
3725xpm_make_color_table_h (void (**put_func) (Lisp_Object,
3726 const unsigned char *,
3727 int,
3728 Lisp_Object),
3729 Lisp_Object (**get_func) (Lisp_Object,
3730 const unsigned char *,
3731 int))
ea1aaa6f
ST
3732{
3733 *put_func = xpm_put_color_table_h;
3734 *get_func = xpm_get_color_table_h;
3735 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
9ecf6403
YM
3736 make_float (DEFAULT_REHASH_SIZE),
3737 make_float (DEFAULT_REHASH_THRESHOLD),
3738 Qnil, Qnil, Qnil);
ea1aaa6f
ST
3739}
3740
3741static void
3d608a86
J
3742xpm_put_color_table_h (Lisp_Object color_table,
3743 const unsigned char *chars_start,
3744 int chars_len,
3745 Lisp_Object color)
ea1aaa6f
ST
3746{
3747 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
0de4bb68 3748 EMACS_UINT hash_code;
ea1aaa6f
ST
3749 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3750
3751 hash_lookup (table, chars, &hash_code);
3752 hash_put (table, chars, color, hash_code);
3753}
3754
3755static Lisp_Object
3d608a86
J
3756xpm_get_color_table_h (Lisp_Object color_table,
3757 const unsigned char *chars_start,
3758 int chars_len)
ea1aaa6f
ST
3759{
3760 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
d3411f89
PE
3761 ptrdiff_t i =
3762 hash_lookup (table, make_unibyte_string (chars_start, chars_len), NULL);
ea1aaa6f
ST
3763
3764 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3765}
3766
3767enum xpm_color_key {
3768 XPM_COLOR_KEY_S,
3769 XPM_COLOR_KEY_M,
3770 XPM_COLOR_KEY_G4,
3771 XPM_COLOR_KEY_G,
3772 XPM_COLOR_KEY_C
3773};
3774
46accb8f 3775static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
ea1aaa6f
ST
3776
3777static int
3d608a86 3778xpm_str_to_color_key (const char *s)
ea1aaa6f
ST
3779{
3780 int i;
3781
3782 for (i = 0;
3783 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3784 i++)
3785 if (strcmp (xpm_color_key_strings[i], s) == 0)
3786 return i;
3787 return -1;
3788}
3789
578098f3 3790static bool
3d608a86
J
3791xpm_load_image (struct frame *f,
3792 struct image *img,
3793 const unsigned char *contents,
3794 const unsigned char *end)
ea1aaa6f 3795{
46accb8f 3796 const unsigned char *s = contents, *beg, *str;
ea1aaa6f
ST
3797 unsigned char buffer[BUFSIZ];
3798 int width, height, x, y;
3799 int num_colors, chars_per_pixel;
74ca2eb3
PE
3800 ptrdiff_t len;
3801 int LA1;
46accb8f
YM
3802 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3803 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
ea1aaa6f 3804 Lisp_Object frame, color_symbols, color_table;
578098f3
PE
3805 int best_key;
3806 bool have_mask = 0;
ea1aaa6f
ST
3807 XImagePtr ximg = NULL, mask_img = NULL;
3808
3809#define match() \
3810 LA1 = xpm_scan (&s, end, &beg, &len)
3811
9ecf6403
YM
3812#define expect(TOKEN) \
3813 if (LA1 != (TOKEN)) \
3814 goto failure; \
3815 else \
ea1aaa6f
ST
3816 match ()
3817
9ecf6403 3818#define expect_ident(IDENT) \
ea1aaa6f 3819 if (LA1 == XPM_TK_IDENT \
9ecf6403
YM
3820 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
3821 match (); \
3822 else \
ea1aaa6f
ST
3823 goto failure
3824
3825 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
3826 goto failure;
3827 s += 9;
ed3751c8 3828 match ();
ea1aaa6f
ST
3829 expect_ident ("static");
3830 expect_ident ("char");
3831 expect ('*');
3832 expect (XPM_TK_IDENT);
3833 expect ('[');
3834 expect (']');
3835 expect ('=');
3836 expect ('{');
3837 expect (XPM_TK_STRING);
3838 if (len >= BUFSIZ)
3839 goto failure;
3840 memcpy (buffer, beg, len);
3841 buffer[len] = '\0';
3842 if (sscanf (buffer, "%d %d %d %d", &width, &height,
9ecf6403 3843 &num_colors, &chars_per_pixel) != 4
ea1aaa6f
ST
3844 || width <= 0 || height <= 0
3845 || num_colors <= 0 || chars_per_pixel <= 0)
3846 goto failure;
de297941
YM
3847
3848 if (!check_image_size (f, width, height))
3849 {
10ea2b82 3850 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
de297941
YM
3851 goto failure;
3852 }
3853
ca4aa935
PE
3854 if (!x_create_x_image_and_pixmap (f, width, height, 0,
3855 &ximg, &img->pixmap)
3856#ifndef HAVE_NS
3857 || !x_create_x_image_and_pixmap (f, width, height, 1,
3858 &mask_img, &img->mask)
3859#endif
3860 )
3861 {
3862 image_error ("Image too large", Qnil, Qnil);
3863 goto failure;
3864 }
3865
ea1aaa6f
ST
3866 expect (',');
3867
3868 XSETFRAME (frame, f);
3869 if (!NILP (Fxw_display_color_p (frame)))
3870 best_key = XPM_COLOR_KEY_C;
3871 else if (!NILP (Fx_display_grayscale_p (frame)))
3872 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
9ecf6403 3873 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
ea1aaa6f
ST
3874 else
3875 best_key = XPM_COLOR_KEY_M;
3876
3877 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3878 if (chars_per_pixel == 1)
3879 color_table = xpm_make_color_table_v (&put_color_table,
9ecf6403 3880 &get_color_table);
ea1aaa6f
ST
3881 else
3882 color_table = xpm_make_color_table_h (&put_color_table,
9ecf6403 3883 &get_color_table);
ea1aaa6f
ST
3884
3885 while (num_colors-- > 0)
3886 {
25a48bd0 3887 char *color, *max_color;
ea1aaa6f
ST
3888 int key, next_key, max_key = 0;
3889 Lisp_Object symbol_color = Qnil, color_val;
3890 XColor cdef;
3891
3892 expect (XPM_TK_STRING);
3893 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
9ecf6403 3894 goto failure;
ea1aaa6f
ST
3895 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
3896 buffer[len - chars_per_pixel] = '\0';
3897
3898 str = strtok (buffer, " \t");
3899 if (str == NULL)
9ecf6403 3900 goto failure;
ea1aaa6f
ST
3901 key = xpm_str_to_color_key (str);
3902 if (key < 0)
9ecf6403 3903 goto failure;
ea1aaa6f 3904 do
9ecf6403
YM
3905 {
3906 color = strtok (NULL, " \t");
3907 if (color == NULL)
3908 goto failure;
ea1aaa6f 3909
9db94f82 3910 while ((str = strtok (NULL, " \t")) != NULL)
9ecf6403
YM
3911 {
3912 next_key = xpm_str_to_color_key (str);
3913 if (next_key >= 0)
3914 break;
3915 color[strlen (color)] = ' ';
3916 }
ea1aaa6f 3917
9ecf6403
YM
3918 if (key == XPM_COLOR_KEY_S)
3919 {
3920 if (NILP (symbol_color))
3921 symbol_color = build_string (color);
3922 }
3923 else if (max_key < key && key <= best_key)
3924 {
3925 max_key = key;
3926 max_color = color;
3927 }
3928 key = next_key;
3929 }
ea1aaa6f
ST
3930 while (str);
3931
3932 color_val = Qnil;
3933 if (!NILP (color_symbols) && !NILP (symbol_color))
9ecf6403
YM
3934 {
3935 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
3936
3937 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
9db94f82 3938 {
25a48bd0 3939 if (xstrcasecmp (SSDATA (XCDR (specified_color)), "None") == 0)
9db94f82 3940 color_val = Qt;
6045c4fd 3941 else if (x_defined_color (f, SSDATA (XCDR (specified_color)),
9db94f82
YM
3942 &cdef, 0))
3943 color_val = make_number (cdef.pixel);
3944 }
9ecf6403 3945 }
ea1aaa6f 3946 if (NILP (color_val) && max_key > 0)
9db94f82 3947 {
05131107 3948 if (xstrcasecmp (max_color, "None") == 0)
9db94f82
YM
3949 color_val = Qt;
3950 else if (x_defined_color (f, max_color, &cdef, 0))
3951 color_val = make_number (cdef.pixel);
3952 }
ea1aaa6f 3953 if (!NILP (color_val))
9ecf6403 3954 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
ea1aaa6f
ST
3955
3956 expect (',');
3957 }
3958
ea1aaa6f
ST
3959 for (y = 0; y < height; y++)
3960 {
3961 expect (XPM_TK_STRING);
3962 str = beg;
3963 if (len < width * chars_per_pixel)
9ecf6403 3964 goto failure;
ea1aaa6f 3965 for (x = 0; x < width; x++, str += chars_per_pixel)
9ecf6403
YM
3966 {
3967 Lisp_Object color_val =
3968 (*get_color_table) (color_table, str, chars_per_pixel);
3969
3970 XPutPixel (ximg, x, y,
3971 (INTEGERP (color_val) ? XINT (color_val)
3972 : FRAME_FOREGROUND_PIXEL (f)));
edfda783 3973#ifndef HAVE_NS
9ecf6403
YM
3974 XPutPixel (mask_img, x, y,
3975 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
3976 : (have_mask = 1, PIX_MASK_RETAIN)));
edfda783 3977#else
ed3751c8
JB
3978 if (EQ (color_val, Qt))
3979 ns_set_alpha (ximg, x, y, 0);
edfda783 3980#endif
9ecf6403 3981 }
ea1aaa6f 3982 if (y + 1 < height)
9ecf6403 3983 expect (',');
ea1aaa6f
ST
3984 }
3985
3986 img->width = width;
3987 img->height = height;
3988
0b8ac842
YM
3989 /* Maybe fill in the background field while we have ximg handy. */
3990 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3991 IMAGE_BACKGROUND (img, f, ximg);
3992
ea1aaa6f
ST
3993 x_put_x_image (f, ximg, img->pixmap, width, height);
3994 x_destroy_x_image (ximg);
edfda783 3995#ifndef HAVE_NS
ea1aaa6f
ST
3996 if (have_mask)
3997 {
9ecf6403
YM
3998 /* Fill in the background_transparent field while we have the
3999 mask handy. */
4000 image_background_transparent (img, f, mask_img);
4001
ea1aaa6f
ST
4002 x_put_x_image (f, mask_img, img->mask, width, height);
4003 x_destroy_x_image (mask_img);
4004 }
4005 else
4006 {
4007 x_destroy_x_image (mask_img);
4008 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4009 img->mask = NO_PIXMAP;
4010 }
edfda783 4011#endif
ea1aaa6f
ST
4012 return 1;
4013
4014 failure:
4015 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
ea1aaa6f
ST
4016 x_destroy_x_image (ximg);
4017 x_destroy_x_image (mask_img);
4018 x_clear_image (f, img);
4019 return 0;
4020
4021#undef match
4022#undef expect
4023#undef expect_ident
4024}
4025
578098f3 4026static bool
3d608a86
J
4027xpm_load (struct frame *f,
4028 struct image *img)
ea1aaa6f 4029{
578098f3 4030 bool success_p = 0;
ea1aaa6f
ST
4031 Lisp_Object file_name;
4032
4033 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4034 file_name = image_spec_value (img->spec, QCfile, NULL);
4035 if (STRINGP (file_name))
4036 {
4037 Lisp_Object file;
4038 unsigned char *contents;
dd52fcea 4039 ptrdiff_t size;
ea1aaa6f
ST
4040
4041 file = x_find_image_file (file_name);
ea1aaa6f 4042 if (!STRINGP (file))
9ecf6403
YM
4043 {
4044 image_error ("Cannot find image file `%s'", file_name, Qnil);
9ecf6403
YM
4045 return 0;
4046 }
ea1aaa6f 4047
6045c4fd 4048 contents = slurp_file (SSDATA (file), &size);
ea1aaa6f 4049 if (contents == NULL)
9ecf6403
YM
4050 {
4051 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
9ecf6403
YM
4052 return 0;
4053 }
ea1aaa6f
ST
4054
4055 success_p = xpm_load_image (f, img, contents, contents + size);
4056 xfree (contents);
ea1aaa6f
ST
4057 }
4058 else
4059 {
4060 Lisp_Object data;
4061
4062 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
4063 if (!STRINGP (data))
4064 {
4065 image_error ("Invalid image data `%s'", data, Qnil);
4066 return 0;
4067 }
ea1aaa6f 4068 success_p = xpm_load_image (f, img, SDATA (data),
9ecf6403 4069 SDATA (data) + SBYTES (data));
ea1aaa6f
ST
4070 }
4071
4072 return success_p;
4073}
4074
9e2a2647 4075#endif /* HAVE_NS && !HAVE_XPM */
b0da69a7 4076
ea1aaa6f 4077
4ef0d4d0
KS
4078\f
4079/***********************************************************************
4080 Color table
4081 ***********************************************************************/
4082
4083#ifdef COLOR_TABLE_SUPPORT
4084
4085/* An entry in the color table mapping an RGB color to a pixel color. */
4086
4087struct ct_color
4088{
4089 int r, g, b;
4090 unsigned long pixel;
4091
4092 /* Next in color table collision list. */
4093 struct ct_color *next;
4094};
4095
4096/* The bucket vector size to use. Must be prime. */
4097
4098#define CT_SIZE 101
4099
4100/* Value is a hash of the RGB color given by R, G, and B. */
4101
4102#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4103
4104/* The color hash table. */
4105
cd44d2eb 4106static struct ct_color **ct_table;
4ef0d4d0
KS
4107
4108/* Number of entries in the color table. */
4109
cd44d2eb 4110static int ct_colors_allocated;
ddff3151
PE
4111enum
4112{
4113 ct_colors_allocated_max =
4114 min (INT_MAX,
4115 min (PTRDIFF_MAX, SIZE_MAX) / sizeof (unsigned long))
4116};
4ef0d4d0
KS
4117
4118/* Initialize the color table. */
4119
4120static void
d3da34e0 4121init_color_table (void)
4ef0d4d0
KS
4122{
4123 int size = CT_SIZE * sizeof (*ct_table);
23f86fce 4124 ct_table = xzalloc (size);
4ef0d4d0
KS
4125 ct_colors_allocated = 0;
4126}
4127
4128
4129/* Free memory associated with the color table. */
4130
4131static void
d3da34e0 4132free_color_table (void)
4ef0d4d0
KS
4133{
4134 int i;
4135 struct ct_color *p, *next;
4136
4137 for (i = 0; i < CT_SIZE; ++i)
4138 for (p = ct_table[i]; p; p = next)
4139 {
4140 next = p->next;
4141 xfree (p);
4142 }
4143
4144 xfree (ct_table);
4145 ct_table = NULL;
4146}
4147
4148
4149/* Value is a pixel color for RGB color R, G, B on frame F. If an
4150 entry for that color already is in the color table, return the
4151 pixel color of that entry. Otherwise, allocate a new color for R,
4152 G, B, and make an entry in the color table. */
4153
4154static unsigned long
d3da34e0 4155lookup_rgb_color (struct frame *f, int r, int g, int b)
4ef0d4d0
KS
4156{
4157 unsigned hash = CT_HASH_RGB (r, g, b);
4158 int i = hash % CT_SIZE;
4159 struct ct_color *p;
4160 Display_Info *dpyinfo;
4161
4162 /* Handle TrueColor visuals specially, which improves performance by
4163 two orders of magnitude. Freeing colors on TrueColor visuals is
4164 a nop, and pixel colors specify RGB values directly. See also
4165 the Xlib spec, chapter 3.1. */
4166 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4167 if (dpyinfo->red_bits > 0)
4168 {
4169 unsigned long pr, pg, pb;
4170
4171 /* Apply gamma-correction like normal color allocation does. */
4172 if (f->gamma)
4173 {
4174 XColor color;
4175 color.red = r, color.green = g, color.blue = b;
4176 gamma_correct (f, &color);
4177 r = color.red, g = color.green, b = color.blue;
4178 }
4179
4180 /* Scale down RGB values to the visual's bits per RGB, and shift
4181 them to the right position in the pixel color. Note that the
4182 original RGB values are 16-bit values, as usual in X. */
4183 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4184 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4185 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4186
4187 /* Assemble the pixel color. */
4188 return pr | pg | pb;
4189 }
1f026899 4190
4ef0d4d0
KS
4191 for (p = ct_table[i]; p; p = p->next)
4192 if (p->r == r && p->g == g && p->b == b)
4193 break;
4194
4195 if (p == NULL)
4196 {
4197
4198#ifdef HAVE_X_WINDOWS
4199 XColor color;
4200 Colormap cmap;
578098f3 4201 bool rc;
ddff3151
PE
4202#else
4203 COLORREF color;
4204#endif
4ef0d4d0 4205
ddff3151
PE
4206 if (ct_colors_allocated_max <= ct_colors_allocated)
4207 return FRAME_FOREGROUND_PIXEL (f);
4208
4209#ifdef HAVE_X_WINDOWS
4ef0d4d0
KS
4210 color.red = r;
4211 color.green = g;
4212 color.blue = b;
4213
4214 cmap = FRAME_X_COLORMAP (f);
4215 rc = x_alloc_nearest_color (f, cmap, &color);
4216 if (rc)
4217 {
4218 ++ct_colors_allocated;
23f86fce 4219 p = xmalloc (sizeof *p);
4ef0d4d0
KS
4220 p->r = r;
4221 p->g = g;
4222 p->b = b;
4223 p->pixel = color.pixel;
4224 p->next = ct_table[i];
4225 ct_table[i] = p;
4226 }
4227 else
4228 return FRAME_FOREGROUND_PIXEL (f);
4229
4230#else
4ef0d4d0
KS
4231#ifdef HAVE_NTGUI
4232 color = PALETTERGB (r, g, b);
4233#else
4234 color = RGB_TO_ULONG (r, g, b);
4235#endif /* HAVE_NTGUI */
4236 ++ct_colors_allocated;
23f86fce 4237 p = xmalloc (sizeof *p);
4ef0d4d0
KS
4238 p->r = r;
4239 p->g = g;
4240 p->b = b;
4241 p->pixel = color;
4242 p->next = ct_table[i];
4243 ct_table[i] = p;
4244#endif /* HAVE_X_WINDOWS */
4245
4246 }
4247
4248 return p->pixel;
4249}
4250
4251
4252/* Look up pixel color PIXEL which is used on frame F in the color
4253 table. If not already present, allocate it. Value is PIXEL. */
4254
4255static unsigned long
d3da34e0 4256lookup_pixel_color (struct frame *f, unsigned long pixel)
4ef0d4d0
KS
4257{
4258 int i = pixel % CT_SIZE;
4259 struct ct_color *p;
4260
4261 for (p = ct_table[i]; p; p = p->next)
4262 if (p->pixel == pixel)
4263 break;
4264
4265 if (p == NULL)
4266 {
4267 XColor color;
4268 Colormap cmap;
578098f3 4269 bool rc;
4ef0d4d0 4270
ddff3151
PE
4271 if (ct_colors_allocated_max <= ct_colors_allocated)
4272 return FRAME_FOREGROUND_PIXEL (f);
4273
4ef0d4d0
KS
4274#ifdef HAVE_X_WINDOWS
4275 cmap = FRAME_X_COLORMAP (f);
4276 color.pixel = pixel;
4277 x_query_color (f, &color);
4278 rc = x_alloc_nearest_color (f, cmap, &color);
4279#else
4d7e6e51 4280 block_input ();
4ef0d4d0
KS
4281 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4282 color.pixel = pixel;
4283 XQueryColor (NULL, cmap, &color);
4284 rc = x_alloc_nearest_color (f, cmap, &color);
4d7e6e51 4285 unblock_input ();
4ef0d4d0
KS
4286#endif /* HAVE_X_WINDOWS */
4287
4288 if (rc)
4289 {
4290 ++ct_colors_allocated;
4291
23f86fce 4292 p = xmalloc (sizeof *p);
4ef0d4d0
KS
4293 p->r = color.red;
4294 p->g = color.green;
4295 p->b = color.blue;
4296 p->pixel = pixel;
4297 p->next = ct_table[i];
4298 ct_table[i] = p;
4299 }
4300 else
4301 return FRAME_FOREGROUND_PIXEL (f);
4302 }
4303 return p->pixel;
4304}
4305
4306
4307/* Value is a vector of all pixel colors contained in the color table,
4308 allocated via xmalloc. Set *N to the number of colors. */
4309
4310static unsigned long *
d3da34e0 4311colors_in_color_table (int *n)
4ef0d4d0
KS
4312{
4313 int i, j;
4314 struct ct_color *p;
4315 unsigned long *colors;
4316
4317 if (ct_colors_allocated == 0)
4318 {
4319 *n = 0;
4320 colors = NULL;
4321 }
4322 else
4323 {
23f86fce 4324 colors = xmalloc (ct_colors_allocated * sizeof *colors);
4ef0d4d0
KS
4325 *n = ct_colors_allocated;
4326
4327 for (i = j = 0; i < CT_SIZE; ++i)
4328 for (p = ct_table[i]; p; p = p->next)
4329 colors[j++] = p->pixel;
4330 }
4331
4332 return colors;
4333}
4334
4335#else /* COLOR_TABLE_SUPPORT */
4336
4337static unsigned long
7c3320d8 4338lookup_rgb_color (struct frame *f, int r, int g, int b)
4ef0d4d0
KS
4339{
4340 unsigned long pixel;
4341
4ef0d4d0
KS
4342#ifdef HAVE_NTGUI
4343 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4344#endif /* HAVE_NTGUI */
4345
edfda783
AR
4346#ifdef HAVE_NS
4347 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4348#endif /* HAVE_NS */
4ef0d4d0
KS
4349 return pixel;
4350}
4351
4352static void
7c3320d8 4353init_color_table (void)
4ef0d4d0
KS
4354{
4355}
4356#endif /* COLOR_TABLE_SUPPORT */
4357
4358\f
4359/***********************************************************************
4360 Algorithms
4361 ***********************************************************************/
4362
4ef0d4d0
KS
4363/* Edge detection matrices for different edge-detection
4364 strategies. */
4365
4366static int emboss_matrix[9] = {
4367 /* x - 1 x x + 1 */
4368 2, -1, 0, /* y - 1 */
4369 -1, 0, 1, /* y */
4370 0, 1, -2 /* y + 1 */
4371};
4372
4373static int laplace_matrix[9] = {
4374 /* x - 1 x x + 1 */
4375 1, 0, 0, /* y - 1 */
4376 0, 0, 0, /* y */
4377 0, 0, -1 /* y + 1 */
4378};
4379
4380/* Value is the intensity of the color whose red/green/blue values
4381 are R, G, and B. */
4382
4383#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4384
4385
4386/* On frame F, return an array of XColor structures describing image
4387 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
578098f3 4388 means also fill the red/green/blue members of the XColor
4ef0d4d0
KS
4389 structures. Value is a pointer to the array of XColors structures,
4390 allocated with xmalloc; it must be freed by the caller. */
4391
4392static XColor *
578098f3 4393x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4ef0d4d0
KS
4394{
4395 int x, y;
4396 XColor *colors, *p;
4397 XImagePtr_or_DC ximg;
4398#ifdef HAVE_NTGUI
4399 HDC hdc;
4400 HGDIOBJ prev;
4401#endif /* HAVE_NTGUI */
4402
ddff3151
PE
4403 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *colors / img->width < img->height)
4404 memory_full (SIZE_MAX);
23f86fce 4405 colors = xmalloc (sizeof *colors * img->width * img->height);
4ef0d4d0
KS
4406
4407#ifndef HAVE_NTGUI
4408 /* Get the X image IMG->pixmap. */
4409 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4410 0, 0, img->width, img->height, ~0, ZPixmap);
4411#else
4412 /* Load the image into a memory device context. */
4413 hdc = get_frame_dc (f);
4414 ximg = CreateCompatibleDC (hdc);
4415 release_frame_dc (f, hdc);
4416 prev = SelectObject (ximg, img->pixmap);
4417#endif /* HAVE_NTGUI */
4418
4419 /* Fill the `pixel' members of the XColor array. I wished there
4420 were an easy and portable way to circumvent XGetPixel. */
4421 p = colors;
4422 for (y = 0; y < img->height; ++y)
4423 {
8b7d0a16 4424#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
6045c4fd 4425 XColor *row = p;
4ef0d4d0 4426 for (x = 0; x < img->width; ++x, ++p)
8b7d0a16 4427 p->pixel = GET_PIXEL (ximg, x, y);
4ef0d4d0
KS
4428 if (rgb_p)
4429 x_query_colors (f, row, img->width);
4430
4431#else
4432
4433 for (x = 0; x < img->width; ++x, ++p)
4434 {
4435 /* W32_TODO: palette support needed here? */
4436 p->pixel = GET_PIXEL (ximg, x, y);
4437 if (rgb_p)
4438 {
4ef0d4d0
KS
4439 p->red = RED16_FROM_ULONG (p->pixel);
4440 p->green = GREEN16_FROM_ULONG (p->pixel);
4441 p->blue = BLUE16_FROM_ULONG (p->pixel);
4ef0d4d0
KS
4442 }
4443 }
4444#endif /* HAVE_X_WINDOWS */
4445 }
4446
4447 Destroy_Image (ximg, prev);
4448
4449 return colors;
4450}
4451
4452#ifdef HAVE_NTGUI
4453
4454/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4455 created with CreateDIBSection, with the pointer to the bit values
4456 stored in ximg->data. */
4457
3046a84b 4458static void
7c3320d8 4459XPutPixel (XImagePtr ximg, int x, int y, COLORREF color)
4ef0d4d0
KS
4460{
4461 int width = ximg->info.bmiHeader.biWidth;
4ef0d4d0
KS
4462 unsigned char * pixel;
4463
4464 /* True color images. */
4465 if (ximg->info.bmiHeader.biBitCount == 24)
4466 {
4467 int rowbytes = width * 3;
4468 /* Ensure scanlines are aligned on 4 byte boundaries. */
4469 if (rowbytes % 4)
4470 rowbytes += 4 - (rowbytes % 4);
4471
4472 pixel = ximg->data + y * rowbytes + x * 3;
4473 /* Windows bitmaps are in BGR order. */
4474 *pixel = GetBValue (color);
4475 *(pixel + 1) = GetGValue (color);
4476 *(pixel + 2) = GetRValue (color);
4477 }
4478 /* Monochrome images. */
4479 else if (ximg->info.bmiHeader.biBitCount == 1)
4480 {
4481 int rowbytes = width / 8;
4482 /* Ensure scanlines are aligned on 4 byte boundaries. */
4483 if (rowbytes % 4)
4484 rowbytes += 4 - (rowbytes % 4);
4485 pixel = ximg->data + y * rowbytes + x / 8;
4486 /* Filter out palette info. */
4487 if (color & 0x00ffffff)
4488 *pixel = *pixel | (1 << x % 8);
4489 else
4490 *pixel = *pixel & ~(1 << x % 8);
4491 }
4492 else
4493 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4494}
4495
4496#endif /* HAVE_NTGUI */
4497
4498/* Create IMG->pixmap from an array COLORS of XColor structures, whose
4499 RGB members are set. F is the frame on which this all happens.
4500 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4501
4502static void
d3da34e0 4503x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4ef0d4d0
KS
4504{
4505 int x, y;
edfda783 4506 XImagePtr oimg = NULL;
9d7112ed 4507 Pixmap pixmap;
4ef0d4d0
KS
4508 XColor *p;
4509
4510 init_color_table ();
4511
4512 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4513 &oimg, &pixmap);
4514 p = colors;
4515 for (y = 0; y < img->height; ++y)
4516 for (x = 0; x < img->width; ++x, ++p)
4517 {
4518 unsigned long pixel;
4519 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4520 XPutPixel (oimg, x, y, pixel);
4521 }
4522
4523 xfree (colors);
4524 x_clear_image_1 (f, img, 1, 0, 1);
4525
4526 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4527 x_destroy_x_image (oimg);
4528 img->pixmap = pixmap;
4529#ifdef COLOR_TABLE_SUPPORT
4530 img->colors = colors_in_color_table (&img->ncolors);
4531 free_color_table ();
4532#endif /* COLOR_TABLE_SUPPORT */
4533}
4534
4535
4536/* On frame F, perform edge-detection on image IMG.
4537
4538 MATRIX is a nine-element array specifying the transformation
4539 matrix. See emboss_matrix for an example.
4540
4541 COLOR_ADJUST is a color adjustment added to each pixel of the
4542 outgoing image. */
4543
4544static void
d3da34e0 4545x_detect_edges (struct frame *f, struct image *img, int *matrix, int color_adjust)
4ef0d4d0
KS
4546{
4547 XColor *colors = x_to_xcolors (f, img, 1);
4548 XColor *new, *p;
4549 int x, y, i, sum;
4550
4551 for (i = sum = 0; i < 9; ++i)
1ea40aa2 4552 sum += eabs (matrix[i]);
4ef0d4d0
KS
4553
4554#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4555
ddff3151
PE
4556 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *new / img->width < img->height)
4557 memory_full (SIZE_MAX);
23f86fce 4558 new = xmalloc (sizeof *new * img->width * img->height);
4ef0d4d0
KS
4559
4560 for (y = 0; y < img->height; ++y)
4561 {
4562 p = COLOR (new, 0, y);
4563 p->red = p->green = p->blue = 0xffff/2;
4564 p = COLOR (new, img->width - 1, y);
4565 p->red = p->green = p->blue = 0xffff/2;
4566 }
4567
4568 for (x = 1; x < img->width - 1; ++x)
4569 {
4570 p = COLOR (new, x, 0);
4571 p->red = p->green = p->blue = 0xffff/2;
4572 p = COLOR (new, x, img->height - 1);
4573 p->red = p->green = p->blue = 0xffff/2;
4574 }
4575
4576 for (y = 1; y < img->height - 1; ++y)
4577 {
4578 p = COLOR (new, 1, y);
4579
4580 for (x = 1; x < img->width - 1; ++x, ++p)
4581 {
6ae141d6 4582 int r, g, b, yy, xx;
4ef0d4d0
KS
4583
4584 r = g = b = i = 0;
6ae141d6
PE
4585 for (yy = y - 1; yy < y + 2; ++yy)
4586 for (xx = x - 1; xx < x + 2; ++xx, ++i)
4ef0d4d0
KS
4587 if (matrix[i])
4588 {
6ae141d6 4589 XColor *t = COLOR (colors, xx, yy);
4ef0d4d0
KS
4590 r += matrix[i] * t->red;
4591 g += matrix[i] * t->green;
4592 b += matrix[i] * t->blue;
4593 }
4594
4595 r = (r / sum + color_adjust) & 0xffff;
4596 g = (g / sum + color_adjust) & 0xffff;
4597 b = (b / sum + color_adjust) & 0xffff;
4598 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4599 }
4600 }
4601
4602 xfree (colors);
4603 x_from_xcolors (f, img, new);
4604
4605#undef COLOR
4606}
4607
4608
4609/* Perform the pre-defined `emboss' edge-detection on image IMG
4610 on frame F. */
4611
4612static void
d3da34e0 4613x_emboss (struct frame *f, struct image *img)
4ef0d4d0
KS
4614{
4615 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4616}
4617
4618
4619/* Transform image IMG which is used on frame F with a Laplace
4620 edge-detection algorithm. The result is an image that can be used
4621 to draw disabled buttons, for example. */
4622
4623static void
d3da34e0 4624x_laplace (struct frame *f, struct image *img)
4ef0d4d0
KS
4625{
4626 x_detect_edges (f, img, laplace_matrix, 45000);
4627}
4628
4629
4630/* Perform edge-detection on image IMG on frame F, with specified
4631 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4632
4633 MATRIX must be either
4634
4635 - a list of at least 9 numbers in row-major form
4636 - a vector of at least 9 numbers
4637
4638 COLOR_ADJUST nil means use a default; otherwise it must be a
4639 number. */
4640
4641static void
d3da34e0
JB
4642x_edge_detection (struct frame *f, struct image *img, Lisp_Object matrix,
4643 Lisp_Object color_adjust)
4ef0d4d0
KS
4644{
4645 int i = 0;
4646 int trans[9];
4647
4648 if (CONSP (matrix))
4649 {
4650 for (i = 0;
4651 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
4652 ++i, matrix = XCDR (matrix))
4653 trans[i] = XFLOATINT (XCAR (matrix));
4654 }
4655 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
4656 {
4657 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
4658 trans[i] = XFLOATINT (AREF (matrix, i));
4659 }
4660
4661 if (NILP (color_adjust))
4662 color_adjust = make_number (0xffff / 2);
4663
4664 if (i == 9 && NUMBERP (color_adjust))
77a765fd 4665 x_detect_edges (f, img, trans, XFLOATINT (color_adjust));
4ef0d4d0
KS
4666}
4667
4668
4669/* Transform image IMG on frame F so that it looks disabled. */
4670
4671static void
d3da34e0 4672x_disable_image (struct frame *f, struct image *img)
4ef0d4d0
KS
4673{
4674 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4675#ifdef HAVE_NTGUI
4676 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
4677#else
4678 int n_planes = dpyinfo->n_planes;
4679#endif /* HAVE_NTGUI */
4680
4681 if (n_planes >= 2)
4682 {
4683 /* Color (or grayscale). Convert to gray, and equalize. Just
4684 drawing such images with a stipple can look very odd, so
4685 we're using this method instead. */
4686 XColor *colors = x_to_xcolors (f, img, 1);
4687 XColor *p, *end;
4688 const int h = 15000;
4689 const int l = 30000;
4690
4691 for (p = colors, end = colors + img->width * img->height;
4692 p < end;
4693 ++p)
4694 {
4695 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
4696 int i2 = (0xffff - h - l) * i / 0xffff + l;
4697 p->red = p->green = p->blue = i2;
4698 }
4699
4700 x_from_xcolors (f, img, colors);
4701 }
4702
4703 /* Draw a cross over the disabled image, if we must or if we
4704 should. */
4705 if (n_planes < 2 || cross_disabled_images)
4706 {
4707#ifndef HAVE_NTGUI
5afa3a81 4708#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
edfda783 4709
4ef0d4d0 4710#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4ef0d4d0 4711
6045c4fd
PE
4712 Display *dpy = FRAME_X_DISPLAY (f);
4713 GC gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4ef0d4d0
KS
4714 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4715 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4716 img->width - 1, img->height - 1);
4717 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
4718 img->width - 1, 0);
4719 XFreeGC (dpy, gc);
4720
4721 if (img->mask)
4722 {
ae8279db 4723 gc = XCreateGC (dpy, img->mask, 0, NULL);
4ef0d4d0
KS
4724 XSetForeground (dpy, gc, MaskForeground (f));
4725 XDrawLine (dpy, img->mask, gc, 0, 0,
4726 img->width - 1, img->height - 1);
4727 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
4728 img->width - 1, 0);
4729 XFreeGC (dpy, gc);
4730 }
edfda783 4731#endif /* !HAVE_NS */
4ef0d4d0
KS
4732#else
4733 HDC hdc, bmpdc;
4734 HGDIOBJ prev;
4735
4736 hdc = get_frame_dc (f);
4737 bmpdc = CreateCompatibleDC (hdc);
4738 release_frame_dc (f, hdc);
4739
4740 prev = SelectObject (bmpdc, img->pixmap);
4741
4742 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
4743 MoveToEx (bmpdc, 0, 0, NULL);
4744 LineTo (bmpdc, img->width - 1, img->height - 1);
4745 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4746 LineTo (bmpdc, img->width - 1, 0);
4747
4748 if (img->mask)
4749 {
4750 SelectObject (bmpdc, img->mask);
4751 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
4752 MoveToEx (bmpdc, 0, 0, NULL);
4753 LineTo (bmpdc, img->width - 1, img->height - 1);
4754 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4755 LineTo (bmpdc, img->width - 1, 0);
4756 }
4757 SelectObject (bmpdc, prev);
4758 DeleteDC (bmpdc);
4759#endif /* HAVE_NTGUI */
4760 }
4761}
4762
4763
4764/* Build a mask for image IMG which is used on frame F. FILE is the
4765 name of an image file, for error messages. HOW determines how to
4766 determine the background color of IMG. If it is a list '(R G B)',
4767 with R, G, and B being integers >= 0, take that as the color of the
4768 background. Otherwise, determine the background color of IMG
578098f3 4769 heuristically. */
4ef0d4d0 4770
578098f3 4771static void
d3da34e0 4772x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4ef0d4d0
KS
4773{
4774 XImagePtr_or_DC ximg;
4775#ifndef HAVE_NTGUI
4776 XImagePtr mask_img;
4777#else
4778 HDC frame_dc;
4779 HGDIOBJ prev;
4780 char *mask_img;
4781 int row_width;
4782#endif /* HAVE_NTGUI */
578098f3
PE
4783 int x, y;
4784 bool rc, use_img_background;
4ef0d4d0
KS
4785 unsigned long bg = 0;
4786
4787 if (img->mask)
4788 {
4789 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4790 img->mask = NO_PIXMAP;
4791 img->background_transparent_valid = 0;
4792 }
4793
4794#ifndef HAVE_NTGUI
edfda783 4795#ifndef HAVE_NS
4ef0d4d0
KS
4796 /* Create an image and pixmap serving as mask. */
4797 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
4798 &mask_img, &img->mask);
4799 if (!rc)
578098f3 4800 return;
edfda783 4801#endif /* !HAVE_NS */
4ef0d4d0
KS
4802
4803 /* Get the X image of IMG->pixmap. */
4804 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4805 img->width, img->height,
4806 ~0, ZPixmap);
4807#else
4808 /* Create the bit array serving as mask. */
4809 row_width = (img->width + 7) / 8;
23f86fce 4810 mask_img = xzalloc (row_width * img->height);
4ef0d4d0
KS
4811
4812 /* Create a memory device context for IMG->pixmap. */
4813 frame_dc = get_frame_dc (f);
4814 ximg = CreateCompatibleDC (frame_dc);
4815 release_frame_dc (f, frame_dc);
4816 prev = SelectObject (ximg, img->pixmap);
4817#endif /* HAVE_NTGUI */
4818
4819 /* Determine the background color of ximg. If HOW is `(R G B)'
4820 take that as color. Otherwise, use the image's background color. */
4821 use_img_background = 1;
4822
4823 if (CONSP (how))
4824 {
4825 int rgb[3], i;
4826
4827 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
4828 {
4829 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
4830 how = XCDR (how);
4831 }
4832
4833 if (i == 3 && NILP (how))
4834 {
4835 char color_name[30];
4836 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
4837 bg = (
4838#ifdef HAVE_NTGUI
4839 0x00ffffff & /* Filter out palette info. */
4840#endif /* HAVE_NTGUI */
4841 x_alloc_image_color (f, img, build_string (color_name), 0));
4842 use_img_background = 0;
4843 }
4844 }
4845
4846 if (use_img_background)
6ac3c7bb 4847 bg = four_corners_best (ximg, img->corners, img->width, img->height);
4ef0d4d0
KS
4848
4849 /* Set all bits in mask_img to 1 whose color in ximg is different
4850 from the background color bg. */
4851#ifndef HAVE_NTGUI
4852 for (y = 0; y < img->height; ++y)
4853 for (x = 0; x < img->width; ++x)
edfda783 4854#ifndef HAVE_NS
4ef0d4d0 4855 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
9ecf6403 4856 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
edfda783
AR
4857#else
4858 if (XGetPixel (ximg, x, y) == bg)
ed3751c8 4859 ns_set_alpha (ximg, x, y, 0);
edfda783
AR
4860#endif /* HAVE_NS */
4861#ifndef HAVE_NS
4ef0d4d0
KS
4862 /* Fill in the background_transparent field while we have the mask handy. */
4863 image_background_transparent (img, f, mask_img);
4864
4865 /* Put mask_img into img->mask. */
4866 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
4867 x_destroy_x_image (mask_img);
edfda783 4868#endif /* !HAVE_NS */
4ef0d4d0
KS
4869#else
4870 for (y = 0; y < img->height; ++y)
4871 for (x = 0; x < img->width; ++x)
4872 {
4873 COLORREF p = GetPixel (ximg, x, y);
4874 if (p != bg)
4875 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
4876 }
4877
4878 /* Create the mask image. */
4879 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
4880 mask_img);
4881 /* Fill in the background_transparent field while we have the mask handy. */
4882 SelectObject (ximg, img->mask);
4883 image_background_transparent (img, f, ximg);
4884
4885 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4886 xfree (mask_img);
4887#endif /* HAVE_NTGUI */
4888
4889 Destroy_Image (ximg, prev);
4ef0d4d0
KS
4890}
4891
4892\f
4893/***********************************************************************
4894 PBM (mono, gray, color)
4895 ***********************************************************************/
4896
578098f3
PE
4897static bool pbm_image_p (Lisp_Object object);
4898static bool pbm_load (struct frame *f, struct image *img);
4ef0d4d0
KS
4899
4900/* The symbol `pbm' identifying images of this type. */
4901
955cbe7b 4902static Lisp_Object Qpbm;
4ef0d4d0
KS
4903
4904/* Indices of image specification fields in gs_format, below. */
4905
4906enum pbm_keyword_index
4907{
4908 PBM_TYPE,
4909 PBM_FILE,
4910 PBM_DATA,
4911 PBM_ASCENT,
4912 PBM_MARGIN,
4913 PBM_RELIEF,
4914 PBM_ALGORITHM,
4915 PBM_HEURISTIC_MASK,
4916 PBM_MASK,
4917 PBM_FOREGROUND,
4918 PBM_BACKGROUND,
4919 PBM_LAST
4920};
4921
4922/* Vector of image_keyword structures describing the format
4923 of valid user-defined image specifications. */
4924
91433552 4925static const struct image_keyword pbm_format[PBM_LAST] =
4ef0d4d0
KS
4926{
4927 {":type", IMAGE_SYMBOL_VALUE, 1},
4928 {":file", IMAGE_STRING_VALUE, 0},
4929 {":data", IMAGE_STRING_VALUE, 0},
4930 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 4931 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
4932 {":relief", IMAGE_INTEGER_VALUE, 0},
4933 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4934 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4935 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4936 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
4937 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
4938};
4939
4940/* Structure describing the image type `pbm'. */
4941
4942static struct image_type pbm_type =
4943{
4944 &Qpbm,
4945 pbm_image_p,
4946 pbm_load,
4947 x_clear_image,
bb4d86b4 4948 NULL,
4ef0d4d0
KS
4949 NULL
4950};
4951
4952
578098f3 4953/* Return true if OBJECT is a valid PBM image specification. */
4ef0d4d0 4954
578098f3 4955static bool
d3da34e0 4956pbm_image_p (Lisp_Object object)
4ef0d4d0
KS
4957{
4958 struct image_keyword fmt[PBM_LAST];
4959
72af86bd 4960 memcpy (fmt, pbm_format, sizeof fmt);
4ef0d4d0
KS
4961
4962 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
4963 return 0;
4964
4965 /* Must specify either :data or :file. */
4966 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
4967}
4968
4969
4970/* Scan a decimal number from *S and return it. Advance *S while
4971 reading the number. END is the end of the string. Value is -1 at
4972 end of input. */
4973
4974static int
d3da34e0 4975pbm_scan_number (unsigned char **s, unsigned char *end)
4ef0d4d0
KS
4976{
4977 int c = 0, val = -1;
4978
4979 while (*s < end)
4980 {
4981 /* Skip white-space. */
620f13b0 4982 while (*s < end && (c = *(*s)++, c_isspace (c)))
4ef0d4d0
KS
4983 ;
4984
4985 if (c == '#')
4986 {
4987 /* Skip comment to end of line. */
4988 while (*s < end && (c = *(*s)++, c != '\n'))
4989 ;
4990 }
620f13b0 4991 else if (c_isdigit (c))
4ef0d4d0
KS
4992 {
4993 /* Read decimal number. */
4994 val = c - '0';
620f13b0 4995 while (*s < end && (c = *(*s)++, c_isdigit (c)))
4ef0d4d0
KS
4996 val = 10 * val + c - '0';
4997 break;
4998 }
4999 else
5000 break;
5001 }
5002
5003 return val;
5004}
5005
5006
5007#ifdef HAVE_NTGUI
5008#if 0 /* Unused. ++kfs */
5009
5010/* Read FILE into memory. Value is a pointer to a buffer allocated
5011 with xmalloc holding FILE's contents. Value is null if an error
5012 occurred. *SIZE is set to the size of the file. */
5013
5014static char *
1dae0f0a 5015pbm_read_file (Lisp_Object file, int *size)
4ef0d4d0
KS
5016{
5017 FILE *fp = NULL;
5018 char *buf = NULL;
5019 struct stat st;
5020
5021 if (stat (SDATA (file), &st) == 0
5022 && (fp = fopen (SDATA (file), "rb")) != NULL
dd52fcea 5023 && 0 <= st.st_size && st.st_size <= min (PTRDIFF_MAX, SIZE_MAX)
23f86fce 5024 && (buf = xmalloc (st.st_size),
4ef0d4d0
KS
5025 fread (buf, 1, st.st_size, fp) == st.st_size))
5026 {
5027 *size = st.st_size;
5028 fclose (fp);
5029 }
5030 else
5031 {
5032 if (fp)
5033 fclose (fp);
5034 if (buf)
5035 {
5036 xfree (buf);
5037 buf = NULL;
5038 }
5039 }
5040
5041 return buf;
5042}
5043#endif
5044#endif /* HAVE_NTGUI */
5045
5046/* Load PBM image IMG for use on frame F. */
5047
578098f3 5048static bool
d3da34e0 5049pbm_load (struct frame *f, struct image *img)
4ef0d4d0 5050{
578098f3
PE
5051 bool raw_p;
5052 int x, y;
4ef0d4d0
KS
5053 int width, height, max_color_idx = 0;
5054 XImagePtr ximg;
5055 Lisp_Object file, specified_file;
5056 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
4ef0d4d0
KS
5057 unsigned char *contents = NULL;
5058 unsigned char *end, *p;
dd52fcea 5059 ptrdiff_t size;
4ef0d4d0
KS
5060
5061 specified_file = image_spec_value (img->spec, QCfile, NULL);
4ef0d4d0
KS
5062
5063 if (STRINGP (specified_file))
5064 {
5065 file = x_find_image_file (specified_file);
5066 if (!STRINGP (file))
5067 {
5068 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
5069 return 0;
5070 }
5071
42a5b22f 5072 contents = slurp_file (SSDATA (file), &size);
4ef0d4d0
KS
5073 if (contents == NULL)
5074 {
5075 image_error ("Error reading `%s'", file, Qnil);
4ef0d4d0
KS
5076 return 0;
5077 }
5078
5079 p = contents;
5080 end = contents + size;
5081 }
5082 else
5083 {
5084 Lisp_Object data;
5085 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
5086 if (!STRINGP (data))
5087 {
5088 image_error ("Invalid image data `%s'", data, Qnil);
5089 return 0;
5090 }
4ef0d4d0
KS
5091 p = SDATA (data);
5092 end = p + SBYTES (data);
5093 }
5094
5095 /* Check magic number. */
5096 if (end - p < 2 || *p++ != 'P')
5097 {
5098 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5099 error:
5100 xfree (contents);
4ef0d4d0
KS
5101 return 0;
5102 }
5103
5104 switch (*p++)
5105 {
5106 case '1':
5107 raw_p = 0, type = PBM_MONO;
5108 break;
5109
5110 case '2':
5111 raw_p = 0, type = PBM_GRAY;
5112 break;
5113
5114 case '3':
5115 raw_p = 0, type = PBM_COLOR;
5116 break;
5117
5118 case '4':
5119 raw_p = 1, type = PBM_MONO;
5120 break;
5121
5122 case '5':
5123 raw_p = 1, type = PBM_GRAY;
5124 break;
5125
5126 case '6':
5127 raw_p = 1, type = PBM_COLOR;
5128 break;
5129
5130 default:
5131 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5132 goto error;
5133 }
5134
5135 /* Read width, height, maximum color-component. Characters
5136 starting with `#' up to the end of a line are ignored. */
5137 width = pbm_scan_number (&p, end);
5138 height = pbm_scan_number (&p, end);
5139
5140 if (type != PBM_MONO)
5141 {
5142 max_color_idx = pbm_scan_number (&p, end);
b9c89e11
JR
5143 if (max_color_idx > 65535 || max_color_idx < 0)
5144 {
5145 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
5146 goto error;
5147 }
4ef0d4d0
KS
5148 }
5149
b9c89e11
JR
5150 if (!check_image_size (f, width, height))
5151 {
10ea2b82 5152 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
b9c89e11
JR
5153 goto error;
5154 }
4ef0d4d0
KS
5155
5156 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5157 &ximg, &img->pixmap))
5158 goto error;
5159
5160 /* Initialize the color hash table. */
5161 init_color_table ();
5162
5163 if (type == PBM_MONO)
5164 {
5165 int c = 0, g;
5166 struct image_keyword fmt[PBM_LAST];
5167 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5168 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5169
5170 /* Parse the image specification. */
72af86bd 5171 memcpy (fmt, pbm_format, sizeof fmt);
4ef0d4d0
KS
5172 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5173
5174 /* Get foreground and background colors, maybe allocate colors. */
5175 if (fmt[PBM_FOREGROUND].count
5176 && STRINGP (fmt[PBM_FOREGROUND].value))
5177 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5178 if (fmt[PBM_BACKGROUND].count
5179 && STRINGP (fmt[PBM_BACKGROUND].value))
5180 {
5181 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5182 img->background = bg;
5183 img->background_valid = 1;
5184 }
5185
5186 for (y = 0; y < height; ++y)
5187 for (x = 0; x < width; ++x)
5188 {
5189 if (raw_p)
5190 {
5191 if ((x & 7) == 0)
c295e710
CY
5192 {
5193 if (p >= end)
5194 {
5195 x_destroy_x_image (ximg);
5196 x_clear_image (f, img);
5197 image_error ("Invalid image size in image `%s'",
5198 img->spec, Qnil);
5199 goto error;
5200 }
5201 c = *p++;
5202 }
4ef0d4d0
KS
5203 g = c & 0x80;
5204 c <<= 1;
5205 }
5206 else
5207 g = pbm_scan_number (&p, end);
5208
5209 XPutPixel (ximg, x, y, g ? fg : bg);
5210 }
5211 }
5212 else
5213 {
b9c89e11
JR
5214 int expected_size = height * width;
5215 if (max_color_idx > 255)
5216 expected_size *= 2;
5217 if (type == PBM_COLOR)
5218 expected_size *= 3;
5219
5220 if (raw_p && p + expected_size > end)
39e653ea
CY
5221 {
5222 x_destroy_x_image (ximg);
fb0b0862 5223 x_clear_image (f, img);
39e653ea
CY
5224 image_error ("Invalid image size in image `%s'",
5225 img->spec, Qnil);
5226 goto error;
5227 }
5228
4ef0d4d0
KS
5229 for (y = 0; y < height; ++y)
5230 for (x = 0; x < width; ++x)
5231 {
5232 int r, g, b;
5233
b9c89e11
JR
5234 if (type == PBM_GRAY && raw_p)
5235 {
5236 r = g = b = *p++;
5237 if (max_color_idx > 255)
5238 r = g = b = r * 256 + *p++;
5239 }
5240 else if (type == PBM_GRAY)
5241 r = g = b = pbm_scan_number (&p, end);
4ef0d4d0
KS
5242 else if (raw_p)
5243 {
5244 r = *p++;
b9c89e11
JR
5245 if (max_color_idx > 255)
5246 r = r * 256 + *p++;
4ef0d4d0 5247 g = *p++;
b9c89e11
JR
5248 if (max_color_idx > 255)
5249 g = g * 256 + *p++;
4ef0d4d0 5250 b = *p++;
b9c89e11
JR
5251 if (max_color_idx > 255)
5252 b = b * 256 + *p++;
4ef0d4d0
KS
5253 }
5254 else
5255 {
5256 r = pbm_scan_number (&p, end);
5257 g = pbm_scan_number (&p, end);
5258 b = pbm_scan_number (&p, end);
5259 }
5260
5261 if (r < 0 || g < 0 || b < 0)
5262 {
5263 x_destroy_x_image (ximg);
5264 image_error ("Invalid pixel value in image `%s'",
5265 img->spec, Qnil);
5266 goto error;
5267 }
5268
5269 /* RGB values are now in the range 0..max_color_idx.
5270 Scale this to the range 0..0xffff supported by X. */
5271 r = (double) r * 65535 / max_color_idx;
5272 g = (double) g * 65535 / max_color_idx;
5273 b = (double) b * 65535 / max_color_idx;
5274 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5275 }
5276 }
5277
5278#ifdef COLOR_TABLE_SUPPORT
5279 /* Store in IMG->colors the colors allocated for the image, and
5280 free the color table. */
5281 img->colors = colors_in_color_table (&img->ncolors);
5282 free_color_table ();
5283#endif /* COLOR_TABLE_SUPPORT */
5284
5285 img->width = width;
5286 img->height = height;
5287
5288 /* Maybe fill in the background field while we have ximg handy. */
5289
5290 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
5291 /* Casting avoids a GCC warning. */
5292 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
5293
5294 /* Put the image into a pixmap. */
5295 x_put_x_image (f, ximg, img->pixmap, width, height);
5296 x_destroy_x_image (ximg);
5297
5298 /* X and W32 versions did it here, MAC version above. ++kfs
1f026899 5299 img->width = width;
4ef0d4d0
KS
5300 img->height = height; */
5301
4ef0d4d0
KS
5302 xfree (contents);
5303 return 1;
5304}
5305
5306\f
5307/***********************************************************************
5308 PNG
5309 ***********************************************************************/
5310
9e2a2647 5311#if defined (HAVE_PNG) || defined (HAVE_NS)
4ef0d4d0
KS
5312
5313/* Function prototypes. */
5314
578098f3
PE
5315static bool png_image_p (Lisp_Object object);
5316static bool png_load (struct frame *f, struct image *img);
4ef0d4d0
KS
5317
5318/* The symbol `png' identifying images of this type. */
5319
955cbe7b 5320static Lisp_Object Qpng;
4ef0d4d0
KS
5321
5322/* Indices of image specification fields in png_format, below. */
5323
5324enum png_keyword_index
5325{
5326 PNG_TYPE,
5327 PNG_DATA,
5328 PNG_FILE,
5329 PNG_ASCENT,
5330 PNG_MARGIN,
5331 PNG_RELIEF,
5332 PNG_ALGORITHM,
5333 PNG_HEURISTIC_MASK,
5334 PNG_MASK,
5335 PNG_BACKGROUND,
5336 PNG_LAST
5337};
5338
5339/* Vector of image_keyword structures describing the format
5340 of valid user-defined image specifications. */
5341
91433552 5342static const struct image_keyword png_format[PNG_LAST] =
4ef0d4d0
KS
5343{
5344 {":type", IMAGE_SYMBOL_VALUE, 1},
5345 {":data", IMAGE_STRING_VALUE, 0},
5346 {":file", IMAGE_STRING_VALUE, 0},
5347 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 5348 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
5349 {":relief", IMAGE_INTEGER_VALUE, 0},
5350 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5351 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5352 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5353 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5354};
5355
a9e7a9d5 5356#if defined HAVE_NTGUI && defined WINDOWSNT
578098f3 5357static bool init_png_functions (void);
bb4d86b4
CY
5358#else
5359#define init_png_functions NULL
5360#endif
5361
4ef0d4d0
KS
5362/* Structure describing the image type `png'. */
5363
5364static struct image_type png_type =
5365{
5366 &Qpng,
5367 png_image_p,
5368 png_load,
5369 x_clear_image,
bb4d86b4 5370 init_png_functions,
4ef0d4d0
KS
5371 NULL
5372};
5373
578098f3 5374/* Return true if OBJECT is a valid PNG image specification. */
4ef0d4d0 5375
578098f3 5376static bool
d3da34e0 5377png_image_p (Lisp_Object object)
4ef0d4d0
KS
5378{
5379 struct image_keyword fmt[PNG_LAST];
72af86bd 5380 memcpy (fmt, png_format, sizeof fmt);
4ef0d4d0
KS
5381
5382 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5383 return 0;
5384
5385 /* Must specify either the :data or :file keyword. */
5386 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5387}
5388
9e2a2647 5389#endif /* HAVE_PNG || HAVE_NS */
4ef0d4d0
KS
5390
5391
5392#ifdef HAVE_PNG
5393
0fda9b75 5394#ifdef WINDOWSNT
4ef0d4d0
KS
5395/* PNG library details. */
5396
14beddf4
CY
5397DEF_IMGLIB_FN (png_voidp, png_get_io_ptr, (png_structp));
5398DEF_IMGLIB_FN (int, png_sig_cmp, (png_bytep, png_size_t, png_size_t));
5399DEF_IMGLIB_FN (png_structp, png_create_read_struct, (png_const_charp, png_voidp,
5400 png_error_ptr, png_error_ptr));
5401DEF_IMGLIB_FN (png_infop, png_create_info_struct, (png_structp));
5402DEF_IMGLIB_FN (void, png_destroy_read_struct, (png_structpp, png_infopp, png_infopp));
5403DEF_IMGLIB_FN (void, png_set_read_fn, (png_structp, png_voidp, png_rw_ptr));
5404DEF_IMGLIB_FN (void, png_set_sig_bytes, (png_structp, int));
5405DEF_IMGLIB_FN (void, png_read_info, (png_structp, png_infop));
5406DEF_IMGLIB_FN (png_uint_32, png_get_IHDR, (png_structp, png_infop,
850690cc
JB
5407 png_uint_32 *, png_uint_32 *,
5408 int *, int *, int *, int *, int *));
14beddf4
CY
5409DEF_IMGLIB_FN (png_uint_32, png_get_valid, (png_structp, png_infop, png_uint_32));
5410DEF_IMGLIB_FN (void, png_set_strip_16, (png_structp));
5411DEF_IMGLIB_FN (void, png_set_expand, (png_structp));
5412DEF_IMGLIB_FN (void, png_set_gray_to_rgb, (png_structp));
5413DEF_IMGLIB_FN (void, png_set_background, (png_structp, png_color_16p,
850690cc 5414 int, int, double));
14beddf4
CY
5415DEF_IMGLIB_FN (png_uint_32, png_get_bKGD, (png_structp, png_infop, png_color_16p *));
5416DEF_IMGLIB_FN (void, png_read_update_info, (png_structp, png_infop));
5417DEF_IMGLIB_FN (png_byte, png_get_channels, (png_structp, png_infop));
5418DEF_IMGLIB_FN (png_size_t, png_get_rowbytes, (png_structp, png_infop));
5419DEF_IMGLIB_FN (void, png_read_image, (png_structp, png_bytepp));
5420DEF_IMGLIB_FN (void, png_read_end, (png_structp, png_infop));
5421DEF_IMGLIB_FN (void, png_error, (png_structp, png_const_charp));
4ef0d4d0 5422
7f9c5df9 5423#if (PNG_LIBPNG_VER >= 10500)
14beddf4
CY
5424DEF_IMGLIB_FN (void, png_longjmp, (png_structp, int));
5425DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn, (png_structp, png_longjmp_ptr, size_t));
7f9c5df9 5426#endif /* libpng version >= 1.5 */
4ef0d4d0 5427
578098f3 5428static bool
d07ff9db 5429init_png_functions (void)
4ef0d4d0
KS
5430{
5431 HMODULE library;
5432
d07ff9db 5433 if (!(library = w32_delayed_load (Qpng)))
4ef0d4d0
KS
5434 return 0;
5435
5436 LOAD_IMGLIB_FN (library, png_get_io_ptr);
285d07e2 5437 LOAD_IMGLIB_FN (library, png_sig_cmp);
4ef0d4d0
KS
5438 LOAD_IMGLIB_FN (library, png_create_read_struct);
5439 LOAD_IMGLIB_FN (library, png_create_info_struct);
5440 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5441 LOAD_IMGLIB_FN (library, png_set_read_fn);
4ef0d4d0
KS
5442 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5443 LOAD_IMGLIB_FN (library, png_read_info);
5444 LOAD_IMGLIB_FN (library, png_get_IHDR);
5445 LOAD_IMGLIB_FN (library, png_get_valid);
5446 LOAD_IMGLIB_FN (library, png_set_strip_16);
5447 LOAD_IMGLIB_FN (library, png_set_expand);
5448 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5449 LOAD_IMGLIB_FN (library, png_set_background);
5450 LOAD_IMGLIB_FN (library, png_get_bKGD);
5451 LOAD_IMGLIB_FN (library, png_read_update_info);
5452 LOAD_IMGLIB_FN (library, png_get_channels);
5453 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5454 LOAD_IMGLIB_FN (library, png_read_image);
5455 LOAD_IMGLIB_FN (library, png_read_end);
5456 LOAD_IMGLIB_FN (library, png_error);
7f9c5df9
CY
5457
5458#if (PNG_LIBPNG_VER >= 10500)
5459 LOAD_IMGLIB_FN (library, png_longjmp);
5460 LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
5461#endif /* libpng version >= 1.5 */
5462
4ef0d4d0
KS
5463 return 1;
5464}
5465#else
5466
5467#define fn_png_get_io_ptr png_get_io_ptr
285d07e2 5468#define fn_png_sig_cmp png_sig_cmp
4ef0d4d0
KS
5469#define fn_png_create_read_struct png_create_read_struct
5470#define fn_png_create_info_struct png_create_info_struct
5471#define fn_png_destroy_read_struct png_destroy_read_struct
5472#define fn_png_set_read_fn png_set_read_fn
4ef0d4d0
KS
5473#define fn_png_set_sig_bytes png_set_sig_bytes
5474#define fn_png_read_info png_read_info
5475#define fn_png_get_IHDR png_get_IHDR
5476#define fn_png_get_valid png_get_valid
5477#define fn_png_set_strip_16 png_set_strip_16
5478#define fn_png_set_expand png_set_expand
5479#define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5480#define fn_png_set_background png_set_background
5481#define fn_png_get_bKGD png_get_bKGD
5482#define fn_png_read_update_info png_read_update_info
5483#define fn_png_get_channels png_get_channels
5484#define fn_png_get_rowbytes png_get_rowbytes
5485#define fn_png_read_image png_read_image
5486#define fn_png_read_end png_read_end
5487#define fn_png_error png_error
5488
7f9c5df9
CY
5489#if (PNG_LIBPNG_VER >= 10500)
5490#define fn_png_longjmp png_longjmp
5491#define fn_png_set_longjmp_fn png_set_longjmp_fn
5492#endif /* libpng version >= 1.5 */
5493
0fda9b75 5494#endif /* WINDOWSNT */
4ef0d4d0 5495
0328b6de
PE
5496/* Possibly inefficient/inexact substitutes for _setjmp and _longjmp.
5497 Do not use sys_setjmp, as PNG supports only jmp_buf. The _longjmp
7105c8cb
EZ
5498 substitute may munge the signal mask, but that should be OK here.
5499 MinGW (MS-Windows) uses _setjmp and defines setjmp to _setjmp in
5500 the system header setjmp.h; don't mess up that. */
0328b6de 5501#ifndef HAVE__SETJMP
39a57ad0 5502# define _setjmp(j) setjmp (j)
0328b6de
PE
5503# define _longjmp longjmp
5504#endif
7f9c5df9
CY
5505
5506#if (PNG_LIBPNG_VER < 10500)
af26b72c 5507#define PNG_LONGJMP(ptr) (_longjmp ((ptr)->jmpbuf, 1))
7f9c5df9
CY
5508#define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
5509#else
df61c790 5510/* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */
c2e79cb4 5511#define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
7f9c5df9 5512#define PNG_JMPBUF(ptr) \
af26b72c 5513 (*fn_png_set_longjmp_fn ((ptr), _longjmp, sizeof (jmp_buf)))
7f9c5df9
CY
5514#endif
5515
4ef0d4d0
KS
5516/* Error and warning handlers installed when the PNG library
5517 is initialized. */
5518
845ca893 5519static _Noreturn void
d3da34e0 5520my_png_error (png_struct *png_ptr, const char *msg)
4ef0d4d0 5521{
a54e2c05 5522 eassert (png_ptr != NULL);
5be1c984
EZ
5523 /* Avoid compiler warning about deprecated direct access to
5524 png_ptr's fields in libpng versions 1.4.x. */
4ef0d4d0 5525 image_error ("PNG error: %s", build_string (msg), Qnil);
7f9c5df9 5526 PNG_LONGJMP (png_ptr);
4ef0d4d0
KS
5527}
5528
5529
5530static void
d3da34e0 5531my_png_warning (png_struct *png_ptr, const char *msg)
4ef0d4d0 5532{
a54e2c05 5533 eassert (png_ptr != NULL);
4ef0d4d0
KS
5534 image_error ("PNG warning: %s", build_string (msg), Qnil);
5535}
5536
5537/* Memory source for PNG decoding. */
5538
5539struct png_memory_storage
5540{
5541 unsigned char *bytes; /* The data */
3f791afe
PE
5542 ptrdiff_t len; /* How big is it? */
5543 ptrdiff_t index; /* Where are we? */
4ef0d4d0
KS
5544};
5545
5546
5547/* Function set as reader function when reading PNG image from memory.
5548 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5549 bytes from the input to DATA. */
5550
5551static void
d3da34e0 5552png_read_from_memory (png_structp png_ptr, png_bytep data, png_size_t length)
4ef0d4d0
KS
5553{
5554 struct png_memory_storage *tbr
5555 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5556
5557 if (length > tbr->len - tbr->index)
5558 fn_png_error (png_ptr, "Read error");
5559
72af86bd 5560 memcpy (data, tbr->bytes + tbr->index, length);
4ef0d4d0
KS
5561 tbr->index = tbr->index + length;
5562}
5563
b0da69a7 5564
9a22a004
JB
5565/* Function set as reader function when reading PNG image from a file.
5566 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5567 bytes from the input to DATA. */
5568
5569static void
d3da34e0 5570png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
9a22a004
JB
5571{
5572 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
5573
5574 if (fread (data, 1, length, fp) < length)
5575 fn_png_error (png_ptr, "Read error");
5576}
5577
5578
578098f3 5579/* Load PNG image IMG for use on frame F. Value is true if
4ef0d4d0
KS
5580 successful. */
5581
40bce90b
PE
5582struct png_load_context
5583{
0328b6de 5584 /* These are members so that longjmp doesn't munge local variables. */
40bce90b
PE
5585 png_struct *png_ptr;
5586 png_info *info_ptr;
5587 png_info *end_info;
5588 FILE *fp;
5589 png_byte *pixels;
5590 png_byte **rows;
5591};
5592
578098f3 5593static bool
40bce90b 5594png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
4ef0d4d0
KS
5595{
5596 Lisp_Object file, specified_file;
5597 Lisp_Object specified_data;
5adf60bc
PE
5598 int x, y;
5599 ptrdiff_t i;
4ef0d4d0 5600 XImagePtr ximg, mask_img = NULL;
40bce90b 5601 png_struct *png_ptr;
4ef0d4d0 5602 png_info *info_ptr = NULL, *end_info = NULL;
40bce90b 5603 FILE *fp = NULL;
4ef0d4d0 5604 png_byte sig[8];
40bce90b
PE
5605 png_byte *pixels = NULL;
5606 png_byte **rows = NULL;
4ef0d4d0
KS
5607 png_uint_32 width, height;
5608 int bit_depth, color_type, interlace_type;
5609 png_byte channels;
5610 png_uint_32 row_bytes;
578098f3 5611 bool transparent_p;
4ef0d4d0
KS
5612 struct png_memory_storage tbr; /* Data to be read */
5613
5614 /* Find out what file to load. */
5615 specified_file = image_spec_value (img->spec, QCfile, NULL);
5616 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0
KS
5617
5618 if (NILP (specified_data))
5619 {
5620 file = x_find_image_file (specified_file);
5621 if (!STRINGP (file))
5622 {
5623 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
5624 return 0;
5625 }
5626
5627 /* Open the image file. */
42a5b22f 5628 fp = fopen (SSDATA (file), "rb");
4ef0d4d0
KS
5629 if (!fp)
5630 {
5631 image_error ("Cannot open image file `%s'", file, Qnil);
4ef0d4d0
KS
5632 return 0;
5633 }
5634
5635 /* Check PNG signature. */
5636 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
285d07e2 5637 || fn_png_sig_cmp (sig, 0, sizeof sig))
4ef0d4d0
KS
5638 {
5639 image_error ("Not a PNG file: `%s'", file, Qnil);
4ef0d4d0
KS
5640 fclose (fp);
5641 return 0;
5642 }
5643 }
5644 else
5645 {
7574650a
AS
5646 if (!STRINGP (specified_data))
5647 {
5648 image_error ("Invalid image data `%s'", specified_data, Qnil);
5649 return 0;
5650 }
5651
4ef0d4d0
KS
5652 /* Read from memory. */
5653 tbr.bytes = SDATA (specified_data);
5654 tbr.len = SBYTES (specified_data);
5655 tbr.index = 0;
5656
5657 /* Check PNG signature. */
5658 if (tbr.len < sizeof sig
285d07e2 5659 || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
4ef0d4d0
KS
5660 {
5661 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
4ef0d4d0
KS
5662 return 0;
5663 }
5664
5665 /* Need to skip past the signature. */
5666 tbr.bytes += sizeof (sig);
5667 }
5668
df61c790
AS
5669 /* Initialize read and info structs for PNG lib. */
5670 png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
5671 NULL, my_png_error,
5672 my_png_warning);
40bce90b 5673 if (png_ptr)
4ef0d4d0 5674 {
40bce90b
PE
5675 info_ptr = fn_png_create_info_struct (png_ptr);
5676 end_info = fn_png_create_info_struct (png_ptr);
4ef0d4d0
KS
5677 }
5678
40bce90b
PE
5679 c->png_ptr = png_ptr;
5680 c->info_ptr = info_ptr;
5681 c->end_info = end_info;
5682 c->fp = fp;
5683 c->pixels = pixels;
5684 c->rows = rows;
5685
5686 if (! (info_ptr && end_info))
4ef0d4d0 5687 {
40bce90b
PE
5688 fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
5689 png_ptr = 0;
4ef0d4d0 5690 }
40bce90b 5691 if (! png_ptr)
4ef0d4d0 5692 {
4ef0d4d0 5693 if (fp) fclose (fp);
4ef0d4d0
KS
5694 return 0;
5695 }
5696
5697 /* Set error jump-back. We come back here when the PNG library
5698 detects an error. */
af26b72c 5699 if (_setjmp (PNG_JMPBUF (png_ptr)))
4ef0d4d0
KS
5700 {
5701 error:
40bce90b
PE
5702 if (c->png_ptr)
5703 fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
5704 xfree (c->pixels);
5705 xfree (c->rows);
5706 if (c->fp)
5707 fclose (c->fp);
4ef0d4d0
KS
5708 return 0;
5709 }
5710
40bce90b
PE
5711 /* Silence a bogus diagnostic; see GCC bug 54561. */
5712 IF_LINT (fp = c->fp);
5713
4ef0d4d0
KS
5714 /* Read image info. */
5715 if (!NILP (specified_data))
5716 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
5717 else
9a22a004 5718 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
4ef0d4d0
KS
5719
5720 fn_png_set_sig_bytes (png_ptr, sizeof sig);
5721 fn_png_read_info (png_ptr, info_ptr);
5722 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
5723 &interlace_type, NULL, NULL);
5724
3f791afe
PE
5725 if (! (width <= INT_MAX && height <= INT_MAX
5726 && check_image_size (f, width, height)))
10ea2b82
JR
5727 {
5728 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5729 goto error;
5730 }
ca4aa935
PE
5731
5732 /* Create the X image and pixmap now, so that the work below can be
5733 omitted if the image is too large for X. */
5734 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5735 &img->pixmap))
5736 goto error;
5737
4ef0d4d0
KS
5738 /* If image contains simply transparency data, we prefer to
5739 construct a clipping mask. */
5740 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
5741 transparent_p = 1;
5742 else
5743 transparent_p = 0;
5744
5745 /* This function is easier to write if we only have to handle
5746 one data format: RGB or RGBA with 8 bits per channel. Let's
5747 transform other formats into that format. */
5748
5749 /* Strip more than 8 bits per channel. */
5750 if (bit_depth == 16)
5751 fn_png_set_strip_16 (png_ptr);
5752
5753 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5754 if available. */
5755 fn_png_set_expand (png_ptr);
5756
5757 /* Convert grayscale images to RGB. */
5758 if (color_type == PNG_COLOR_TYPE_GRAY
5759 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5760 fn_png_set_gray_to_rgb (png_ptr);
5761
4ef0d4d0
KS
5762 /* Handle alpha channel by combining the image with a background
5763 color. Do this only if a real alpha channel is supplied. For
5764 simple transparency, we prefer a clipping mask. */
5765 if (!transparent_p)
5766 {
917ac1a9 5767 /* png_color_16 *image_bg; */
4ef0d4d0
KS
5768 Lisp_Object specified_bg
5769 = image_spec_value (img->spec, QCbackground, NULL);
c4f13f44 5770 int shift = (bit_depth == 16) ? 0 : 8;
4ef0d4d0
KS
5771
5772 if (STRINGP (specified_bg))
5773 /* The user specified `:background', use that. */
5774 {
4ef0d4d0 5775 XColor color;
42a5b22f 5776 if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
4ef0d4d0
KS
5777 {
5778 png_color_16 user_bg;
5779
72af86bd 5780 memset (&user_bg, 0, sizeof user_bg);
c4f13f44
CY
5781 user_bg.red = color.red >> shift;
5782 user_bg.green = color.green >> shift;
5783 user_bg.blue = color.blue >> shift;
4ef0d4d0
KS
5784
5785 fn_png_set_background (png_ptr, &user_bg,
5786 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5787 }
5788 }
4ef0d4d0
KS
5789 else
5790 {
c4f13f44
CY
5791 /* We use the current frame background, ignoring any default
5792 background color set by the image. */
8b7d0a16 5793#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4ef0d4d0
KS
5794 XColor color;
5795 png_color_16 frame_background;
5796
5797 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5798 x_query_color (f, &color);
5799
72af86bd 5800 memset (&frame_background, 0, sizeof frame_background);
c4f13f44
CY
5801 frame_background.red = color.red >> shift;
5802 frame_background.green = color.green >> shift;
5803 frame_background.blue = color.blue >> shift;
4ef0d4d0
KS
5804#endif /* HAVE_X_WINDOWS */
5805
4ef0d4d0
KS
5806 fn_png_set_background (png_ptr, &frame_background,
5807 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5808 }
5809 }
5810
5811 /* Update info structure. */
5812 fn_png_read_update_info (png_ptr, info_ptr);
5813
5814 /* Get number of channels. Valid values are 1 for grayscale images
5815 and images with a palette, 2 for grayscale images with transparency
5816 information (alpha channel), 3 for RGB images, and 4 for RGB
5817 images with alpha channel, i.e. RGBA. If conversions above were
5818 sufficient we should only have 3 or 4 channels here. */
5819 channels = fn_png_get_channels (png_ptr, info_ptr);
a54e2c05 5820 eassert (channels == 3 || channels == 4);
4ef0d4d0
KS
5821
5822 /* Number of bytes needed for one row of the image. */
5823 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
5824
5825 /* Allocate memory for the image. */
3f791afe
PE
5826 if (min (PTRDIFF_MAX, SIZE_MAX) / sizeof *rows < height
5827 || min (PTRDIFF_MAX, SIZE_MAX) / sizeof *pixels / height < row_bytes)
5828 memory_full (SIZE_MAX);
40bce90b
PE
5829 c->pixels = pixels = xmalloc (sizeof *pixels * row_bytes * height);
5830 c->rows = rows = xmalloc (height * sizeof *rows);
4ef0d4d0
KS
5831 for (i = 0; i < height; ++i)
5832 rows[i] = pixels + i * row_bytes;
5833
5834 /* Read the entire image. */
5835 fn_png_read_image (png_ptr, rows);
5836 fn_png_read_end (png_ptr, info_ptr);
5837 if (fp)
5838 {
5839 fclose (fp);
40bce90b 5840 c->fp = NULL;
4ef0d4d0
KS
5841 }
5842
4ef0d4d0
KS
5843 /* Create an image and pixmap serving as mask if the PNG image
5844 contains an alpha channel. */
5845 if (channels == 4
5846 && !transparent_p
5847 && !x_create_x_image_and_pixmap (f, width, height, 1,
5848 &mask_img, &img->mask))
5849 {
5850 x_destroy_x_image (ximg);
5851 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
5852 img->pixmap = NO_PIXMAP;
5853 goto error;
5854 }
5855
5856 /* Fill the X image and mask from PNG data. */
5857 init_color_table ();
5858
5859 for (y = 0; y < height; ++y)
5860 {
5861 png_byte *p = rows[y];
5862
5863 for (x = 0; x < width; ++x)
5864 {
13464394 5865 int r, g, b;
4ef0d4d0
KS
5866
5867 r = *p++ << 8;
5868 g = *p++ << 8;
5869 b = *p++ << 8;
5870 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5871 /* An alpha channel, aka mask channel, associates variable
5872 transparency with an image. Where other image formats
5873 support binary transparency---fully transparent or fully
5874 opaque---PNG allows up to 254 levels of partial transparency.
5875 The PNG library implements partial transparency by combining
5876 the image with a specified background color.
5877
5878 I'm not sure how to handle this here nicely: because the
5879 background on which the image is displayed may change, for
5880 real alpha channel support, it would be necessary to create
5881 a new image for each possible background.
5882
5883 What I'm doing now is that a mask is created if we have
5884 boolean transparency information. Otherwise I'm using
5885 the frame's background color to combine the image with. */
5886
5887 if (channels == 4)
5888 {
5889 if (mask_img)
9ecf6403 5890 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
4ef0d4d0
KS
5891 ++p;
5892 }
5893 }
5894 }
5895
5896 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5897 /* Set IMG's background color from the PNG image, unless the user
5898 overrode it. */
5899 {
5900 png_color_16 *bg;
5901 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
5902 {
5903 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
5904 img->background_valid = 1;
5905 }
5906 }
5907
5908#ifdef COLOR_TABLE_SUPPORT
5909 /* Remember colors allocated for this image. */
5910 img->colors = colors_in_color_table (&img->ncolors);
5911 free_color_table ();
5912#endif /* COLOR_TABLE_SUPPORT */
5913
5914 /* Clean up. */
40bce90b 5915 fn_png_destroy_read_struct (&c->png_ptr, &c->info_ptr, &c->end_info);
4ef0d4d0
KS
5916 xfree (rows);
5917 xfree (pixels);
5918
5919 img->width = width;
5920 img->height = height;
5921
2e09fef1
EZ
5922 /* Maybe fill in the background field while we have ximg handy.
5923 Casting avoids a GCC warning. */
5924 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
5925
5926 /* Put the image into the pixmap, then free the X image and its buffer. */
5927 x_put_x_image (f, ximg, img->pixmap, width, height);
5928 x_destroy_x_image (ximg);
5929
5930 /* Same for the mask. */
5931 if (mask_img)
5932 {
2e09fef1
EZ
5933 /* Fill in the background_transparent field while we have the
5934 mask handy. Casting avoids a GCC warning. */
5935 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
4ef0d4d0
KS
5936
5937 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5938 x_destroy_x_image (mask_img);
5939 }
5940
4ef0d4d0
KS
5941 return 1;
5942}
5943
578098f3 5944static bool
40bce90b
PE
5945png_load (struct frame *f, struct image *img)
5946{
5947 struct png_load_context c;
5948 return png_load_body (f, img, &c);
5949}
5950
4ef0d4d0
KS
5951#else /* HAVE_PNG */
5952
edfda783 5953#ifdef HAVE_NS
578098f3 5954static bool
edfda783
AR
5955png_load (struct frame *f, struct image *img)
5956{
5e617bc2
JB
5957 return ns_load_image (f, img,
5958 image_spec_value (img->spec, QCfile, NULL),
5959 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
5960}
5961#endif /* HAVE_NS */
5962
5963
4ef0d4d0
KS
5964#endif /* !HAVE_PNG */
5965
5966
5967\f
5968/***********************************************************************
5969 JPEG
5970 ***********************************************************************/
5971
9e2a2647 5972#if defined (HAVE_JPEG) || defined (HAVE_NS)
4ef0d4d0 5973
578098f3
PE
5974static bool jpeg_image_p (Lisp_Object object);
5975static bool jpeg_load (struct frame *f, struct image *img);
4ef0d4d0
KS
5976
5977/* The symbol `jpeg' identifying images of this type. */
5978
955cbe7b 5979static Lisp_Object Qjpeg;
4ef0d4d0
KS
5980
5981/* Indices of image specification fields in gs_format, below. */
5982
5983enum jpeg_keyword_index
5984{
5985 JPEG_TYPE,
5986 JPEG_DATA,
5987 JPEG_FILE,
5988 JPEG_ASCENT,
5989 JPEG_MARGIN,
5990 JPEG_RELIEF,
5991 JPEG_ALGORITHM,
5992 JPEG_HEURISTIC_MASK,
5993 JPEG_MASK,
5994 JPEG_BACKGROUND,
5995 JPEG_LAST
5996};
5997
5998/* Vector of image_keyword structures describing the format
5999 of valid user-defined image specifications. */
6000
91433552 6001static const struct image_keyword jpeg_format[JPEG_LAST] =
4ef0d4d0
KS
6002{
6003 {":type", IMAGE_SYMBOL_VALUE, 1},
6004 {":data", IMAGE_STRING_VALUE, 0},
6005 {":file", IMAGE_STRING_VALUE, 0},
6006 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 6007 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
6008 {":relief", IMAGE_INTEGER_VALUE, 0},
6009 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6010 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6011 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6012 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6013};
6014
a9e7a9d5 6015#if defined HAVE_NTGUI && defined WINDOWSNT
578098f3 6016static bool init_jpeg_functions (void);
bb4d86b4
CY
6017#else
6018#define init_jpeg_functions NULL
6019#endif
6020
4ef0d4d0
KS
6021/* Structure describing the image type `jpeg'. */
6022
6023static struct image_type jpeg_type =
6024{
6025 &Qjpeg,
6026 jpeg_image_p,
6027 jpeg_load,
6028 x_clear_image,
bb4d86b4 6029 init_jpeg_functions,
4ef0d4d0
KS
6030 NULL
6031};
6032
578098f3 6033/* Return true if OBJECT is a valid JPEG image specification. */
4ef0d4d0 6034
578098f3 6035static bool
d3da34e0 6036jpeg_image_p (Lisp_Object object)
4ef0d4d0
KS
6037{
6038 struct image_keyword fmt[JPEG_LAST];
6039
72af86bd 6040 memcpy (fmt, jpeg_format, sizeof fmt);
4ef0d4d0
KS
6041
6042 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6043 return 0;
6044
6045 /* Must specify either the :data or :file keyword. */
6046 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6047}
6048
9e2a2647 6049#endif /* HAVE_JPEG || HAVE_NS */
4ef0d4d0
KS
6050
6051#ifdef HAVE_JPEG
6052
6053/* Work around a warning about HAVE_STDLIB_H being redefined in
6054 jconfig.h. */
6055#ifdef HAVE_STDLIB_H
4ef0d4d0
KS
6056#undef HAVE_STDLIB_H
6057#endif /* HAVE_STLIB_H */
6058
66354420 6059#if defined (HAVE_NTGUI) && !defined (__WIN32__)
28893db2
JB
6060/* In older releases of the jpeg library, jpeglib.h will define boolean
6061 differently depending on __WIN32__, so make sure it is defined. */
66354420
JR
6062#define __WIN32__ 1
6063#endif
6064
93aa5c81
DC
6065/* rpcndr.h (via windows.h) and jpeglib.h both define boolean types.
6066 Some versions of jpeglib try to detect whether rpcndr.h is loaded,
6067 using the Windows boolean type instead of the jpeglib boolean type
6068 if so. Cygwin jpeglib, however, doesn't try to detect whether its
6069 headers are included along with windows.h, so under Cygwin, jpeglib
6070 attempts to define a conflicting boolean type. Worse, forcing
6071 Cygwin jpeglib headers to use the Windows boolean type doesn't work
6072 because it created an ABI incompatibility between the
6073 already-compiled jpeg library and the header interface definition.
6074
6075 The best we can do is to define jpeglib's boolean type to a
6076 different name. This name, jpeg_boolean, remains in effect through
6077 the rest of image.c.
6078*/
a9e7a9d5 6079#if defined CYGWIN && defined HAVE_NTGUI
0fda9b75 6080#define boolean jpeg_boolean
2ae3a8a7 6081#endif
4ef0d4d0
KS
6082#include <jpeglib.h>
6083#include <jerror.h>
4ef0d4d0 6084
0fda9b75 6085#ifdef WINDOWSNT
4ef0d4d0
KS
6086
6087/* JPEG library details. */
14beddf4
CY
6088DEF_IMGLIB_FN (void, jpeg_CreateDecompress, (j_decompress_ptr, int, size_t));
6089DEF_IMGLIB_FN (boolean, jpeg_start_decompress, (j_decompress_ptr));
6090DEF_IMGLIB_FN (boolean, jpeg_finish_decompress, (j_decompress_ptr));
6091DEF_IMGLIB_FN (void, jpeg_destroy_decompress, (j_decompress_ptr));
6092DEF_IMGLIB_FN (int, jpeg_read_header, (j_decompress_ptr, boolean));
6093DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines, (j_decompress_ptr, JSAMPARRAY, JDIMENSION));
6094DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error, (struct jpeg_error_mgr *));
6095DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart, (j_decompress_ptr, int));
4ef0d4d0 6096
578098f3 6097static bool
d07ff9db 6098init_jpeg_functions (void)
4ef0d4d0
KS
6099{
6100 HMODULE library;
6101
d07ff9db 6102 if (!(library = w32_delayed_load (Qjpeg)))
4ef0d4d0
KS
6103 return 0;
6104
6105 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6106 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6107 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6108 LOAD_IMGLIB_FN (library, jpeg_read_header);
4ef0d4d0
KS
6109 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6110 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6111 LOAD_IMGLIB_FN (library, jpeg_std_error);
6112 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6113 return 1;
6114}
6115
6116/* Wrapper since we can't directly assign the function pointer
6117 to another function pointer that was declared more completely easily. */
6118static boolean
7c3320d8 6119jpeg_resync_to_restart_wrapper (j_decompress_ptr cinfo, int desired)
4ef0d4d0
KS
6120{
6121 return fn_jpeg_resync_to_restart (cinfo, desired);
6122}
6123
6124#else
6125
5e617bc2 6126#define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress (a)
4ef0d4d0
KS
6127#define fn_jpeg_start_decompress jpeg_start_decompress
6128#define fn_jpeg_finish_decompress jpeg_finish_decompress
6129#define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6130#define fn_jpeg_read_header jpeg_read_header
6131#define fn_jpeg_read_scanlines jpeg_read_scanlines
4ef0d4d0
KS
6132#define fn_jpeg_std_error jpeg_std_error
6133#define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6134
0fda9b75 6135#endif /* WINDOWSNT */
4ef0d4d0
KS
6136
6137struct my_jpeg_error_mgr
6138{
6139 struct jpeg_error_mgr pub;
0328b6de 6140 sys_jmp_buf setjmp_buffer;
40bce90b 6141
0328b6de 6142 /* The remaining members are so that longjmp doesn't munge local
40bce90b
PE
6143 variables. */
6144 struct jpeg_decompress_struct cinfo;
6145 enum
6146 {
6147 MY_JPEG_ERROR_EXIT,
6148 MY_JPEG_INVALID_IMAGE_SIZE,
6149 MY_JPEG_CANNOT_CREATE_X
6150 } failure_code;
5f0cb45a
PE
6151#ifdef lint
6152 FILE *fp;
6153#endif
4ef0d4d0
KS
6154};
6155
6156
845ca893 6157static _Noreturn void
d3da34e0 6158my_error_exit (j_common_ptr cinfo)
4ef0d4d0
KS
6159{
6160 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
40bce90b 6161 mgr->failure_code = MY_JPEG_ERROR_EXIT;
0328b6de 6162 sys_longjmp (mgr->setjmp_buffer, 1);
4ef0d4d0
KS
6163}
6164
6165
6166/* Init source method for JPEG data source manager. Called by
6167 jpeg_read_header() before any data is actually read. See
6168 libjpeg.doc from the JPEG lib distribution. */
6169
6170static void
d3da34e0 6171our_common_init_source (j_decompress_ptr cinfo)
b25a72ab
JB
6172{
6173}
6174
6175
6176/* Method to terminate data source. Called by
6177 jpeg_finish_decompress() after all data has been processed. */
6178
6179static void
d3da34e0 6180our_common_term_source (j_decompress_ptr cinfo)
4ef0d4d0
KS
6181{
6182}
6183
6184
6185/* Fill input buffer method for JPEG data source manager. Called
6186 whenever more data is needed. We read the whole image in one step,
6187 so this only adds a fake end of input marker at the end. */
6188
5a1539f3 6189static JOCTET our_memory_buffer[2];
aca946f3 6190
4ef0d4d0 6191static boolean
d3da34e0 6192our_memory_fill_input_buffer (j_decompress_ptr cinfo)
4ef0d4d0
KS
6193{
6194 /* Insert a fake EOI marker. */
6195 struct jpeg_source_mgr *src = cinfo->src;
4ef0d4d0 6196
5a1539f3
MB
6197 our_memory_buffer[0] = (JOCTET) 0xFF;
6198 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
4ef0d4d0 6199
5a1539f3 6200 src->next_input_byte = our_memory_buffer;
4ef0d4d0 6201 src->bytes_in_buffer = 2;
e0e30823 6202 return 1;
4ef0d4d0
KS
6203}
6204
6205
6206/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6207 is the JPEG data source manager. */
6208
6209static void
d3da34e0 6210our_memory_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
4ef0d4d0
KS
6211{
6212 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6213
6214 if (src)
6215 {
6216 if (num_bytes > src->bytes_in_buffer)
6217 ERREXIT (cinfo, JERR_INPUT_EOF);
6218
6219 src->bytes_in_buffer -= num_bytes;
6220 src->next_input_byte += num_bytes;
6221 }
6222}
6223
6224
4ef0d4d0
KS
6225/* Set up the JPEG lib for reading an image from DATA which contains
6226 LEN bytes. CINFO is the decompression info structure created for
6227 reading the image. */
6228
6229static void
92547ff9 6230jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, ptrdiff_t len)
4ef0d4d0
KS
6231{
6232 struct jpeg_source_mgr *src;
6233
6234 if (cinfo->src == NULL)
6235 {
6236 /* First time for this JPEG object? */
6237 cinfo->src = (struct jpeg_source_mgr *)
6238 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6239 sizeof (struct jpeg_source_mgr));
6240 src = (struct jpeg_source_mgr *) cinfo->src;
6241 src->next_input_byte = data;
6242 }
6243
6244 src = (struct jpeg_source_mgr *) cinfo->src;
b25a72ab
JB
6245 src->init_source = our_common_init_source;
6246 src->fill_input_buffer = our_memory_fill_input_buffer;
6247 src->skip_input_data = our_memory_skip_input_data;
4ef0d4d0 6248 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
b25a72ab 6249 src->term_source = our_common_term_source;
4ef0d4d0
KS
6250 src->bytes_in_buffer = len;
6251 src->next_input_byte = data;
6252}
6253
6254
b25a72ab
JB
6255struct jpeg_stdio_mgr
6256{
6257 struct jpeg_source_mgr mgr;
6258 boolean finished;
6259 FILE *file;
6260 JOCTET *buffer;
6261};
6262
6263
6264/* Size of buffer to read JPEG from file.
6265 Not too big, as we want to use alloc_small. */
6266#define JPEG_STDIO_BUFFER_SIZE 8192
6267
6268
6269/* Fill input buffer method for JPEG data source manager. Called
6270 whenever more data is needed. The data is read from a FILE *. */
6271
6272static boolean
d3da34e0 6273our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
b25a72ab
JB
6274{
6275 struct jpeg_stdio_mgr *src;
6276
6277 src = (struct jpeg_stdio_mgr *) cinfo->src;
6278 if (!src->finished)
6279 {
3f791afe 6280 ptrdiff_t bytes;
b25a72ab
JB
6281
6282 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6283 if (bytes > 0)
6284 src->mgr.bytes_in_buffer = bytes;
6285 else
6286 {
6287 WARNMS (cinfo, JWRN_JPEG_EOF);
6288 src->finished = 1;
6289 src->buffer[0] = (JOCTET) 0xFF;
6290 src->buffer[1] = (JOCTET) JPEG_EOI;
6291 src->mgr.bytes_in_buffer = 2;
6292 }
6293 src->mgr.next_input_byte = src->buffer;
6294 }
6295
6296 return 1;
6297}
6298
6299
6300/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6301 is the JPEG data source manager. */
6302
6303static void
d3da34e0 6304our_stdio_skip_input_data (j_decompress_ptr cinfo, long int num_bytes)
b25a72ab
JB
6305{
6306 struct jpeg_stdio_mgr *src;
6307 src = (struct jpeg_stdio_mgr *) cinfo->src;
6308
6309 while (num_bytes > 0 && !src->finished)
6310 {
6311 if (num_bytes <= src->mgr.bytes_in_buffer)
6312 {
6313 src->mgr.bytes_in_buffer -= num_bytes;
6314 src->mgr.next_input_byte += num_bytes;
6315 break;
6316 }
6317 else
6318 {
6319 num_bytes -= src->mgr.bytes_in_buffer;
6320 src->mgr.bytes_in_buffer = 0;
6321 src->mgr.next_input_byte = NULL;
6322
6323 our_stdio_fill_input_buffer (cinfo);
6324 }
6325 }
6326}
6327
6328
6329/* Set up the JPEG lib for reading an image from a FILE *.
6330 CINFO is the decompression info structure created for
6331 reading the image. */
6332
6333static void
d3da34e0 6334jpeg_file_src (j_decompress_ptr cinfo, FILE *fp)
b25a72ab
JB
6335{
6336 struct jpeg_stdio_mgr *src;
6337
6338 if (cinfo->src != NULL)
6339 src = (struct jpeg_stdio_mgr *) cinfo->src;
6340 else
6341 {
6342 /* First time for this JPEG object? */
6343 cinfo->src = (struct jpeg_source_mgr *)
6344 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6345 sizeof (struct jpeg_stdio_mgr));
6346 src = (struct jpeg_stdio_mgr *) cinfo->src;
6347 src->buffer = (JOCTET *)
6348 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6349 JPEG_STDIO_BUFFER_SIZE);
6350 }
6351
6352 src->file = fp;
6353 src->finished = 0;
6354 src->mgr.init_source = our_common_init_source;
6355 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6356 src->mgr.skip_input_data = our_stdio_skip_input_data;
6357 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6358 src->mgr.term_source = our_common_term_source;
6359 src->mgr.bytes_in_buffer = 0;
6360 src->mgr.next_input_byte = NULL;
6361}
6362
6363
4ef0d4d0
KS
6364/* Load image IMG for use on frame F. Patterned after example.c
6365 from the JPEG lib. */
6366
578098f3 6367static bool
40bce90b
PE
6368jpeg_load_body (struct frame *f, struct image *img,
6369 struct my_jpeg_error_mgr *mgr)
4ef0d4d0 6370{
4ef0d4d0
KS
6371 Lisp_Object file, specified_file;
6372 Lisp_Object specified_data;
40bce90b 6373 FILE *fp = NULL;
4ef0d4d0
KS
6374 JSAMPARRAY buffer;
6375 int row_stride, x, y;
6376 XImagePtr ximg = NULL;
4ef0d4d0
KS
6377 unsigned long *colors;
6378 int width, height;
4ef0d4d0
KS
6379
6380 /* Open the JPEG file. */
6381 specified_file = image_spec_value (img->spec, QCfile, NULL);
6382 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0
KS
6383
6384 if (NILP (specified_data))
6385 {
6386 file = x_find_image_file (specified_file);
6387 if (!STRINGP (file))
6388 {
6389 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
6390 return 0;
6391 }
6392
42a5b22f 6393 fp = fopen (SSDATA (file), "rb");
4ef0d4d0
KS
6394 if (fp == NULL)
6395 {
6396 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
6397 return 0;
6398 }
6399 }
7574650a
AS
6400 else if (!STRINGP (specified_data))
6401 {
6402 image_error ("Invalid image data `%s'", specified_data, Qnil);
6403 return 0;
6404 }
4ef0d4d0 6405
5f0cb45a
PE
6406 IF_LINT (mgr->fp = fp);
6407
4ef0d4d0 6408 /* Customize libjpeg's error handling to call my_error_exit when an
df61c790 6409 error is detected. This function will perform a longjmp. */
40bce90b
PE
6410 mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
6411 mgr->pub.error_exit = my_error_exit;
0328b6de 6412 if (sys_setjmp (mgr->setjmp_buffer))
4ef0d4d0 6413 {
40bce90b 6414 switch (mgr->failure_code)
4ef0d4d0 6415 {
40bce90b
PE
6416 case MY_JPEG_ERROR_EXIT:
6417 {
6418 char buf[JMSG_LENGTH_MAX];
6419 mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf);
6420 image_error ("Error reading JPEG image `%s': %s", img->spec,
6421 build_string (buf));
6422 break;
6423 }
6424
6425 case MY_JPEG_INVALID_IMAGE_SIZE:
6426 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
6427 break;
6428
6429 case MY_JPEG_CANNOT_CREATE_X:
6430 break;
4ef0d4d0
KS
6431 }
6432
6433 /* Close the input file and destroy the JPEG object. */
6434 if (fp)
40bce90b
PE
6435 fclose (fp);
6436 fn_jpeg_destroy_decompress (&mgr->cinfo);
4ef0d4d0
KS
6437
6438 /* If we already have an XImage, free that. */
6439 x_destroy_x_image (ximg);
6440
6441 /* Free pixmap and colors. */
6442 x_clear_image (f, img);
4ef0d4d0
KS
6443 return 0;
6444 }
6445
5f0cb45a
PE
6446 /* Silence a bogus diagnostic; see GCC bug 54561. */
6447 IF_LINT (fp = mgr->fp);
6448
4ef0d4d0
KS
6449 /* Create the JPEG decompression object. Let it read from fp.
6450 Read the JPEG image header. */
40bce90b 6451 fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
4ef0d4d0
KS
6452
6453 if (NILP (specified_data))
40bce90b 6454 jpeg_file_src (&mgr->cinfo, fp);
4ef0d4d0 6455 else
40bce90b 6456 jpeg_memory_src (&mgr->cinfo, SDATA (specified_data),
4ef0d4d0
KS
6457 SBYTES (specified_data));
6458
40bce90b 6459 fn_jpeg_read_header (&mgr->cinfo, 1);
4ef0d4d0
KS
6460
6461 /* Customize decompression so that color quantization will be used.
6462 Start decompression. */
40bce90b
PE
6463 mgr->cinfo.quantize_colors = 1;
6464 fn_jpeg_start_decompress (&mgr->cinfo);
6465 width = img->width = mgr->cinfo.output_width;
6466 height = img->height = mgr->cinfo.output_height;
4ef0d4d0 6467
f1f25b99
CY
6468 if (!check_image_size (f, width, height))
6469 {
40bce90b 6470 mgr->failure_code = MY_JPEG_INVALID_IMAGE_SIZE;
0328b6de 6471 sys_longjmp (mgr->setjmp_buffer, 1);
f1f25b99
CY
6472 }
6473
4ef0d4d0
KS
6474 /* Create X image and pixmap. */
6475 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
40bce90b
PE
6476 {
6477 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
0328b6de 6478 sys_longjmp (mgr->setjmp_buffer, 1);
40bce90b 6479 }
4ef0d4d0
KS
6480
6481 /* Allocate colors. When color quantization is used,
40bce90b
PE
6482 mgr->cinfo.actual_number_of_colors has been set with the number of
6483 colors generated, and mgr->cinfo.colormap is a two-dimensional array
6484 of color indices in the range 0..mgr->cinfo.actual_number_of_colors.
4ef0d4d0
KS
6485 No more than 255 colors will be generated. */
6486 {
6487 int i, ir, ig, ib;
6488
40bce90b 6489 if (mgr->cinfo.out_color_components > 2)
4ef0d4d0 6490 ir = 0, ig = 1, ib = 2;
40bce90b 6491 else if (mgr->cinfo.out_color_components > 1)
4ef0d4d0
KS
6492 ir = 0, ig = 1, ib = 0;
6493 else
6494 ir = 0, ig = 0, ib = 0;
6495
6496 /* Use the color table mechanism because it handles colors that
6497 cannot be allocated nicely. Such colors will be replaced with
6498 a default color, and we don't have to care about which colors
6499 can be freed safely, and which can't. */
6500 init_color_table ();
40bce90b 6501 colors = alloca (mgr->cinfo.actual_number_of_colors * sizeof *colors);
4ef0d4d0 6502
40bce90b 6503 for (i = 0; i < mgr->cinfo.actual_number_of_colors; ++i)
4ef0d4d0
KS
6504 {
6505 /* Multiply RGB values with 255 because X expects RGB values
6506 in the range 0..0xffff. */
40bce90b
PE
6507 int r = mgr->cinfo.colormap[ir][i] << 8;
6508 int g = mgr->cinfo.colormap[ig][i] << 8;
6509 int b = mgr->cinfo.colormap[ib][i] << 8;
4ef0d4d0
KS
6510 colors[i] = lookup_rgb_color (f, r, g, b);
6511 }
6512
6513#ifdef COLOR_TABLE_SUPPORT
6514 /* Remember those colors actually allocated. */
6515 img->colors = colors_in_color_table (&img->ncolors);
6516 free_color_table ();
6517#endif /* COLOR_TABLE_SUPPORT */
6518 }
6519
6520 /* Read pixels. */
40bce90b
PE
6521 row_stride = width * mgr->cinfo.output_components;
6522 buffer = mgr->cinfo.mem->alloc_sarray ((j_common_ptr) &mgr->cinfo,
6523 JPOOL_IMAGE, row_stride, 1);
4ef0d4d0
KS
6524 for (y = 0; y < height; ++y)
6525 {
40bce90b
PE
6526 fn_jpeg_read_scanlines (&mgr->cinfo, buffer, 1);
6527 for (x = 0; x < mgr->cinfo.output_width; ++x)
4ef0d4d0
KS
6528 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6529 }
6530
6531 /* Clean up. */
40bce90b
PE
6532 fn_jpeg_finish_decompress (&mgr->cinfo);
6533 fn_jpeg_destroy_decompress (&mgr->cinfo);
4ef0d4d0 6534 if (fp)
40bce90b 6535 fclose (fp);
4ef0d4d0
KS
6536
6537 /* Maybe fill in the background field while we have ximg handy. */
6538 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
6539 /* Casting avoids a GCC warning. */
6540 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
6541
6542 /* Put the image into the pixmap. */
6543 x_put_x_image (f, ximg, img->pixmap, width, height);
6544 x_destroy_x_image (ximg);
4ef0d4d0
KS
6545 return 1;
6546}
6547
578098f3 6548static bool
40bce90b
PE
6549jpeg_load (struct frame *f, struct image *img)
6550{
6551 struct my_jpeg_error_mgr mgr;
6552 return jpeg_load_body (f, img, &mgr);
6553}
6554
4ef0d4d0
KS
6555#else /* HAVE_JPEG */
6556
edfda783 6557#ifdef HAVE_NS
578098f3 6558static bool
edfda783
AR
6559jpeg_load (struct frame *f, struct image *img)
6560{
ed3751c8
JB
6561 return ns_load_image (f, img,
6562 image_spec_value (img->spec, QCfile, NULL),
6563 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
6564}
6565#endif /* HAVE_NS */
6566
4ef0d4d0
KS
6567#endif /* !HAVE_JPEG */
6568
6569
6570\f
6571/***********************************************************************
6572 TIFF
6573 ***********************************************************************/
6574
9e2a2647 6575#if defined (HAVE_TIFF) || defined (HAVE_NS)
4ef0d4d0 6576
578098f3
PE
6577static bool tiff_image_p (Lisp_Object object);
6578static bool tiff_load (struct frame *f, struct image *img);
4ef0d4d0
KS
6579
6580/* The symbol `tiff' identifying images of this type. */
6581
955cbe7b 6582static Lisp_Object Qtiff;
4ef0d4d0
KS
6583
6584/* Indices of image specification fields in tiff_format, below. */
6585
6586enum tiff_keyword_index
6587{
6588 TIFF_TYPE,
6589 TIFF_DATA,
6590 TIFF_FILE,
6591 TIFF_ASCENT,
6592 TIFF_MARGIN,
6593 TIFF_RELIEF,
6594 TIFF_ALGORITHM,
6595 TIFF_HEURISTIC_MASK,
6596 TIFF_MASK,
6597 TIFF_BACKGROUND,
58279503 6598 TIFF_INDEX,
4ef0d4d0
KS
6599 TIFF_LAST
6600};
6601
6602/* Vector of image_keyword structures describing the format
6603 of valid user-defined image specifications. */
6604
91433552 6605static const struct image_keyword tiff_format[TIFF_LAST] =
4ef0d4d0
KS
6606{
6607 {":type", IMAGE_SYMBOL_VALUE, 1},
6608 {":data", IMAGE_STRING_VALUE, 0},
6609 {":file", IMAGE_STRING_VALUE, 0},
6610 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 6611 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
6612 {":relief", IMAGE_INTEGER_VALUE, 0},
6613 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6614 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6615 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
58279503
JR
6616 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6617 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
4ef0d4d0
KS
6618};
6619
bb4d86b4 6620#ifdef HAVE_NTGUI
578098f3 6621static bool init_tiff_functions (void);
bb4d86b4
CY
6622#else
6623#define init_tiff_functions NULL
6624#endif
6625
4ef0d4d0
KS
6626/* Structure describing the image type `tiff'. */
6627
6628static struct image_type tiff_type =
6629{
6630 &Qtiff,
6631 tiff_image_p,
6632 tiff_load,
6633 x_clear_image,
bb4d86b4 6634 init_tiff_functions,
4ef0d4d0
KS
6635 NULL
6636};
6637
578098f3 6638/* Return true if OBJECT is a valid TIFF image specification. */
4ef0d4d0 6639
578098f3 6640static bool
d3da34e0 6641tiff_image_p (Lisp_Object object)
4ef0d4d0
KS
6642{
6643 struct image_keyword fmt[TIFF_LAST];
72af86bd 6644 memcpy (fmt, tiff_format, sizeof fmt);
4ef0d4d0
KS
6645
6646 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6647 return 0;
6648
6649 /* Must specify either the :data or :file keyword. */
6650 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6651}
6652
9e2a2647 6653#endif /* HAVE_TIFF || HAVE_NS */
4ef0d4d0
KS
6654
6655#ifdef HAVE_TIFF
6656
6657#include <tiffio.h>
6658
0fda9b75 6659#ifdef WINDOWSNT
4ef0d4d0
KS
6660
6661/* TIFF library details. */
14beddf4
CY
6662DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler, (TIFFErrorHandler));
6663DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler, (TIFFErrorHandler));
6664DEF_IMGLIB_FN (TIFF *, TIFFOpen, (const char *, const char *));
6665DEF_IMGLIB_FN (TIFF *, TIFFClientOpen, (const char *, const char *, thandle_t,
850690cc
JB
6666 TIFFReadWriteProc, TIFFReadWriteProc,
6667 TIFFSeekProc, TIFFCloseProc, TIFFSizeProc,
6668 TIFFMapFileProc, TIFFUnmapFileProc));
14beddf4
CY
6669DEF_IMGLIB_FN (int, TIFFGetField, (TIFF *, ttag_t, ...));
6670DEF_IMGLIB_FN (int, TIFFReadRGBAImage, (TIFF *, uint32, uint32, uint32 *, int));
6671DEF_IMGLIB_FN (void, TIFFClose, (TIFF *));
6672DEF_IMGLIB_FN (int, TIFFSetDirectory, (TIFF *, tdir_t));
4ef0d4d0 6673
578098f3 6674static bool
d07ff9db 6675init_tiff_functions (void)
4ef0d4d0
KS
6676{
6677 HMODULE library;
6678
d07ff9db 6679 if (!(library = w32_delayed_load (Qtiff)))
4ef0d4d0
KS
6680 return 0;
6681
6682 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6683 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6684 LOAD_IMGLIB_FN (library, TIFFOpen);
6685 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6686 LOAD_IMGLIB_FN (library, TIFFGetField);
6687 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6688 LOAD_IMGLIB_FN (library, TIFFClose);
58279503 6689 LOAD_IMGLIB_FN (library, TIFFSetDirectory);
4ef0d4d0
KS
6690 return 1;
6691}
6692
6693#else
6694
6695#define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6696#define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6697#define fn_TIFFOpen TIFFOpen
6698#define fn_TIFFClientOpen TIFFClientOpen
6699#define fn_TIFFGetField TIFFGetField
6700#define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6701#define fn_TIFFClose TIFFClose
58279503 6702#define fn_TIFFSetDirectory TIFFSetDirectory
0fda9b75 6703#endif /* WINDOWSNT */
4ef0d4d0
KS
6704
6705
6706/* Reading from a memory buffer for TIFF images Based on the PNG
6707 memory source, but we have to provide a lot of extra functions.
6708 Blah.
6709
6710 We really only need to implement read and seek, but I am not
6711 convinced that the TIFF library is smart enough not to destroy
6712 itself if we only hand it the function pointers we need to
6713 override. */
6714
6715typedef struct
6716{
6717 unsigned char *bytes;
3f791afe
PE
6718 ptrdiff_t len;
6719 ptrdiff_t index;
4ef0d4d0
KS
6720}
6721tiff_memory_source;
6722
3f791afe 6723static tsize_t
d3da34e0 6724tiff_read_from_memory (thandle_t data, tdata_t buf, tsize_t size)
4ef0d4d0
KS
6725{
6726 tiff_memory_source *src = (tiff_memory_source *) data;
6727
3f791afe 6728 size = min (size, src->len - src->index);
72af86bd 6729 memcpy (buf, src->bytes + src->index, size);
4ef0d4d0
KS
6730 src->index += size;
6731 return size;
6732}
6733
3f791afe 6734static tsize_t
d3da34e0 6735tiff_write_from_memory (thandle_t data, tdata_t buf, tsize_t size)
4ef0d4d0 6736{
3f791afe 6737 return -1;
4ef0d4d0
KS
6738}
6739
6740static toff_t
d3da34e0 6741tiff_seek_in_memory (thandle_t data, toff_t off, int whence)
4ef0d4d0
KS
6742{
6743 tiff_memory_source *src = (tiff_memory_source *) data;
3f791afe 6744 ptrdiff_t idx;
4ef0d4d0
KS
6745
6746 switch (whence)
6747 {
6748 case SEEK_SET: /* Go from beginning of source. */
6749 idx = off;
6750 break;
6751
6752 case SEEK_END: /* Go from end of source. */
6753 idx = src->len + off;
6754 break;
6755
6756 case SEEK_CUR: /* Go from current position. */
6757 idx = src->index + off;
6758 break;
6759
6760 default: /* Invalid `whence'. */
6761 return -1;
6762 }
6763
6764 if (idx > src->len || idx < 0)
6765 return -1;
6766
6767 src->index = idx;
6768 return src->index;
6769}
6770
6771static int
d3da34e0 6772tiff_close_memory (thandle_t data)
4ef0d4d0
KS
6773{
6774 /* NOOP */
6775 return 0;
6776}
6777
6778static int
d3da34e0 6779tiff_mmap_memory (thandle_t data, tdata_t *pbase, toff_t *psize)
4ef0d4d0
KS
6780{
6781 /* It is already _IN_ memory. */
6782 return 0;
6783}
6784
6785static void
d3da34e0 6786tiff_unmap_memory (thandle_t data, tdata_t base, toff_t size)
4ef0d4d0
KS
6787{
6788 /* We don't need to do this. */
6789}
6790
6791static toff_t
d3da34e0 6792tiff_size_of_memory (thandle_t data)
4ef0d4d0
KS
6793{
6794 return ((tiff_memory_source *) data)->len;
6795}
6796
b41c3a35
EZ
6797/* GCC 3.x on x86 Windows targets has a bug that triggers an internal
6798 compiler error compiling tiff_handler, see Bugzilla bug #17406
6799 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17406). Declaring
6800 this function as external works around that problem. */
6801#if defined (__MINGW32__) && __GNUC__ == 3
6802# define MINGW_STATIC
6803#else
6804# define MINGW_STATIC static
6805#endif
4ef0d4d0 6806
b41c3a35
EZ
6807MINGW_STATIC void
6808tiff_handler (const char *, const char *, const char *, va_list)
13464394 6809 ATTRIBUTE_FORMAT_PRINTF (3, 0);
b41c3a35 6810MINGW_STATIC void
13464394
PE
6811tiff_handler (const char *log_format, const char *title,
6812 const char *format, va_list ap)
6813{
6814 /* doprnt is not suitable here, as TIFF handlers are called from
6815 libtiff and are passed arbitrary printf directives. Instead, use
6816 vsnprintf, taking care to be portable to nonstandard environments
6817 where vsnprintf returns -1 on buffer overflow. Since it's just a
6818 log entry, it's OK to truncate it. */
6819 char buf[4000];
6820 int len = vsnprintf (buf, sizeof buf, format, ap);
6821 add_to_log (log_format, build_string (title),
6822 make_string (buf, max (0, min (len, sizeof buf - 1))));
6823}
b41c3a35 6824#undef MINGW_STATIC
13464394 6825
5e2d4a30
PE
6826static void tiff_error_handler (const char *, const char *, va_list)
6827 ATTRIBUTE_FORMAT_PRINTF (2, 0);
4ef0d4d0 6828static void
d3da34e0 6829tiff_error_handler (const char *title, const char *format, va_list ap)
4ef0d4d0 6830{
13464394 6831 tiff_handler ("TIFF error: %s %s", title, format, ap);
4ef0d4d0
KS
6832}
6833
6834
5e2d4a30
PE
6835static void tiff_warning_handler (const char *, const char *, va_list)
6836 ATTRIBUTE_FORMAT_PRINTF (2, 0);
4ef0d4d0 6837static void
d3da34e0 6838tiff_warning_handler (const char *title, const char *format, va_list ap)
4ef0d4d0 6839{
13464394 6840 tiff_handler ("TIFF warning: %s %s", title, format, ap);
4ef0d4d0
KS
6841}
6842
6843
578098f3 6844/* Load TIFF image IMG for use on frame F. Value is true if
4ef0d4d0
KS
6845 successful. */
6846
578098f3 6847static bool
d3da34e0 6848tiff_load (struct frame *f, struct image *img)
4ef0d4d0
KS
6849{
6850 Lisp_Object file, specified_file;
6851 Lisp_Object specified_data;
6852 TIFF *tiff;
58279503 6853 int width, height, x, y, count;
4ef0d4d0 6854 uint32 *buf;
03d0a109 6855 int rc;
4ef0d4d0 6856 XImagePtr ximg;
4ef0d4d0 6857 tiff_memory_source memsrc;
58279503 6858 Lisp_Object image;
4ef0d4d0
KS
6859
6860 specified_file = image_spec_value (img->spec, QCfile, NULL);
6861 specified_data = image_spec_value (img->spec, QCdata, NULL);
4ef0d4d0 6862
5e2d4a30
PE
6863 fn_TIFFSetErrorHandler ((TIFFErrorHandler) tiff_error_handler);
6864 fn_TIFFSetWarningHandler ((TIFFErrorHandler) tiff_warning_handler);
4ef0d4d0
KS
6865
6866 if (NILP (specified_data))
6867 {
6868 /* Read from a file */
6869 file = x_find_image_file (specified_file);
6870 if (!STRINGP (file))
6871 {
6872 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
6873 return 0;
6874 }
6875
df61c790 6876 /* Try to open the image file. */
b19beacc 6877 tiff = fn_TIFFOpen (SSDATA (file), "r");
4ef0d4d0
KS
6878 if (tiff == NULL)
6879 {
6880 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
6881 return 0;
6882 }
6883 }
6884 else
6885 {
7574650a
AS
6886 if (!STRINGP (specified_data))
6887 {
6888 image_error ("Invalid image data `%s'", specified_data, Qnil);
6889 return 0;
6890 }
6891
4ef0d4d0
KS
6892 /* Memory source! */
6893 memsrc.bytes = SDATA (specified_data);
6894 memsrc.len = SBYTES (specified_data);
6895 memsrc.index = 0;
6896
3082f617 6897 tiff = fn_TIFFClientOpen ("memory_source", "r", (thandle_t)&memsrc,
3f791afe
PE
6898 tiff_read_from_memory,
6899 tiff_write_from_memory,
df61c790
AS
6900 tiff_seek_in_memory,
6901 tiff_close_memory,
6902 tiff_size_of_memory,
6903 tiff_mmap_memory,
6904 tiff_unmap_memory);
4ef0d4d0
KS
6905
6906 if (!tiff)
6907 {
6908 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
4ef0d4d0
KS
6909 return 0;
6910 }
6911 }
6912
58279503
JR
6913 image = image_spec_value (img->spec, QCindex, NULL);
6914 if (INTEGERP (image))
6915 {
13464394
PE
6916 EMACS_INT ino = XFASTINT (image);
6917 if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
6918 && fn_TIFFSetDirectory (tiff, ino)))
58279503
JR
6919 {
6920 image_error ("Invalid image number `%s' in image `%s'",
6921 image, img->spec);
6922 fn_TIFFClose (tiff);
58279503
JR
6923 return 0;
6924 }
6925 }
6926
4ef0d4d0
KS
6927 /* Get width and height of the image, and allocate a raster buffer
6928 of width x height 32-bit values. */
6929 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
6930 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
f1f25b99
CY
6931
6932 if (!check_image_size (f, width, height))
6933 {
10ea2b82 6934 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
58279503 6935 fn_TIFFClose (tiff);
f1f25b99
CY
6936 return 0;
6937 }
6938
ca4aa935
PE
6939 /* Create the X image and pixmap. */
6940 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
6941 && x_create_x_image_and_pixmap (f, width, height, 0,
6942 &ximg, &img->pixmap)))
6943 {
6944 fn_TIFFClose (tiff);
6945 return 0;
6946 }
6947
23f86fce 6948 buf = xmalloc (sizeof *buf * width * height);
4ef0d4d0
KS
6949
6950 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
58279503
JR
6951
6952 /* Count the number of images in the file. */
03d0a109
PE
6953 for (count = 1; fn_TIFFSetDirectory (tiff, count); count++)
6954 continue;
58279503
JR
6955
6956 if (count > 1)
b50691aa
CY
6957 img->lisp_data = Fcons (Qcount,
6958 Fcons (make_number (count),
6959 img->lisp_data));
58279503 6960
4ef0d4d0
KS
6961 fn_TIFFClose (tiff);
6962 if (!rc)
6963 {
6964 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
6965 xfree (buf);
4ef0d4d0
KS
6966 return 0;
6967 }
6968
4ef0d4d0
KS
6969 /* Initialize the color table. */
6970 init_color_table ();
6971
6972 /* Process the pixel raster. Origin is in the lower-left corner. */
6973 for (y = 0; y < height; ++y)
6974 {
6975 uint32 *row = buf + y * width;
6976
6977 for (x = 0; x < width; ++x)
6978 {
6979 uint32 abgr = row[x];
6980 int r = TIFFGetR (abgr) << 8;
6981 int g = TIFFGetG (abgr) << 8;
6982 int b = TIFFGetB (abgr) << 8;
6983 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
6984 }
6985 }
6986
6987#ifdef COLOR_TABLE_SUPPORT
6988 /* Remember the colors allocated for the image. Free the color table. */
6989 img->colors = colors_in_color_table (&img->ncolors);
6990 free_color_table ();
6991#endif /* COLOR_TABLE_SUPPORT */
6992
6993 img->width = width;
6994 img->height = height;
6995
6996 /* Maybe fill in the background field while we have ximg handy. */
6997 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
6998 /* Casting avoids a GCC warning on W32. */
6999 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
7000
7001 /* Put the image into the pixmap, then free the X image and its buffer. */
7002 x_put_x_image (f, ximg, img->pixmap, width, height);
7003 x_destroy_x_image (ximg);
7004 xfree (buf);
7005
4ef0d4d0
KS
7006 return 1;
7007}
7008
7009#else /* HAVE_TIFF */
7010
edfda783 7011#ifdef HAVE_NS
578098f3 7012static bool
edfda783
AR
7013tiff_load (struct frame *f, struct image *img)
7014{
ed3751c8
JB
7015 return ns_load_image (f, img,
7016 image_spec_value (img->spec, QCfile, NULL),
7017 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
7018}
7019#endif /* HAVE_NS */
7020
4ef0d4d0
KS
7021#endif /* !HAVE_TIFF */
7022
7023
7024\f
7025/***********************************************************************
7026 GIF
7027 ***********************************************************************/
7028
9e2a2647 7029#if defined (HAVE_GIF) || defined (HAVE_NS)
4ef0d4d0 7030
578098f3
PE
7031static bool gif_image_p (Lisp_Object object);
7032static bool gif_load (struct frame *f, struct image *img);
f57e2426 7033static void gif_clear_image (struct frame *f, struct image *img);
4ef0d4d0
KS
7034
7035/* The symbol `gif' identifying images of this type. */
7036
955cbe7b 7037static Lisp_Object Qgif;
4ef0d4d0
KS
7038
7039/* Indices of image specification fields in gif_format, below. */
7040
7041enum gif_keyword_index
7042{
7043 GIF_TYPE,
7044 GIF_DATA,
7045 GIF_FILE,
7046 GIF_ASCENT,
7047 GIF_MARGIN,
7048 GIF_RELIEF,
7049 GIF_ALGORITHM,
7050 GIF_HEURISTIC_MASK,
7051 GIF_MASK,
7052 GIF_IMAGE,
7053 GIF_BACKGROUND,
7054 GIF_LAST
7055};
7056
7057/* Vector of image_keyword structures describing the format
7058 of valid user-defined image specifications. */
7059
91433552 7060static const struct image_keyword gif_format[GIF_LAST] =
4ef0d4d0
KS
7061{
7062 {":type", IMAGE_SYMBOL_VALUE, 1},
7063 {":data", IMAGE_STRING_VALUE, 0},
7064 {":file", IMAGE_STRING_VALUE, 0},
7065 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 7066 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
7067 {":relief", IMAGE_INTEGER_VALUE, 0},
7068 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7069 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7070 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
58279503 7071 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
4ef0d4d0
KS
7072 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7073};
7074
a9e7a9d5 7075#if defined HAVE_NTGUI && defined WINDOWSNT
578098f3 7076static bool init_gif_functions (void);
bb4d86b4
CY
7077#else
7078#define init_gif_functions NULL
7079#endif
7080
4ef0d4d0
KS
7081/* Structure describing the image type `gif'. */
7082
7083static struct image_type gif_type =
7084{
7085 &Qgif,
7086 gif_image_p,
7087 gif_load,
6ac3c7bb 7088 gif_clear_image,
bb4d86b4 7089 init_gif_functions,
4ef0d4d0
KS
7090 NULL
7091};
7092
6ac3c7bb
KS
7093/* Free X resources of GIF image IMG which is used on frame F. */
7094
7095static void
d3da34e0 7096gif_clear_image (struct frame *f, struct image *img)
6ac3c7bb 7097{
b50691aa 7098 img->lisp_data = Qnil;
6ac3c7bb
KS
7099 x_clear_image (f, img);
7100}
7101
578098f3 7102/* Return true if OBJECT is a valid GIF image specification. */
4ef0d4d0 7103
578098f3 7104static bool
d3da34e0 7105gif_image_p (Lisp_Object object)
4ef0d4d0
KS
7106{
7107 struct image_keyword fmt[GIF_LAST];
72af86bd 7108 memcpy (fmt, gif_format, sizeof fmt);
4ef0d4d0
KS
7109
7110 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7111 return 0;
7112
7113 /* Must specify either the :data or :file keyword. */
7114 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7115}
7116
9e2a2647 7117#endif /* HAVE_GIF */
4ef0d4d0
KS
7118
7119#ifdef HAVE_GIF
7120
9e2a2647 7121#if defined (HAVE_NTGUI)
2e09fef1
EZ
7122/* winuser.h might define DrawText to DrawTextA or DrawTextW.
7123 Undefine before redefining to avoid a preprocessor warning. */
7124#ifdef DrawText
7125#undef DrawText
7126#endif
4ef0d4d0
KS
7127/* avoid conflict with QuickdrawText.h */
7128#define DrawText gif_DrawText
7129#include <gif_lib.h>
7130#undef DrawText
7131
9e2a2647 7132#else /* HAVE_NTGUI */
4ef0d4d0
KS
7133
7134#include <gif_lib.h>
7135
9e2a2647 7136#endif /* HAVE_NTGUI */
4ef0d4d0
KS
7137
7138
0fda9b75 7139#ifdef WINDOWSNT
4ef0d4d0
KS
7140
7141/* GIF library details. */
14beddf4
CY
7142DEF_IMGLIB_FN (int, DGifCloseFile, (GifFileType *));
7143DEF_IMGLIB_FN (int, DGifSlurp, (GifFileType *));
7144DEF_IMGLIB_FN (GifFileType *, DGifOpen, (void *, InputFunc));
7145DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName, (const char *));
4ef0d4d0 7146
578098f3 7147static bool
d07ff9db 7148init_gif_functions (void)
4ef0d4d0
KS
7149{
7150 HMODULE library;
7151
d07ff9db 7152 if (!(library = w32_delayed_load (Qgif)))
4ef0d4d0
KS
7153 return 0;
7154
7155 LOAD_IMGLIB_FN (library, DGifCloseFile);
7156 LOAD_IMGLIB_FN (library, DGifSlurp);
7157 LOAD_IMGLIB_FN (library, DGifOpen);
7158 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7159 return 1;
7160}
7161
7162#else
7163
7164#define fn_DGifCloseFile DGifCloseFile
7165#define fn_DGifSlurp DGifSlurp
7166#define fn_DGifOpen DGifOpen
7167#define fn_DGifOpenFileName DGifOpenFileName
7168
0fda9b75 7169#endif /* WINDOWSNT */
4ef0d4d0
KS
7170
7171/* Reading a GIF image from memory
7172 Based on the PNG memory stuff to a certain extent. */
7173
7174typedef struct
7175{
7176 unsigned char *bytes;
3f791afe
PE
7177 ptrdiff_t len;
7178 ptrdiff_t index;
4ef0d4d0
KS
7179}
7180gif_memory_source;
7181
7182/* Make the current memory source available to gif_read_from_memory.
7183 It's done this way because not all versions of libungif support
7184 a UserData field in the GifFileType structure. */
7185static gif_memory_source *current_gif_memory_src;
7186
7187static int
d3da34e0 7188gif_read_from_memory (GifFileType *file, GifByteType *buf, int len)
4ef0d4d0
KS
7189{
7190 gif_memory_source *src = current_gif_memory_src;
7191
7192 if (len > src->len - src->index)
7193 return -1;
7194
72af86bd 7195 memcpy (buf, src->bytes + src->index, len);
4ef0d4d0
KS
7196 src->index += len;
7197 return len;
7198}
7199
7200
578098f3 7201/* Load GIF image IMG for use on frame F. Value is true if
4ef0d4d0
KS
7202 successful. */
7203
91433552
DN
7204static const int interlace_start[] = {0, 4, 2, 1};
7205static const int interlace_increment[] = {8, 8, 4, 2};
aca946f3 7206
17c0c952
JD
7207#define GIF_LOCAL_DESCRIPTOR_EXTENSION 249
7208
578098f3 7209static bool
d3da34e0 7210gif_load (struct frame *f, struct image *img)
4ef0d4d0 7211{
60002bf5
CY
7212 Lisp_Object file;
7213 int rc, width, height, x, y, i, j;
4ef0d4d0
KS
7214 XImagePtr ximg;
7215 ColorMapObject *gif_color_map;
7216 unsigned long pixel_colors[256];
7217 GifFileType *gif;
4ef0d4d0 7218 gif_memory_source memsrc;
60002bf5
CY
7219 Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7220 Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
7221 Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL);
7222 unsigned long bgcolor = 0;
13464394 7223 EMACS_INT idx;
4ef0d4d0
KS
7224
7225 if (NILP (specified_data))
7226 {
7227 file = x_find_image_file (specified_file);
7228 if (!STRINGP (file))
7229 {
7230 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4ef0d4d0
KS
7231 return 0;
7232 }
7233
df61c790 7234 /* Open the GIF file. */
2037898d 7235 gif = fn_DGifOpenFileName (SSDATA (file));
4ef0d4d0
KS
7236 if (gif == NULL)
7237 {
7238 image_error ("Cannot open `%s'", file, Qnil);
4ef0d4d0
KS
7239 return 0;
7240 }
7241 }
7242 else
7243 {
7574650a
AS
7244 if (!STRINGP (specified_data))
7245 {
7246 image_error ("Invalid image data `%s'", specified_data, Qnil);
7247 return 0;
7248 }
7249
4ef0d4d0
KS
7250 /* Read from memory! */
7251 current_gif_memory_src = &memsrc;
7252 memsrc.bytes = SDATA (specified_data);
7253 memsrc.len = SBYTES (specified_data);
7254 memsrc.index = 0;
7255
df61c790 7256 gif = fn_DGifOpen (&memsrc, gif_read_from_memory);
4ef0d4d0
KS
7257 if (!gif)
7258 {
7259 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
4ef0d4d0
KS
7260 return 0;
7261 }
7262 }
7263
f1f25b99
CY
7264 /* Before reading entire contents, check the declared image size. */
7265 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7266 {
10ea2b82 7267 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99 7268 fn_DGifCloseFile (gif);
f1f25b99
CY
7269 return 0;
7270 }
7271
4ef0d4d0
KS
7272 /* Read entire contents. */
7273 rc = fn_DGifSlurp (gif);
60002bf5 7274 if (rc == GIF_ERROR || gif->ImageCount <= 0)
4ef0d4d0
KS
7275 {
7276 image_error ("Error reading `%s'", img->spec, Qnil);
7277 fn_DGifCloseFile (gif);
4ef0d4d0
KS
7278 return 0;
7279 }
7280
60002bf5
CY
7281 /* Which sub-image are we to display? */
7282 {
33290528
PE
7283 Lisp_Object image_number = image_spec_value (img->spec, QCindex, NULL);
7284 idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
60002bf5 7285 if (idx < 0 || idx >= gif->ImageCount)
17c0c952 7286 {
60002bf5 7287 image_error ("Invalid image number `%s' in image `%s'",
33290528 7288 image_number, img->spec);
60002bf5
CY
7289 fn_DGifCloseFile (gif);
7290 return 0;
17c0c952 7291 }
60002bf5 7292 }
17c0c952 7293
e013fb34
CY
7294 width = img->width = gif->SWidth;
7295 height = img->height = gif->SHeight;
0f4aca46 7296
e013fb34
CY
7297 img->corners[TOP_CORNER] = gif->SavedImages[0].ImageDesc.Top;
7298 img->corners[LEFT_CORNER] = gif->SavedImages[0].ImageDesc.Left;
8d903f4e
AS
7299 img->corners[BOT_CORNER]
7300 = img->corners[TOP_CORNER] + gif->SavedImages[0].ImageDesc.Height;
7301 img->corners[RIGHT_CORNER]
7302 = img->corners[LEFT_CORNER] + gif->SavedImages[0].ImageDesc.Width;
4ef0d4d0 7303
f1f25b99
CY
7304 if (!check_image_size (f, width, height))
7305 {
10ea2b82 7306 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99 7307 fn_DGifCloseFile (gif);
f1f25b99
CY
7308 return 0;
7309 }
7310
4ef0d4d0
KS
7311 /* Create the X image and pixmap. */
7312 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7313 {
7314 fn_DGifCloseFile (gif);
4ef0d4d0
KS
7315 return 0;
7316 }
7317
60002bf5
CY
7318 /* Clear the part of the screen image not covered by the image.
7319 Full animated GIF support requires more here (see the gif89 spec,
7320 disposal methods). Let's simply assume that the part not covered
7321 by a sub-image is in the frame's background color. */
6ac3c7bb 7322 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
4ef0d4d0
KS
7323 for (x = 0; x < width; ++x)
7324 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7325
6ac3c7bb 7326 for (y = img->corners[BOT_CORNER]; y < height; ++y)
4ef0d4d0
KS
7327 for (x = 0; x < width; ++x)
7328 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7329
6ac3c7bb 7330 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
4ef0d4d0 7331 {
6ac3c7bb 7332 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
4ef0d4d0 7333 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6ac3c7bb 7334 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
4ef0d4d0
KS
7335 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7336 }
7337
60002bf5 7338 /* Read the GIF image into the X image. */
4ef0d4d0 7339
60002bf5
CY
7340 /* FIXME: With the current implementation, loading an animated gif
7341 is quadratic in the number of animation frames, since each frame
7342 is a separate struct image. We must provide a way for a single
7343 gif_load call to construct and save all animation frames. */
4ef0d4d0 7344
60002bf5
CY
7345 init_color_table ();
7346 if (STRINGP (specified_bg))
7347 bgcolor = x_alloc_image_color (f, img, specified_bg,
7348 FRAME_BACKGROUND_PIXEL (f));
7349 for (j = 0; j <= idx; ++j)
7350 {
7351 /* We use a local variable `raster' here because RasterBits is a
7352 char *, which invites problems with bytes >= 0x80. */
7353 struct SavedImage *subimage = gif->SavedImages + j;
7354 unsigned char *raster = (unsigned char *) subimage->RasterBits;
7355 int transparency_color_index = -1;
7356 int disposal = 0;
e013fb34
CY
7357 int subimg_width = subimage->ImageDesc.Width;
7358 int subimg_height = subimage->ImageDesc.Height;
7359 int subimg_top = subimage->ImageDesc.Top;
7360 int subimg_left = subimage->ImageDesc.Left;
60002bf5
CY
7361
7362 /* Find the Graphic Control Extension block for this sub-image.
7363 Extract the disposal method and transparency color. */
7364 for (i = 0; i < subimage->ExtensionBlockCount; i++)
4ef0d4d0 7365 {
60002bf5 7366 ExtensionBlock *extblock = subimage->ExtensionBlocks + i;
4ef0d4d0 7367
60002bf5
CY
7368 if ((extblock->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION)
7369 && extblock->ByteCount == 4
7370 && extblock->Bytes[0] & 1)
4ef0d4d0 7371 {
60002bf5
CY
7372 /* From gif89a spec: 1 = "keep in place", 2 = "restore
7373 to background". Treat any other value like 2. */
7374 disposal = (extblock->Bytes[0] >> 2) & 7;
2547adb1 7375 transparency_color_index = (unsigned char) extblock->Bytes[3];
60002bf5 7376 break;
4ef0d4d0 7377 }
4ef0d4d0 7378 }
60002bf5
CY
7379
7380 /* We can't "keep in place" the first subimage. */
7381 if (j == 0)
7382 disposal = 2;
7383
e013fb34
CY
7384 /* For disposal == 0, the spec says "No disposal specified. The
7385 decoder is not required to take any action." In practice, it
7386 seems we need to treat this like "keep in place", see e.g.
7387 http://upload.wikimedia.org/wikipedia/commons/3/37/Clock.gif */
7388 if (disposal == 0)
7389 disposal = 1;
7390
60002bf5
CY
7391 /* Allocate subimage colors. */
7392 memset (pixel_colors, 0, sizeof pixel_colors);
7393 gif_color_map = subimage->ImageDesc.ColorMap;
7394 if (!gif_color_map)
7395 gif_color_map = gif->SColorMap;
7396
7397 if (gif_color_map)
7398 for (i = 0; i < gif_color_map->ColorCount; ++i)
4ef0d4d0 7399 {
60002bf5
CY
7400 if (transparency_color_index == i)
7401 pixel_colors[i] = STRINGP (specified_bg)
7402 ? bgcolor : FRAME_BACKGROUND_PIXEL (f);
7403 else
7404 {
7405 int r = gif_color_map->Colors[i].Red << 8;
7406 int g = gif_color_map->Colors[i].Green << 8;
7407 int b = gif_color_map->Colors[i].Blue << 8;
7408 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7409 }
4ef0d4d0 7410 }
60002bf5
CY
7411
7412 /* Apply the pixel values. */
7413 if (gif->SavedImages[j].ImageDesc.Interlace)
7414 {
7415 int row, pass;
7416
7417 for (y = 0, row = interlace_start[0], pass = 0;
e013fb34 7418 y < subimg_height;
60002bf5
CY
7419 y++, row += interlace_increment[pass])
7420 {
e013fb34 7421 if (row >= subimg_height)
60002bf5
CY
7422 {
7423 row = interlace_start[++pass];
e013fb34 7424 while (row >= subimg_height)
60002bf5
CY
7425 row = interlace_start[++pass];
7426 }
7427
e013fb34 7428 for (x = 0; x < subimg_width; x++)
60002bf5 7429 {
e013fb34 7430 int c = raster[y * subimg_width + x];
60002bf5 7431 if (transparency_color_index != c || disposal != 1)
e013fb34
CY
7432 XPutPixel (ximg, x + subimg_left, row + subimg_top,
7433 pixel_colors[c]);
60002bf5
CY
7434 }
7435 }
7436 }
7437 else
7438 {
e013fb34
CY
7439 for (y = 0; y < subimg_height; ++y)
7440 for (x = 0; x < subimg_width; ++x)
60002bf5 7441 {
e013fb34 7442 int c = raster[y * subimg_width + x];
60002bf5 7443 if (transparency_color_index != c || disposal != 1)
e013fb34
CY
7444 XPutPixel (ximg, x + subimg_left, y + subimg_top,
7445 pixel_colors[c]);
60002bf5
CY
7446 }
7447 }
4ef0d4d0
KS
7448 }
7449
60002bf5
CY
7450#ifdef COLOR_TABLE_SUPPORT
7451 img->colors = colors_in_color_table (&img->ncolors);
7452 free_color_table ();
7453#endif /* COLOR_TABLE_SUPPORT */
7454
1546c559
JL
7455 /* Save GIF image extension data for `image-metadata'.
7456 Format is (count IMAGES extension-data (FUNCTION "BYTES" ...)). */
b50691aa 7457 img->lisp_data = Qnil;
60002bf5 7458 if (gif->SavedImages[idx].ExtensionBlockCount > 0)
6ac3c7bb 7459 {
13464394 7460 int delay = 0;
60002bf5
CY
7461 ExtensionBlock *ext = gif->SavedImages[idx].ExtensionBlocks;
7462 for (i = 0; i < gif->SavedImages[idx].ExtensionBlockCount; i++, ext++)
6ac3c7bb 7463 /* Append (... FUNCTION "BYTES") */
1100a63c
CY
7464 {
7465 img->lisp_data
7466 = Fcons (make_number (ext->Function),
7467 Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7468 img->lisp_data));
7469 if (ext->Function == GIF_LOCAL_DESCRIPTOR_EXTENSION
7470 && ext->ByteCount == 4)
7471 {
7472 delay = ext->Bytes[2] << CHAR_BIT;
7473 delay |= ext->Bytes[1];
7474 }
7475 }
b50691aa 7476 img->lisp_data = Fcons (Qextension_data,
1100a63c
CY
7477 Fcons (img->lisp_data, Qnil));
7478 if (delay)
7479 img->lisp_data
7480 = Fcons (Qdelay,
13464394 7481 Fcons (make_float (delay / 100.0),
1100a63c 7482 img->lisp_data));
6ac3c7bb 7483 }
1100a63c 7484
6ac3c7bb 7485 if (gif->ImageCount > 1)
b50691aa
CY
7486 img->lisp_data = Fcons (Qcount,
7487 Fcons (make_number (gif->ImageCount),
7488 img->lisp_data));
6ac3c7bb 7489
4ef0d4d0
KS
7490 fn_DGifCloseFile (gif);
7491
7492 /* Maybe fill in the background field while we have ximg handy. */
7493 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2e09fef1
EZ
7494 /* Casting avoids a GCC warning. */
7495 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
4ef0d4d0
KS
7496
7497 /* Put the image into the pixmap, then free the X image and its buffer. */
7498 x_put_x_image (f, ximg, img->pixmap, width, height);
7499 x_destroy_x_image (ximg);
7500
4ef0d4d0
KS
7501 return 1;
7502}
7503
2e09fef1 7504#else /* !HAVE_GIF */
4ef0d4d0 7505
edfda783 7506#ifdef HAVE_NS
578098f3 7507static bool
edfda783
AR
7508gif_load (struct frame *f, struct image *img)
7509{
ed3751c8
JB
7510 return ns_load_image (f, img,
7511 image_spec_value (img->spec, QCfile, NULL),
7512 image_spec_value (img->spec, QCdata, NULL));
edfda783
AR
7513}
7514#endif /* HAVE_NS */
7515
4ef0d4d0
KS
7516#endif /* HAVE_GIF */
7517
7518
3de25479 7519/***********************************************************************
a32d4040 7520 ImageMagick
4917006b 7521***********************************************************************/
3de25479 7522#if defined (HAVE_IMAGEMAGICK)
3de25479 7523
4b66faf3 7524static Lisp_Object Qimagemagick;
a32d4040 7525
578098f3
PE
7526static bool imagemagick_image_p (Lisp_Object);
7527static bool imagemagick_load (struct frame *, struct image *);
d66c4c7c
CY
7528static void imagemagick_clear_image (struct frame *, struct image *);
7529
a32d4040 7530/* Indices of image specification fields in imagemagick_format. */
3de25479
JV
7531
7532enum imagemagick_keyword_index
4917006b
JV
7533 {
7534 IMAGEMAGICK_TYPE,
7535 IMAGEMAGICK_DATA,
7536 IMAGEMAGICK_FILE,
7537 IMAGEMAGICK_ASCENT,
7538 IMAGEMAGICK_MARGIN,
7539 IMAGEMAGICK_RELIEF,
7540 IMAGEMAGICK_ALGORITHM,
7541 IMAGEMAGICK_HEURISTIC_MASK,
7542 IMAGEMAGICK_MASK,
7543 IMAGEMAGICK_BACKGROUND,
c7f514b5
JV
7544 IMAGEMAGICK_HEIGHT,
7545 IMAGEMAGICK_WIDTH,
7546 IMAGEMAGICK_ROTATION,
7547 IMAGEMAGICK_CROP,
4917006b
JV
7548 IMAGEMAGICK_LAST
7549 };
3de25479
JV
7550
7551/* Vector of image_keyword structures describing the format
7552 of valid user-defined image specifications. */
7553
7554static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
4917006b
JV
7555 {
7556 {":type", IMAGE_SYMBOL_VALUE, 1},
7557 {":data", IMAGE_STRING_VALUE, 0},
7558 {":file", IMAGE_STRING_VALUE, 0},
7559 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 7560 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4917006b
JV
7561 {":relief", IMAGE_INTEGER_VALUE, 0},
7562 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7563 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7564 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
c7f514b5 7565 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
7574650a
AS
7566 {":height", IMAGE_INTEGER_VALUE, 0},
7567 {":width", IMAGE_INTEGER_VALUE, 0},
7568 {":rotation", IMAGE_NUMBER_VALUE, 0},
c7f514b5 7569 {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
4917006b 7570 };
a32d4040 7571
bb4d86b4 7572#ifdef HAVE_NTGUI
578098f3 7573static bool init_imagemagick_functions (void);
bb4d86b4
CY
7574#else
7575#define init_imagemagick_functions NULL
7576#endif
7577
d66c4c7c
CY
7578/* Structure describing the image type for any image handled via
7579 ImageMagick. */
7580
7581static struct image_type imagemagick_type =
7582 {
7583 &Qimagemagick,
7584 imagemagick_image_p,
7585 imagemagick_load,
7586 imagemagick_clear_image,
bb4d86b4 7587 init_imagemagick_functions,
d66c4c7c
CY
7588 NULL
7589 };
7590
3de25479
JV
7591/* Free X resources of imagemagick image IMG which is used on frame F. */
7592
7593static void
4917006b
JV
7594imagemagick_clear_image (struct frame *f,
7595 struct image *img)
3de25479 7596{
3de25479
JV
7597 x_clear_image (f, img);
7598}
7599
578098f3 7600/* Return true if OBJECT is a valid IMAGEMAGICK image specification. Do
3de25479
JV
7601 this by calling parse_image_spec and supplying the keywords that
7602 identify the IMAGEMAGICK format. */
7603
578098f3 7604static bool
4917006b 7605imagemagick_image_p (Lisp_Object object)
3de25479
JV
7606{
7607 struct image_keyword fmt[IMAGEMAGICK_LAST];
dbfe4532 7608 memcpy (fmt, imagemagick_format, sizeof fmt);
3de25479
JV
7609
7610 if (!parse_image_spec (object, fmt, IMAGEMAGICK_LAST, Qimagemagick))
7611 return 0;
7612
7613 /* Must specify either the :data or :file keyword. */
7614 return fmt[IMAGEMAGICK_FILE].count + fmt[IMAGEMAGICK_DATA].count == 1;
7615}
7616
7617/* The GIF library also defines DrawRectangle, but its never used in Emacs.
c7015153 7618 Therefore rename the function so it doesn't collide with ImageMagick. */
3de25479
JV
7619#define DrawRectangle DrawRectangleGif
7620#include <wand/MagickWand.h>
7621
60737f02
PE
7622/* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
7623 Emacs seems to work fine with the hidden version, so unhide it. */
7624#include <magick/version.h>
7625#if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
7626extern WandExport void PixelGetMagickColor (const PixelWand *,
7627 MagickPixelPacket *);
7628#endif
7629
d1d7b339
JL
7630/* Log ImageMagick error message.
7631 Useful when a ImageMagick function returns the status `MagickFalse'. */
7632
7633static void
7634imagemagick_error (MagickWand *wand)
7635{
7636 char *description;
7637 ExceptionType severity;
7638
7639 description = MagickGetException (wand, &severity);
7640 image_error ("ImageMagick error: %s",
1130ecfc 7641 build_string (description),
d1d7b339
JL
7642 Qnil);
7643 description = (char *) MagickRelinquishMemory (description);
7644}
7645
d66c4c7c
CY
7646/* Helper function for imagemagick_load, which does the actual loading
7647 given contents and size, apart from frame and image structures,
7648 passed from imagemagick_load. Uses librimagemagick to do most of
7649 the image processing.
3de25479 7650
d66c4c7c
CY
7651 F is a pointer to the Emacs frame; IMG to the image structure to
7652 prepare; CONTENTS is the string containing the IMAGEMAGICK data to
7653 be parsed; SIZE is the number of bytes of data; and FILENAME is
7654 either the file name or the image data.
3de25479 7655
578098f3 7656 Return true if successful. */
3de25479 7657
578098f3 7658static bool
d66c4c7c
CY
7659imagemagick_load_image (struct frame *f, struct image *img,
7660 unsigned char *contents, unsigned int size,
33290528 7661 char *filename)
3de25479 7662{
1b9b4cf4 7663 size_t width, height;
d66c4c7c 7664 MagickBooleanType status;
3de25479 7665 XImagePtr ximg;
1b9b4cf4
CY
7666 int x, y;
7667 MagickWand *image_wand;
7668 MagickWand *ping_wand;
3de25479 7669 PixelIterator *iterator;
1b9b4cf4 7670 PixelWand **pixels, *bg_wand = NULL;
3de25479 7671 MagickPixelPacket pixel;
4917006b 7672 Lisp_Object image;
7574650a 7673 Lisp_Object value;
33290528 7674 Lisp_Object crop;
13464394 7675 EMACS_INT ino;
4917006b
JV
7676 int desired_width, desired_height;
7677 double rotation;
7574650a 7678 int pixelwidth;
7574650a 7679
a32d4040
CY
7680 /* Handle image index for image types who can contain more than one image.
7681 Interface :index is same as for GIF. First we "ping" the image to see how
7682 many sub-images it contains. Pinging is faster than loading the image to
7683 find out things about it. */
f853f599 7684
a32d4040 7685 /* Initialize the imagemagick environment. */
f853f599 7686 MagickWandGenesis ();
3de25479
JV
7687 image = image_spec_value (img->spec, QCindex, NULL);
7688 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7574650a 7689 ping_wand = NewMagickWand ();
d1d7b339 7690 /* MagickSetResolution (ping_wand, 2, 2); (Bug#10112) */
fa4fdb5c 7691
1b9b4cf4
CY
7692 status = filename
7693 ? MagickPingImage (ping_wand, filename)
7694 : MagickPingImageBlob (ping_wand, contents, size);
7574650a 7695
d1d7b339
JL
7696 if (status == MagickFalse)
7697 {
7698 imagemagick_error (ping_wand);
7699 DestroyMagickWand (ping_wand);
7700 return 0;
7701 }
fa4fdb5c 7702
1b9b4cf4 7703 if (ino < 0 || ino >= MagickGetNumberImages (ping_wand))
7574650a
AS
7704 {
7705 image_error ("Invalid image number `%s' in image `%s'",
7706 image, img->spec);
7707 DestroyMagickWand (ping_wand);
7708 return 0;
f3700365 7709 }
431dab04 7710
5e617bc2 7711 if (MagickGetNumberImages (ping_wand) > 1)
b50691aa 7712 img->lisp_data =
d2a2d277 7713 Fcons (Qcount,
7574650a 7714 Fcons (make_number (MagickGetNumberImages (ping_wand)),
b50691aa 7715 img->lisp_data));
f3700365
JV
7716
7717 DestroyMagickWand (ping_wand);
f853f599 7718
d66c4c7c 7719 /* Now we know how many images are inside the file. If it's not a
1b9b4cf4 7720 bundle, the number is one. Load the image data. */
f3700365 7721
1b9b4cf4 7722 image_wand = NewMagickWand ();
f3700365 7723
1b9b4cf4
CY
7724 if ((filename
7725 ? MagickReadImage (image_wand, filename)
7726 : MagickReadImageBlob (image_wand, contents, size))
7727 == MagickFalse)
f3700365 7728 {
1b9b4cf4
CY
7729 imagemagick_error (image_wand);
7730 goto imagemagick_error;
f3700365 7731 }
f853f599 7732
1b9b4cf4
CY
7733 /* Retrieve the frame's background color, for use later. */
7734 {
7735 XColor bgcolor;
7736 Lisp_Object specified_bg;
7737
7738 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7739 if (!STRINGP (specified_bg)
7740 || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0))
7741 {
7742#ifndef HAVE_NS
7743 bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f);
7744 x_query_color (f, &bgcolor);
7745#else
7746 ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1);
7747#endif
7748 }
7749
7750 bg_wand = NewPixelWand ();
7751 PixelSetRed (bg_wand, (double) bgcolor.red / 65535);
7752 PixelSetGreen (bg_wand, (double) bgcolor.green / 65535);
7753 PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535);
7754 }
7755
d2a2d277 7756 /* If width and/or height is set in the display spec assume we want
a32d4040 7757 to scale to those values. If either h or w is unspecified, the
f3700365 7758 unspecified should be calculated from the specified to preserve
549a73b9 7759 aspect ratio. */
3de25479
JV
7760 value = image_spec_value (img->spec, QCwidth, NULL);
7761 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
7762 value = image_spec_value (img->spec, QCheight, NULL);
7763 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
c7f514b5 7764
bdf6a35d
JV
7765 height = MagickGetImageHeight (image_wand);
7766 width = MagickGetImageWidth (image_wand);
7767
a32d4040
CY
7768 if (desired_width != -1 && desired_height == -1)
7769 /* w known, calculate h. */
7770 desired_height = (double) desired_width / width * height;
7771 if (desired_width == -1 && desired_height != -1)
7772 /* h known, calculate w. */
7773 desired_width = (double) desired_height / height * width;
7774 if (desired_width != -1 && desired_height != -1)
4917006b 7775 {
7574650a
AS
7776 status = MagickScaleImage (image_wand, desired_width, desired_height);
7777 if (status == MagickFalse)
7778 {
7779 image_error ("Imagemagick scale failed", Qnil, Qnil);
d1d7b339 7780 imagemagick_error (image_wand);
7574650a
AS
7781 goto imagemagick_error;
7782 }
3de25479 7783 }
3de25479 7784
f3700365 7785 /* crop behaves similar to image slicing in Emacs but is more memory
7574650a
AS
7786 efficient. */
7787 crop = image_spec_value (img->spec, QCcrop, NULL);
7788
13464394 7789 if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
7574650a 7790 {
a32d4040
CY
7791 /* After some testing, it seems MagickCropImage is the fastest crop
7792 function in ImageMagick. This crop function seems to do less copying
7793 than the alternatives, but it still reads the entire image into memory
13464394 7794 before cropping, which is apparently difficult to avoid when using
a32d4040 7795 imagemagick. */
13464394 7796 size_t crop_width = XINT (XCAR (crop));
7574650a 7797 crop = XCDR (crop);
13464394 7798 if (CONSP (crop) && TYPE_RANGED_INTEGERP (size_t, XCAR (crop)))
7574650a 7799 {
13464394 7800 size_t crop_height = XINT (XCAR (crop));
7574650a 7801 crop = XCDR (crop);
13464394 7802 if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
7574650a 7803 {
13464394 7804 ssize_t crop_x = XINT (XCAR (crop));
7574650a 7805 crop = XCDR (crop);
13464394 7806 if (CONSP (crop) && TYPE_RANGED_INTEGERP (ssize_t, XCAR (crop)))
7574650a 7807 {
13464394
PE
7808 ssize_t crop_y = XINT (XCAR (crop));
7809 MagickCropImage (image_wand, crop_width, crop_height,
7810 crop_x, crop_y);
7574650a
AS
7811 }
7812 }
7813 }
7814 }
7815
d2a2d277
JV
7816 /* Furthermore :rotation. we need background color and angle for
7817 rotation. */
3de25479 7818 /*
d2a2d277
JV
7819 TODO background handling for rotation specified_bg =
7820 image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP
549a73b9 7821 (specified_bg). */
4917006b
JV
7822 value = image_spec_value (img->spec, QCrotation, NULL);
7823 if (FLOATP (value))
7824 {
3de25479 7825 rotation = extract_float (value);
1b9b4cf4 7826 status = MagickRotateImage (image_wand, bg_wand, rotation);
4917006b
JV
7827 if (status == MagickFalse)
7828 {
7829 image_error ("Imagemagick image rotate failed", Qnil, Qnil);
d1d7b339 7830 imagemagick_error (image_wand);
4917006b
JV
7831 goto imagemagick_error;
7832 }
3de25479 7833 }
7574650a 7834
d66c4c7c 7835 /* Finally we are done manipulating the image. Figure out the
e1dbe924 7836 resulting width/height and transfer ownership to Emacs. */
4917006b
JV
7837 height = MagickGetImageHeight (image_wand);
7838 width = MagickGetImageWidth (image_wand);
7574650a 7839
1b9b4cf4
CY
7840 /* Set the canvas background color to the frame or specified
7841 background, and flatten the image. Note: as of ImageMagick
7842 6.6.0, SVG image transparency is not handled properly
7843 (e.g. etc/images/splash.svg shows a white background always). */
7844 {
7845 MagickWand *new_wand;
7846 MagickSetImageBackgroundColor (image_wand, bg_wand);
0e25d334 7847#ifdef HAVE_MAGICKMERGEIMAGELAYERS
1b9b4cf4 7848 new_wand = MagickMergeImageLayers (image_wand, MergeLayer);
0e25d334
CY
7849#else
7850 new_wand = MagickFlattenImages (image_wand);
7851#endif
1b9b4cf4
CY
7852 DestroyMagickWand (image_wand);
7853 image_wand = new_wand;
7854 }
7855
3f791afe
PE
7856 if (! (width <= INT_MAX && height <= INT_MAX
7857 && check_image_size (f, width, height)))
3de25479
JV
7858 {
7859 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7860 goto imagemagick_error;
7861 }
7574650a 7862
3de25479
JV
7863 /* We can now get a valid pixel buffer from the imagemagick file, if all
7864 went ok. */
3de25479
JV
7865
7866 init_color_table ();
af008560 7867
0e25d334
CY
7868#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
7869 if (imagemagick_render_type != 0)
7870 {
7871 /* Magicexportimage is normally faster than pixelpushing. This
7872 method is also well tested. Some aspects of this method are
7873 ad-hoc and needs to be more researched. */
7874 int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/
7875 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/
7876 /* Try to create a x pixmap to hold the imagemagick pixmap. */
7877 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth,
7878 &ximg, &img->pixmap))
7879 {
7880#ifdef COLOR_TABLE_SUPPORT
7881 free_color_table ();
7882#endif
7883 image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
7884 goto imagemagick_error;
7885 }
7886
7887 /* Oddly, the below code doesn't seem to work:*/
7888 /* switch(ximg->bitmap_unit){ */
7889 /* case 8: */
7890 /* pixelwidth=CharPixel; */
7891 /* break; */
7892 /* case 16: */
7893 /* pixelwidth=ShortPixel; */
7894 /* break; */
7895 /* case 32: */
7896 /* pixelwidth=LongPixel; */
7897 /* break; */
7898 /* } */
7899 /*
7900 Here im just guessing the format of the bitmap.
7901 happens to work fine for:
7902 - bw djvu images
7903 on rgb display.
7904 seems about 3 times as fast as pixel pushing(not carefully measured)
7905 */
7906 pixelwidth = CharPixel; /*??? TODO figure out*/
7907 MagickExportImagePixels (image_wand, 0, 0, width, height,
7908 exportdepth, pixelwidth, ximg->data);
7909 }
7910 else
7911#endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */
4917006b 7912 {
13464394
PE
7913 size_t image_height;
7914
4917006b 7915 /* Try to create a x pixmap to hold the imagemagick pixmap. */
d2a2d277
JV
7916 if (!x_create_x_image_and_pixmap (f, width, height, 0,
7917 &ximg, &img->pixmap))
4917006b 7918 {
466cbae9
AS
7919#ifdef COLOR_TABLE_SUPPORT
7920 free_color_table ();
7921#endif
5e617bc2 7922 image_error ("Imagemagick X bitmap allocation failure", Qnil, Qnil);
4917006b
JV
7923 goto imagemagick_error;
7924 }
7574650a 7925
53964682 7926 /* Copy imagemagick image to x with primitive yet robust pixel
4917006b 7927 pusher loop. This has been tested a lot with many different
549a73b9 7928 images. */
7574650a 7929
4917006b
JV
7930 /* Copy pixels from the imagemagick image structure to the x image map. */
7931 iterator = NewPixelIterator (image_wand);
7574650a 7932 if (iterator == (PixelIterator *) NULL)
4917006b 7933 {
466cbae9
AS
7934#ifdef COLOR_TABLE_SUPPORT
7935 free_color_table ();
7936#endif
7937 x_destroy_x_image (ximg);
d2a2d277
JV
7938 image_error ("Imagemagick pixel iterator creation failed",
7939 Qnil, Qnil);
3de25479 7940 goto imagemagick_error;
4917006b
JV
7941 }
7942
13464394
PE
7943 image_height = MagickGetImageHeight (image_wand);
7944 for (y = 0; y < image_height; y++)
4917006b
JV
7945 {
7946 pixels = PixelGetNextIteratorRow (iterator, &width);
7574650a 7947 if (pixels == (PixelWand **) NULL)
4917006b
JV
7948 break;
7949 for (x = 0; x < (long) width; x++)
7950 {
7951 PixelGetMagickColor (pixels[x], &pixel);
d2a2d277
JV
7952 XPutPixel (ximg, x, y,
7953 lookup_rgb_color (f,
7954 pixel.red,
7955 pixel.green,
7956 pixel.blue));
4917006b
JV
7957 }
7958 }
7959 DestroyPixelIterator (iterator);
3de25479 7960 }
3ed42149 7961
3de25479
JV
7962#ifdef COLOR_TABLE_SUPPORT
7963 /* Remember colors allocated for this image. */
7964 img->colors = colors_in_color_table (&img->ncolors);
7965 free_color_table ();
7966#endif /* COLOR_TABLE_SUPPORT */
7967
3de25479
JV
7968 img->width = width;
7969 img->height = height;
7970
3de25479
JV
7971 /* Put the image into the pixmap, then free the X image and its
7972 buffer. */
7973 x_put_x_image (f, ximg, img->pixmap, width, height);
3de25479
JV
7974 x_destroy_x_image (ximg);
7975
f3700365 7976 /* Final cleanup. image_wand should be the only resource left. */
3de25479 7977 DestroyMagickWand (image_wand);
1b9b4cf4
CY
7978 if (bg_wand) DestroyPixelWand (bg_wand);
7979
03d32f1b 7980 /* `MagickWandTerminus' terminates the imagemagick environment. */
f853f599 7981 MagickWandTerminus ();
3de25479
JV
7982
7983 return 1;
7984
7985 imagemagick_error:
466cbae9 7986 DestroyMagickWand (image_wand);
1b9b4cf4
CY
7987 if (bg_wand) DestroyPixelWand (bg_wand);
7988
f853f599 7989 MagickWandTerminus ();
3de25479
JV
7990 /* TODO more cleanup. */
7991 image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
3de25479
JV
7992 return 0;
7993}
7994
4917006b 7995
578098f3 7996/* Load IMAGEMAGICK image IMG for use on frame F. Value is true if
4917006b
JV
7997 successful. this function will go into the imagemagick_type structure, and
7998 the prototype thus needs to be compatible with that structure. */
7999
578098f3 8000static bool
d66c4c7c 8001imagemagick_load (struct frame *f, struct image *img)
4917006b 8002{
578098f3 8003 bool success_p = 0;
4917006b
JV
8004 Lisp_Object file_name;
8005
8006 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8007 file_name = image_spec_value (img->spec, QCfile, NULL);
8008 if (STRINGP (file_name))
8009 {
8010 Lisp_Object file;
4917006b
JV
8011
8012 file = x_find_image_file (file_name);
4917006b
JV
8013 if (!STRINGP (file))
8014 {
8015 image_error ("Cannot find image file `%s'", file_name, Qnil);
4917006b
JV
8016 return 0;
8017 }
33290528 8018 success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
4917006b
JV
8019 }
8020 /* Else its not a file, its a lisp object. Load the image from a
8021 lisp object rather than a file. */
8022 else
8023 {
8024 Lisp_Object data;
8025
8026 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
8027 if (!STRINGP (data))
8028 {
8029 image_error ("Invalid image data `%s'", data, Qnil);
8030 return 0;
8031 }
d2a2d277
JV
8032 success_p = imagemagick_load_image (f, img, SDATA (data),
8033 SBYTES (data), NULL);
4917006b
JV
8034 }
8035
8036 return success_p;
8037}
8038
a7ca3326 8039DEFUN ("imagemagick-types", Fimagemagick_types, Simagemagick_types, 0, 0, 0,
d66c4c7c
CY
8040 doc: /* Return a list of image types supported by ImageMagick.
8041Each entry in this list is a symbol named after an ImageMagick format
8042tag. See the ImageMagick manual for a list of ImageMagick formats and
8043their descriptions (http://www.imagemagick.org/script/formats.php).
dd605cc4 8044You can also try the shell command: `identify -list format'.
d66c4c7c
CY
8045
8046Note that ImageMagick recognizes many file-types that Emacs does not
32d72c2f
GM
8047recognize as images, such as C. See `imagemagick-types-enable'
8048and `imagemagick-types-inhibit'. */)
a8101f66 8049 (void)
3de25479
JV
8050{
8051 Lisp_Object typelist = Qnil;
1ab0dee5 8052 size_t numf = 0;
3de25479 8053 ExceptionInfo ex;
2277de02 8054 char **imtypes;
3f791afe 8055 size_t i;
3de25479 8056 Lisp_Object Qimagemagicktype;
2277de02
JD
8057
8058 GetExceptionInfo(&ex);
8059 imtypes = GetMagickList ("*", &numf, &ex);
8060 DestroyExceptionInfo(&ex);
8061
4917006b
JV
8062 for (i = 0; i < numf; i++)
8063 {
8064 Qimagemagicktype = intern (imtypes[i]);
f3700365
JV
8065 typelist = Fcons (Qimagemagicktype, typelist);
8066 }
d1d7b339 8067 return Fnreverse (typelist);
3de25479 8068}
7574650a 8069
3de25479
JV
8070#endif /* defined (HAVE_IMAGEMAGICK) */
8071
8072
4ef0d4d0 8073\f
4ab27a43
GM
8074/***********************************************************************
8075 SVG
8076 ***********************************************************************/
8077
8078#if defined (HAVE_RSVG)
8079
8080/* Function prototypes. */
8081
578098f3
PE
8082static bool svg_image_p (Lisp_Object object);
8083static bool svg_load (struct frame *f, struct image *img);
4ab27a43 8084
578098f3
PE
8085static bool svg_load_image (struct frame *, struct image *,
8086 unsigned char *, ptrdiff_t);
4ab27a43
GM
8087
8088/* The symbol `svg' identifying images of this type. */
8089
4b66faf3 8090static Lisp_Object Qsvg;
4ab27a43
GM
8091
8092/* Indices of image specification fields in svg_format, below. */
8093
8094enum svg_keyword_index
8095{
8096 SVG_TYPE,
8097 SVG_DATA,
8098 SVG_FILE,
8099 SVG_ASCENT,
8100 SVG_MARGIN,
8101 SVG_RELIEF,
8102 SVG_ALGORITHM,
8103 SVG_HEURISTIC_MASK,
8104 SVG_MASK,
8105 SVG_BACKGROUND,
8106 SVG_LAST
8107};
8108
8109/* Vector of image_keyword structures describing the format
8110 of valid user-defined image specifications. */
8111
91433552 8112static const struct image_keyword svg_format[SVG_LAST] =
4ab27a43
GM
8113{
8114 {":type", IMAGE_SYMBOL_VALUE, 1},
8115 {":data", IMAGE_STRING_VALUE, 0},
8116 {":file", IMAGE_STRING_VALUE, 0},
8117 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 8118 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ab27a43
GM
8119 {":relief", IMAGE_INTEGER_VALUE, 0},
8120 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8121 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8122 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8123 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8124};
8125
bb4d86b4 8126#ifdef HAVE_NTGUI
578098f3 8127static bool init_svg_functions (void);
bb4d86b4
CY
8128#else
8129#define init_svg_functions NULL
8130#endif
8131
4ab27a43
GM
8132/* Structure describing the image type `svg'. Its the same type of
8133 structure defined for all image formats, handled by emacs image
8134 functions. See struct image_type in dispextern.h. */
8135
8136static struct image_type svg_type =
8137{
4ab27a43 8138 &Qsvg,
4ab27a43 8139 svg_image_p,
4ab27a43 8140 svg_load,
4ab27a43 8141 x_clear_image,
bb4d86b4 8142 init_svg_functions,
c21e6151 8143 NULL
4ab27a43
GM
8144};
8145
8146
578098f3 8147/* Return true if OBJECT is a valid SVG image specification. Do
4ab27a43
GM
8148 this by calling parse_image_spec and supplying the keywords that
8149 identify the SVG format. */
8150
578098f3 8151static bool
d3da34e0 8152svg_image_p (Lisp_Object object)
4ab27a43
GM
8153{
8154 struct image_keyword fmt[SVG_LAST];
72af86bd 8155 memcpy (fmt, svg_format, sizeof fmt);
4ab27a43
GM
8156
8157 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
8158 return 0;
8159
8160 /* Must specify either the :data or :file keyword. */
8161 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
8162}
8163
8164#include <librsvg/rsvg.h>
8165
0fda9b75 8166#ifdef WINDOWSNT
5fc9fdeb
JR
8167
8168/* SVG library functions. */
df61c790
AS
8169DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new);
8170DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
8171DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
8172DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
8173DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
df61c790
AS
8174
8175DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
8176DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
8177DEF_IMGLIB_FN (guchar *, gdk_pixbuf_get_pixels);
8178DEF_IMGLIB_FN (int, gdk_pixbuf_get_rowstride);
8179DEF_IMGLIB_FN (GdkColorspace, gdk_pixbuf_get_colorspace);
8180DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels);
8181DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha);
8182DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample);
8183
8184DEF_IMGLIB_FN (void, g_type_init);
8185DEF_IMGLIB_FN (void, g_object_unref);
8186DEF_IMGLIB_FN (void, g_error_free);
5fc9fdeb 8187
df23bf08 8188Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
5fc9fdeb 8189
578098f3 8190static bool
d07ff9db 8191init_svg_functions (void)
5fc9fdeb 8192{
df23bf08 8193 HMODULE library, gdklib, glib, gobject;
5fc9fdeb 8194
d07ff9db
CY
8195 if (!(glib = w32_delayed_load (Qglib))
8196 || !(gobject = w32_delayed_load (Qgobject))
8197 || !(gdklib = w32_delayed_load (Qgdk_pixbuf))
8198 || !(library = w32_delayed_load (Qsvg)))
5fc9fdeb
JR
8199 return 0;
8200
8201 LOAD_IMGLIB_FN (library, rsvg_handle_new);
e025c9c2 8202 LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
5fc9fdeb
JR
8203 LOAD_IMGLIB_FN (library, rsvg_handle_write);
8204 LOAD_IMGLIB_FN (library, rsvg_handle_close);
8205 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
5fc9fdeb
JR
8206
8207 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
8208 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
8209 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
8210 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
8211 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
8212 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
8213 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
8214 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
8215
df23bf08
JR
8216 LOAD_IMGLIB_FN (gobject, g_type_init);
8217 LOAD_IMGLIB_FN (gobject, g_object_unref);
5fc9fdeb 8218 LOAD_IMGLIB_FN (glib, g_error_free);
df23bf08 8219
5fc9fdeb
JR
8220 return 1;
8221}
4ab27a43 8222
5fc9fdeb
JR
8223#else
8224/* The following aliases for library functions allow dynamic loading
8225 to be used on some platforms. */
4ab27a43 8226#define fn_rsvg_handle_new rsvg_handle_new
e025c9c2 8227#define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
4ab27a43
GM
8228#define fn_rsvg_handle_write rsvg_handle_write
8229#define fn_rsvg_handle_close rsvg_handle_close
8230#define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
4ab27a43 8231
5fc9fdeb
JR
8232#define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8233#define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8234#define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8235#define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8236#define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8237#define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8238#define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
4ab27a43
GM
8239#define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8240
5fc9fdeb
JR
8241#define fn_g_type_init g_type_init
8242#define fn_g_object_unref g_object_unref
8243#define fn_g_error_free g_error_free
0fda9b75 8244#endif /* !WINDOWSNT */
4ab27a43 8245
578098f3
PE
8246/* Load SVG image IMG for use on frame F. Value is true if
8247 successful. */
4ab27a43 8248
578098f3 8249static bool
d3da34e0 8250svg_load (struct frame *f, struct image *img)
4ab27a43 8251{
578098f3 8252 bool success_p = 0;
4ab27a43
GM
8253 Lisp_Object file_name;
8254
8255 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8256 file_name = image_spec_value (img->spec, QCfile, NULL);
8257 if (STRINGP (file_name))
8258 {
8259 Lisp_Object file;
8260 unsigned char *contents;
dd52fcea 8261 ptrdiff_t size;
4ab27a43
GM
8262
8263 file = x_find_image_file (file_name);
4ab27a43 8264 if (!STRINGP (file))
c21e6151
YM
8265 {
8266 image_error ("Cannot find image file `%s'", file_name, Qnil);
c21e6151
YM
8267 return 0;
8268 }
8269
4ab27a43 8270 /* Read the entire file into memory. */
33290528 8271 contents = slurp_file (SSDATA (file), &size);
4ab27a43 8272 if (contents == NULL)
c21e6151
YM
8273 {
8274 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
c21e6151
YM
8275 return 0;
8276 }
4ab27a43 8277 /* If the file was slurped into memory properly, parse it. */
c21e6151 8278 success_p = svg_load_image (f, img, contents, size);
4ab27a43 8279 xfree (contents);
4ab27a43
GM
8280 }
8281 /* Else its not a file, its a lisp object. Load the image from a
8282 lisp object rather than a file. */
8283 else
8284 {
8285 Lisp_Object data;
8286
8287 data = image_spec_value (img->spec, QCdata, NULL);
7574650a
AS
8288 if (!STRINGP (data))
8289 {
8290 image_error ("Invalid image data `%s'", data, Qnil);
8291 return 0;
8292 }
4ab27a43
GM
8293 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
8294 }
8295
8296 return success_p;
8297}
8298
bbe6f2aa
JB
8299/* svg_load_image is a helper function for svg_load, which does the
8300 actual loading given contents and size, apart from frame and image
8301 structures, passed from svg_load.
4ab27a43 8302
bbe6f2aa 8303 Uses librsvg to do most of the image processing.
c21e6151 8304
578098f3
PE
8305 Returns true when successful. */
8306static bool
d3da34e0
JB
8307svg_load_image (struct frame *f, /* Pointer to emacs frame structure. */
8308 struct image *img, /* Pointer to emacs image structure. */
8309 unsigned char *contents, /* String containing the SVG XML data to be parsed. */
dd52fcea 8310 ptrdiff_t size) /* Size of data in bytes. */
4ab27a43
GM
8311{
8312 RsvgHandle *rsvg_handle;
e025c9c2 8313 RsvgDimensionData dimension_data;
33290528 8314 GError *err = NULL;
4ab27a43
GM
8315 GdkPixbuf *pixbuf;
8316 int width;
8317 int height;
8318 const guint8 *pixels;
8319 int rowstride;
8320 XImagePtr ximg;
c21e6151 8321 Lisp_Object specified_bg;
4ab27a43
GM
8322 XColor background;
8323 int x;
8324 int y;
8325
8326 /* g_type_init is a glib function that must be called prior to using
8327 gnome type library functions. */
5fc9fdeb 8328 fn_g_type_init ();
4ab27a43 8329 /* Make a handle to a new rsvg object. */
df61c790 8330 rsvg_handle = fn_rsvg_handle_new ();
4ab27a43
GM
8331
8332 /* Parse the contents argument and fill in the rsvg_handle. */
33290528
PE
8333 fn_rsvg_handle_write (rsvg_handle, contents, size, &err);
8334 if (err) goto rsvg_error;
4ab27a43
GM
8335
8336 /* The parsing is complete, rsvg_handle is ready to used, close it
8337 for further writes. */
33290528
PE
8338 fn_rsvg_handle_close (rsvg_handle, &err);
8339 if (err) goto rsvg_error;
e025c9c2
CY
8340
8341 fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
8342 if (! check_image_size (f, dimension_data.width, dimension_data.height))
10ea2b82
JR
8343 {
8344 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
8345 goto rsvg_error;
8346 }
b2996e57 8347
4ab27a43
GM
8348 /* We can now get a valid pixel buffer from the svg file, if all
8349 went ok. */
df61c790 8350 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
e025c9c2
CY
8351 if (!pixbuf) goto rsvg_error;
8352 fn_g_object_unref (rsvg_handle);
4ab27a43
GM
8353
8354 /* Extract some meta data from the svg handle. */
8355 width = fn_gdk_pixbuf_get_width (pixbuf);
8356 height = fn_gdk_pixbuf_get_height (pixbuf);
df61c790 8357 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
4ab27a43
GM
8358 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
8359
8360 /* Validate the svg meta data. */
8361 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
8362 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
8363 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
8364 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8365
8366 /* Try to create a x pixmap to hold the svg pixmap. */
c21e6151
YM
8367 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8368 {
5fc9fdeb 8369 fn_g_object_unref (pixbuf);
c21e6151
YM
8370 return 0;
8371 }
4ab27a43
GM
8372
8373 init_color_table ();
8374
c21e6151
YM
8375 /* Handle alpha channel by combining the image with a background
8376 color. */
8377 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8d3c4e79 8378 if (!STRINGP (specified_bg)
33290528 8379 || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
c21e6151 8380 {
d7e008d0 8381#ifndef HAVE_NS
c21e6151
YM
8382 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8383 x_query_color (f, &background);
d7e008d0 8384#else
ed3751c8 8385 ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1);
d7e008d0 8386#endif
c21e6151 8387 }
4ab27a43 8388
8d3c4e79
CY
8389 /* SVG pixmaps specify transparency in the last byte, so right
8390 shift 8 bits to get rid of it, since emacs doesn't support
8391 transparency. */
8392 background.red >>= 8;
8393 background.green >>= 8;
8394 background.blue >>= 8;
8395
4ab27a43
GM
8396 /* This loop handles opacity values, since Emacs assumes
8397 non-transparent images. Each pixel must be "flattened" by
bbe6f2aa
JB
8398 calculating the resulting color, given the transparency of the
8399 pixel, and the image background color. */
4ab27a43
GM
8400 for (y = 0; y < height; ++y)
8401 {
8402 for (x = 0; x < width; ++x)
8403 {
13464394
PE
8404 int red;
8405 int green;
8406 int blue;
8407 int opacity;
4ab27a43
GM
8408
8409 red = *pixels++;
8410 green = *pixels++;
8411 blue = *pixels++;
8412 opacity = *pixels++;
8413
8414 red = ((red * opacity)
8415 + (background.red * ((1 << 8) - opacity)));
8416 green = ((green * opacity)
8417 + (background.green * ((1 << 8) - opacity)));
8418 blue = ((blue * opacity)
8419 + (background.blue * ((1 << 8) - opacity)));
8420
8421 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
8422 }
8423
8424 pixels += rowstride - 4 * width;
8425 }
8426
8427#ifdef COLOR_TABLE_SUPPORT
8428 /* Remember colors allocated for this image. */
8429 img->colors = colors_in_color_table (&img->ncolors);
8430 free_color_table ();
8431#endif /* COLOR_TABLE_SUPPORT */
8432
5fc9fdeb 8433 fn_g_object_unref (pixbuf);
4ab27a43 8434
c21e6151
YM
8435 img->width = width;
8436 img->height = height;
8437
8438 /* Maybe fill in the background field while we have ximg handy.
8439 Casting avoids a GCC warning. */
8440 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8441
4ab27a43
GM
8442 /* Put the image into the pixmap, then free the X image and its
8443 buffer. */
8444 x_put_x_image (f, ximg, img->pixmap, width, height);
8445 x_destroy_x_image (ximg);
8446
4ab27a43
GM
8447 return 1;
8448
8449 rsvg_error:
e025c9c2 8450 fn_g_object_unref (rsvg_handle);
4ab27a43
GM
8451 /* FIXME: Use error->message so the user knows what is the actual
8452 problem with the image. */
8453 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
33290528 8454 fn_g_error_free (err);
4ab27a43
GM
8455 return 0;
8456}
8457
8458#endif /* defined (HAVE_RSVG) */
8459
8460
8461
4ef0d4d0
KS
8462\f
8463/***********************************************************************
8464 Ghostscript
8465 ***********************************************************************/
8466
8467#ifdef HAVE_X_WINDOWS
8468#define HAVE_GHOSTSCRIPT 1
8469#endif /* HAVE_X_WINDOWS */
8470
4ef0d4d0
KS
8471#ifdef HAVE_GHOSTSCRIPT
8472
578098f3
PE
8473static bool gs_image_p (Lisp_Object object);
8474static bool gs_load (struct frame *f, struct image *img);
f57e2426 8475static void gs_clear_image (struct frame *f, struct image *img);
4ef0d4d0
KS
8476
8477/* Keyword symbols. */
8478
955cbe7b 8479static Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
4ef0d4d0
KS
8480
8481/* Indices of image specification fields in gs_format, below. */
8482
8483enum gs_keyword_index
8484{
8485 GS_TYPE,
8486 GS_PT_WIDTH,
8487 GS_PT_HEIGHT,
8488 GS_FILE,
8489 GS_LOADER,
8490 GS_BOUNDING_BOX,
8491 GS_ASCENT,
8492 GS_MARGIN,
8493 GS_RELIEF,
8494 GS_ALGORITHM,
8495 GS_HEURISTIC_MASK,
8496 GS_MASK,
8497 GS_BACKGROUND,
8498 GS_LAST
8499};
8500
8501/* Vector of image_keyword structures describing the format
8502 of valid user-defined image specifications. */
8503
91433552 8504static const struct image_keyword gs_format[GS_LAST] =
4ef0d4d0
KS
8505{
8506 {":type", IMAGE_SYMBOL_VALUE, 1},
8507 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8508 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8509 {":file", IMAGE_STRING_VALUE, 1},
8510 {":loader", IMAGE_FUNCTION_VALUE, 0},
8511 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8512 {":ascent", IMAGE_ASCENT_VALUE, 0},
c4a07a4c 8513 {":margin", IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
4ef0d4d0
KS
8514 {":relief", IMAGE_INTEGER_VALUE, 0},
8515 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8516 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8517 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8518 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8519};
8520
8521/* Structure describing the image type `ghostscript'. */
8522
8523static struct image_type gs_type =
8524{
8525 &Qpostscript,
8526 gs_image_p,
8527 gs_load,
8528 gs_clear_image,
d07ff9db 8529 NULL,
4ef0d4d0
KS
8530 NULL
8531};
8532
8533
8534/* Free X resources of Ghostscript image IMG which is used on frame F. */
8535
8536static void
d3da34e0 8537gs_clear_image (struct frame *f, struct image *img)
4ef0d4d0 8538{
4ef0d4d0
KS
8539 x_clear_image (f, img);
8540}
8541
8542
578098f3 8543/* Return true if OBJECT is a valid Ghostscript image
4ef0d4d0
KS
8544 specification. */
8545
578098f3 8546static bool
d3da34e0 8547gs_image_p (Lisp_Object object)
4ef0d4d0
KS
8548{
8549 struct image_keyword fmt[GS_LAST];
8550 Lisp_Object tem;
8551 int i;
8552
72af86bd 8553 memcpy (fmt, gs_format, sizeof fmt);
4ef0d4d0
KS
8554
8555 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8556 return 0;
8557
8558 /* Bounding box must be a list or vector containing 4 integers. */
8559 tem = fmt[GS_BOUNDING_BOX].value;
8560 if (CONSP (tem))
8561 {
8562 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8563 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8564 return 0;
8565 if (!NILP (tem))
8566 return 0;
8567 }
8568 else if (VECTORP (tem))
8569 {
77b37c05 8570 if (ASIZE (tem) != 4)
4ef0d4d0
KS
8571 return 0;
8572 for (i = 0; i < 4; ++i)
28be1ada 8573 if (!INTEGERP (AREF (tem, i)))
4ef0d4d0
KS
8574 return 0;
8575 }
8576 else
8577 return 0;
8578
8579 return 1;
8580}
8581
8582
578098f3 8583/* Load Ghostscript image IMG for use on frame F. Value is true
4ef0d4d0
KS
8584 if successful. */
8585
578098f3 8586static bool
d3da34e0 8587gs_load (struct frame *f, struct image *img)
4ef0d4d0 8588{
13464394
PE
8589 uprintmax_t printnum1, printnum2;
8590 char buffer[sizeof " " + INT_STRLEN_BOUND (printmax_t)];
4ef0d4d0 8591 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
4ef0d4d0
KS
8592 Lisp_Object frame;
8593 double in_width, in_height;
8594 Lisp_Object pixel_colors = Qnil;
8595
8596 /* Compute pixel size of pixmap needed from the given size in the
8597 image specification. Sizes in the specification are in pt. 1 pt
8598 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8599 info. */
8600 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7574650a 8601 in_width = INTEGERP (pt_width) ? XFASTINT (pt_width) / 72.0 : 0;
13464394 8602 in_width *= FRAME_X_DISPLAY_INFO (f)->resx;
4ef0d4d0 8603 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7574650a 8604 in_height = INTEGERP (pt_height) ? XFASTINT (pt_height) / 72.0 : 0;
13464394 8605 in_height *= FRAME_X_DISPLAY_INFO (f)->resy;
4ef0d4d0 8606
13464394
PE
8607 if (! (in_width <= INT_MAX && in_height <= INT_MAX
8608 && check_image_size (f, in_width, in_height)))
f1f25b99 8609 {
10ea2b82 8610 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
f1f25b99
CY
8611 return 0;
8612 }
13464394
PE
8613 img->width = in_width;
8614 img->height = in_height;
f1f25b99 8615
4ef0d4d0 8616 /* Create the pixmap. */
a54e2c05 8617 eassert (img->pixmap == NO_PIXMAP);
4ef0d4d0 8618
ca4aa935
PE
8619 if (x_check_image_size (0, img->width, img->height))
8620 {
8621 /* Only W32 version did BLOCK_INPUT here. ++kfs */
4d7e6e51 8622 block_input ();
ca4aa935
PE
8623 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8624 img->width, img->height,
8625 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
4d7e6e51 8626 unblock_input ();
ca4aa935 8627 }
4ef0d4d0
KS
8628
8629 if (!img->pixmap)
8630 {
8631 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8632 return 0;
8633 }
8634
8635 /* Call the loader to fill the pixmap. It returns a process object
8636 if successful. We do not record_unwind_protect here because
8637 other places in redisplay like calling window scroll functions
8638 don't either. Let the Lisp loader use `unwind-protect' instead. */
13464394
PE
8639 printnum1 = FRAME_X_WINDOW (f);
8640 printnum2 = img->pixmap;
620f13b0 8641 window_and_pixmap_id
a8290ec3 8642 = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
4ef0d4d0 8643
13464394
PE
8644 printnum1 = FRAME_FOREGROUND_PIXEL (f);
8645 printnum2 = FRAME_BACKGROUND_PIXEL (f);
a8290ec3
DA
8646 pixel_colors
8647 = make_formatted_string (buffer, "%"pMu" %"pMu, printnum1, printnum2);
4ef0d4d0
KS
8648
8649 XSETFRAME (frame, f);
8650 loader = image_spec_value (img->spec, QCloader, NULL);
8651 if (NILP (loader))
8652 loader = intern ("gs-load-image");
8653
b50691aa
CY
8654 img->lisp_data = call6 (loader, frame, img->spec,
8655 make_number (img->width),
8656 make_number (img->height),
8657 window_and_pixmap_id,
8658 pixel_colors);
8659 return PROCESSP (img->lisp_data);
4ef0d4d0
KS
8660}
8661
8662
8663/* Kill the Ghostscript process that was started to fill PIXMAP on
8664 frame F. Called from XTread_socket when receiving an event
8665 telling Emacs that Ghostscript has finished drawing. */
8666
8667void
d3da34e0 8668x_kill_gs_process (Pixmap pixmap, struct frame *f)
4ef0d4d0 8669{
354884c4 8670 struct image_cache *c = FRAME_IMAGE_CACHE (f);
13464394
PE
8671 int class;
8672 ptrdiff_t i;
4ef0d4d0
KS
8673 struct image *img;
8674
8675 /* Find the image containing PIXMAP. */
8676 for (i = 0; i < c->used; ++i)
8677 if (c->images[i]->pixmap == pixmap)
8678 break;
8679
8680 /* Should someone in between have cleared the image cache, for
8681 instance, give up. */
8682 if (i == c->used)
8683 return;
8684
8685 /* Kill the GS process. We should have found PIXMAP in the image
8686 cache and its image should contain a process object. */
8687 img = c->images[i];
a54e2c05 8688 eassert (PROCESSP (img->lisp_data));
b50691aa
CY
8689 Fkill_process (img->lisp_data, Qnil);
8690 img->lisp_data = Qnil;
4ef0d4d0
KS
8691
8692#if defined (HAVE_X_WINDOWS)
8693
8694 /* On displays with a mutable colormap, figure out the colors
8695 allocated for the image by looking at the pixels of an XImage for
8696 img->pixmap. */
8697 class = FRAME_X_VISUAL (f)->class;
8698 if (class != StaticColor && class != StaticGray && class != TrueColor)
8699 {
8700 XImagePtr ximg;
8701
4d7e6e51 8702 block_input ();
4ef0d4d0
KS
8703
8704 /* Try to get an XImage for img->pixmep. */
8705 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8706 0, 0, img->width, img->height, ~0, ZPixmap);
8707 if (ximg)
8708 {
8709 int x, y;
8710
8711 /* Initialize the color table. */
8712 init_color_table ();
8713
8714 /* For each pixel of the image, look its color up in the
8715 color table. After having done so, the color table will
8716 contain an entry for each color used by the image. */
8717 for (y = 0; y < img->height; ++y)
8718 for (x = 0; x < img->width; ++x)
8719 {
8720 unsigned long pixel = XGetPixel (ximg, x, y);
8721 lookup_pixel_color (f, pixel);
8722 }
8723
8724 /* Record colors in the image. Free color table and XImage. */
8725#ifdef COLOR_TABLE_SUPPORT
8726 img->colors = colors_in_color_table (&img->ncolors);
8727 free_color_table ();
8728#endif
8729 XDestroyImage (ximg);
8730
8731#if 0 /* This doesn't seem to be the case. If we free the colors
8732 here, we get a BadAccess later in x_clear_image when
8733 freeing the colors. */
8734 /* We have allocated colors once, but Ghostscript has also
8735 allocated colors on behalf of us. So, to get the
8736 reference counts right, free them once. */
8737 if (img->ncolors)
8738 x_free_colors (f, img->colors, img->ncolors);
8739#endif
8740 }
8741 else
8742 image_error ("Cannot get X image of `%s'; colors will not be freed",
8743 img->spec, Qnil);
8744
4d7e6e51 8745 unblock_input ();
4ef0d4d0
KS
8746 }
8747#endif /* HAVE_X_WINDOWS */
8748
8749 /* Now that we have the pixmap, compute mask and transform the
8750 image if requested. */
4d7e6e51 8751 block_input ();
4ef0d4d0 8752 postprocess_image (f, img);
4d7e6e51 8753 unblock_input ();
4ef0d4d0
KS
8754}
8755
8756#endif /* HAVE_GHOSTSCRIPT */
8757
8758\f
8759/***********************************************************************
8760 Tests
8761 ***********************************************************************/
8762
e509cfa6 8763#ifdef GLYPH_DEBUG
4ef0d4d0 8764
a7ca3326 8765DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
4ef0d4d0 8766 doc: /* Value is non-nil if SPEC is a valid image specification. */)
5842a27b 8767 (Lisp_Object spec)
4ef0d4d0
KS
8768{
8769 return valid_image_p (spec) ? Qt : Qnil;
8770}
8771
8772
a7ca3326 8773DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
5842a27b 8774 (Lisp_Object spec)
4ef0d4d0 8775{
13464394 8776 ptrdiff_t id = -1;
4ef0d4d0
KS
8777
8778 if (valid_image_p (spec))
8779 id = lookup_image (SELECTED_FRAME (), spec);
8780
8781 debug_print (spec);
8782 return make_number (id);
8783}
8784
e509cfa6 8785#endif /* GLYPH_DEBUG */
4ef0d4d0
KS
8786
8787
8788/***********************************************************************
8789 Initialization
8790 ***********************************************************************/
8791
d07ff9db 8792DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0,
0855eb52
JB
8793 doc: /* Initialize image library implementing image type TYPE.
8794Return non-nil if TYPE is a supported image type.
8795
d07ff9db
CY
8796If image libraries are loaded dynamically (currently only the case on
8797MS-Windows), load the library for TYPE if it is not yet loaded, using
8798the library file(s) specified by `dynamic-library-alist'. */)
8799 (Lisp_Object type)
0855eb52 8800{
d07ff9db 8801 return lookup_image_type (type) ? Qt : Qnil;
bb4d86b4 8802}
0855eb52 8803
bb4d86b4 8804/* Look up image type TYPE, and return a pointer to its image_type
d07ff9db 8805 structure. Return 0 if TYPE is not a known image type. */
bb4d86b4
CY
8806
8807static struct image_type *
d07ff9db 8808lookup_image_type (Lisp_Object type)
bb4d86b4 8809{
2f142cc5 8810 /* Types pbm and xbm are built-in and always available. */
bb4d86b4 8811 if (EQ (type, Qpbm))
d07ff9db 8812 return define_image_type (&pbm_type);
bb4d86b4
CY
8813
8814 if (EQ (type, Qxbm))
d07ff9db 8815 return define_image_type (&xbm_type);
2f142cc5 8816
9e2a2647 8817#if defined (HAVE_XPM) || defined (HAVE_NS)
0855eb52 8818 if (EQ (type, Qxpm))
d07ff9db 8819 return define_image_type (&xpm_type);
0855eb52
JB
8820#endif
8821
9e2a2647 8822#if defined (HAVE_JPEG) || defined (HAVE_NS)
0855eb52 8823 if (EQ (type, Qjpeg))
d07ff9db 8824 return define_image_type (&jpeg_type);
0855eb52
JB
8825#endif
8826
9e2a2647 8827#if defined (HAVE_TIFF) || defined (HAVE_NS)
0855eb52 8828 if (EQ (type, Qtiff))
d07ff9db 8829 return define_image_type (&tiff_type);
0855eb52
JB
8830#endif
8831
9e2a2647 8832#if defined (HAVE_GIF) || defined (HAVE_NS)
0855eb52 8833 if (EQ (type, Qgif))
d07ff9db 8834 return define_image_type (&gif_type);
0855eb52
JB
8835#endif
8836
9e2a2647 8837#if defined (HAVE_PNG) || defined (HAVE_NS)
0855eb52 8838 if (EQ (type, Qpng))
d07ff9db 8839 return define_image_type (&png_type);
0855eb52
JB
8840#endif
8841
4ab27a43
GM
8842#if defined (HAVE_RSVG)
8843 if (EQ (type, Qsvg))
d07ff9db 8844 return define_image_type (&svg_type);
4ab27a43 8845#endif
c21e6151 8846
3de25479 8847#if defined (HAVE_IMAGEMAGICK)
7574650a 8848 if (EQ (type, Qimagemagick))
d07ff9db 8849 return define_image_type (&imagemagick_type);
3de25479
JV
8850#endif
8851
0855eb52
JB
8852#ifdef HAVE_GHOSTSCRIPT
8853 if (EQ (type, Qpostscript))
d07ff9db 8854 return define_image_type (&gs_type);
0855eb52
JB
8855#endif
8856
bb4d86b4 8857 return NULL;
0855eb52
JB
8858}
8859
aa15c6bb
JB
8860/* Reset image_types before dumping.
8861 Called from Fdump_emacs. */
8862
8863void
8864reset_image_types (void)
8865{
8866 while (image_types)
8867 {
8868 struct image_type *next = image_types->next;
8869 xfree (image_types);
8870 image_types = next;
8871 }
0855eb52
JB
8872}
8873
4ef0d4d0 8874void
d3da34e0 8875syms_of_image (void)
4ef0d4d0 8876{
aa15c6bb 8877 /* Initialize this only once; it will be reset before dumping. */
6e6fc3fd
RS
8878 image_types = NULL;
8879
91af3942 8880 /* Must be defined now because we're going to update it below, while
0855eb52 8881 defining the supported image types. */
29208e82 8882 DEFVAR_LISP ("image-types", Vimage_types,
0855eb52 8883 doc: /* List of potentially supported image types.
bbe6f2aa 8884Each element of the list is a symbol for an image type, like 'jpeg or 'png.
0855eb52
JB
8885To check whether it is really supported, use `image-type-available-p'. */);
8886 Vimage_types = Qnil;
8887
29208e82 8888 DEFVAR_LISP ("max-image-size", Vmax_image_size,
7df4765a
KS
8889 doc: /* Maximum size of images.
8890Emacs will not load an image into memory if its pixel width or
8891pixel height exceeds this limit.
8892
8893If the value is an integer, it directly specifies the maximum
8894image height and width, measured in pixels. If it is a floating
8895point number, it specifies the maximum image height and width
8896as a ratio to the frame height and width. If the value is
8897non-numeric, there is no explicit limit on the size of images. */);
f1f25b99
CY
8898 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8899
1100a63c
CY
8900 DEFSYM (Qcount, "count");
8901 DEFSYM (Qextension_data, "extension-data");
8902 DEFSYM (Qdelay, "delay");
8903
8904 DEFSYM (QCascent, ":ascent");
8905 DEFSYM (QCmargin, ":margin");
8906 DEFSYM (QCrelief, ":relief");
8907 DEFSYM (QCconversion, ":conversion");
8908 DEFSYM (QCcolor_symbols, ":color-symbols");
8909 DEFSYM (QCheuristic_mask, ":heuristic-mask");
8910 DEFSYM (QCindex, ":index");
8911 DEFSYM (QCgeometry, ":geometry");
8912 DEFSYM (QCcrop, ":crop");
8913 DEFSYM (QCrotation, ":rotation");
8914 DEFSYM (QCmatrix, ":matrix");
8915 DEFSYM (QCcolor_adjustment, ":color-adjustment");
8916 DEFSYM (QCmask, ":mask");
8917
8918 DEFSYM (Qlaplace, "laplace");
8919 DEFSYM (Qemboss, "emboss");
8920 DEFSYM (Qedge_detection, "edge-detection");
8921 DEFSYM (Qheuristic, "heuristic");
8922
8923 DEFSYM (Qpostscript, "postscript");
4ef0d4d0 8924#ifdef HAVE_GHOSTSCRIPT
5fc9fdeb 8925 ADD_IMAGE_TYPE (Qpostscript);
1100a63c
CY
8926 DEFSYM (QCloader, ":loader");
8927 DEFSYM (QCbounding_box, ":bounding-box");
8928 DEFSYM (QCpt_width, ":pt-width");
8929 DEFSYM (QCpt_height, ":pt-height");
4ef0d4d0
KS
8930#endif /* HAVE_GHOSTSCRIPT */
8931
5be1c984 8932#ifdef HAVE_NTGUI
1100a63c 8933 DEFSYM (Qlibpng_version, "libpng-version");
0514b4be 8934 Fset (Qlibpng_version,
5be1c984 8935#if HAVE_PNG
0514b4be 8936 make_number (PNG_LIBPNG_VER)
5be1c984 8937#else
0514b4be 8938 make_number (-1)
5be1c984 8939#endif
0514b4be 8940 );
5be1c984
EZ
8941#endif
8942
bb4d86b4
CY
8943 DEFSYM (Qpbm, "pbm");
8944 ADD_IMAGE_TYPE (Qpbm);
8945
8946 DEFSYM (Qxbm, "xbm");
8947 ADD_IMAGE_TYPE (Qxbm);
8948
9e2a2647 8949#if defined (HAVE_XPM) || defined (HAVE_NS)
1100a63c 8950 DEFSYM (Qxpm, "xpm");
5fc9fdeb 8951 ADD_IMAGE_TYPE (Qxpm);
4ef0d4d0
KS
8952#endif
8953
9e2a2647 8954#if defined (HAVE_JPEG) || defined (HAVE_NS)
1100a63c 8955 DEFSYM (Qjpeg, "jpeg");
5fc9fdeb 8956 ADD_IMAGE_TYPE (Qjpeg);
4ef0d4d0
KS
8957#endif
8958
9e2a2647 8959#if defined (HAVE_TIFF) || defined (HAVE_NS)
1100a63c 8960 DEFSYM (Qtiff, "tiff");
5fc9fdeb 8961 ADD_IMAGE_TYPE (Qtiff);
4ef0d4d0
KS
8962#endif
8963
9e2a2647 8964#if defined (HAVE_GIF) || defined (HAVE_NS)
1100a63c 8965 DEFSYM (Qgif, "gif");
5fc9fdeb 8966 ADD_IMAGE_TYPE (Qgif);
4ef0d4d0
KS
8967#endif
8968
9e2a2647 8969#if defined (HAVE_PNG) || defined (HAVE_NS)
1100a63c 8970 DEFSYM (Qpng, "png");
5fc9fdeb 8971 ADD_IMAGE_TYPE (Qpng);
4ef0d4d0
KS
8972#endif
8973
3de25479 8974#if defined (HAVE_IMAGEMAGICK)
1100a63c 8975 DEFSYM (Qimagemagick, "imagemagick");
3de25479
JV
8976 ADD_IMAGE_TYPE (Qimagemagick);
8977#endif
7574650a 8978
4ab27a43 8979#if defined (HAVE_RSVG)
1100a63c 8980 DEFSYM (Qsvg, "svg");
5fc9fdeb
JR
8981 ADD_IMAGE_TYPE (Qsvg);
8982#ifdef HAVE_NTGUI
df23bf08 8983 /* Other libraries used directly by svg code. */
1100a63c
CY
8984 DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
8985 DEFSYM (Qglib, "glib");
8986 DEFSYM (Qgobject, "gobject");
5fc9fdeb
JR
8987#endif /* HAVE_NTGUI */
8988#endif /* HAVE_RSVG */
4ab27a43 8989
0855eb52 8990 defsubr (&Sinit_image_library);
7574650a 8991#ifdef HAVE_IMAGEMAGICK
3de25479 8992 defsubr (&Simagemagick_types);
7574650a 8993#endif
4ef0d4d0 8994 defsubr (&Sclear_image_cache);
110683ad 8995 defsubr (&Simage_flush);
4ef0d4d0
KS
8996 defsubr (&Simage_size);
8997 defsubr (&Simage_mask_p);
1546c559 8998 defsubr (&Simage_metadata);
4ef0d4d0 8999
e509cfa6 9000#ifdef GLYPH_DEBUG
4ef0d4d0
KS
9001 defsubr (&Simagep);
9002 defsubr (&Slookup_image);
9003#endif
9004
29208e82 9005 DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
4ef0d4d0 9006 doc: /* Non-nil means always draw a cross over disabled images.
3046a84b 9007Disabled images are those having a `:conversion disabled' property.
4ef0d4d0
KS
9008A cross is always drawn on black & white displays. */);
9009 cross_disabled_images = 0;
9010
29208e82 9011 DEFVAR_LISP ("x-bitmap-file-path", Vx_bitmap_file_path,
4ef0d4d0
KS
9012 doc: /* List of directories to search for window system bitmap files. */);
9013 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
9014
29208e82 9015 DEFVAR_LISP ("image-cache-eviction-delay", Vimage_cache_eviction_delay,
98fe5161
CY
9016 doc: /* Maximum time after which images are removed from the cache.
9017When an image has not been displayed this many seconds, Emacs
9018automatically removes it from the image cache. If the cache contains
9019a large number of images, the actual eviction time may be shorter.
9020The value can also be nil, meaning the cache is never cleared.
9021
9022The function `clear-image-cache' disregards this variable. */);
9023 Vimage_cache_eviction_delay = make_number (300);
7574650a 9024#ifdef HAVE_IMAGEMAGICK
af008560
GM
9025 DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type,
9026 doc: /* Integer indicating which ImageMagick rendering method to use.
9027The options are:
9028 0 -- the default method (pixel pushing)
9029 1 -- a newer method ("MagickExportImagePixels") that may perform
9030 better (speed etc) in some cases, but has not been as thoroughly
9031 tested with Emacs as the default method. This method requires
9032 ImageMagick version 6.4.6 (approximately) or later.
9033*/);
9034 /* MagickExportImagePixels is in 6.4.6-9, but not 6.4.4-10. */
9035 imagemagick_render_type = 0;
7574650a 9036#endif
4ef0d4d0 9037
4ef0d4d0 9038}