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