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