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