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