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