* customize.texi (Composite Types): Move alist/plist from Simple Types (Bug#7545).
[emacs.git] / src / image.c
blob5a1be6e4747f5eed5f48593f2f15e3fea7007092
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ctype.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 #ifdef HAVE_PNG
31 #if defined HAVE_LIBPNG_PNG_H
32 # include <libpng/png.h>
33 #else
34 # include <png.h>
35 #endif
36 #endif
38 #include <setjmp.h>
40 /* This makes the fields of a Display accessible, in Xlib header files. */
42 #define XLIB_ILLEGAL_ACCESS
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>
51 #include "character.h"
52 #include "coding.h"
53 #include "termhooks.h"
54 #include "font.h"
56 #ifdef HAVE_X_WINDOWS
57 #include "xterm.h"
58 #include <sys/types.h>
59 #include <sys/stat.h>
61 #define COLOR_TABLE_SUPPORT 1
63 typedef struct x_bitmap_record Bitmap_Record;
64 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
65 #define NO_PIXMAP None
67 #define RGB_PIXEL_COLOR unsigned long
69 #define PIX_MASK_RETAIN 0
70 #define PIX_MASK_DRAW 1
71 #endif /* HAVE_X_WINDOWS */
74 #ifdef HAVE_NTGUI
75 #include "w32term.h"
77 /* W32_TODO : Color tables on W32. */
78 #undef COLOR_TABLE_SUPPORT
80 typedef struct w32_bitmap_record Bitmap_Record;
81 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
82 #define NO_PIXMAP 0
84 #define RGB_PIXEL_COLOR COLORREF
86 #define PIX_MASK_RETAIN 0
87 #define PIX_MASK_DRAW 1
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)
93 /* Functions from w32term.c that depend on XColor (so can't go in w32term.h
94 without modifying lots of files). */
95 extern void x_query_colors (struct frame *f, XColor *colors, int ncolors);
96 extern void x_query_color (struct frame *f, XColor *color);
98 /* Version of libpng that we were compiled with, or -1 if no PNG
99 support was compiled in. This is tested by w32-win.el to correctly
100 set up the alist used to search for PNG libraries. */
101 Lisp_Object Qlibpng_version;
102 #endif /* HAVE_NTGUI */
104 #ifdef HAVE_NS
105 #include "nsterm.h"
106 #include <sys/types.h>
107 #include <sys/stat.h>
109 #undef COLOR_TABLE_SUPPORT
111 typedef struct ns_bitmap_record Bitmap_Record;
113 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
114 #define NO_PIXMAP 0
116 #define RGB_PIXEL_COLOR unsigned long
117 #define ZPixmap 0
119 #define PIX_MASK_RETAIN 0
120 #define PIX_MASK_DRAW 1
122 #define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
123 #define x_defined_color(f, name, color_def, alloc) \
124 ns_defined_color (f, name, color_def, alloc, 0)
125 #define FRAME_X_SCREEN(f) 0
126 #define DefaultDepthOfScreen(screen) x_display_list->n_planes
127 #endif /* HAVE_NS */
130 /* Search path for bitmap files. */
132 Lisp_Object Vx_bitmap_file_path;
135 static void x_disable_image P_ ((struct frame *, struct image *));
136 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
137 Lisp_Object));
139 static void init_color_table P_ ((void));
140 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
141 #ifdef COLOR_TABLE_SUPPORT
142 static void free_color_table P_ ((void));
143 static unsigned long *colors_in_color_table P_ ((int *n));
144 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
145 #endif
147 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
148 id, which is just an int that this section returns. Bitmaps are
149 reference counted so they can be shared among frames.
151 Bitmap indices are guaranteed to be > 0, so a negative number can
152 be used to indicate no bitmap.
154 If you use x_create_bitmap_from_data, then you must keep track of
155 the bitmaps yourself. That is, creating a bitmap from the same
156 data more than once will not be caught. */
158 #ifdef HAVE_NS
159 XImagePtr
160 XGetImage (Display *display, Pixmap pixmap, int x, int y,
161 unsigned int width, unsigned int height,
162 unsigned long plane_mask, int format)
164 /* TODO: not sure what this function is supposed to do.. */
165 ns_retain_object(pixmap);
166 return pixmap;
169 /* use with imgs created by ns_image_for_XPM */
170 unsigned long
171 XGetPixel (XImagePtr ximage, int x, int y)
173 return ns_get_pixel(ximage, x, y);
176 /* use with imgs created by ns_image_for_XPM; alpha set to 1;
177 pixel is assumed to be in form RGB */
178 void
179 XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
181 ns_put_pixel(ximage, x, y, pixel);
183 #endif /* HAVE_NS */
186 /* Functions to access the contents of a bitmap, given an id. */
189 x_bitmap_height (f, id)
190 FRAME_PTR f;
191 int id;
193 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
197 x_bitmap_width (f, id)
198 FRAME_PTR f;
199 int id;
201 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
204 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
206 x_bitmap_pixmap (f, id)
207 FRAME_PTR f;
208 int id;
210 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
212 #endif
214 #ifdef HAVE_X_WINDOWS
216 x_bitmap_mask (f, id)
217 FRAME_PTR f;
218 int id;
220 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
222 #endif
224 /* Allocate a new bitmap record. Returns index of new record. */
226 static int
227 x_allocate_bitmap_record (f)
228 FRAME_PTR f;
230 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
231 int i;
233 if (dpyinfo->bitmaps == NULL)
235 dpyinfo->bitmaps_size = 10;
236 dpyinfo->bitmaps
237 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
238 dpyinfo->bitmaps_last = 1;
239 return 1;
242 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
243 return ++dpyinfo->bitmaps_last;
245 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
246 if (dpyinfo->bitmaps[i].refcount == 0)
247 return i + 1;
249 dpyinfo->bitmaps_size *= 2;
250 dpyinfo->bitmaps
251 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
252 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
253 return ++dpyinfo->bitmaps_last;
256 /* Add one reference to the reference count of the bitmap with id ID. */
258 void
259 x_reference_bitmap (f, id)
260 FRAME_PTR f;
261 int id;
263 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
266 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
269 x_create_bitmap_from_data (f, bits, width, height)
270 struct frame *f;
271 char *bits;
272 unsigned int width, height;
274 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
275 int id;
277 #ifdef HAVE_X_WINDOWS
278 Pixmap bitmap;
279 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
280 bits, width, height);
281 if (! bitmap)
282 return -1;
283 #endif /* HAVE_X_WINDOWS */
285 #ifdef HAVE_NTGUI
286 Pixmap bitmap;
287 bitmap = CreateBitmap (width, height,
288 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
289 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
290 bits);
291 if (! bitmap)
292 return -1;
293 #endif /* HAVE_NTGUI */
295 #ifdef HAVE_NS
296 void *bitmap = ns_image_from_XBM(bits, width, height);
297 if (!bitmap)
298 return -1;
299 #endif
301 id = x_allocate_bitmap_record (f);
303 #ifdef HAVE_NS
304 dpyinfo->bitmaps[id - 1].img = bitmap;
305 dpyinfo->bitmaps[id - 1].depth = 1;
306 #endif
308 dpyinfo->bitmaps[id - 1].file = NULL;
309 dpyinfo->bitmaps[id - 1].height = height;
310 dpyinfo->bitmaps[id - 1].width = width;
311 dpyinfo->bitmaps[id - 1].refcount = 1;
313 #ifdef HAVE_X_WINDOWS
314 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
315 dpyinfo->bitmaps[id - 1].have_mask = 0;
316 dpyinfo->bitmaps[id - 1].depth = 1;
317 #endif /* HAVE_X_WINDOWS */
319 #ifdef HAVE_NTGUI
320 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
321 dpyinfo->bitmaps[id - 1].hinst = NULL;
322 dpyinfo->bitmaps[id - 1].depth = 1;
323 #endif /* HAVE_NTGUI */
325 return id;
328 /* Create bitmap from file FILE for frame F. */
331 x_create_bitmap_from_file (f, file)
332 struct frame *f;
333 Lisp_Object file;
335 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
337 #ifdef HAVE_NTGUI
338 return -1; /* W32_TODO : bitmap support */
339 #endif /* HAVE_NTGUI */
341 #ifdef HAVE_NS
342 int id;
343 void *bitmap = ns_image_from_file(file);
345 if (!bitmap)
346 return -1;
349 id = x_allocate_bitmap_record (f);
350 dpyinfo->bitmaps[id - 1].img = bitmap;
351 dpyinfo->bitmaps[id - 1].refcount = 1;
352 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
353 dpyinfo->bitmaps[id - 1].depth = 1;
354 dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
355 dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
356 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
357 return id;
358 #endif
360 #ifdef HAVE_X_WINDOWS
361 unsigned int width, height;
362 Pixmap bitmap;
363 int xhot, yhot, result, id;
364 Lisp_Object found;
365 int fd;
366 char *filename;
368 /* Look for an existing bitmap with the same name. */
369 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
371 if (dpyinfo->bitmaps[id].refcount
372 && dpyinfo->bitmaps[id].file
373 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
375 ++dpyinfo->bitmaps[id].refcount;
376 return id + 1;
380 /* Search bitmap-file-path for the file, if appropriate. */
381 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
382 if (fd < 0)
383 return -1;
384 emacs_close (fd);
386 filename = (char *) SDATA (found);
388 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
389 filename, &width, &height, &bitmap, &xhot, &yhot);
390 if (result != BitmapSuccess)
391 return -1;
393 id = x_allocate_bitmap_record (f);
394 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
395 dpyinfo->bitmaps[id - 1].have_mask = 0;
396 dpyinfo->bitmaps[id - 1].refcount = 1;
397 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
398 dpyinfo->bitmaps[id - 1].depth = 1;
399 dpyinfo->bitmaps[id - 1].height = height;
400 dpyinfo->bitmaps[id - 1].width = width;
401 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
403 return id;
404 #endif /* HAVE_X_WINDOWS */
407 /* Free bitmap B. */
409 static void
410 free_bitmap_record (dpyinfo, bm)
411 Display_Info *dpyinfo;
412 Bitmap_Record *bm;
414 #ifdef HAVE_X_WINDOWS
415 XFreePixmap (dpyinfo->display, bm->pixmap);
416 if (bm->have_mask)
417 XFreePixmap (dpyinfo->display, bm->mask);
418 #endif /* HAVE_X_WINDOWS */
420 #ifdef HAVE_NTGUI
421 DeleteObject (bm->pixmap);
422 #endif /* HAVE_NTGUI */
424 #ifdef HAVE_NS
425 ns_release_object(bm->img);
426 #endif
428 if (bm->file)
430 xfree (bm->file);
431 bm->file = NULL;
435 /* Remove reference to bitmap with id number ID. */
437 void
438 x_destroy_bitmap (f, id)
439 FRAME_PTR f;
440 int id;
442 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
444 if (id > 0)
446 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
448 if (--bm->refcount == 0)
450 BLOCK_INPUT;
451 free_bitmap_record (dpyinfo, bm);
452 UNBLOCK_INPUT;
457 /* Free all the bitmaps for the display specified by DPYINFO. */
459 void
460 x_destroy_all_bitmaps (dpyinfo)
461 Display_Info *dpyinfo;
463 int i;
464 Bitmap_Record *bm = dpyinfo->bitmaps;
466 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
467 if (bm->refcount > 0)
468 free_bitmap_record (dpyinfo, bm);
470 dpyinfo->bitmaps_last = 0;
474 #ifdef HAVE_X_WINDOWS
476 /* Useful functions defined in the section
477 `Image type independent image structures' below. */
479 static unsigned long four_corners_best P_ ((XImagePtr ximg,
480 int *corners,
481 unsigned long width,
482 unsigned long height));
484 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
485 int depth, XImagePtr *ximg,
486 Pixmap *pixmap));
488 static void x_destroy_x_image P_ ((XImagePtr ximg));
491 /* Create a mask of a bitmap. Note is this not a perfect mask.
492 It's nicer with some borders in this context */
495 x_create_bitmap_mask (f, id)
496 struct frame *f;
497 int id;
499 Pixmap pixmap, mask;
500 XImagePtr ximg, mask_img;
501 unsigned long width, height;
502 int result;
503 unsigned long bg;
504 unsigned long x, y, xp, xm, yp, ym;
505 GC gc;
507 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
509 if (!(id > 0))
510 return -1;
512 pixmap = x_bitmap_pixmap (f, id);
513 width = x_bitmap_width (f, id);
514 height = x_bitmap_height (f, id);
516 BLOCK_INPUT;
517 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
518 ~0, ZPixmap);
520 if (!ximg)
522 UNBLOCK_INPUT;
523 return -1;
526 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
528 UNBLOCK_INPUT;
529 if (!result)
531 XDestroyImage (ximg);
532 return -1;
535 bg = four_corners_best (ximg, NULL, width, height);
537 for (y = 0; y < ximg->height; ++y)
539 for (x = 0; x < ximg->width; ++x)
541 xp = x != ximg->width - 1 ? x + 1 : 0;
542 xm = x != 0 ? x - 1 : ximg->width - 1;
543 yp = y != ximg->height - 1 ? y + 1 : 0;
544 ym = y != 0 ? y - 1 : ximg->height - 1;
545 if (XGetPixel (ximg, x, y) == bg
546 && XGetPixel (ximg, x, yp) == bg
547 && XGetPixel (ximg, x, ym) == bg
548 && XGetPixel (ximg, xp, y) == bg
549 && XGetPixel (ximg, xp, yp) == bg
550 && XGetPixel (ximg, xp, ym) == bg
551 && XGetPixel (ximg, xm, y) == bg
552 && XGetPixel (ximg, xm, yp) == bg
553 && XGetPixel (ximg, xm, ym) == bg)
554 XPutPixel (mask_img, x, y, 0);
555 else
556 XPutPixel (mask_img, x, y, 1);
560 xassert (interrupt_input_blocked);
561 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
562 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
563 width, height);
564 XFreeGC (FRAME_X_DISPLAY (f), gc);
566 dpyinfo->bitmaps[id - 1].have_mask = 1;
567 dpyinfo->bitmaps[id - 1].mask = mask;
569 XDestroyImage (ximg);
570 x_destroy_x_image (mask_img);
572 return 0;
575 #endif /* HAVE_X_WINDOWS */
578 /***********************************************************************
579 Image types
580 ***********************************************************************/
582 /* Value is the number of elements of vector VECTOR. */
584 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
586 /* List of supported image types. Use define_image_type to add new
587 types. Use lookup_image_type to find a type for a given symbol. */
589 static struct image_type *image_types;
591 /* A list of symbols, one for each supported image type. */
593 Lisp_Object Vimage_types;
595 /* An alist of image types and libraries that implement the type. */
597 Lisp_Object Vimage_library_alist;
599 /* Cache for delayed-loading image types. */
601 static Lisp_Object Vimage_type_cache;
603 /* The symbol `xbm' which is used as the type symbol for XBM images. */
605 Lisp_Object Qxbm;
607 /* Keywords. */
609 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
610 extern Lisp_Object QCdata, QCtype;
611 extern Lisp_Object Qcenter;
612 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
613 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
614 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
616 /* Other symbols. */
618 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
620 /* Time in seconds after which images should be removed from the cache
621 if not displayed. */
623 Lisp_Object Vimage_cache_eviction_delay;
625 /* Function prototypes. */
627 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
628 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
629 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
630 static void x_laplace P_ ((struct frame *, struct image *));
631 static void x_emboss P_ ((struct frame *, struct image *));
632 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
633 Lisp_Object));
635 #define CACHE_IMAGE_TYPE(type, status) \
636 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
638 #define ADD_IMAGE_TYPE(type) \
639 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
641 /* Define a new image type from TYPE. This adds a copy of TYPE to
642 image_types and caches the loading status of TYPE. */
644 static Lisp_Object
645 define_image_type (type, loaded)
646 struct image_type *type;
647 int loaded;
649 Lisp_Object success;
651 if (!loaded)
652 success = Qnil;
653 else
655 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
656 The initialized data segment is read-only. */
657 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
658 bcopy (type, p, sizeof *p);
659 p->next = image_types;
660 image_types = p;
661 success = Qt;
664 CACHE_IMAGE_TYPE (*type->type, success);
665 return success;
669 /* Look up image type SYMBOL, and return a pointer to its image_type
670 structure. Value is null if SYMBOL is not a known image type. */
672 static INLINE struct image_type *
673 lookup_image_type (symbol)
674 Lisp_Object symbol;
676 struct image_type *type;
678 /* We must initialize the image-type if it hasn't been already. */
679 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
680 return 0; /* unimplemented */
682 for (type = image_types; type; type = type->next)
683 if (EQ (symbol, *type->type))
684 break;
686 return type;
690 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
691 valid image specification is a list whose car is the symbol
692 `image', and whose rest is a property list. The property list must
693 contain a value for key `:type'. That value must be the name of a
694 supported image type. The rest of the property list depends on the
695 image type. */
698 valid_image_p (object)
699 Lisp_Object object;
701 int valid_p = 0;
703 if (IMAGEP (object))
705 Lisp_Object tem;
707 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
708 if (EQ (XCAR (tem), QCtype))
710 tem = XCDR (tem);
711 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
713 struct image_type *type;
714 type = lookup_image_type (XCAR (tem));
715 if (type)
716 valid_p = type->valid_p (object);
719 break;
723 return valid_p;
727 /* Log error message with format string FORMAT and argument ARG.
728 Signaling an error, e.g. when an image cannot be loaded, is not a
729 good idea because this would interrupt redisplay, and the error
730 message display would lead to another redisplay. This function
731 therefore simply displays a message. */
733 static void
734 image_error (format, arg1, arg2)
735 char *format;
736 Lisp_Object arg1, arg2;
738 add_to_log (format, arg1, arg2);
743 /***********************************************************************
744 Image specifications
745 ***********************************************************************/
747 enum image_value_type
749 IMAGE_DONT_CHECK_VALUE_TYPE,
750 IMAGE_STRING_VALUE,
751 IMAGE_STRING_OR_NIL_VALUE,
752 IMAGE_SYMBOL_VALUE,
753 IMAGE_POSITIVE_INTEGER_VALUE,
754 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
755 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
756 IMAGE_ASCENT_VALUE,
757 IMAGE_INTEGER_VALUE,
758 IMAGE_FUNCTION_VALUE,
759 IMAGE_NUMBER_VALUE,
760 IMAGE_BOOL_VALUE
763 /* Structure used when parsing image specifications. */
765 struct image_keyword
767 /* Name of keyword. */
768 char *name;
770 /* The type of value allowed. */
771 enum image_value_type type;
773 /* Non-zero means key must be present. */
774 int mandatory_p;
776 /* Used to recognize duplicate keywords in a property list. */
777 int count;
779 /* The value that was found. */
780 Lisp_Object value;
784 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
785 int, Lisp_Object));
786 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
789 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
790 has the format (image KEYWORD VALUE ...). One of the keyword/
791 value pairs must be `:type TYPE'. KEYWORDS is a vector of
792 image_keywords structures of size NKEYWORDS describing other
793 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
795 static int
796 parse_image_spec (spec, keywords, nkeywords, type)
797 Lisp_Object spec;
798 struct image_keyword *keywords;
799 int nkeywords;
800 Lisp_Object type;
802 int i;
803 Lisp_Object plist;
805 if (!IMAGEP (spec))
806 return 0;
808 plist = XCDR (spec);
809 while (CONSP (plist))
811 Lisp_Object key, value;
813 /* First element of a pair must be a symbol. */
814 key = XCAR (plist);
815 plist = XCDR (plist);
816 if (!SYMBOLP (key))
817 return 0;
819 /* There must follow a value. */
820 if (!CONSP (plist))
821 return 0;
822 value = XCAR (plist);
823 plist = XCDR (plist);
825 /* Find key in KEYWORDS. Error if not found. */
826 for (i = 0; i < nkeywords; ++i)
827 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
828 break;
830 if (i == nkeywords)
831 continue;
833 /* Record that we recognized the keyword. If a keywords
834 was found more than once, it's an error. */
835 keywords[i].value = value;
836 ++keywords[i].count;
838 if (keywords[i].count > 1)
839 return 0;
841 /* Check type of value against allowed type. */
842 switch (keywords[i].type)
844 case IMAGE_STRING_VALUE:
845 if (!STRINGP (value))
846 return 0;
847 break;
849 case IMAGE_STRING_OR_NIL_VALUE:
850 if (!STRINGP (value) && !NILP (value))
851 return 0;
852 break;
854 case IMAGE_SYMBOL_VALUE:
855 if (!SYMBOLP (value))
856 return 0;
857 break;
859 case IMAGE_POSITIVE_INTEGER_VALUE:
860 if (!INTEGERP (value) || XINT (value) <= 0)
861 return 0;
862 break;
864 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
865 if (INTEGERP (value) && XINT (value) >= 0)
866 break;
867 if (CONSP (value)
868 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
869 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
870 break;
871 return 0;
873 case IMAGE_ASCENT_VALUE:
874 if (SYMBOLP (value) && EQ (value, Qcenter))
875 break;
876 else if (INTEGERP (value)
877 && XINT (value) >= 0
878 && XINT (value) <= 100)
879 break;
880 return 0;
882 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
883 if (!INTEGERP (value) || XINT (value) < 0)
884 return 0;
885 break;
887 case IMAGE_DONT_CHECK_VALUE_TYPE:
888 break;
890 case IMAGE_FUNCTION_VALUE:
891 value = indirect_function (value);
892 if (SUBRP (value)
893 || COMPILEDP (value)
894 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
895 break;
896 return 0;
898 case IMAGE_NUMBER_VALUE:
899 if (!INTEGERP (value) && !FLOATP (value))
900 return 0;
901 break;
903 case IMAGE_INTEGER_VALUE:
904 if (!INTEGERP (value))
905 return 0;
906 break;
908 case IMAGE_BOOL_VALUE:
909 if (!NILP (value) && !EQ (value, Qt))
910 return 0;
911 break;
913 default:
914 abort ();
915 break;
918 if (EQ (key, QCtype) && !EQ (type, value))
919 return 0;
922 /* Check that all mandatory fields are present. */
923 for (i = 0; i < nkeywords; ++i)
924 if (keywords[i].mandatory_p && keywords[i].count == 0)
925 return 0;
927 return NILP (plist);
931 /* Return the value of KEY in image specification SPEC. Value is nil
932 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
933 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
935 static Lisp_Object
936 image_spec_value (spec, key, found)
937 Lisp_Object spec, key;
938 int *found;
940 Lisp_Object tail;
942 xassert (valid_image_p (spec));
944 for (tail = XCDR (spec);
945 CONSP (tail) && CONSP (XCDR (tail));
946 tail = XCDR (XCDR (tail)))
948 if (EQ (XCAR (tail), key))
950 if (found)
951 *found = 1;
952 return XCAR (XCDR (tail));
956 if (found)
957 *found = 0;
958 return Qnil;
962 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
963 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
964 PIXELS non-nil means return the size in pixels, otherwise return the
965 size in canonical character units.
966 FRAME is the frame on which the image will be displayed. FRAME nil
967 or omitted means use the selected frame. */)
968 (spec, pixels, frame)
969 Lisp_Object spec, pixels, frame;
971 Lisp_Object size;
973 size = Qnil;
974 if (valid_image_p (spec))
976 struct frame *f = check_x_frame (frame);
977 int id = lookup_image (f, spec);
978 struct image *img = IMAGE_FROM_ID (f, id);
979 int width = img->width + 2 * img->hmargin;
980 int height = img->height + 2 * img->vmargin;
982 if (NILP (pixels))
983 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
984 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
985 else
986 size = Fcons (make_number (width), make_number (height));
988 else
989 error ("Invalid image specification");
991 return size;
995 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
996 doc: /* Return t if image SPEC has a mask bitmap.
997 FRAME is the frame on which the image will be displayed. FRAME nil
998 or omitted means use the selected frame. */)
999 (spec, frame)
1000 Lisp_Object spec, frame;
1002 Lisp_Object mask;
1004 mask = Qnil;
1005 if (valid_image_p (spec))
1007 struct frame *f = check_x_frame (frame);
1008 int id = lookup_image (f, spec);
1009 struct image *img = IMAGE_FROM_ID (f, id);
1010 if (img->mask)
1011 mask = Qt;
1013 else
1014 error ("Invalid image specification");
1016 return mask;
1019 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1020 doc: /* Return extension data for image SPEC.
1021 FRAME is the frame on which the image will be displayed. FRAME nil
1022 or omitted means use the selected frame. */)
1023 (spec, frame)
1024 Lisp_Object spec, frame;
1026 Lisp_Object ext;
1028 ext = Qnil;
1029 if (valid_image_p (spec))
1031 struct frame *f = check_x_frame (frame);
1032 int id = lookup_image (f, spec);
1033 struct image *img = IMAGE_FROM_ID (f, id);
1034 ext = img->data.lisp_val;
1037 return ext;
1041 /***********************************************************************
1042 Image type independent image structures
1043 ***********************************************************************/
1045 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1046 static void free_image P_ ((struct frame *f, struct image *img));
1047 static int check_image_size P_ ((struct frame *f, int width, int height));
1049 #define MAX_IMAGE_SIZE 6.0
1050 Lisp_Object Vmax_image_size;
1052 /* Allocate and return a new image structure for image specification
1053 SPEC. SPEC has a hash value of HASH. */
1055 static struct image *
1056 make_image (spec, hash)
1057 Lisp_Object spec;
1058 unsigned hash;
1060 struct image *img = (struct image *) xmalloc (sizeof *img);
1061 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1063 xassert (valid_image_p (spec));
1064 bzero (img, sizeof *img);
1065 img->dependencies = NILP (file) ? Qnil : list1 (file);
1066 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1067 xassert (img->type != NULL);
1068 img->spec = spec;
1069 img->data.lisp_val = Qnil;
1070 img->ascent = DEFAULT_IMAGE_ASCENT;
1071 img->hash = hash;
1072 img->corners[BOT_CORNER] = -1; /* Full image */
1073 return img;
1077 /* Free image IMG which was used on frame F, including its resources. */
1079 static void
1080 free_image (f, img)
1081 struct frame *f;
1082 struct image *img;
1084 if (img)
1086 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1088 /* Remove IMG from the hash table of its cache. */
1089 if (img->prev)
1090 img->prev->next = img->next;
1091 else
1092 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1094 if (img->next)
1095 img->next->prev = img->prev;
1097 c->images[img->id] = NULL;
1099 /* Free resources, then free IMG. */
1100 img->type->free (f, img);
1101 xfree (img);
1105 /* Return 1 if the given widths and heights are valid for display;
1106 otherwise, return 0. */
1109 check_image_size (f, width, height)
1110 struct frame *f;
1111 int width;
1112 int height;
1114 int w, h;
1116 if (width <= 0 || height <= 0)
1117 return 0;
1119 if (INTEGERP (Vmax_image_size))
1120 w = h = XINT (Vmax_image_size);
1121 else if (FLOATP (Vmax_image_size))
1123 if (f != NULL)
1125 w = FRAME_PIXEL_WIDTH (f);
1126 h = FRAME_PIXEL_HEIGHT (f);
1128 else
1129 w = h = 1024; /* Arbitrary size for unknown frame. */
1130 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1131 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1133 else
1134 return 1;
1136 return (width <= w && height <= h);
1139 /* Prepare image IMG for display on frame F. Must be called before
1140 drawing an image. */
1142 void
1143 prepare_image_for_display (f, img)
1144 struct frame *f;
1145 struct image *img;
1147 EMACS_TIME t;
1149 /* We're about to display IMG, so set its timestamp to `now'. */
1150 EMACS_GET_TIME (t);
1151 img->timestamp = EMACS_SECS (t);
1153 /* If IMG doesn't have a pixmap yet, load it now, using the image
1154 type dependent loader function. */
1155 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1156 img->load_failed_p = img->type->load (f, img) == 0;
1161 /* Value is the number of pixels for the ascent of image IMG when
1162 drawn in face FACE. */
1165 image_ascent (img, face, slice)
1166 struct image *img;
1167 struct face *face;
1168 struct glyph_slice *slice;
1170 int height;
1171 int ascent;
1173 if (slice->height == img->height)
1174 height = img->height + img->vmargin;
1175 else if (slice->y == 0)
1176 height = slice->height + img->vmargin;
1177 else
1178 height = slice->height;
1180 if (img->ascent == CENTERED_IMAGE_ASCENT)
1182 if (face->font)
1184 #ifdef HAVE_NTGUI
1185 /* W32 specific version. Why?. ++kfs */
1186 ascent = height / 2 - (FONT_DESCENT (face->font)
1187 - FONT_BASE (face->font)) / 2;
1188 #else
1189 /* This expression is arranged so that if the image can't be
1190 exactly centered, it will be moved slightly up. This is
1191 because a typical font is `top-heavy' (due to the presence
1192 uppercase letters), so the image placement should err towards
1193 being top-heavy too. It also just generally looks better. */
1194 ascent = (height + FONT_BASE(face->font)
1195 - FONT_DESCENT(face->font) + 1) / 2;
1196 #endif /* HAVE_NTGUI */
1198 else
1199 ascent = height / 2;
1201 else
1202 ascent = (int) (height * img->ascent / 100.0);
1204 return ascent;
1208 /* Image background colors. */
1210 /* Find the "best" corner color of a bitmap.
1211 On W32, XIMG is assumed to a device context with the bitmap selected. */
1213 static RGB_PIXEL_COLOR
1214 four_corners_best (ximg, corners, width, height)
1215 XImagePtr_or_DC ximg;
1216 int *corners;
1217 unsigned long width, height;
1219 RGB_PIXEL_COLOR corner_pixels[4], best;
1220 int i, best_count;
1222 if (corners && corners[BOT_CORNER] >= 0)
1224 /* Get the colors at the corner_pixels of ximg. */
1225 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1226 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1227 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1228 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1230 else
1232 /* Get the colors at the corner_pixels of ximg. */
1233 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1234 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1235 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1236 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1238 /* Choose the most frequently found color as background. */
1239 for (i = best_count = 0; i < 4; ++i)
1241 int j, n;
1243 for (j = n = 0; j < 4; ++j)
1244 if (corner_pixels[i] == corner_pixels[j])
1245 ++n;
1247 if (n > best_count)
1248 best = corner_pixels[i], best_count = n;
1251 return best;
1254 /* Portability macros */
1256 #ifdef HAVE_NTGUI
1258 #define Destroy_Image(img_dc, prev) \
1259 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1261 #define Free_Pixmap(display, pixmap) \
1262 DeleteObject (pixmap)
1264 #elif defined (HAVE_NS)
1266 #define Destroy_Image(ximg, dummy) \
1267 ns_release_object(ximg)
1269 #define Free_Pixmap(display, pixmap) \
1270 ns_release_object(pixmap)
1272 #else
1274 #define Destroy_Image(ximg, dummy) \
1275 XDestroyImage (ximg)
1277 #define Free_Pixmap(display, pixmap) \
1278 XFreePixmap (display, pixmap)
1280 #endif /* !HAVE_NTGUI && !HAVE_NS */
1283 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1284 it is guessed heuristically. If non-zero, XIMG is an existing
1285 XImage object (or device context with the image selected on W32) to
1286 use for the heuristic. */
1288 RGB_PIXEL_COLOR
1289 image_background (img, f, ximg)
1290 struct image *img;
1291 struct frame *f;
1292 XImagePtr_or_DC ximg;
1294 if (! img->background_valid)
1295 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1297 int free_ximg = !ximg;
1298 #ifdef HAVE_NTGUI
1299 HGDIOBJ prev;
1300 #endif /* HAVE_NTGUI */
1302 if (free_ximg)
1304 #ifndef HAVE_NTGUI
1305 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1306 0, 0, img->width, img->height, ~0, ZPixmap);
1307 #else
1308 HDC frame_dc = get_frame_dc (f);
1309 ximg = CreateCompatibleDC (frame_dc);
1310 release_frame_dc (f, frame_dc);
1311 prev = SelectObject (ximg, img->pixmap);
1312 #endif /* !HAVE_NTGUI */
1315 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1317 if (free_ximg)
1318 Destroy_Image (ximg, prev);
1320 img->background_valid = 1;
1323 return img->background;
1326 /* Return the `background_transparent' field of IMG. If IMG doesn't
1327 have one yet, it is guessed heuristically. If non-zero, MASK is an
1328 existing XImage object to use for the heuristic. */
1331 image_background_transparent (img, f, mask)
1332 struct image *img;
1333 struct frame *f;
1334 XImagePtr_or_DC mask;
1336 if (! img->background_transparent_valid)
1337 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1339 if (img->mask)
1341 int free_mask = !mask;
1342 #ifdef HAVE_NTGUI
1343 HGDIOBJ prev;
1344 #endif /* HAVE_NTGUI */
1346 if (free_mask)
1348 #ifndef HAVE_NTGUI
1349 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1350 0, 0, img->width, img->height, ~0, ZPixmap);
1351 #else
1352 HDC frame_dc = get_frame_dc (f);
1353 mask = CreateCompatibleDC (frame_dc);
1354 release_frame_dc (f, frame_dc);
1355 prev = SelectObject (mask, img->mask);
1356 #endif /* HAVE_NTGUI */
1359 img->background_transparent
1360 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1362 if (free_mask)
1363 Destroy_Image (mask, prev);
1365 else
1366 img->background_transparent = 0;
1368 img->background_transparent_valid = 1;
1371 return img->background_transparent;
1375 /***********************************************************************
1376 Helper functions for X image types
1377 ***********************************************************************/
1379 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1380 int, int));
1381 static void x_clear_image P_ ((struct frame *f, struct image *img));
1382 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1383 struct image *img,
1384 Lisp_Object color_name,
1385 unsigned long dflt));
1388 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1389 free the pixmap if any. MASK_P non-zero means clear the mask
1390 pixmap if any. COLORS_P non-zero means free colors allocated for
1391 the image, if any. */
1393 static void
1394 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1395 struct frame *f;
1396 struct image *img;
1397 int pixmap_p, mask_p, colors_p;
1399 if (pixmap_p && img->pixmap)
1401 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1402 img->pixmap = NO_PIXMAP;
1403 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1404 img->background_valid = 0;
1407 if (mask_p && img->mask)
1409 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1410 img->mask = NO_PIXMAP;
1411 img->background_transparent_valid = 0;
1414 if (colors_p && img->ncolors)
1416 /* W32_TODO: color table support. */
1417 #ifdef HAVE_X_WINDOWS
1418 x_free_colors (f, img->colors, img->ncolors);
1419 #endif /* HAVE_X_WINDOWS */
1420 xfree (img->colors);
1421 img->colors = NULL;
1422 img->ncolors = 0;
1427 /* Free X resources of image IMG which is used on frame F. */
1429 static void
1430 x_clear_image (f, img)
1431 struct frame *f;
1432 struct image *img;
1434 BLOCK_INPUT;
1435 x_clear_image_1 (f, img, 1, 1, 1);
1436 UNBLOCK_INPUT;
1440 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1441 cannot be allocated, use DFLT. Add a newly allocated color to
1442 IMG->colors, so that it can be freed again. Value is the pixel
1443 color. */
1445 static unsigned long
1446 x_alloc_image_color (f, img, color_name, dflt)
1447 struct frame *f;
1448 struct image *img;
1449 Lisp_Object color_name;
1450 unsigned long dflt;
1452 XColor color;
1453 unsigned long result;
1455 xassert (STRINGP (color_name));
1457 if (x_defined_color (f, SDATA (color_name), &color, 1))
1459 /* This isn't called frequently so we get away with simply
1460 reallocating the color vector to the needed size, here. */
1461 ++img->ncolors;
1462 img->colors =
1463 (unsigned long *) xrealloc (img->colors,
1464 img->ncolors * sizeof *img->colors);
1465 img->colors[img->ncolors - 1] = color.pixel;
1466 result = color.pixel;
1468 else
1469 result = dflt;
1471 return result;
1476 /***********************************************************************
1477 Image Cache
1478 ***********************************************************************/
1480 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1481 static void cache_image P_ ((struct frame *f, struct image *img));
1482 static void postprocess_image P_ ((struct frame *, struct image *));
1484 /* Return a new, initialized image cache that is allocated from the
1485 heap. Call free_image_cache to free an image cache. */
1487 struct image_cache *
1488 make_image_cache ()
1490 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1491 int size;
1493 bzero (c, sizeof *c);
1494 c->size = 50;
1495 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1496 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1497 c->buckets = (struct image **) xmalloc (size);
1498 bzero (c->buckets, size);
1499 return c;
1503 /* Find an image matching SPEC in the cache, and return it. If no
1504 image is found, return NULL. */
1505 static struct image *
1506 search_image_cache (f, spec, hash)
1507 struct frame *f;
1508 Lisp_Object spec;
1509 unsigned hash;
1511 struct image *img;
1512 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1513 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1515 if (!c) return NULL;
1517 /* If the image spec does not specify a background color, the cached
1518 image must have the same background color as the current frame.
1519 The foreground color must also match, for the sake of monochrome
1520 images.
1522 In fact, we could ignore the foreground color matching condition
1523 for color images, or if the image spec specifies :foreground;
1524 similarly we could ignore the background color matching condition
1525 for formats that don't use transparency (such as jpeg), or if the
1526 image spec specifies :background. However, the extra memory
1527 usage is probably negligible in practice, so we don't bother. */
1529 for (img = c->buckets[i]; img; img = img->next)
1530 if (img->hash == hash
1531 && !NILP (Fequal (img->spec, spec))
1532 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1533 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1534 break;
1535 return img;
1539 /* Search frame F for an image with spec SPEC, and free it. */
1541 static void
1542 uncache_image (f, spec)
1543 struct frame *f;
1544 Lisp_Object spec;
1546 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1547 if (img)
1549 free_image (f, img);
1550 /* As display glyphs may still be referring to the image ID, we
1551 must garbage the frame (Bug#6426). */
1552 SET_FRAME_GARBAGED (f);
1557 /* Free image cache of frame F. Be aware that X frames share images
1558 caches. */
1560 void
1561 free_image_cache (f)
1562 struct frame *f;
1564 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1565 if (c)
1567 int i;
1569 /* Cache should not be referenced by any frame when freed. */
1570 xassert (c->refcount == 0);
1572 for (i = 0; i < c->used; ++i)
1573 free_image (f, c->images[i]);
1574 xfree (c->images);
1575 xfree (c->buckets);
1576 xfree (c);
1577 FRAME_IMAGE_CACHE (f) = NULL;
1582 /* Clear image cache of frame F. FILTER=t means free all images.
1583 FILTER=nil means clear only images that haven't been
1584 displayed for some time.
1585 Else, only free the images which have FILTER in their `dependencies'.
1586 Should be called from time to time to reduce the number of loaded images.
1587 If image-cache-eviction-delay is non-nil, this frees images in the cache
1588 which weren't displayed for at least that many seconds. */
1590 void
1591 clear_image_cache (struct frame *f, Lisp_Object filter)
1593 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1595 if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
1597 EMACS_TIME t;
1598 unsigned long old;
1599 int i, nfreed;
1601 EMACS_GET_TIME (t);
1602 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1604 /* Block input so that we won't be interrupted by a SIGIO
1605 while being in an inconsistent state. */
1606 BLOCK_INPUT;
1608 for (i = nfreed = 0; i < c->used; ++i)
1610 struct image *img = c->images[i];
1611 if (img != NULL
1612 && (NILP (filter) ? img->timestamp < old
1613 : (EQ (Qt, filter)
1614 || !NILP (Fmember (filter, img->dependencies)))))
1616 free_image (f, img);
1617 ++nfreed;
1621 /* We may be clearing the image cache because, for example,
1622 Emacs was iconified for a longer period of time. In that
1623 case, current matrices may still contain references to
1624 images freed above. So, clear these matrices. */
1625 if (nfreed)
1627 Lisp_Object tail, frame;
1629 FOR_EACH_FRAME (tail, frame)
1631 struct frame *f = XFRAME (frame);
1632 if (FRAME_IMAGE_CACHE (f) == c)
1633 clear_current_matrices (f);
1636 ++windows_or_buffers_changed;
1639 UNBLOCK_INPUT;
1643 void
1644 clear_image_caches (Lisp_Object filter)
1646 /* FIXME: We want to do
1647 * struct terminal *t;
1648 * for (t = terminal_list; t; t = t->next_terminal)
1649 * clear_image_cache (t, filter); */
1650 Lisp_Object tail, frame;
1651 FOR_EACH_FRAME (tail, frame)
1652 if (FRAME_WINDOW_P (XFRAME (frame)))
1653 clear_image_cache (XFRAME (frame), filter);
1656 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1657 0, 1, 0,
1658 doc: /* Clear the image cache.
1659 FILTER nil or a frame means clear all images in the selected frame.
1660 FILTER t means clear the image caches of all frames.
1661 Anything else, means only clear those images which refer to FILTER,
1662 which is then usually a filename. */)
1663 (filter)
1664 Lisp_Object filter;
1666 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1667 clear_image_caches (filter);
1668 else
1669 clear_image_cache (check_x_frame (filter), Qt);
1671 return Qnil;
1675 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1676 1, 2, 0,
1677 doc: /* Refresh the image with specification SPEC on frame FRAME.
1678 If SPEC specifies an image file, the displayed image is updated with
1679 the current contents of that file.
1680 FRAME nil or omitted means use the selected frame.
1681 FRAME t means refresh the image on all frames. */)
1682 (spec, frame)
1683 Lisp_Object spec, frame;
1685 if (!valid_image_p (spec))
1686 error ("Invalid image specification");
1688 if (EQ (frame, Qt))
1690 Lisp_Object tail;
1691 FOR_EACH_FRAME (tail, frame)
1693 struct frame *f = XFRAME (frame);
1694 if (FRAME_WINDOW_P (f))
1695 uncache_image (f, spec);
1698 else
1699 uncache_image (check_x_frame (frame), spec);
1701 return Qnil;
1705 /* Compute masks and transform image IMG on frame F, as specified
1706 by the image's specification, */
1708 static void
1709 postprocess_image (f, img)
1710 struct frame *f;
1711 struct image *img;
1713 /* Manipulation of the image's mask. */
1714 if (img->pixmap)
1716 Lisp_Object conversion, spec;
1717 Lisp_Object mask;
1719 spec = img->spec;
1721 /* `:heuristic-mask t'
1722 `:mask heuristic'
1723 means build a mask heuristically.
1724 `:heuristic-mask (R G B)'
1725 `:mask (heuristic (R G B))'
1726 means build a mask from color (R G B) in the
1727 image.
1728 `:mask nil'
1729 means remove a mask, if any. */
1731 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1732 if (!NILP (mask))
1733 x_build_heuristic_mask (f, img, mask);
1734 else
1736 int found_p;
1738 mask = image_spec_value (spec, QCmask, &found_p);
1740 if (EQ (mask, Qheuristic))
1741 x_build_heuristic_mask (f, img, Qt);
1742 else if (CONSP (mask)
1743 && EQ (XCAR (mask), Qheuristic))
1745 if (CONSP (XCDR (mask)))
1746 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1747 else
1748 x_build_heuristic_mask (f, img, XCDR (mask));
1750 else if (NILP (mask) && found_p && img->mask)
1752 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1753 img->mask = NO_PIXMAP;
1758 /* Should we apply an image transformation algorithm? */
1759 conversion = image_spec_value (spec, QCconversion, NULL);
1760 if (EQ (conversion, Qdisabled))
1761 x_disable_image (f, img);
1762 else if (EQ (conversion, Qlaplace))
1763 x_laplace (f, img);
1764 else if (EQ (conversion, Qemboss))
1765 x_emboss (f, img);
1766 else if (CONSP (conversion)
1767 && EQ (XCAR (conversion), Qedge_detection))
1769 Lisp_Object tem;
1770 tem = XCDR (conversion);
1771 if (CONSP (tem))
1772 x_edge_detection (f, img,
1773 Fplist_get (tem, QCmatrix),
1774 Fplist_get (tem, QCcolor_adjustment));
1780 /* Return the id of image with Lisp specification SPEC on frame F.
1781 SPEC must be a valid Lisp image specification (see valid_image_p). */
1784 lookup_image (f, spec)
1785 struct frame *f;
1786 Lisp_Object spec;
1788 struct image_cache *c;
1789 struct image *img;
1790 unsigned hash;
1791 struct gcpro gcpro1;
1792 EMACS_TIME now;
1794 /* F must be a window-system frame, and SPEC must be a valid image
1795 specification. */
1796 xassert (FRAME_WINDOW_P (f));
1797 xassert (valid_image_p (spec));
1799 c = FRAME_IMAGE_CACHE (f);
1801 GCPRO1 (spec);
1803 /* Look up SPEC in the hash table of the image cache. */
1804 hash = sxhash (spec, 0);
1805 img = search_image_cache (f, spec, hash);
1806 if (img && img->load_failed_p)
1808 free_image (f, img);
1809 img = NULL;
1812 /* If not found, create a new image and cache it. */
1813 if (img == NULL)
1815 extern Lisp_Object Qpostscript;
1817 BLOCK_INPUT;
1818 img = make_image (spec, hash);
1819 cache_image (f, img);
1820 img->load_failed_p = img->type->load (f, img) == 0;
1821 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
1822 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
1824 /* If we can't load the image, and we don't have a width and
1825 height, use some arbitrary width and height so that we can
1826 draw a rectangle for it. */
1827 if (img->load_failed_p)
1829 Lisp_Object value;
1831 value = image_spec_value (spec, QCwidth, NULL);
1832 img->width = (INTEGERP (value)
1833 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1834 value = image_spec_value (spec, QCheight, NULL);
1835 img->height = (INTEGERP (value)
1836 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1838 else
1840 /* Handle image type independent image attributes
1841 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1842 `:background COLOR'. */
1843 Lisp_Object ascent, margin, relief, bg;
1845 ascent = image_spec_value (spec, QCascent, NULL);
1846 if (INTEGERP (ascent))
1847 img->ascent = XFASTINT (ascent);
1848 else if (EQ (ascent, Qcenter))
1849 img->ascent = CENTERED_IMAGE_ASCENT;
1851 margin = image_spec_value (spec, QCmargin, NULL);
1852 if (INTEGERP (margin) && XINT (margin) >= 0)
1853 img->vmargin = img->hmargin = XFASTINT (margin);
1854 else if (CONSP (margin) && INTEGERP (XCAR (margin))
1855 && INTEGERP (XCDR (margin)))
1857 if (XINT (XCAR (margin)) > 0)
1858 img->hmargin = XFASTINT (XCAR (margin));
1859 if (XINT (XCDR (margin)) > 0)
1860 img->vmargin = XFASTINT (XCDR (margin));
1863 relief = image_spec_value (spec, QCrelief, NULL);
1864 if (INTEGERP (relief))
1866 img->relief = XINT (relief);
1867 img->hmargin += eabs (img->relief);
1868 img->vmargin += eabs (img->relief);
1871 if (! img->background_valid)
1873 bg = image_spec_value (img->spec, QCbackground, NULL);
1874 if (!NILP (bg))
1876 img->background
1877 = x_alloc_image_color (f, img, bg,
1878 FRAME_BACKGROUND_PIXEL (f));
1879 img->background_valid = 1;
1883 /* Do image transformations and compute masks, unless we
1884 don't have the image yet. */
1885 if (!EQ (*img->type->type, Qpostscript))
1886 postprocess_image (f, img);
1889 UNBLOCK_INPUT;
1892 /* We're using IMG, so set its timestamp to `now'. */
1893 EMACS_GET_TIME (now);
1894 img->timestamp = EMACS_SECS (now);
1896 UNGCPRO;
1898 /* Value is the image id. */
1899 return img->id;
1903 /* Cache image IMG in the image cache of frame F. */
1905 static void
1906 cache_image (f, img)
1907 struct frame *f;
1908 struct image *img;
1910 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1911 int i;
1913 /* Find a free slot in c->images. */
1914 for (i = 0; i < c->used; ++i)
1915 if (c->images[i] == NULL)
1916 break;
1918 /* If no free slot found, maybe enlarge c->images. */
1919 if (i == c->used && c->used == c->size)
1921 c->size *= 2;
1922 c->images = (struct image **) xrealloc (c->images,
1923 c->size * sizeof *c->images);
1926 /* Add IMG to c->images, and assign IMG an id. */
1927 c->images[i] = img;
1928 img->id = i;
1929 if (i == c->used)
1930 ++c->used;
1932 /* Add IMG to the cache's hash table. */
1933 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1934 img->next = c->buckets[i];
1935 if (img->next)
1936 img->next->prev = img;
1937 img->prev = NULL;
1938 c->buckets[i] = img;
1942 /* Call FN on every image in the image cache of frame F. Used to mark
1943 Lisp Objects in the image cache. */
1945 /* Mark Lisp objects in image IMG. */
1947 static void
1948 mark_image (img)
1949 struct image *img;
1951 mark_object (img->spec);
1952 mark_object (img->dependencies);
1954 if (!NILP (img->data.lisp_val))
1955 mark_object (img->data.lisp_val);
1959 void
1960 mark_image_cache (struct image_cache *c)
1962 if (c)
1964 int i;
1965 for (i = 0; i < c->used; ++i)
1966 if (c->images[i])
1967 mark_image (c->images[i]);
1973 /***********************************************************************
1974 X / NS / W32 support code
1975 ***********************************************************************/
1977 #ifdef HAVE_NTGUI
1979 /* Macro for defining functions that will be loaded from image DLLs. */
1980 #define DEF_IMGLIB_FN(rettype, func) rettype (FAR CDECL *fn_##func)()
1982 /* Macro for loading those image functions from the library. */
1983 #define LOAD_IMGLIB_FN(lib,func) { \
1984 fn_##func = (void *) GetProcAddress (lib, #func); \
1985 if (!fn_##func) return 0; \
1988 /* Load a DLL implementing an image type.
1989 The `image-library-alist' variable associates a symbol,
1990 identifying an image type, to a list of possible filenames.
1991 The function returns NULL if no library could be loaded for
1992 the given image type, or if the library was previously loaded;
1993 else the handle of the DLL. */
1994 static HMODULE
1995 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
1997 HMODULE library = NULL;
1999 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2001 Lisp_Object dlls = Fassq (type, libraries);
2003 if (CONSP (dlls))
2004 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2006 CHECK_STRING_CAR (dlls);
2007 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2008 break;
2012 return library;
2015 #endif /* HAVE_NTGUI */
2017 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2018 XImagePtr *, Pixmap *));
2019 static void x_destroy_x_image P_ ((XImagePtr));
2020 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2023 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2024 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2025 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2026 via xmalloc. Print error messages via image_error if an error
2027 occurs. Value is non-zero if successful.
2029 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2030 should indicate the bit depth of the image. */
2032 static int
2033 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2034 struct frame *f;
2035 int width, height, depth;
2036 XImagePtr *ximg;
2037 Pixmap *pixmap;
2039 #ifdef HAVE_X_WINDOWS
2040 Display *display = FRAME_X_DISPLAY (f);
2041 Window window = FRAME_X_WINDOW (f);
2042 Screen *screen = FRAME_X_SCREEN (f);
2044 xassert (interrupt_input_blocked);
2046 if (depth <= 0)
2047 depth = DefaultDepthOfScreen (screen);
2048 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2049 depth, ZPixmap, 0, NULL, width, height,
2050 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2051 if (*ximg == NULL)
2053 image_error ("Unable to allocate X image", Qnil, Qnil);
2054 return 0;
2057 /* Allocate image raster. */
2058 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2060 /* Allocate a pixmap of the same size. */
2061 *pixmap = XCreatePixmap (display, window, width, height, depth);
2062 if (*pixmap == NO_PIXMAP)
2064 x_destroy_x_image (*ximg);
2065 *ximg = NULL;
2066 image_error ("Unable to create X pixmap", Qnil, Qnil);
2067 return 0;
2070 return 1;
2071 #endif /* HAVE_X_WINDOWS */
2073 #ifdef HAVE_NTGUI
2075 BITMAPINFOHEADER *header;
2076 HDC hdc;
2077 int scanline_width_bits;
2078 int remainder;
2079 int palette_colors = 0;
2081 if (depth == 0)
2082 depth = 24;
2084 if (depth != 1 && depth != 4 && depth != 8
2085 && depth != 16 && depth != 24 && depth != 32)
2087 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2088 return 0;
2091 scanline_width_bits = width * depth;
2092 remainder = scanline_width_bits % 32;
2094 if (remainder)
2095 scanline_width_bits += 32 - remainder;
2097 /* Bitmaps with a depth less than 16 need a palette. */
2098 /* BITMAPINFO structure already contains the first RGBQUAD. */
2099 if (depth < 16)
2100 palette_colors = 1 << depth - 1;
2102 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2103 if (*ximg == NULL)
2105 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2106 return 0;
2109 header = &((*ximg)->info.bmiHeader);
2110 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2111 header->biSize = sizeof (*header);
2112 header->biWidth = width;
2113 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2114 header->biPlanes = 1;
2115 header->biBitCount = depth;
2116 header->biCompression = BI_RGB;
2117 header->biClrUsed = palette_colors;
2119 /* TODO: fill in palette. */
2120 if (depth == 1)
2122 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2123 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2124 (*ximg)->info.bmiColors[0].rgbRed = 0;
2125 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2126 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2127 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2128 (*ximg)->info.bmiColors[1].rgbRed = 255;
2129 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2132 hdc = get_frame_dc (f);
2134 /* Create a DIBSection and raster array for the bitmap,
2135 and store its handle in *pixmap. */
2136 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2137 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2138 /* casting avoids a GCC warning */
2139 (void **)&((*ximg)->data), NULL, 0);
2141 /* Realize display palette and garbage all frames. */
2142 release_frame_dc (f, hdc);
2144 if (*pixmap == NULL)
2146 DWORD err = GetLastError ();
2147 Lisp_Object errcode;
2148 /* All system errors are < 10000, so the following is safe. */
2149 XSETINT (errcode, (int) err);
2150 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2151 x_destroy_x_image (*ximg);
2152 return 0;
2155 return 1;
2157 #endif /* HAVE_NTGUI */
2159 #ifdef HAVE_NS
2160 *pixmap = ns_image_for_XPM(width, height, depth);
2161 if (*pixmap == 0)
2163 *ximg = NULL;
2164 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2165 return 0;
2167 *ximg = *pixmap;
2168 return 1;
2169 #endif
2173 /* Destroy XImage XIMG. Free XIMG->data. */
2175 static void
2176 x_destroy_x_image (ximg)
2177 XImagePtr ximg;
2179 xassert (interrupt_input_blocked);
2180 if (ximg)
2182 #ifdef HAVE_X_WINDOWS
2183 xfree (ximg->data);
2184 ximg->data = NULL;
2185 XDestroyImage (ximg);
2186 #endif /* HAVE_X_WINDOWS */
2187 #ifdef HAVE_NTGUI
2188 /* Data will be freed by DestroyObject. */
2189 ximg->data = NULL;
2190 xfree (ximg);
2191 #endif /* HAVE_NTGUI */
2192 #ifdef HAVE_NS
2193 ns_release_object(ximg);
2194 #endif /* HAVE_NS */
2199 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2200 are width and height of both the image and pixmap. */
2202 static void
2203 x_put_x_image (f, ximg, pixmap, width, height)
2204 struct frame *f;
2205 XImagePtr ximg;
2206 Pixmap pixmap;
2207 int width, height;
2209 #ifdef HAVE_X_WINDOWS
2210 GC gc;
2212 xassert (interrupt_input_blocked);
2213 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2214 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2215 XFreeGC (FRAME_X_DISPLAY (f), gc);
2216 #endif /* HAVE_X_WINDOWS */
2218 #ifdef HAVE_NTGUI
2219 #if 0 /* I don't think this is necessary looking at where it is used. */
2220 HDC hdc = get_frame_dc (f);
2221 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2222 release_frame_dc (f, hdc);
2223 #endif
2224 #endif /* HAVE_NTGUI */
2226 #ifdef HAVE_NS
2227 xassert (ximg == pixmap);
2228 ns_retain_object(ximg);
2229 #endif
2233 /***********************************************************************
2234 File Handling
2235 ***********************************************************************/
2237 static unsigned char *slurp_file P_ ((char *, int *));
2240 /* Find image file FILE. Look in data-directory/images, then
2241 x-bitmap-file-path. Value is the encoded full name of the file
2242 found, or nil if not found. */
2244 Lisp_Object
2245 x_find_image_file (file)
2246 Lisp_Object file;
2248 Lisp_Object file_found, search_path;
2249 struct gcpro gcpro1, gcpro2;
2250 int fd;
2252 file_found = Qnil;
2253 /* TODO I think this should use something like image-load-path
2254 instead. Unfortunately, that can contain non-string elements. */
2255 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2256 Vdata_directory),
2257 Vx_bitmap_file_path);
2258 GCPRO2 (file_found, search_path);
2260 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2261 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2263 if (fd == -1)
2264 file_found = Qnil;
2265 else
2267 file_found = ENCODE_FILE (file_found);
2268 close (fd);
2271 UNGCPRO;
2272 return file_found;
2276 /* Read FILE into memory. Value is a pointer to a buffer allocated
2277 with xmalloc holding FILE's contents. Value is null if an error
2278 occurred. *SIZE is set to the size of the file. */
2280 static unsigned char *
2281 slurp_file (file, size)
2282 char *file;
2283 int *size;
2285 FILE *fp = NULL;
2286 unsigned char *buf = NULL;
2287 struct stat st;
2289 if (stat (file, &st) == 0
2290 && (fp = fopen (file, "rb")) != NULL
2291 && (buf = (unsigned char *) xmalloc (st.st_size),
2292 fread (buf, 1, st.st_size, fp) == st.st_size))
2294 *size = st.st_size;
2295 fclose (fp);
2297 else
2299 if (fp)
2300 fclose (fp);
2301 if (buf)
2303 xfree (buf);
2304 buf = NULL;
2308 return buf;
2313 /***********************************************************************
2314 XBM images
2315 ***********************************************************************/
2317 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
2318 static int xbm_load P_ ((struct frame *f, struct image *img));
2319 static int xbm_load_image P_ ((struct frame *f, struct image *img,
2320 unsigned char *, unsigned char *));
2321 static int xbm_image_p P_ ((Lisp_Object object));
2322 static int xbm_read_bitmap_data P_ ((struct frame *f,
2323 unsigned char *, unsigned char *,
2324 int *, int *, unsigned char **, int));
2325 static int xbm_file_p P_ ((Lisp_Object));
2328 /* Indices of image specification fields in xbm_format, below. */
2330 enum xbm_keyword_index
2332 XBM_TYPE,
2333 XBM_FILE,
2334 XBM_WIDTH,
2335 XBM_HEIGHT,
2336 XBM_DATA,
2337 XBM_FOREGROUND,
2338 XBM_BACKGROUND,
2339 XBM_ASCENT,
2340 XBM_MARGIN,
2341 XBM_RELIEF,
2342 XBM_ALGORITHM,
2343 XBM_HEURISTIC_MASK,
2344 XBM_MASK,
2345 XBM_LAST
2348 /* Vector of image_keyword structures describing the format
2349 of valid XBM image specifications. */
2351 static const struct image_keyword xbm_format[XBM_LAST] =
2353 {":type", IMAGE_SYMBOL_VALUE, 1},
2354 {":file", IMAGE_STRING_VALUE, 0},
2355 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2356 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2357 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2358 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2359 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2360 {":ascent", IMAGE_ASCENT_VALUE, 0},
2361 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2362 {":relief", IMAGE_INTEGER_VALUE, 0},
2363 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2364 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2365 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2368 /* Structure describing the image type XBM. */
2370 static struct image_type xbm_type =
2372 &Qxbm,
2373 xbm_image_p,
2374 xbm_load,
2375 x_clear_image,
2376 NULL
2379 /* Tokens returned from xbm_scan. */
2381 enum xbm_token
2383 XBM_TK_IDENT = 256,
2384 XBM_TK_NUMBER
2388 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2389 A valid specification is a list starting with the symbol `image'
2390 The rest of the list is a property list which must contain an
2391 entry `:type xbm..
2393 If the specification specifies a file to load, it must contain
2394 an entry `:file FILENAME' where FILENAME is a string.
2396 If the specification is for a bitmap loaded from memory it must
2397 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2398 WIDTH and HEIGHT are integers > 0. DATA may be:
2400 1. a string large enough to hold the bitmap data, i.e. it must
2401 have a size >= (WIDTH + 7) / 8 * HEIGHT
2403 2. a bool-vector of size >= WIDTH * HEIGHT
2405 3. a vector of strings or bool-vectors, one for each line of the
2406 bitmap.
2408 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
2409 may not be specified in this case because they are defined in the
2410 XBM file.
2412 Both the file and data forms may contain the additional entries
2413 `:background COLOR' and `:foreground COLOR'. If not present,
2414 foreground and background of the frame on which the image is
2415 displayed is used. */
2417 static int
2418 xbm_image_p (object)
2419 Lisp_Object object;
2421 struct image_keyword kw[XBM_LAST];
2423 bcopy (xbm_format, kw, sizeof kw);
2424 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2425 return 0;
2427 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2429 if (kw[XBM_FILE].count)
2431 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2432 return 0;
2434 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2436 /* In-memory XBM file. */
2437 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2438 return 0;
2440 else
2442 Lisp_Object data;
2443 int width, height;
2445 /* Entries for `:width', `:height' and `:data' must be present. */
2446 if (!kw[XBM_WIDTH].count
2447 || !kw[XBM_HEIGHT].count
2448 || !kw[XBM_DATA].count)
2449 return 0;
2451 data = kw[XBM_DATA].value;
2452 width = XFASTINT (kw[XBM_WIDTH].value);
2453 height = XFASTINT (kw[XBM_HEIGHT].value);
2455 /* Check type of data, and width and height against contents of
2456 data. */
2457 if (VECTORP (data))
2459 int i;
2461 /* Number of elements of the vector must be >= height. */
2462 if (XVECTOR_SIZE (data) < height)
2463 return 0;
2465 /* Each string or bool-vector in data must be large enough
2466 for one line of the image. */
2467 for (i = 0; i < height; ++i)
2469 Lisp_Object elt = XVECTOR (data)->contents[i];
2471 if (STRINGP (elt))
2473 if (SCHARS (elt)
2474 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2475 return 0;
2477 else if (BOOL_VECTOR_P (elt))
2479 if (XBOOL_VECTOR (elt)->size < width)
2480 return 0;
2482 else
2483 return 0;
2486 else if (STRINGP (data))
2488 if (SCHARS (data)
2489 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2490 return 0;
2492 else if (BOOL_VECTOR_P (data))
2494 if (XBOOL_VECTOR (data)->size < width * height)
2495 return 0;
2497 else
2498 return 0;
2501 return 1;
2505 /* Scan a bitmap file. FP is the stream to read from. Value is
2506 either an enumerator from enum xbm_token, or a character for a
2507 single-character token, or 0 at end of file. If scanning an
2508 identifier, store the lexeme of the identifier in SVAL. If
2509 scanning a number, store its value in *IVAL. */
2511 static int
2512 xbm_scan (s, end, sval, ival)
2513 unsigned char **s, *end;
2514 char *sval;
2515 int *ival;
2517 unsigned int c;
2519 loop:
2521 /* Skip white space. */
2522 while (*s < end && (c = *(*s)++, isspace (c)))
2525 if (*s >= end)
2526 c = 0;
2527 else if (isdigit (c))
2529 int value = 0, digit;
2531 if (c == '0' && *s < end)
2533 c = *(*s)++;
2534 if (c == 'x' || c == 'X')
2536 while (*s < end)
2538 c = *(*s)++;
2539 if (isdigit (c))
2540 digit = c - '0';
2541 else if (c >= 'a' && c <= 'f')
2542 digit = c - 'a' + 10;
2543 else if (c >= 'A' && c <= 'F')
2544 digit = c - 'A' + 10;
2545 else
2546 break;
2547 value = 16 * value + digit;
2550 else if (isdigit (c))
2552 value = c - '0';
2553 while (*s < end
2554 && (c = *(*s)++, isdigit (c)))
2555 value = 8 * value + c - '0';
2558 else
2560 value = c - '0';
2561 while (*s < end
2562 && (c = *(*s)++, isdigit (c)))
2563 value = 10 * value + c - '0';
2566 if (*s < end)
2567 *s = *s - 1;
2568 *ival = value;
2569 c = XBM_TK_NUMBER;
2571 else if (isalpha (c) || c == '_')
2573 *sval++ = c;
2574 while (*s < end
2575 && (c = *(*s)++, (isalnum (c) || c == '_')))
2576 *sval++ = c;
2577 *sval = 0;
2578 if (*s < end)
2579 *s = *s - 1;
2580 c = XBM_TK_IDENT;
2582 else if (c == '/' && **s == '*')
2584 /* C-style comment. */
2585 ++*s;
2586 while (**s && (**s != '*' || *(*s + 1) != '/'))
2587 ++*s;
2588 if (**s)
2590 *s += 2;
2591 goto loop;
2595 return c;
2598 #ifdef HAVE_NTGUI
2600 /* Create a Windows bitmap from X bitmap data. */
2601 static HBITMAP
2602 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2604 static unsigned char swap_nibble[16]
2605 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2606 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2607 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2608 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2609 int i, j, w1, w2;
2610 unsigned char *bits, *p;
2611 HBITMAP bmp;
2613 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2614 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2615 bits = (unsigned char *) alloca (height * w2);
2616 bzero (bits, height * w2);
2617 for (i = 0; i < height; i++)
2619 p = bits + i*w2;
2620 for (j = 0; j < w1; j++)
2622 /* Bitswap XBM bytes to match how Windows does things. */
2623 unsigned char c = *data++;
2624 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2625 | (swap_nibble[(c>>4) & 0xf]));
2628 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2630 return bmp;
2633 static void
2634 convert_mono_to_color_image (f, img, foreground, background)
2635 struct frame *f;
2636 struct image *img;
2637 COLORREF foreground, background;
2639 HDC hdc, old_img_dc, new_img_dc;
2640 HGDIOBJ old_prev, new_prev;
2641 HBITMAP new_pixmap;
2643 hdc = get_frame_dc (f);
2644 old_img_dc = CreateCompatibleDC (hdc);
2645 new_img_dc = CreateCompatibleDC (hdc);
2646 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2647 release_frame_dc (f, hdc);
2648 old_prev = SelectObject (old_img_dc, img->pixmap);
2649 new_prev = SelectObject (new_img_dc, new_pixmap);
2650 /* Windows convention for mono bitmaps is black = background,
2651 white = foreground. */
2652 SetTextColor (new_img_dc, background);
2653 SetBkColor (new_img_dc, foreground);
2655 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2656 0, 0, SRCCOPY);
2658 SelectObject (old_img_dc, old_prev);
2659 SelectObject (new_img_dc, new_prev);
2660 DeleteDC (old_img_dc);
2661 DeleteDC (new_img_dc);
2662 DeleteObject (img->pixmap);
2663 if (new_pixmap == 0)
2664 fprintf (stderr, "Failed to convert image to color.\n");
2665 else
2666 img->pixmap = new_pixmap;
2669 #define XBM_BIT_SHUFFLE(b) (~(b))
2671 #else
2673 #define XBM_BIT_SHUFFLE(b) (b)
2675 #endif /* HAVE_NTGUI */
2678 static void
2679 Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
2680 struct frame *f;
2681 struct image *img;
2682 char *data;
2683 RGB_PIXEL_COLOR fg, bg;
2684 int non_default_colors;
2686 #ifdef HAVE_NTGUI
2687 img->pixmap
2688 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2690 /* If colors were specified, transfer the bitmap to a color one. */
2691 if (non_default_colors)
2692 convert_mono_to_color_image (f, img, fg, bg);
2694 #elif defined (HAVE_NS)
2695 img->pixmap = ns_image_from_XBM(data, img->width, img->height);
2697 #else
2698 img->pixmap
2699 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2700 FRAME_X_WINDOW (f),
2701 data,
2702 img->width, img->height,
2703 fg, bg,
2704 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
2705 #endif /* !HAVE_NTGUI && !HAVE_NS */
2710 /* Replacement for XReadBitmapFileData which isn't available under old
2711 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2712 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2713 the image. Return in *DATA the bitmap data allocated with xmalloc.
2714 Value is non-zero if successful. DATA null means just test if
2715 CONTENTS looks like an in-memory XBM file. If INHIBIT_IMAGE_ERROR
2716 is non-zero, inhibit the call to image_error when the image size is
2717 invalid (the bitmap remains unread). */
2719 static int
2720 xbm_read_bitmap_data (f, contents, end, width, height, data, inhibit_image_error)
2721 struct frame *f;
2722 unsigned char *contents, *end;
2723 int *width, *height;
2724 unsigned char **data;
2725 int inhibit_image_error;
2727 unsigned char *s = contents;
2728 char buffer[BUFSIZ];
2729 int padding_p = 0;
2730 int v10 = 0;
2731 int bytes_per_line, i, nbytes;
2732 unsigned char *p;
2733 int value;
2734 int LA1;
2736 #define match() \
2737 LA1 = xbm_scan (&s, end, buffer, &value)
2739 #define expect(TOKEN) \
2740 if (LA1 != (TOKEN)) \
2741 goto failure; \
2742 else \
2743 match ()
2745 #define expect_ident(IDENT) \
2746 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2747 match (); \
2748 else \
2749 goto failure
2751 *width = *height = -1;
2752 if (data)
2753 *data = NULL;
2754 LA1 = xbm_scan (&s, end, buffer, &value);
2756 /* Parse defines for width, height and hot-spots. */
2757 while (LA1 == '#')
2759 match ();
2760 expect_ident ("define");
2761 expect (XBM_TK_IDENT);
2763 if (LA1 == XBM_TK_NUMBER)
2765 char *p = strrchr (buffer, '_');
2766 p = p ? p + 1 : buffer;
2767 if (strcmp (p, "width") == 0)
2768 *width = value;
2769 else if (strcmp (p, "height") == 0)
2770 *height = value;
2772 expect (XBM_TK_NUMBER);
2775 if (!check_image_size (f, *width, *height))
2777 if (!inhibit_image_error)
2778 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
2779 goto failure;
2781 else if (data == NULL)
2782 goto success;
2784 /* Parse bits. Must start with `static'. */
2785 expect_ident ("static");
2786 if (LA1 == XBM_TK_IDENT)
2788 if (strcmp (buffer, "unsigned") == 0)
2790 match ();
2791 expect_ident ("char");
2793 else if (strcmp (buffer, "short") == 0)
2795 match ();
2796 v10 = 1;
2797 if (*width % 16 && *width % 16 < 9)
2798 padding_p = 1;
2800 else if (strcmp (buffer, "char") == 0)
2801 match ();
2802 else
2803 goto failure;
2805 else
2806 goto failure;
2808 expect (XBM_TK_IDENT);
2809 expect ('[');
2810 expect (']');
2811 expect ('=');
2812 expect ('{');
2814 bytes_per_line = (*width + 7) / 8 + padding_p;
2815 nbytes = bytes_per_line * *height;
2816 p = *data = (unsigned char *) xmalloc (nbytes);
2818 if (v10)
2820 for (i = 0; i < nbytes; i += 2)
2822 int val = value;
2823 expect (XBM_TK_NUMBER);
2825 *p++ = XBM_BIT_SHUFFLE (val);
2826 if (!padding_p || ((i + 2) % bytes_per_line))
2827 *p++ = XBM_BIT_SHUFFLE (value >> 8);
2829 if (LA1 == ',' || LA1 == '}')
2830 match ();
2831 else
2832 goto failure;
2835 else
2837 for (i = 0; i < nbytes; ++i)
2839 int val = value;
2840 expect (XBM_TK_NUMBER);
2842 *p++ = XBM_BIT_SHUFFLE (val);
2844 if (LA1 == ',' || LA1 == '}')
2845 match ();
2846 else
2847 goto failure;
2851 success:
2852 return 1;
2854 failure:
2856 if (data && *data)
2858 xfree (*data);
2859 *data = NULL;
2861 return 0;
2863 #undef match
2864 #undef expect
2865 #undef expect_ident
2869 /* Load XBM image IMG which will be displayed on frame F from buffer
2870 CONTENTS. END is the end of the buffer. Value is non-zero if
2871 successful. */
2873 static int
2874 xbm_load_image (f, img, contents, end)
2875 struct frame *f;
2876 struct image *img;
2877 unsigned char *contents, *end;
2879 int rc;
2880 unsigned char *data;
2881 int success_p = 0;
2883 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height,
2884 &data, 0);
2885 if (rc)
2887 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2888 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2889 int non_default_colors = 0;
2890 Lisp_Object value;
2892 xassert (img->width > 0 && img->height > 0);
2894 /* Get foreground and background colors, maybe allocate colors. */
2895 value = image_spec_value (img->spec, QCforeground, NULL);
2896 if (!NILP (value))
2898 foreground = x_alloc_image_color (f, img, value, foreground);
2899 non_default_colors = 1;
2901 value = image_spec_value (img->spec, QCbackground, NULL);
2902 if (!NILP (value))
2904 background = x_alloc_image_color (f, img, value, background);
2905 img->background = background;
2906 img->background_valid = 1;
2907 non_default_colors = 1;
2910 Create_Pixmap_From_Bitmap_Data (f, img, data,
2911 foreground, background,
2912 non_default_colors);
2913 xfree (data);
2915 if (img->pixmap == NO_PIXMAP)
2917 x_clear_image (f, img);
2918 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
2920 else
2921 success_p = 1;
2923 else
2924 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2926 return success_p;
2930 /* Value is non-zero if DATA looks like an in-memory XBM file. */
2932 static int
2933 xbm_file_p (data)
2934 Lisp_Object data;
2936 int w, h;
2937 return (STRINGP (data)
2938 && xbm_read_bitmap_data (NULL, SDATA (data),
2939 (SDATA (data) + SBYTES (data)),
2940 &w, &h, NULL, 1));
2944 /* Fill image IMG which is used on frame F with pixmap data. Value is
2945 non-zero if successful. */
2947 static int
2948 xbm_load (f, img)
2949 struct frame *f;
2950 struct image *img;
2952 int success_p = 0;
2953 Lisp_Object file_name;
2955 xassert (xbm_image_p (img->spec));
2957 /* If IMG->spec specifies a file name, create a non-file spec from it. */
2958 file_name = image_spec_value (img->spec, QCfile, NULL);
2959 if (STRINGP (file_name))
2961 Lisp_Object file;
2962 unsigned char *contents;
2963 int size;
2964 struct gcpro gcpro1;
2966 file = x_find_image_file (file_name);
2967 GCPRO1 (file);
2968 if (!STRINGP (file))
2970 image_error ("Cannot find image file `%s'", file_name, Qnil);
2971 UNGCPRO;
2972 return 0;
2975 contents = slurp_file (SDATA (file), &size);
2976 if (contents == NULL)
2978 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
2979 UNGCPRO;
2980 return 0;
2983 success_p = xbm_load_image (f, img, contents, contents + size);
2984 UNGCPRO;
2986 else
2988 struct image_keyword fmt[XBM_LAST];
2989 Lisp_Object data;
2990 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2991 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2992 int non_default_colors = 0;
2993 char *bits;
2994 int parsed_p;
2995 int in_memory_file_p = 0;
2997 /* See if data looks like an in-memory XBM file. */
2998 data = image_spec_value (img->spec, QCdata, NULL);
2999 in_memory_file_p = xbm_file_p (data);
3001 /* Parse the image specification. */
3002 bcopy (xbm_format, fmt, sizeof fmt);
3003 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3004 xassert (parsed_p);
3006 /* Get specified width, and height. */
3007 if (!in_memory_file_p)
3009 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3010 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3011 xassert (img->width > 0 && img->height > 0);
3014 /* Get foreground and background colors, maybe allocate colors. */
3015 if (fmt[XBM_FOREGROUND].count
3016 && STRINGP (fmt[XBM_FOREGROUND].value))
3018 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3019 foreground);
3020 non_default_colors = 1;
3023 if (fmt[XBM_BACKGROUND].count
3024 && STRINGP (fmt[XBM_BACKGROUND].value))
3026 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3027 background);
3028 non_default_colors = 1;
3031 if (in_memory_file_p)
3032 success_p = xbm_load_image (f, img, SDATA (data),
3033 (SDATA (data)
3034 + SBYTES (data)));
3035 else
3037 if (VECTORP (data))
3039 int i;
3040 char *p;
3041 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3043 p = bits = (char *) alloca (nbytes * img->height);
3044 for (i = 0; i < img->height; ++i, p += nbytes)
3046 Lisp_Object line = XVECTOR (data)->contents[i];
3047 if (STRINGP (line))
3048 bcopy (SDATA (line), p, nbytes);
3049 else
3050 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3053 else if (STRINGP (data))
3054 bits = SDATA (data);
3055 else
3056 bits = XBOOL_VECTOR (data)->data;
3058 #ifdef WINDOWSNT
3060 char *invertedBits;
3061 int nbytes, i;
3062 /* Windows mono bitmaps are reversed compared with X. */
3063 invertedBits = bits;
3064 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3065 * img->height;
3066 bits = (char *) alloca(nbytes);
3067 for (i = 0; i < nbytes; i++)
3068 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3070 #endif
3071 /* Create the pixmap. */
3073 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3074 foreground, background,
3075 non_default_colors);
3076 if (img->pixmap)
3077 success_p = 1;
3078 else
3080 image_error ("Unable to create pixmap for XBM image `%s'",
3081 img->spec, Qnil);
3082 x_clear_image (f, img);
3087 return success_p;
3092 /***********************************************************************
3093 XPM images
3094 ***********************************************************************/
3096 #if defined (HAVE_XPM) || defined (HAVE_NS)
3098 static int xpm_image_p P_ ((Lisp_Object object));
3099 static int xpm_load P_ ((struct frame *f, struct image *img));
3100 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3102 #endif /* HAVE_XPM || HAVE_NS */
3104 #ifdef HAVE_XPM
3105 #ifdef HAVE_NTGUI
3106 /* Indicate to xpm.h that we don't have Xlib. */
3107 #define FOR_MSW
3108 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3109 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3110 #define XColor xpm_XColor
3111 #define XImage xpm_XImage
3112 #define Display xpm_Display
3113 #define PIXEL_ALREADY_TYPEDEFED
3114 #include "X11/xpm.h"
3115 #undef FOR_MSW
3116 #undef XColor
3117 #undef XImage
3118 #undef Display
3119 #undef PIXEL_ALREADY_TYPEDEFED
3120 #else
3121 #include "X11/xpm.h"
3122 #endif /* HAVE_NTGUI */
3123 #endif /* HAVE_XPM */
3125 #if defined (HAVE_XPM) || defined (HAVE_NS)
3126 /* The symbol `xpm' identifying XPM-format images. */
3128 Lisp_Object Qxpm;
3130 /* Indices of image specification fields in xpm_format, below. */
3132 enum xpm_keyword_index
3134 XPM_TYPE,
3135 XPM_FILE,
3136 XPM_DATA,
3137 XPM_ASCENT,
3138 XPM_MARGIN,
3139 XPM_RELIEF,
3140 XPM_ALGORITHM,
3141 XPM_HEURISTIC_MASK,
3142 XPM_MASK,
3143 XPM_COLOR_SYMBOLS,
3144 XPM_BACKGROUND,
3145 XPM_LAST
3148 /* Vector of image_keyword structures describing the format
3149 of valid XPM image specifications. */
3151 static const struct image_keyword xpm_format[XPM_LAST] =
3153 {":type", IMAGE_SYMBOL_VALUE, 1},
3154 {":file", IMAGE_STRING_VALUE, 0},
3155 {":data", IMAGE_STRING_VALUE, 0},
3156 {":ascent", IMAGE_ASCENT_VALUE, 0},
3157 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3158 {":relief", IMAGE_INTEGER_VALUE, 0},
3159 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3160 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3161 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3162 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3163 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3166 /* Structure describing the image type XPM. */
3168 static struct image_type xpm_type =
3170 &Qxpm,
3171 xpm_image_p,
3172 xpm_load,
3173 x_clear_image,
3174 NULL
3177 #ifdef HAVE_X_WINDOWS
3179 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3180 functions for allocating image colors. Our own functions handle
3181 color allocation failures more gracefully than the ones on the XPM
3182 lib. */
3184 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3185 #define ALLOC_XPM_COLORS
3186 #endif
3187 #endif /* HAVE_X_WINDOWS */
3189 #ifdef ALLOC_XPM_COLORS
3191 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3192 static void xpm_free_color_cache P_ ((void));
3193 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3194 static int xpm_color_bucket P_ ((char *));
3195 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3196 XColor *, int));
3198 /* An entry in a hash table used to cache color definitions of named
3199 colors. This cache is necessary to speed up XPM image loading in
3200 case we do color allocations ourselves. Without it, we would need
3201 a call to XParseColor per pixel in the image. */
3203 struct xpm_cached_color
3205 /* Next in collision chain. */
3206 struct xpm_cached_color *next;
3208 /* Color definition (RGB and pixel color). */
3209 XColor color;
3211 /* Color name. */
3212 char name[1];
3215 /* The hash table used for the color cache, and its bucket vector
3216 size. */
3218 #define XPM_COLOR_CACHE_BUCKETS 1001
3219 struct xpm_cached_color **xpm_color_cache;
3221 /* Initialize the color cache. */
3223 static void
3224 xpm_init_color_cache (f, attrs)
3225 struct frame *f;
3226 XpmAttributes *attrs;
3228 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3229 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3230 memset (xpm_color_cache, 0, nbytes);
3231 init_color_table ();
3233 if (attrs->valuemask & XpmColorSymbols)
3235 int i;
3236 XColor color;
3238 for (i = 0; i < attrs->numsymbols; ++i)
3239 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3240 attrs->colorsymbols[i].value, &color))
3242 color.pixel = lookup_rgb_color (f, color.red, color.green,
3243 color.blue);
3244 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3249 /* Free the color cache. */
3251 static void
3252 xpm_free_color_cache ()
3254 struct xpm_cached_color *p, *next;
3255 int i;
3257 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3258 for (p = xpm_color_cache[i]; p; p = next)
3260 next = p->next;
3261 xfree (p);
3264 xfree (xpm_color_cache);
3265 xpm_color_cache = NULL;
3266 free_color_table ();
3269 /* Return the bucket index for color named COLOR_NAME in the color
3270 cache. */
3272 static int
3273 xpm_color_bucket (color_name)
3274 char *color_name;
3276 unsigned h = 0;
3277 char *s;
3279 for (s = color_name; *s; ++s)
3280 h = (h << 2) ^ *s;
3281 return h %= XPM_COLOR_CACHE_BUCKETS;
3285 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3286 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3287 entry added. */
3289 static struct xpm_cached_color *
3290 xpm_cache_color (f, color_name, color, bucket)
3291 struct frame *f;
3292 char *color_name;
3293 XColor *color;
3294 int bucket;
3296 size_t nbytes;
3297 struct xpm_cached_color *p;
3299 if (bucket < 0)
3300 bucket = xpm_color_bucket (color_name);
3302 nbytes = sizeof *p + strlen (color_name);
3303 p = (struct xpm_cached_color *) xmalloc (nbytes);
3304 strcpy (p->name, color_name);
3305 p->color = *color;
3306 p->next = xpm_color_cache[bucket];
3307 xpm_color_cache[bucket] = p;
3308 return p;
3311 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3312 return the cached definition in *COLOR. Otherwise, make a new
3313 entry in the cache and allocate the color. Value is zero if color
3314 allocation failed. */
3316 static int
3317 xpm_lookup_color (f, color_name, color)
3318 struct frame *f;
3319 char *color_name;
3320 XColor *color;
3322 struct xpm_cached_color *p;
3323 int h = xpm_color_bucket (color_name);
3325 for (p = xpm_color_cache[h]; p; p = p->next)
3326 if (strcmp (p->name, color_name) == 0)
3327 break;
3329 if (p != NULL)
3330 *color = p->color;
3331 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3332 color_name, color))
3334 color->pixel = lookup_rgb_color (f, color->red, color->green,
3335 color->blue);
3336 p = xpm_cache_color (f, color_name, color, h);
3338 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3339 with transparency, and it's useful. */
3340 else if (strcmp ("opaque", color_name) == 0)
3342 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
3343 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3344 p = xpm_cache_color (f, color_name, color, h);
3347 return p != NULL;
3351 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3352 CLOSURE is a pointer to the frame on which we allocate the
3353 color. Return in *COLOR the allocated color. Value is non-zero
3354 if successful. */
3356 static int
3357 xpm_alloc_color (dpy, cmap, color_name, color, closure)
3358 Display *dpy;
3359 Colormap cmap;
3360 char *color_name;
3361 XColor *color;
3362 void *closure;
3364 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3368 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3369 is a pointer to the frame on which we allocate the color. Value is
3370 non-zero if successful. */
3372 static int
3373 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
3374 Display *dpy;
3375 Colormap cmap;
3376 Pixel *pixels;
3377 int npixels;
3378 void *closure;
3380 return 1;
3383 #endif /* ALLOC_XPM_COLORS */
3386 #ifdef HAVE_NTGUI
3388 /* XPM library details. */
3390 DEF_IMGLIB_FN (void, XpmFreeAttributes);
3391 DEF_IMGLIB_FN (int, XpmCreateImageFromBuffer);
3392 DEF_IMGLIB_FN (int, XpmReadFileToImage);
3393 DEF_IMGLIB_FN (void, XImageFree);
3395 static int
3396 init_xpm_functions (Lisp_Object libraries)
3398 HMODULE library;
3400 if (!(library = w32_delayed_load (libraries, Qxpm)))
3401 return 0;
3403 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3404 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3405 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3406 LOAD_IMGLIB_FN (library, XImageFree);
3407 return 1;
3410 #endif /* HAVE_NTGUI */
3413 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3414 for XPM images. Such a list must consist of conses whose car and
3415 cdr are strings. */
3417 static int
3418 xpm_valid_color_symbols_p (color_symbols)
3419 Lisp_Object color_symbols;
3421 while (CONSP (color_symbols))
3423 Lisp_Object sym = XCAR (color_symbols);
3424 if (!CONSP (sym)
3425 || !STRINGP (XCAR (sym))
3426 || !STRINGP (XCDR (sym)))
3427 break;
3428 color_symbols = XCDR (color_symbols);
3431 return NILP (color_symbols);
3435 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3437 static int
3438 xpm_image_p (object)
3439 Lisp_Object object;
3441 struct image_keyword fmt[XPM_LAST];
3442 bcopy (xpm_format, fmt, sizeof fmt);
3443 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3444 /* Either `:file' or `:data' must be present. */
3445 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3446 /* Either no `:color-symbols' or it's a list of conses
3447 whose car and cdr are strings. */
3448 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3449 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3452 #endif /* HAVE_XPM || HAVE_NS */
3454 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3456 x_create_bitmap_from_xpm_data (f, bits)
3457 struct frame *f;
3458 char **bits;
3460 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3461 int id, rc;
3462 XpmAttributes attrs;
3463 Pixmap bitmap, mask;
3465 bzero (&attrs, sizeof attrs);
3467 attrs.visual = FRAME_X_VISUAL (f);
3468 attrs.colormap = FRAME_X_COLORMAP (f);
3469 attrs.valuemask |= XpmVisual;
3470 attrs.valuemask |= XpmColormap;
3472 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3473 bits, &bitmap, &mask, &attrs);
3474 if (rc != XpmSuccess)
3476 XpmFreeAttributes (&attrs);
3477 return -1;
3480 id = x_allocate_bitmap_record (f);
3481 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3482 dpyinfo->bitmaps[id - 1].have_mask = 1;
3483 dpyinfo->bitmaps[id - 1].mask = mask;
3484 dpyinfo->bitmaps[id - 1].file = NULL;
3485 dpyinfo->bitmaps[id - 1].height = attrs.height;
3486 dpyinfo->bitmaps[id - 1].width = attrs.width;
3487 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3488 dpyinfo->bitmaps[id - 1].refcount = 1;
3490 XpmFreeAttributes (&attrs);
3491 return id;
3493 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3495 /* Load image IMG which will be displayed on frame F. Value is
3496 non-zero if successful. */
3498 #ifdef HAVE_XPM
3500 static int
3501 xpm_load (f, img)
3502 struct frame *f;
3503 struct image *img;
3505 int rc;
3506 XpmAttributes attrs;
3507 Lisp_Object specified_file, color_symbols;
3508 #ifdef HAVE_NTGUI
3509 HDC hdc;
3510 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3511 #endif /* HAVE_NTGUI */
3513 /* Configure the XPM lib. Use the visual of frame F. Allocate
3514 close colors. Return colors allocated. */
3515 bzero (&attrs, sizeof attrs);
3517 #ifndef HAVE_NTGUI
3518 attrs.visual = FRAME_X_VISUAL (f);
3519 attrs.colormap = FRAME_X_COLORMAP (f);
3520 attrs.valuemask |= XpmVisual;
3521 attrs.valuemask |= XpmColormap;
3522 #endif /* HAVE_NTGUI */
3524 #ifdef ALLOC_XPM_COLORS
3525 /* Allocate colors with our own functions which handle
3526 failing color allocation more gracefully. */
3527 attrs.color_closure = f;
3528 attrs.alloc_color = xpm_alloc_color;
3529 attrs.free_colors = xpm_free_colors;
3530 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3531 #else /* not ALLOC_XPM_COLORS */
3532 /* Let the XPM lib allocate colors. */
3533 attrs.valuemask |= XpmReturnAllocPixels;
3534 #ifdef XpmAllocCloseColors
3535 attrs.alloc_close_colors = 1;
3536 attrs.valuemask |= XpmAllocCloseColors;
3537 #else /* not XpmAllocCloseColors */
3538 attrs.closeness = 600;
3539 attrs.valuemask |= XpmCloseness;
3540 #endif /* not XpmAllocCloseColors */
3541 #endif /* ALLOC_XPM_COLORS */
3543 /* If image specification contains symbolic color definitions, add
3544 these to `attrs'. */
3545 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3546 if (CONSP (color_symbols))
3548 Lisp_Object tail;
3549 XpmColorSymbol *xpm_syms;
3550 int i, size;
3552 attrs.valuemask |= XpmColorSymbols;
3554 /* Count number of symbols. */
3555 attrs.numsymbols = 0;
3556 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3557 ++attrs.numsymbols;
3559 /* Allocate an XpmColorSymbol array. */
3560 size = attrs.numsymbols * sizeof *xpm_syms;
3561 xpm_syms = (XpmColorSymbol *) alloca (size);
3562 bzero (xpm_syms, size);
3563 attrs.colorsymbols = xpm_syms;
3565 /* Fill the color symbol array. */
3566 for (tail = color_symbols, i = 0;
3567 CONSP (tail);
3568 ++i, tail = XCDR (tail))
3570 Lisp_Object name = XCAR (XCAR (tail));
3571 Lisp_Object color = XCDR (XCAR (tail));
3572 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3573 strcpy (xpm_syms[i].name, SDATA (name));
3574 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3575 strcpy (xpm_syms[i].value, SDATA (color));
3579 /* Create a pixmap for the image, either from a file, or from a
3580 string buffer containing data in the same format as an XPM file. */
3581 #ifdef ALLOC_XPM_COLORS
3582 xpm_init_color_cache (f, &attrs);
3583 #endif
3585 specified_file = image_spec_value (img->spec, QCfile, NULL);
3587 #ifdef HAVE_NTGUI
3589 HDC frame_dc = get_frame_dc (f);
3590 hdc = CreateCompatibleDC (frame_dc);
3591 release_frame_dc (f, frame_dc);
3593 #endif /* HAVE_NTGUI */
3595 if (STRINGP (specified_file))
3597 Lisp_Object file = x_find_image_file (specified_file);
3598 if (!STRINGP (file))
3600 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3601 return 0;
3604 #ifdef HAVE_NTGUI
3605 /* XpmReadFileToPixmap is not available in the Windows port of
3606 libxpm. But XpmReadFileToImage almost does what we want. */
3607 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3608 &xpm_image, &xpm_mask,
3609 &attrs);
3610 #else
3611 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3612 SDATA (file), &img->pixmap, &img->mask,
3613 &attrs);
3614 #endif /* HAVE_NTGUI */
3616 else
3618 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3619 #ifdef HAVE_NTGUI
3620 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3621 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3622 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3623 &xpm_image, &xpm_mask,
3624 &attrs);
3625 #else
3626 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3627 SDATA (buffer),
3628 &img->pixmap, &img->mask,
3629 &attrs);
3630 #endif /* HAVE_NTGUI */
3633 if (rc == XpmSuccess)
3635 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3636 img->colors = colors_in_color_table (&img->ncolors);
3637 #else /* not ALLOC_XPM_COLORS */
3638 int i;
3640 #ifdef HAVE_NTGUI
3641 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3642 plus some duplicate attributes. */
3643 if (xpm_image && xpm_image->bitmap)
3645 img->pixmap = xpm_image->bitmap;
3646 /* XImageFree in libXpm frees XImage struct without destroying
3647 the bitmap, which is what we want. */
3648 fn_XImageFree (xpm_image);
3650 if (xpm_mask && xpm_mask->bitmap)
3652 /* The mask appears to be inverted compared with what we expect.
3653 TODO: invert our expectations. See other places where we
3654 have to invert bits because our idea of masks is backwards. */
3655 HGDIOBJ old_obj;
3656 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3658 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3659 SelectObject (hdc, old_obj);
3661 img->mask = xpm_mask->bitmap;
3662 fn_XImageFree (xpm_mask);
3663 DeleteDC (hdc);
3666 DeleteDC (hdc);
3667 #endif /* HAVE_NTGUI */
3669 /* Remember allocated colors. */
3670 img->ncolors = attrs.nalloc_pixels;
3671 img->colors = (unsigned long *) xmalloc (img->ncolors
3672 * sizeof *img->colors);
3673 for (i = 0; i < attrs.nalloc_pixels; ++i)
3675 img->colors[i] = attrs.alloc_pixels[i];
3676 #ifdef DEBUG_X_COLORS
3677 register_color (img->colors[i]);
3678 #endif
3680 #endif /* not ALLOC_XPM_COLORS */
3682 img->width = attrs.width;
3683 img->height = attrs.height;
3684 xassert (img->width > 0 && img->height > 0);
3686 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3687 #ifdef HAVE_NTGUI
3688 fn_XpmFreeAttributes (&attrs);
3689 #else
3690 XpmFreeAttributes (&attrs);
3691 #endif /* HAVE_NTGUI */
3693 else
3695 #ifdef HAVE_NTGUI
3696 DeleteDC (hdc);
3697 #endif /* HAVE_NTGUI */
3699 switch (rc)
3701 case XpmOpenFailed:
3702 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3703 break;
3705 case XpmFileInvalid:
3706 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3707 break;
3709 case XpmNoMemory:
3710 image_error ("Out of memory (%s)", img->spec, Qnil);
3711 break;
3713 case XpmColorFailed:
3714 image_error ("Color allocation error (%s)", img->spec, Qnil);
3715 break;
3717 default:
3718 image_error ("Unknown error (%s)", img->spec, Qnil);
3719 break;
3723 #ifdef ALLOC_XPM_COLORS
3724 xpm_free_color_cache ();
3725 #endif
3726 return rc == XpmSuccess;
3729 #endif /* HAVE_XPM */
3731 #if defined (HAVE_NS) && !defined (HAVE_XPM)
3733 /* XPM support functions for NS where libxpm is not available.
3734 Only XPM version 3 (without any extensions) is supported. */
3736 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
3737 const unsigned char **, int *));
3738 static Lisp_Object xpm_make_color_table_v
3739 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3740 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
3741 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
3742 int, Lisp_Object));
3743 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
3744 const unsigned char *, int));
3745 static Lisp_Object xpm_make_color_table_h
3746 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
3747 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
3748 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
3749 int, Lisp_Object));
3750 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
3751 const unsigned char *, int));
3752 static int xpm_str_to_color_key P_ ((const char *));
3753 static int xpm_load_image P_ ((struct frame *, struct image *,
3754 const unsigned char *, const unsigned char *));
3756 /* Tokens returned from xpm_scan. */
3758 enum xpm_token
3760 XPM_TK_IDENT = 256,
3761 XPM_TK_STRING,
3762 XPM_TK_EOF
3765 /* Scan an XPM data and return a character (< 256) or a token defined
3766 by enum xpm_token above. *S and END are the start (inclusive) and
3767 the end (exclusive) addresses of the data, respectively. Advance
3768 *S while scanning. If token is either XPM_TK_IDENT or
3769 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
3770 length of the corresponding token, respectively. */
3772 static int
3773 xpm_scan (s, end, beg, len)
3774 const unsigned char **s, *end, **beg;
3775 int *len;
3777 int c;
3779 while (*s < end)
3781 /* Skip white-space. */
3782 while (*s < end && (c = *(*s)++, isspace (c)))
3785 /* gnus-pointer.xpm uses '-' in its identifier.
3786 sb-dir-plus.xpm uses '+' in its identifier. */
3787 if (isalpha (c) || c == '_' || c == '-' || c == '+')
3789 *beg = *s - 1;
3790 while (*s < end
3791 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
3792 ++*s;
3793 *len = *s - *beg;
3794 return XPM_TK_IDENT;
3796 else if (c == '"')
3798 *beg = *s;
3799 while (*s < end && **s != '"')
3800 ++*s;
3801 *len = *s - *beg;
3802 if (*s < end)
3803 ++*s;
3804 return XPM_TK_STRING;
3806 else if (c == '/')
3808 if (*s < end && **s == '*')
3810 /* C-style comment. */
3811 ++*s;
3814 while (*s < end && *(*s)++ != '*')
3817 while (*s < end && **s != '/');
3818 if (*s < end)
3819 ++*s;
3821 else
3822 return c;
3824 else
3825 return c;
3828 return XPM_TK_EOF;
3831 /* Functions for color table lookup in XPM data. A key is a string
3832 specifying the color of each pixel in XPM data. A value is either
3833 an integer that specifies a pixel color, Qt that specifies
3834 transparency, or Qnil for the unspecified color. If the length of
3835 the key string is one, a vector is used as a table. Otherwise, a
3836 hash table is used. */
3838 static Lisp_Object
3839 xpm_make_color_table_v (put_func, get_func)
3840 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3841 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
3843 *put_func = xpm_put_color_table_v;
3844 *get_func = xpm_get_color_table_v;
3845 return Fmake_vector (make_number (256), Qnil);
3848 static void
3849 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
3850 Lisp_Object color_table;
3851 const unsigned char *chars_start;
3852 int chars_len;
3853 Lisp_Object color;
3855 XVECTOR (color_table)->contents[*chars_start] = color;
3858 static Lisp_Object
3859 xpm_get_color_table_v (color_table, chars_start, chars_len)
3860 Lisp_Object color_table;
3861 const unsigned char *chars_start;
3862 int chars_len;
3864 return XVECTOR (color_table)->contents[*chars_start];
3867 static Lisp_Object
3868 xpm_make_color_table_h (put_func, get_func)
3869 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3870 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
3872 *put_func = xpm_put_color_table_h;
3873 *get_func = xpm_get_color_table_h;
3874 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
3875 make_float (DEFAULT_REHASH_SIZE),
3876 make_float (DEFAULT_REHASH_THRESHOLD),
3877 Qnil, Qnil, Qnil);
3880 static void
3881 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
3882 Lisp_Object color_table;
3883 const unsigned char *chars_start;
3884 int chars_len;
3885 Lisp_Object color;
3887 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3888 unsigned hash_code;
3889 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
3891 hash_lookup (table, chars, &hash_code);
3892 hash_put (table, chars, color, hash_code);
3895 static Lisp_Object
3896 xpm_get_color_table_h (color_table, chars_start, chars_len)
3897 Lisp_Object color_table;
3898 const unsigned char *chars_start;
3899 int chars_len;
3901 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
3902 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
3903 NULL);
3905 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
3908 enum xpm_color_key {
3909 XPM_COLOR_KEY_S,
3910 XPM_COLOR_KEY_M,
3911 XPM_COLOR_KEY_G4,
3912 XPM_COLOR_KEY_G,
3913 XPM_COLOR_KEY_C
3916 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
3918 static int
3919 xpm_str_to_color_key (s)
3920 const char *s;
3922 int i;
3924 for (i = 0;
3925 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
3926 i++)
3927 if (strcmp (xpm_color_key_strings[i], s) == 0)
3928 return i;
3929 return -1;
3932 static int
3933 xpm_load_image (f, img, contents, end)
3934 struct frame *f;
3935 struct image *img;
3936 const unsigned char *contents, *end;
3938 const unsigned char *s = contents, *beg, *str;
3939 unsigned char buffer[BUFSIZ];
3940 int width, height, x, y;
3941 int num_colors, chars_per_pixel;
3942 int len, LA1;
3943 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
3944 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
3945 Lisp_Object frame, color_symbols, color_table;
3946 int best_key, have_mask = 0;
3947 XImagePtr ximg = NULL, mask_img = NULL;
3949 #define match() \
3950 LA1 = xpm_scan (&s, end, &beg, &len)
3952 #define expect(TOKEN) \
3953 if (LA1 != (TOKEN)) \
3954 goto failure; \
3955 else \
3956 match ()
3958 #define expect_ident(IDENT) \
3959 if (LA1 == XPM_TK_IDENT \
3960 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
3961 match (); \
3962 else \
3963 goto failure
3965 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
3966 goto failure;
3967 s += 9;
3968 match();
3969 expect_ident ("static");
3970 expect_ident ("char");
3971 expect ('*');
3972 expect (XPM_TK_IDENT);
3973 expect ('[');
3974 expect (']');
3975 expect ('=');
3976 expect ('{');
3977 expect (XPM_TK_STRING);
3978 if (len >= BUFSIZ)
3979 goto failure;
3980 memcpy (buffer, beg, len);
3981 buffer[len] = '\0';
3982 if (sscanf (buffer, "%d %d %d %d", &width, &height,
3983 &num_colors, &chars_per_pixel) != 4
3984 || width <= 0 || height <= 0
3985 || num_colors <= 0 || chars_per_pixel <= 0)
3986 goto failure;
3988 if (!check_image_size (f, width, height))
3990 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
3991 goto failure;
3994 expect (',');
3996 XSETFRAME (frame, f);
3997 if (!NILP (Fxw_display_color_p (frame)))
3998 best_key = XPM_COLOR_KEY_C;
3999 else if (!NILP (Fx_display_grayscale_p (frame)))
4000 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4001 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4002 else
4003 best_key = XPM_COLOR_KEY_M;
4005 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4006 if (chars_per_pixel == 1)
4007 color_table = xpm_make_color_table_v (&put_color_table,
4008 &get_color_table);
4009 else
4010 color_table = xpm_make_color_table_h (&put_color_table,
4011 &get_color_table);
4013 while (num_colors-- > 0)
4015 unsigned char *color, *max_color;
4016 int key, next_key, max_key = 0;
4017 Lisp_Object symbol_color = Qnil, color_val;
4018 XColor cdef;
4020 expect (XPM_TK_STRING);
4021 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4022 goto failure;
4023 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4024 buffer[len - chars_per_pixel] = '\0';
4026 str = strtok (buffer, " \t");
4027 if (str == NULL)
4028 goto failure;
4029 key = xpm_str_to_color_key (str);
4030 if (key < 0)
4031 goto failure;
4034 color = strtok (NULL, " \t");
4035 if (color == NULL)
4036 goto failure;
4038 while ((str = strtok (NULL, " \t")) != NULL)
4040 next_key = xpm_str_to_color_key (str);
4041 if (next_key >= 0)
4042 break;
4043 color[strlen (color)] = ' ';
4046 if (key == XPM_COLOR_KEY_S)
4048 if (NILP (symbol_color))
4049 symbol_color = build_string (color);
4051 else if (max_key < key && key <= best_key)
4053 max_key = key;
4054 max_color = color;
4056 key = next_key;
4058 while (str);
4060 color_val = Qnil;
4061 if (!NILP (color_symbols) && !NILP (symbol_color))
4063 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4065 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4067 if (xstrcasecmp (SDATA (XCDR (specified_color)), "None") == 0)
4068 color_val = Qt;
4069 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4070 &cdef, 0))
4071 color_val = make_number (cdef.pixel);
4074 if (NILP (color_val) && max_key > 0)
4076 if (xstrcasecmp (max_color, "None") == 0)
4077 color_val = Qt;
4078 else if (x_defined_color (f, max_color, &cdef, 0))
4079 color_val = make_number (cdef.pixel);
4081 if (!NILP (color_val))
4082 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4084 expect (',');
4087 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4088 &ximg, &img->pixmap)
4089 #ifndef HAVE_NS
4090 || !x_create_x_image_and_pixmap (f, width, height, 1,
4091 &mask_img, &img->mask)
4092 #endif
4095 image_error ("Out of memory (%s)", img->spec, Qnil);
4096 goto error;
4099 for (y = 0; y < height; y++)
4101 expect (XPM_TK_STRING);
4102 str = beg;
4103 if (len < width * chars_per_pixel)
4104 goto failure;
4105 for (x = 0; x < width; x++, str += chars_per_pixel)
4107 Lisp_Object color_val =
4108 (*get_color_table) (color_table, str, chars_per_pixel);
4110 XPutPixel (ximg, x, y,
4111 (INTEGERP (color_val) ? XINT (color_val)
4112 : FRAME_FOREGROUND_PIXEL (f)));
4113 #ifndef HAVE_NS
4114 XPutPixel (mask_img, x, y,
4115 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4116 : (have_mask = 1, PIX_MASK_RETAIN)));
4117 #else
4118 if (EQ(color_val, Qt))
4119 ns_set_alpha(ximg, x, y, 0);
4120 #endif
4122 if (y + 1 < height)
4123 expect (',');
4126 img->width = width;
4127 img->height = height;
4129 /* Maybe fill in the background field while we have ximg handy. */
4130 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4131 IMAGE_BACKGROUND (img, f, ximg);
4133 x_put_x_image (f, ximg, img->pixmap, width, height);
4134 x_destroy_x_image (ximg);
4135 #ifndef HAVE_NS
4136 if (have_mask)
4138 /* Fill in the background_transparent field while we have the
4139 mask handy. */
4140 image_background_transparent (img, f, mask_img);
4142 x_put_x_image (f, mask_img, img->mask, width, height);
4143 x_destroy_x_image (mask_img);
4145 else
4147 x_destroy_x_image (mask_img);
4148 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4149 img->mask = NO_PIXMAP;
4151 #endif
4152 return 1;
4154 failure:
4155 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4156 error:
4157 x_destroy_x_image (ximg);
4158 x_destroy_x_image (mask_img);
4159 x_clear_image (f, img);
4160 return 0;
4162 #undef match
4163 #undef expect
4164 #undef expect_ident
4167 static int
4168 xpm_load (f, img)
4169 struct frame *f;
4170 struct image *img;
4172 int success_p = 0;
4173 Lisp_Object file_name;
4175 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4176 file_name = image_spec_value (img->spec, QCfile, NULL);
4177 if (STRINGP (file_name))
4179 Lisp_Object file;
4180 unsigned char *contents;
4181 int size;
4182 struct gcpro gcpro1;
4184 file = x_find_image_file (file_name);
4185 GCPRO1 (file);
4186 if (!STRINGP (file))
4188 image_error ("Cannot find image file `%s'", file_name, Qnil);
4189 UNGCPRO;
4190 return 0;
4193 contents = slurp_file (SDATA (file), &size);
4194 if (contents == NULL)
4196 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4197 UNGCPRO;
4198 return 0;
4201 success_p = xpm_load_image (f, img, contents, contents + size);
4202 xfree (contents);
4203 UNGCPRO;
4205 else
4207 Lisp_Object data;
4209 data = image_spec_value (img->spec, QCdata, NULL);
4210 success_p = xpm_load_image (f, img, SDATA (data),
4211 SDATA (data) + SBYTES (data));
4214 return success_p;
4217 #endif /* HAVE_NS && !HAVE_XPM */
4221 /***********************************************************************
4222 Color table
4223 ***********************************************************************/
4225 #ifdef COLOR_TABLE_SUPPORT
4227 /* An entry in the color table mapping an RGB color to a pixel color. */
4229 struct ct_color
4231 int r, g, b;
4232 unsigned long pixel;
4234 /* Next in color table collision list. */
4235 struct ct_color *next;
4238 /* The bucket vector size to use. Must be prime. */
4240 #define CT_SIZE 101
4242 /* Value is a hash of the RGB color given by R, G, and B. */
4244 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4246 /* The color hash table. */
4248 struct ct_color **ct_table;
4250 /* Number of entries in the color table. */
4252 int ct_colors_allocated;
4254 /* Initialize the color table. */
4256 static void
4257 init_color_table ()
4259 int size = CT_SIZE * sizeof (*ct_table);
4260 ct_table = (struct ct_color **) xmalloc (size);
4261 bzero (ct_table, size);
4262 ct_colors_allocated = 0;
4266 /* Free memory associated with the color table. */
4268 static void
4269 free_color_table ()
4271 int i;
4272 struct ct_color *p, *next;
4274 for (i = 0; i < CT_SIZE; ++i)
4275 for (p = ct_table[i]; p; p = next)
4277 next = p->next;
4278 xfree (p);
4281 xfree (ct_table);
4282 ct_table = NULL;
4286 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4287 entry for that color already is in the color table, return the
4288 pixel color of that entry. Otherwise, allocate a new color for R,
4289 G, B, and make an entry in the color table. */
4291 static unsigned long
4292 lookup_rgb_color (f, r, g, b)
4293 struct frame *f;
4294 int r, g, b;
4296 unsigned hash = CT_HASH_RGB (r, g, b);
4297 int i = hash % CT_SIZE;
4298 struct ct_color *p;
4299 Display_Info *dpyinfo;
4301 /* Handle TrueColor visuals specially, which improves performance by
4302 two orders of magnitude. Freeing colors on TrueColor visuals is
4303 a nop, and pixel colors specify RGB values directly. See also
4304 the Xlib spec, chapter 3.1. */
4305 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4306 if (dpyinfo->red_bits > 0)
4308 unsigned long pr, pg, pb;
4310 /* Apply gamma-correction like normal color allocation does. */
4311 if (f->gamma)
4313 XColor color;
4314 color.red = r, color.green = g, color.blue = b;
4315 gamma_correct (f, &color);
4316 r = color.red, g = color.green, b = color.blue;
4319 /* Scale down RGB values to the visual's bits per RGB, and shift
4320 them to the right position in the pixel color. Note that the
4321 original RGB values are 16-bit values, as usual in X. */
4322 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4323 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4324 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4326 /* Assemble the pixel color. */
4327 return pr | pg | pb;
4330 for (p = ct_table[i]; p; p = p->next)
4331 if (p->r == r && p->g == g && p->b == b)
4332 break;
4334 if (p == NULL)
4337 #ifdef HAVE_X_WINDOWS
4338 XColor color;
4339 Colormap cmap;
4340 int rc;
4342 color.red = r;
4343 color.green = g;
4344 color.blue = b;
4346 cmap = FRAME_X_COLORMAP (f);
4347 rc = x_alloc_nearest_color (f, cmap, &color);
4348 if (rc)
4350 ++ct_colors_allocated;
4351 p = (struct ct_color *) xmalloc (sizeof *p);
4352 p->r = r;
4353 p->g = g;
4354 p->b = b;
4355 p->pixel = color.pixel;
4356 p->next = ct_table[i];
4357 ct_table[i] = p;
4359 else
4360 return FRAME_FOREGROUND_PIXEL (f);
4362 #else
4363 COLORREF color;
4364 #ifdef HAVE_NTGUI
4365 color = PALETTERGB (r, g, b);
4366 #else
4367 color = RGB_TO_ULONG (r, g, b);
4368 #endif /* HAVE_NTGUI */
4369 ++ct_colors_allocated;
4370 p = (struct ct_color *) xmalloc (sizeof *p);
4371 p->r = r;
4372 p->g = g;
4373 p->b = b;
4374 p->pixel = color;
4375 p->next = ct_table[i];
4376 ct_table[i] = p;
4377 #endif /* HAVE_X_WINDOWS */
4381 return p->pixel;
4385 /* Look up pixel color PIXEL which is used on frame F in the color
4386 table. If not already present, allocate it. Value is PIXEL. */
4388 static unsigned long
4389 lookup_pixel_color (f, pixel)
4390 struct frame *f;
4391 unsigned long pixel;
4393 int i = pixel % CT_SIZE;
4394 struct ct_color *p;
4396 for (p = ct_table[i]; p; p = p->next)
4397 if (p->pixel == pixel)
4398 break;
4400 if (p == NULL)
4402 XColor color;
4403 Colormap cmap;
4404 int rc;
4406 #ifdef HAVE_X_WINDOWS
4407 cmap = FRAME_X_COLORMAP (f);
4408 color.pixel = pixel;
4409 x_query_color (f, &color);
4410 rc = x_alloc_nearest_color (f, cmap, &color);
4411 #else
4412 BLOCK_INPUT;
4413 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4414 color.pixel = pixel;
4415 XQueryColor (NULL, cmap, &color);
4416 rc = x_alloc_nearest_color (f, cmap, &color);
4417 UNBLOCK_INPUT;
4418 #endif /* HAVE_X_WINDOWS */
4420 if (rc)
4422 ++ct_colors_allocated;
4424 p = (struct ct_color *) xmalloc (sizeof *p);
4425 p->r = color.red;
4426 p->g = color.green;
4427 p->b = color.blue;
4428 p->pixel = pixel;
4429 p->next = ct_table[i];
4430 ct_table[i] = p;
4432 else
4433 return FRAME_FOREGROUND_PIXEL (f);
4435 return p->pixel;
4439 /* Value is a vector of all pixel colors contained in the color table,
4440 allocated via xmalloc. Set *N to the number of colors. */
4442 static unsigned long *
4443 colors_in_color_table (n)
4444 int *n;
4446 int i, j;
4447 struct ct_color *p;
4448 unsigned long *colors;
4450 if (ct_colors_allocated == 0)
4452 *n = 0;
4453 colors = NULL;
4455 else
4457 colors = (unsigned long *) xmalloc (ct_colors_allocated
4458 * sizeof *colors);
4459 *n = ct_colors_allocated;
4461 for (i = j = 0; i < CT_SIZE; ++i)
4462 for (p = ct_table[i]; p; p = p->next)
4463 colors[j++] = p->pixel;
4466 return colors;
4469 #else /* COLOR_TABLE_SUPPORT */
4471 static unsigned long
4472 lookup_rgb_color (f, r, g, b)
4473 struct frame *f;
4474 int r, g, b;
4476 unsigned long pixel;
4478 #ifdef HAVE_NTGUI
4479 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4480 #endif /* HAVE_NTGUI */
4482 #ifdef HAVE_NS
4483 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4484 #endif /* HAVE_NS */
4485 return pixel;
4488 static void
4489 init_color_table ()
4492 #endif /* COLOR_TABLE_SUPPORT */
4495 /***********************************************************************
4496 Algorithms
4497 ***********************************************************************/
4499 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
4500 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
4501 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
4503 #ifdef HAVE_NTGUI
4504 static void XPutPixel (XImagePtr , int, int, COLORREF);
4505 #endif /* HAVE_NTGUI */
4507 /* Non-zero means draw a cross on images having `:conversion
4508 disabled'. */
4510 int cross_disabled_images;
4512 /* Edge detection matrices for different edge-detection
4513 strategies. */
4515 static int emboss_matrix[9] = {
4516 /* x - 1 x x + 1 */
4517 2, -1, 0, /* y - 1 */
4518 -1, 0, 1, /* y */
4519 0, 1, -2 /* y + 1 */
4522 static int laplace_matrix[9] = {
4523 /* x - 1 x x + 1 */
4524 1, 0, 0, /* y - 1 */
4525 0, 0, 0, /* y */
4526 0, 0, -1 /* y + 1 */
4529 /* Value is the intensity of the color whose red/green/blue values
4530 are R, G, and B. */
4532 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4535 /* On frame F, return an array of XColor structures describing image
4536 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4537 non-zero means also fill the red/green/blue members of the XColor
4538 structures. Value is a pointer to the array of XColors structures,
4539 allocated with xmalloc; it must be freed by the caller. */
4541 static XColor *
4542 x_to_xcolors (f, img, rgb_p)
4543 struct frame *f;
4544 struct image *img;
4545 int rgb_p;
4547 int x, y;
4548 XColor *colors, *p;
4549 XImagePtr_or_DC ximg;
4550 #ifdef HAVE_NTGUI
4551 HDC hdc;
4552 HGDIOBJ prev;
4553 #endif /* HAVE_NTGUI */
4555 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4557 #ifndef HAVE_NTGUI
4558 /* Get the X image IMG->pixmap. */
4559 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4560 0, 0, img->width, img->height, ~0, ZPixmap);
4561 #else
4562 /* Load the image into a memory device context. */
4563 hdc = get_frame_dc (f);
4564 ximg = CreateCompatibleDC (hdc);
4565 release_frame_dc (f, hdc);
4566 prev = SelectObject (ximg, img->pixmap);
4567 #endif /* HAVE_NTGUI */
4569 /* Fill the `pixel' members of the XColor array. I wished there
4570 were an easy and portable way to circumvent XGetPixel. */
4571 p = colors;
4572 for (y = 0; y < img->height; ++y)
4574 XColor *row = p;
4576 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
4577 for (x = 0; x < img->width; ++x, ++p)
4578 p->pixel = GET_PIXEL (ximg, x, y);
4579 if (rgb_p)
4580 x_query_colors (f, row, img->width);
4582 #else
4584 for (x = 0; x < img->width; ++x, ++p)
4586 /* W32_TODO: palette support needed here? */
4587 p->pixel = GET_PIXEL (ximg, x, y);
4588 if (rgb_p)
4590 p->red = RED16_FROM_ULONG (p->pixel);
4591 p->green = GREEN16_FROM_ULONG (p->pixel);
4592 p->blue = BLUE16_FROM_ULONG (p->pixel);
4595 #endif /* HAVE_X_WINDOWS */
4598 Destroy_Image (ximg, prev);
4600 return colors;
4603 #ifdef HAVE_NTGUI
4605 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4606 created with CreateDIBSection, with the pointer to the bit values
4607 stored in ximg->data. */
4609 static void
4610 XPutPixel (ximg, x, y, color)
4611 XImagePtr ximg;
4612 int x, y;
4613 COLORREF color;
4615 int width = ximg->info.bmiHeader.biWidth;
4616 int height = ximg->info.bmiHeader.biHeight;
4617 unsigned char * pixel;
4619 /* True color images. */
4620 if (ximg->info.bmiHeader.biBitCount == 24)
4622 int rowbytes = width * 3;
4623 /* Ensure scanlines are aligned on 4 byte boundaries. */
4624 if (rowbytes % 4)
4625 rowbytes += 4 - (rowbytes % 4);
4627 pixel = ximg->data + y * rowbytes + x * 3;
4628 /* Windows bitmaps are in BGR order. */
4629 *pixel = GetBValue (color);
4630 *(pixel + 1) = GetGValue (color);
4631 *(pixel + 2) = GetRValue (color);
4633 /* Monochrome images. */
4634 else if (ximg->info.bmiHeader.biBitCount == 1)
4636 int rowbytes = width / 8;
4637 /* Ensure scanlines are aligned on 4 byte boundaries. */
4638 if (rowbytes % 4)
4639 rowbytes += 4 - (rowbytes % 4);
4640 pixel = ximg->data + y * rowbytes + x / 8;
4641 /* Filter out palette info. */
4642 if (color & 0x00ffffff)
4643 *pixel = *pixel | (1 << x % 8);
4644 else
4645 *pixel = *pixel & ~(1 << x % 8);
4647 else
4648 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4651 #endif /* HAVE_NTGUI */
4653 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4654 RGB members are set. F is the frame on which this all happens.
4655 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4657 static void
4658 x_from_xcolors (f, img, colors)
4659 struct frame *f;
4660 struct image *img;
4661 XColor *colors;
4663 int x, y;
4664 XImagePtr oimg = NULL;
4665 Pixmap pixmap;
4666 XColor *p;
4668 init_color_table ();
4670 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4671 &oimg, &pixmap);
4672 p = colors;
4673 for (y = 0; y < img->height; ++y)
4674 for (x = 0; x < img->width; ++x, ++p)
4676 unsigned long pixel;
4677 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4678 XPutPixel (oimg, x, y, pixel);
4681 xfree (colors);
4682 x_clear_image_1 (f, img, 1, 0, 1);
4684 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4685 x_destroy_x_image (oimg);
4686 img->pixmap = pixmap;
4687 #ifdef COLOR_TABLE_SUPPORT
4688 img->colors = colors_in_color_table (&img->ncolors);
4689 free_color_table ();
4690 #endif /* COLOR_TABLE_SUPPORT */
4694 /* On frame F, perform edge-detection on image IMG.
4696 MATRIX is a nine-element array specifying the transformation
4697 matrix. See emboss_matrix for an example.
4699 COLOR_ADJUST is a color adjustment added to each pixel of the
4700 outgoing image. */
4702 static void
4703 x_detect_edges (f, img, matrix, color_adjust)
4704 struct frame *f;
4705 struct image *img;
4706 int matrix[9], color_adjust;
4708 XColor *colors = x_to_xcolors (f, img, 1);
4709 XColor *new, *p;
4710 int x, y, i, sum;
4712 for (i = sum = 0; i < 9; ++i)
4713 sum += eabs (matrix[i]);
4715 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4717 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
4719 for (y = 0; y < img->height; ++y)
4721 p = COLOR (new, 0, y);
4722 p->red = p->green = p->blue = 0xffff/2;
4723 p = COLOR (new, img->width - 1, y);
4724 p->red = p->green = p->blue = 0xffff/2;
4727 for (x = 1; x < img->width - 1; ++x)
4729 p = COLOR (new, x, 0);
4730 p->red = p->green = p->blue = 0xffff/2;
4731 p = COLOR (new, x, img->height - 1);
4732 p->red = p->green = p->blue = 0xffff/2;
4735 for (y = 1; y < img->height - 1; ++y)
4737 p = COLOR (new, 1, y);
4739 for (x = 1; x < img->width - 1; ++x, ++p)
4741 int r, g, b, y1, x1;
4743 r = g = b = i = 0;
4744 for (y1 = y - 1; y1 < y + 2; ++y1)
4745 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
4746 if (matrix[i])
4748 XColor *t = COLOR (colors, x1, y1);
4749 r += matrix[i] * t->red;
4750 g += matrix[i] * t->green;
4751 b += matrix[i] * t->blue;
4754 r = (r / sum + color_adjust) & 0xffff;
4755 g = (g / sum + color_adjust) & 0xffff;
4756 b = (b / sum + color_adjust) & 0xffff;
4757 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4761 xfree (colors);
4762 x_from_xcolors (f, img, new);
4764 #undef COLOR
4768 /* Perform the pre-defined `emboss' edge-detection on image IMG
4769 on frame F. */
4771 static void
4772 x_emboss (f, img)
4773 struct frame *f;
4774 struct image *img;
4776 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4780 /* Transform image IMG which is used on frame F with a Laplace
4781 edge-detection algorithm. The result is an image that can be used
4782 to draw disabled buttons, for example. */
4784 static void
4785 x_laplace (f, img)
4786 struct frame *f;
4787 struct image *img;
4789 x_detect_edges (f, img, laplace_matrix, 45000);
4793 /* Perform edge-detection on image IMG on frame F, with specified
4794 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4796 MATRIX must be either
4798 - a list of at least 9 numbers in row-major form
4799 - a vector of at least 9 numbers
4801 COLOR_ADJUST nil means use a default; otherwise it must be a
4802 number. */
4804 static void
4805 x_edge_detection (f, img, matrix, color_adjust)
4806 struct frame *f;
4807 struct image *img;
4808 Lisp_Object matrix, color_adjust;
4810 int i = 0;
4811 int trans[9];
4813 if (CONSP (matrix))
4815 for (i = 0;
4816 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
4817 ++i, matrix = XCDR (matrix))
4818 trans[i] = XFLOATINT (XCAR (matrix));
4820 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
4822 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
4823 trans[i] = XFLOATINT (AREF (matrix, i));
4826 if (NILP (color_adjust))
4827 color_adjust = make_number (0xffff / 2);
4829 if (i == 9 && NUMBERP (color_adjust))
4830 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
4834 /* Transform image IMG on frame F so that it looks disabled. */
4836 static void
4837 x_disable_image (f, img)
4838 struct frame *f;
4839 struct image *img;
4841 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4842 #ifdef HAVE_NTGUI
4843 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
4844 #else
4845 int n_planes = dpyinfo->n_planes;
4846 #endif /* HAVE_NTGUI */
4848 if (n_planes >= 2)
4850 /* Color (or grayscale). Convert to gray, and equalize. Just
4851 drawing such images with a stipple can look very odd, so
4852 we're using this method instead. */
4853 XColor *colors = x_to_xcolors (f, img, 1);
4854 XColor *p, *end;
4855 const int h = 15000;
4856 const int l = 30000;
4858 for (p = colors, end = colors + img->width * img->height;
4859 p < end;
4860 ++p)
4862 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
4863 int i2 = (0xffff - h - l) * i / 0xffff + l;
4864 p->red = p->green = p->blue = i2;
4867 x_from_xcolors (f, img, colors);
4870 /* Draw a cross over the disabled image, if we must or if we
4871 should. */
4872 if (n_planes < 2 || cross_disabled_images)
4874 #ifndef HAVE_NTGUI
4875 Display *dpy = FRAME_X_DISPLAY (f);
4876 GC gc;
4878 #ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
4880 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4882 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4883 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4884 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4885 img->width - 1, img->height - 1);
4886 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
4887 img->width - 1, 0);
4888 XFreeGC (dpy, gc);
4890 if (img->mask)
4892 gc = XCreateGC (dpy, img->mask, 0, NULL);
4893 XSetForeground (dpy, gc, MaskForeground (f));
4894 XDrawLine (dpy, img->mask, gc, 0, 0,
4895 img->width - 1, img->height - 1);
4896 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
4897 img->width - 1, 0);
4898 XFreeGC (dpy, gc);
4900 #endif /* !HAVE_NS */
4901 #else
4902 HDC hdc, bmpdc;
4903 HGDIOBJ prev;
4905 hdc = get_frame_dc (f);
4906 bmpdc = CreateCompatibleDC (hdc);
4907 release_frame_dc (f, hdc);
4909 prev = SelectObject (bmpdc, img->pixmap);
4911 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
4912 MoveToEx (bmpdc, 0, 0, NULL);
4913 LineTo (bmpdc, img->width - 1, img->height - 1);
4914 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4915 LineTo (bmpdc, img->width - 1, 0);
4917 if (img->mask)
4919 SelectObject (bmpdc, img->mask);
4920 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
4921 MoveToEx (bmpdc, 0, 0, NULL);
4922 LineTo (bmpdc, img->width - 1, img->height - 1);
4923 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4924 LineTo (bmpdc, img->width - 1, 0);
4926 SelectObject (bmpdc, prev);
4927 DeleteDC (bmpdc);
4928 #endif /* HAVE_NTGUI */
4933 /* Build a mask for image IMG which is used on frame F. FILE is the
4934 name of an image file, for error messages. HOW determines how to
4935 determine the background color of IMG. If it is a list '(R G B)',
4936 with R, G, and B being integers >= 0, take that as the color of the
4937 background. Otherwise, determine the background color of IMG
4938 heuristically. Value is non-zero if successful. */
4940 static int
4941 x_build_heuristic_mask (f, img, how)
4942 struct frame *f;
4943 struct image *img;
4944 Lisp_Object how;
4946 XImagePtr_or_DC ximg;
4947 #ifndef HAVE_NTGUI
4948 XImagePtr mask_img;
4949 #else
4950 HDC frame_dc;
4951 HGDIOBJ prev;
4952 char *mask_img;
4953 int row_width;
4954 #endif /* HAVE_NTGUI */
4955 int x, y, rc, use_img_background;
4956 unsigned long bg = 0;
4958 if (img->mask)
4960 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4961 img->mask = NO_PIXMAP;
4962 img->background_transparent_valid = 0;
4965 #ifndef HAVE_NTGUI
4966 #ifndef HAVE_NS
4967 /* Create an image and pixmap serving as mask. */
4968 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
4969 &mask_img, &img->mask);
4970 if (!rc)
4971 return 0;
4972 #endif /* !HAVE_NS */
4974 /* Get the X image of IMG->pixmap. */
4975 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4976 img->width, img->height,
4977 ~0, ZPixmap);
4978 #else
4979 /* Create the bit array serving as mask. */
4980 row_width = (img->width + 7) / 8;
4981 mask_img = xmalloc (row_width * img->height);
4982 bzero (mask_img, row_width * img->height);
4984 /* Create a memory device context for IMG->pixmap. */
4985 frame_dc = get_frame_dc (f);
4986 ximg = CreateCompatibleDC (frame_dc);
4987 release_frame_dc (f, frame_dc);
4988 prev = SelectObject (ximg, img->pixmap);
4989 #endif /* HAVE_NTGUI */
4991 /* Determine the background color of ximg. If HOW is `(R G B)'
4992 take that as color. Otherwise, use the image's background color. */
4993 use_img_background = 1;
4995 if (CONSP (how))
4997 int rgb[3], i;
4999 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5001 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5002 how = XCDR (how);
5005 if (i == 3 && NILP (how))
5007 char color_name[30];
5008 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5009 bg = (
5010 #ifdef HAVE_NTGUI
5011 0x00ffffff & /* Filter out palette info. */
5012 #endif /* HAVE_NTGUI */
5013 x_alloc_image_color (f, img, build_string (color_name), 0));
5014 use_img_background = 0;
5018 if (use_img_background)
5019 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5021 /* Set all bits in mask_img to 1 whose color in ximg is different
5022 from the background color bg. */
5023 #ifndef HAVE_NTGUI
5024 for (y = 0; y < img->height; ++y)
5025 for (x = 0; x < img->width; ++x)
5026 #ifndef HAVE_NS
5027 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5028 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5029 #else
5030 if (XGetPixel (ximg, x, y) == bg)
5031 ns_set_alpha(ximg, x, y, 0);
5032 #endif /* HAVE_NS */
5033 #ifndef HAVE_NS
5034 /* Fill in the background_transparent field while we have the mask handy. */
5035 image_background_transparent (img, f, mask_img);
5037 /* Put mask_img into img->mask. */
5038 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5039 x_destroy_x_image (mask_img);
5040 #endif /* !HAVE_NS */
5041 #else
5042 for (y = 0; y < img->height; ++y)
5043 for (x = 0; x < img->width; ++x)
5045 COLORREF p = GetPixel (ximg, x, y);
5046 if (p != bg)
5047 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5050 /* Create the mask image. */
5051 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5052 mask_img);
5053 /* Fill in the background_transparent field while we have the mask handy. */
5054 SelectObject (ximg, img->mask);
5055 image_background_transparent (img, f, ximg);
5057 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5058 xfree (mask_img);
5059 #endif /* HAVE_NTGUI */
5061 Destroy_Image (ximg, prev);
5063 return 1;
5067 /***********************************************************************
5068 PBM (mono, gray, color)
5069 ***********************************************************************/
5071 static int pbm_image_p P_ ((Lisp_Object object));
5072 static int pbm_load P_ ((struct frame *f, struct image *img));
5073 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5075 /* The symbol `pbm' identifying images of this type. */
5077 Lisp_Object Qpbm;
5079 /* Indices of image specification fields in gs_format, below. */
5081 enum pbm_keyword_index
5083 PBM_TYPE,
5084 PBM_FILE,
5085 PBM_DATA,
5086 PBM_ASCENT,
5087 PBM_MARGIN,
5088 PBM_RELIEF,
5089 PBM_ALGORITHM,
5090 PBM_HEURISTIC_MASK,
5091 PBM_MASK,
5092 PBM_FOREGROUND,
5093 PBM_BACKGROUND,
5094 PBM_LAST
5097 /* Vector of image_keyword structures describing the format
5098 of valid user-defined image specifications. */
5100 static const struct image_keyword pbm_format[PBM_LAST] =
5102 {":type", IMAGE_SYMBOL_VALUE, 1},
5103 {":file", IMAGE_STRING_VALUE, 0},
5104 {":data", IMAGE_STRING_VALUE, 0},
5105 {":ascent", IMAGE_ASCENT_VALUE, 0},
5106 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5107 {":relief", IMAGE_INTEGER_VALUE, 0},
5108 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5109 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5110 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5111 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5112 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5115 /* Structure describing the image type `pbm'. */
5117 static struct image_type pbm_type =
5119 &Qpbm,
5120 pbm_image_p,
5121 pbm_load,
5122 x_clear_image,
5123 NULL
5127 /* Return non-zero if OBJECT is a valid PBM image specification. */
5129 static int
5130 pbm_image_p (object)
5131 Lisp_Object object;
5133 struct image_keyword fmt[PBM_LAST];
5135 bcopy (pbm_format, fmt, sizeof fmt);
5137 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5138 return 0;
5140 /* Must specify either :data or :file. */
5141 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5145 /* Scan a decimal number from *S and return it. Advance *S while
5146 reading the number. END is the end of the string. Value is -1 at
5147 end of input. */
5149 static int
5150 pbm_scan_number (s, end)
5151 unsigned char **s, *end;
5153 int c = 0, val = -1;
5155 while (*s < end)
5157 /* Skip white-space. */
5158 while (*s < end && (c = *(*s)++, isspace (c)))
5161 if (c == '#')
5163 /* Skip comment to end of line. */
5164 while (*s < end && (c = *(*s)++, c != '\n'))
5167 else if (isdigit (c))
5169 /* Read decimal number. */
5170 val = c - '0';
5171 while (*s < end && (c = *(*s)++, isdigit (c)))
5172 val = 10 * val + c - '0';
5173 break;
5175 else
5176 break;
5179 return val;
5183 #ifdef HAVE_NTGUI
5184 #if 0 /* Unused. ++kfs */
5186 /* Read FILE into memory. Value is a pointer to a buffer allocated
5187 with xmalloc holding FILE's contents. Value is null if an error
5188 occurred. *SIZE is set to the size of the file. */
5190 static char *
5191 pbm_read_file (file, size)
5192 Lisp_Object file;
5193 int *size;
5195 FILE *fp = NULL;
5196 char *buf = NULL;
5197 struct stat st;
5199 if (stat (SDATA (file), &st) == 0
5200 && (fp = fopen (SDATA (file), "rb")) != NULL
5201 && (buf = (char *) xmalloc (st.st_size),
5202 fread (buf, 1, st.st_size, fp) == st.st_size))
5204 *size = st.st_size;
5205 fclose (fp);
5207 else
5209 if (fp)
5210 fclose (fp);
5211 if (buf)
5213 xfree (buf);
5214 buf = NULL;
5218 return buf;
5220 #endif
5221 #endif /* HAVE_NTGUI */
5223 /* Load PBM image IMG for use on frame F. */
5225 static int
5226 pbm_load (f, img)
5227 struct frame *f;
5228 struct image *img;
5230 int raw_p, x, y;
5231 int width, height, max_color_idx = 0;
5232 XImagePtr ximg;
5233 Lisp_Object file, specified_file;
5234 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5235 struct gcpro gcpro1;
5236 unsigned char *contents = NULL;
5237 unsigned char *end, *p;
5238 int size;
5240 specified_file = image_spec_value (img->spec, QCfile, NULL);
5241 file = Qnil;
5242 GCPRO1 (file);
5244 if (STRINGP (specified_file))
5246 file = x_find_image_file (specified_file);
5247 if (!STRINGP (file))
5249 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5250 UNGCPRO;
5251 return 0;
5254 contents = slurp_file (SDATA (file), &size);
5255 if (contents == NULL)
5257 image_error ("Error reading `%s'", file, Qnil);
5258 UNGCPRO;
5259 return 0;
5262 p = contents;
5263 end = contents + size;
5265 else
5267 Lisp_Object data;
5268 data = image_spec_value (img->spec, QCdata, NULL);
5269 p = SDATA (data);
5270 end = p + SBYTES (data);
5273 /* Check magic number. */
5274 if (end - p < 2 || *p++ != 'P')
5276 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5277 error:
5278 xfree (contents);
5279 UNGCPRO;
5280 return 0;
5283 switch (*p++)
5285 case '1':
5286 raw_p = 0, type = PBM_MONO;
5287 break;
5289 case '2':
5290 raw_p = 0, type = PBM_GRAY;
5291 break;
5293 case '3':
5294 raw_p = 0, type = PBM_COLOR;
5295 break;
5297 case '4':
5298 raw_p = 1, type = PBM_MONO;
5299 break;
5301 case '5':
5302 raw_p = 1, type = PBM_GRAY;
5303 break;
5305 case '6':
5306 raw_p = 1, type = PBM_COLOR;
5307 break;
5309 default:
5310 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5311 goto error;
5314 /* Read width, height, maximum color-component. Characters
5315 starting with `#' up to the end of a line are ignored. */
5316 width = pbm_scan_number (&p, end);
5317 height = pbm_scan_number (&p, end);
5319 if (type != PBM_MONO)
5321 max_color_idx = pbm_scan_number (&p, end);
5322 if (max_color_idx > 65535 || max_color_idx < 0)
5324 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
5325 goto error;
5329 if (!check_image_size (f, width, height))
5331 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5332 goto error;
5335 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5336 &ximg, &img->pixmap))
5337 goto error;
5339 /* Initialize the color hash table. */
5340 init_color_table ();
5342 if (type == PBM_MONO)
5344 int c = 0, g;
5345 struct image_keyword fmt[PBM_LAST];
5346 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5347 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5349 /* Parse the image specification. */
5350 bcopy (pbm_format, fmt, sizeof fmt);
5351 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5353 /* Get foreground and background colors, maybe allocate colors. */
5354 if (fmt[PBM_FOREGROUND].count
5355 && STRINGP (fmt[PBM_FOREGROUND].value))
5356 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5357 if (fmt[PBM_BACKGROUND].count
5358 && STRINGP (fmt[PBM_BACKGROUND].value))
5360 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5361 img->background = bg;
5362 img->background_valid = 1;
5365 for (y = 0; y < height; ++y)
5366 for (x = 0; x < width; ++x)
5368 if (raw_p)
5370 if ((x & 7) == 0)
5372 if (p >= end)
5374 x_destroy_x_image (ximg);
5375 x_clear_image (f, img);
5376 image_error ("Invalid image size in image `%s'",
5377 img->spec, Qnil);
5378 goto error;
5380 c = *p++;
5382 g = c & 0x80;
5383 c <<= 1;
5385 else
5386 g = pbm_scan_number (&p, end);
5388 XPutPixel (ximg, x, y, g ? fg : bg);
5391 else
5393 int expected_size = height * width;
5394 if (max_color_idx > 255)
5395 expected_size *= 2;
5396 if (type == PBM_COLOR)
5397 expected_size *= 3;
5399 if (raw_p && p + expected_size > end)
5401 x_destroy_x_image (ximg);
5402 x_clear_image (f, img);
5403 image_error ("Invalid image size in image `%s'",
5404 img->spec, Qnil);
5405 goto error;
5408 for (y = 0; y < height; ++y)
5409 for (x = 0; x < width; ++x)
5411 int r, g, b;
5413 if (type == PBM_GRAY && raw_p)
5415 r = g = b = *p++;
5416 if (max_color_idx > 255)
5417 r = g = b = r * 256 + *p++;
5419 else if (type == PBM_GRAY)
5420 r = g = b = pbm_scan_number (&p, end);
5421 else if (raw_p)
5423 r = *p++;
5424 if (max_color_idx > 255)
5425 r = r * 256 + *p++;
5426 g = *p++;
5427 if (max_color_idx > 255)
5428 g = g * 256 + *p++;
5429 b = *p++;
5430 if (max_color_idx > 255)
5431 b = b * 256 + *p++;
5433 else
5435 r = pbm_scan_number (&p, end);
5436 g = pbm_scan_number (&p, end);
5437 b = pbm_scan_number (&p, end);
5440 if (r < 0 || g < 0 || b < 0)
5442 x_destroy_x_image (ximg);
5443 image_error ("Invalid pixel value in image `%s'",
5444 img->spec, Qnil);
5445 goto error;
5448 /* RGB values are now in the range 0..max_color_idx.
5449 Scale this to the range 0..0xffff supported by X. */
5450 r = (double) r * 65535 / max_color_idx;
5451 g = (double) g * 65535 / max_color_idx;
5452 b = (double) b * 65535 / max_color_idx;
5453 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5457 #ifdef COLOR_TABLE_SUPPORT
5458 /* Store in IMG->colors the colors allocated for the image, and
5459 free the color table. */
5460 img->colors = colors_in_color_table (&img->ncolors);
5461 free_color_table ();
5462 #endif /* COLOR_TABLE_SUPPORT */
5464 img->width = width;
5465 img->height = height;
5467 /* Maybe fill in the background field while we have ximg handy. */
5469 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5470 /* Casting avoids a GCC warning. */
5471 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5473 /* Put the image into a pixmap. */
5474 x_put_x_image (f, ximg, img->pixmap, width, height);
5475 x_destroy_x_image (ximg);
5477 /* X and W32 versions did it here, MAC version above. ++kfs
5478 img->width = width;
5479 img->height = height; */
5481 UNGCPRO;
5482 xfree (contents);
5483 return 1;
5487 /***********************************************************************
5489 ***********************************************************************/
5491 #if defined (HAVE_PNG) || defined (HAVE_NS)
5493 /* Function prototypes. */
5495 static int png_image_p P_ ((Lisp_Object object));
5496 static int png_load P_ ((struct frame *f, struct image *img));
5498 /* The symbol `png' identifying images of this type. */
5500 Lisp_Object Qpng;
5502 /* Indices of image specification fields in png_format, below. */
5504 enum png_keyword_index
5506 PNG_TYPE,
5507 PNG_DATA,
5508 PNG_FILE,
5509 PNG_ASCENT,
5510 PNG_MARGIN,
5511 PNG_RELIEF,
5512 PNG_ALGORITHM,
5513 PNG_HEURISTIC_MASK,
5514 PNG_MASK,
5515 PNG_BACKGROUND,
5516 PNG_LAST
5519 /* Vector of image_keyword structures describing the format
5520 of valid user-defined image specifications. */
5522 static const struct image_keyword png_format[PNG_LAST] =
5524 {":type", IMAGE_SYMBOL_VALUE, 1},
5525 {":data", IMAGE_STRING_VALUE, 0},
5526 {":file", IMAGE_STRING_VALUE, 0},
5527 {":ascent", IMAGE_ASCENT_VALUE, 0},
5528 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5529 {":relief", IMAGE_INTEGER_VALUE, 0},
5530 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5531 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5532 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5533 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5536 /* Structure describing the image type `png'. */
5538 static struct image_type png_type =
5540 &Qpng,
5541 png_image_p,
5542 png_load,
5543 x_clear_image,
5544 NULL
5547 /* Return non-zero if OBJECT is a valid PNG image specification. */
5549 static int
5550 png_image_p (object)
5551 Lisp_Object object;
5553 struct image_keyword fmt[PNG_LAST];
5554 bcopy (png_format, fmt, sizeof fmt);
5556 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5557 return 0;
5559 /* Must specify either the :data or :file keyword. */
5560 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5563 #endif /* HAVE_PNG || HAVE_NS */
5566 #ifdef HAVE_PNG
5568 #ifdef HAVE_NTGUI
5569 /* PNG library details. */
5571 DEF_IMGLIB_FN (png_voidp, png_get_io_ptr);
5572 DEF_IMGLIB_FN (int, png_sig_cmp);
5573 DEF_IMGLIB_FN (png_structp, png_create_read_struct);
5574 DEF_IMGLIB_FN (png_infop, png_create_info_struct);
5575 DEF_IMGLIB_FN (void, png_destroy_read_struct);
5576 DEF_IMGLIB_FN (void, png_set_read_fn);
5577 DEF_IMGLIB_FN (void, png_set_sig_bytes);
5578 DEF_IMGLIB_FN (void, png_read_info);
5579 DEF_IMGLIB_FN (png_uint_32, png_get_IHDR);
5580 DEF_IMGLIB_FN (png_uint_32, png_get_valid);
5581 DEF_IMGLIB_FN (void, png_set_strip_16);
5582 DEF_IMGLIB_FN (void, png_set_expand);
5583 DEF_IMGLIB_FN (void, png_set_gray_to_rgb);
5584 DEF_IMGLIB_FN (void, png_set_background);
5585 DEF_IMGLIB_FN (png_uint_32, png_get_bKGD);
5586 DEF_IMGLIB_FN (void, png_read_update_info);
5587 DEF_IMGLIB_FN (png_byte, png_get_channels);
5588 DEF_IMGLIB_FN (png_size_t, png_get_rowbytes);
5589 DEF_IMGLIB_FN (void, png_read_image);
5590 DEF_IMGLIB_FN (void, png_read_end);
5591 DEF_IMGLIB_FN (void, png_error);
5593 #if (PNG_LIBPNG_VER >= 10500)
5594 DEF_IMGLIB_FN (void, png_longjmp);
5595 DEF_IMGLIB_FN (jmp_buf *, png_set_longjmp_fn);
5596 #endif /* libpng version >= 1.5 */
5598 static int
5599 init_png_functions (Lisp_Object libraries)
5601 HMODULE library;
5603 /* Try loading libpng under probable names. */
5604 if (!(library = w32_delayed_load (libraries, Qpng)))
5605 return 0;
5607 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5608 LOAD_IMGLIB_FN (library, png_sig_cmp);
5609 LOAD_IMGLIB_FN (library, png_create_read_struct);
5610 LOAD_IMGLIB_FN (library, png_create_info_struct);
5611 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5612 LOAD_IMGLIB_FN (library, png_set_read_fn);
5613 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5614 LOAD_IMGLIB_FN (library, png_read_info);
5615 LOAD_IMGLIB_FN (library, png_get_IHDR);
5616 LOAD_IMGLIB_FN (library, png_get_valid);
5617 LOAD_IMGLIB_FN (library, png_set_strip_16);
5618 LOAD_IMGLIB_FN (library, png_set_expand);
5619 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5620 LOAD_IMGLIB_FN (library, png_set_background);
5621 LOAD_IMGLIB_FN (library, png_get_bKGD);
5622 LOAD_IMGLIB_FN (library, png_read_update_info);
5623 LOAD_IMGLIB_FN (library, png_get_channels);
5624 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5625 LOAD_IMGLIB_FN (library, png_read_image);
5626 LOAD_IMGLIB_FN (library, png_read_end);
5627 LOAD_IMGLIB_FN (library, png_error);
5629 #if (PNG_LIBPNG_VER >= 10500)
5630 LOAD_IMGLIB_FN (library, png_longjmp);
5631 LOAD_IMGLIB_FN (library, png_set_longjmp_fn);
5632 #endif /* libpng version >= 1.5 */
5634 return 1;
5636 #else
5638 #define fn_png_get_io_ptr png_get_io_ptr
5639 #define fn_png_sig_cmp png_sig_cmp
5640 #define fn_png_create_read_struct png_create_read_struct
5641 #define fn_png_create_info_struct png_create_info_struct
5642 #define fn_png_destroy_read_struct png_destroy_read_struct
5643 #define fn_png_set_read_fn png_set_read_fn
5644 #define fn_png_set_sig_bytes png_set_sig_bytes
5645 #define fn_png_read_info png_read_info
5646 #define fn_png_get_IHDR png_get_IHDR
5647 #define fn_png_get_valid png_get_valid
5648 #define fn_png_set_strip_16 png_set_strip_16
5649 #define fn_png_set_expand png_set_expand
5650 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5651 #define fn_png_set_background png_set_background
5652 #define fn_png_get_bKGD png_get_bKGD
5653 #define fn_png_read_update_info png_read_update_info
5654 #define fn_png_get_channels png_get_channels
5655 #define fn_png_get_rowbytes png_get_rowbytes
5656 #define fn_png_read_image png_read_image
5657 #define fn_png_read_end png_read_end
5658 #define fn_png_error png_error
5660 #if (PNG_LIBPNG_VER >= 10500)
5661 #define fn_png_longjmp png_longjmp
5662 #define fn_png_set_longjmp_fn png_set_longjmp_fn
5663 #endif /* libpng version >= 1.5 */
5665 #endif /* HAVE_NTGUI */
5668 #if (PNG_LIBPNG_VER < 10500)
5669 #define PNG_LONGJMP(ptr) (longjmp ((ptr)->jmpbuf, 1))
5670 #define PNG_JMPBUF(ptr) ((ptr)->jmpbuf)
5671 #else
5672 /* In libpng version 1.5, the jmpbuf member is hidden. (Bug#7908) */
5673 #define PNG_LONGJMP(ptr) (fn_png_longjmp ((ptr), 1))
5674 #define PNG_JMPBUF(ptr) \
5675 (*fn_png_set_longjmp_fn((ptr), longjmp, sizeof (jmp_buf)))
5676 #endif
5678 /* Error and warning handlers installed when the PNG library
5679 is initialized. */
5681 static void
5682 my_png_error (png_ptr, msg)
5683 png_struct *png_ptr;
5684 char *msg;
5686 xassert (png_ptr != NULL);
5687 /* Avoid compiler warning about deprecated direct access to
5688 png_ptr's fields in libpng versions 1.4.x. */
5689 image_error ("PNG error: %s", build_string (msg), Qnil);
5690 PNG_LONGJMP (png_ptr);
5694 static void
5695 my_png_warning (png_ptr, msg)
5696 png_struct *png_ptr;
5697 char *msg;
5699 xassert (png_ptr != NULL);
5700 image_error ("PNG warning: %s", build_string (msg), Qnil);
5703 /* Memory source for PNG decoding. */
5705 struct png_memory_storage
5707 unsigned char *bytes; /* The data */
5708 size_t len; /* How big is it? */
5709 int index; /* Where are we? */
5713 /* Function set as reader function when reading PNG image from memory.
5714 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5715 bytes from the input to DATA. */
5717 static void
5718 png_read_from_memory (png_ptr, data, length)
5719 png_structp png_ptr;
5720 png_bytep data;
5721 png_size_t length;
5723 struct png_memory_storage *tbr
5724 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5726 if (length > tbr->len - tbr->index)
5727 fn_png_error (png_ptr, "Read error");
5729 bcopy (tbr->bytes + tbr->index, data, length);
5730 tbr->index = tbr->index + length;
5734 /* Function set as reader function when reading PNG image from a file.
5735 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5736 bytes from the input to DATA. */
5738 static void
5739 png_read_from_file (png_ptr, data, length)
5740 png_structp png_ptr;
5741 png_bytep data;
5742 png_size_t length;
5744 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
5746 if (fread (data, 1, length, fp) < length)
5747 fn_png_error (png_ptr, "Read error");
5751 /* Load PNG image IMG for use on frame F. Value is non-zero if
5752 successful. */
5754 static int
5755 png_load (f, img)
5756 struct frame *f;
5757 struct image *img;
5759 Lisp_Object file, specified_file;
5760 Lisp_Object specified_data;
5761 int x, y, i;
5762 XImagePtr ximg, mask_img = NULL;
5763 struct gcpro gcpro1;
5764 png_struct *png_ptr = NULL;
5765 png_info *info_ptr = NULL, *end_info = NULL;
5766 FILE *volatile fp = NULL;
5767 png_byte sig[8];
5768 png_byte * volatile pixels = NULL;
5769 png_byte ** volatile rows = NULL;
5770 png_uint_32 width, height;
5771 int bit_depth, color_type, interlace_type;
5772 png_byte channels;
5773 png_uint_32 row_bytes;
5774 int transparent_p;
5775 struct png_memory_storage tbr; /* Data to be read */
5777 /* Find out what file to load. */
5778 specified_file = image_spec_value (img->spec, QCfile, NULL);
5779 specified_data = image_spec_value (img->spec, QCdata, NULL);
5780 file = Qnil;
5781 GCPRO1 (file);
5783 if (NILP (specified_data))
5785 file = x_find_image_file (specified_file);
5786 if (!STRINGP (file))
5788 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5789 UNGCPRO;
5790 return 0;
5793 /* Open the image file. */
5794 fp = fopen (SDATA (file), "rb");
5795 if (!fp)
5797 image_error ("Cannot open image file `%s'", file, Qnil);
5798 UNGCPRO;
5799 return 0;
5802 /* Check PNG signature. */
5803 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
5804 || fn_png_sig_cmp (sig, 0, sizeof sig))
5806 image_error ("Not a PNG file: `%s'", file, Qnil);
5807 UNGCPRO;
5808 fclose (fp);
5809 return 0;
5812 else
5814 /* Read from memory. */
5815 tbr.bytes = SDATA (specified_data);
5816 tbr.len = SBYTES (specified_data);
5817 tbr.index = 0;
5819 /* Check PNG signature. */
5820 if (tbr.len < sizeof sig
5821 || fn_png_sig_cmp (tbr.bytes, 0, sizeof sig))
5823 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
5824 UNGCPRO;
5825 return 0;
5828 /* Need to skip past the signature. */
5829 tbr.bytes += sizeof (sig);
5832 /* Initialize read and info structs for PNG lib. */
5833 png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
5834 NULL, my_png_error,
5835 my_png_warning);
5836 if (!png_ptr)
5838 if (fp) fclose (fp);
5839 UNGCPRO;
5840 return 0;
5843 info_ptr = fn_png_create_info_struct (png_ptr);
5844 if (!info_ptr)
5846 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
5847 if (fp) fclose (fp);
5848 UNGCPRO;
5849 return 0;
5852 end_info = fn_png_create_info_struct (png_ptr);
5853 if (!end_info)
5855 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
5856 if (fp) fclose (fp);
5857 UNGCPRO;
5858 return 0;
5861 /* Set error jump-back. We come back here when the PNG library
5862 detects an error. */
5863 if (setjmp (PNG_JMPBUF (png_ptr)))
5865 error:
5866 if (png_ptr)
5867 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5868 xfree (pixels);
5869 xfree (rows);
5870 if (fp) fclose (fp);
5871 UNGCPRO;
5872 return 0;
5875 /* Read image info. */
5876 if (!NILP (specified_data))
5877 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
5878 else
5879 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
5881 fn_png_set_sig_bytes (png_ptr, sizeof sig);
5882 fn_png_read_info (png_ptr, info_ptr);
5883 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
5884 &interlace_type, NULL, NULL);
5886 if (!check_image_size (f, width, height))
5888 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
5889 goto error;
5891 /* If image contains simply transparency data, we prefer to
5892 construct a clipping mask. */
5893 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
5894 transparent_p = 1;
5895 else
5896 transparent_p = 0;
5898 /* This function is easier to write if we only have to handle
5899 one data format: RGB or RGBA with 8 bits per channel. Let's
5900 transform other formats into that format. */
5902 /* Strip more than 8 bits per channel. */
5903 if (bit_depth == 16)
5904 fn_png_set_strip_16 (png_ptr);
5906 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5907 if available. */
5908 fn_png_set_expand (png_ptr);
5910 /* Convert grayscale images to RGB. */
5911 if (color_type == PNG_COLOR_TYPE_GRAY
5912 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5913 fn_png_set_gray_to_rgb (png_ptr);
5915 /* Handle alpha channel by combining the image with a background
5916 color. Do this only if a real alpha channel is supplied. For
5917 simple transparency, we prefer a clipping mask. */
5918 if (!transparent_p)
5920 /* png_color_16 *image_bg; */
5921 Lisp_Object specified_bg
5922 = image_spec_value (img->spec, QCbackground, NULL);
5923 int shift = (bit_depth == 16) ? 0 : 8;
5925 if (STRINGP (specified_bg))
5926 /* The user specified `:background', use that. */
5928 XColor color;
5929 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
5931 png_color_16 user_bg;
5933 bzero (&user_bg, sizeof user_bg);
5934 user_bg.red = color.red >> shift;
5935 user_bg.green = color.green >> shift;
5936 user_bg.blue = color.blue >> shift;
5938 fn_png_set_background (png_ptr, &user_bg,
5939 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5942 else
5944 /* We use the current frame background, ignoring any default
5945 background color set by the image. */
5946 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
5947 XColor color;
5948 png_color_16 frame_background;
5950 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5951 x_query_color (f, &color);
5953 bzero (&frame_background, sizeof frame_background);
5954 frame_background.red = color.red >> shift;
5955 frame_background.green = color.green >> shift;
5956 frame_background.blue = color.blue >> shift;
5957 #endif /* HAVE_X_WINDOWS */
5959 fn_png_set_background (png_ptr, &frame_background,
5960 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5964 /* Update info structure. */
5965 fn_png_read_update_info (png_ptr, info_ptr);
5967 /* Get number of channels. Valid values are 1 for grayscale images
5968 and images with a palette, 2 for grayscale images with transparency
5969 information (alpha channel), 3 for RGB images, and 4 for RGB
5970 images with alpha channel, i.e. RGBA. If conversions above were
5971 sufficient we should only have 3 or 4 channels here. */
5972 channels = fn_png_get_channels (png_ptr, info_ptr);
5973 xassert (channels == 3 || channels == 4);
5975 /* Number of bytes needed for one row of the image. */
5976 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
5978 /* Allocate memory for the image. */
5979 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
5980 rows = (png_byte **) xmalloc (height * sizeof *rows);
5981 for (i = 0; i < height; ++i)
5982 rows[i] = pixels + i * row_bytes;
5984 /* Read the entire image. */
5985 fn_png_read_image (png_ptr, rows);
5986 fn_png_read_end (png_ptr, info_ptr);
5987 if (fp)
5989 fclose (fp);
5990 fp = NULL;
5993 /* Create the X image and pixmap. */
5994 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5995 &img->pixmap))
5996 goto error;
5998 /* Create an image and pixmap serving as mask if the PNG image
5999 contains an alpha channel. */
6000 if (channels == 4
6001 && !transparent_p
6002 && !x_create_x_image_and_pixmap (f, width, height, 1,
6003 &mask_img, &img->mask))
6005 x_destroy_x_image (ximg);
6006 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6007 img->pixmap = NO_PIXMAP;
6008 goto error;
6011 /* Fill the X image and mask from PNG data. */
6012 init_color_table ();
6014 for (y = 0; y < height; ++y)
6016 png_byte *p = rows[y];
6018 for (x = 0; x < width; ++x)
6020 unsigned r, g, b;
6022 r = *p++ << 8;
6023 g = *p++ << 8;
6024 b = *p++ << 8;
6025 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6026 /* An alpha channel, aka mask channel, associates variable
6027 transparency with an image. Where other image formats
6028 support binary transparency---fully transparent or fully
6029 opaque---PNG allows up to 254 levels of partial transparency.
6030 The PNG library implements partial transparency by combining
6031 the image with a specified background color.
6033 I'm not sure how to handle this here nicely: because the
6034 background on which the image is displayed may change, for
6035 real alpha channel support, it would be necessary to create
6036 a new image for each possible background.
6038 What I'm doing now is that a mask is created if we have
6039 boolean transparency information. Otherwise I'm using
6040 the frame's background color to combine the image with. */
6042 if (channels == 4)
6044 if (mask_img)
6045 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6046 ++p;
6051 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6052 /* Set IMG's background color from the PNG image, unless the user
6053 overrode it. */
6055 png_color_16 *bg;
6056 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6058 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6059 img->background_valid = 1;
6063 #ifdef COLOR_TABLE_SUPPORT
6064 /* Remember colors allocated for this image. */
6065 img->colors = colors_in_color_table (&img->ncolors);
6066 free_color_table ();
6067 #endif /* COLOR_TABLE_SUPPORT */
6069 /* Clean up. */
6070 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6071 xfree (rows);
6072 xfree (pixels);
6074 img->width = width;
6075 img->height = height;
6077 /* Maybe fill in the background field while we have ximg handy.
6078 Casting avoids a GCC warning. */
6079 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6081 /* Put the image into the pixmap, then free the X image and its buffer. */
6082 x_put_x_image (f, ximg, img->pixmap, width, height);
6083 x_destroy_x_image (ximg);
6085 /* Same for the mask. */
6086 if (mask_img)
6088 /* Fill in the background_transparent field while we have the
6089 mask handy. Casting avoids a GCC warning. */
6090 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6092 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6093 x_destroy_x_image (mask_img);
6096 UNGCPRO;
6097 return 1;
6100 #else /* HAVE_PNG */
6102 #ifdef HAVE_NS
6103 static int
6104 png_load (struct frame *f, struct image *img)
6106 return ns_load_image(f, img,
6107 image_spec_value (img->spec, QCfile, NULL),
6108 image_spec_value (img->spec, QCdata, NULL));
6110 #endif /* HAVE_NS */
6113 #endif /* !HAVE_PNG */
6117 /***********************************************************************
6118 JPEG
6119 ***********************************************************************/
6121 #if defined (HAVE_JPEG) || defined (HAVE_NS)
6123 static int jpeg_image_p P_ ((Lisp_Object object));
6124 static int jpeg_load P_ ((struct frame *f, struct image *img));
6126 /* The symbol `jpeg' identifying images of this type. */
6128 Lisp_Object Qjpeg;
6130 /* Indices of image specification fields in gs_format, below. */
6132 enum jpeg_keyword_index
6134 JPEG_TYPE,
6135 JPEG_DATA,
6136 JPEG_FILE,
6137 JPEG_ASCENT,
6138 JPEG_MARGIN,
6139 JPEG_RELIEF,
6140 JPEG_ALGORITHM,
6141 JPEG_HEURISTIC_MASK,
6142 JPEG_MASK,
6143 JPEG_BACKGROUND,
6144 JPEG_LAST
6147 /* Vector of image_keyword structures describing the format
6148 of valid user-defined image specifications. */
6150 static const struct image_keyword jpeg_format[JPEG_LAST] =
6152 {":type", IMAGE_SYMBOL_VALUE, 1},
6153 {":data", IMAGE_STRING_VALUE, 0},
6154 {":file", IMAGE_STRING_VALUE, 0},
6155 {":ascent", IMAGE_ASCENT_VALUE, 0},
6156 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6157 {":relief", IMAGE_INTEGER_VALUE, 0},
6158 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6159 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6160 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6161 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6164 /* Structure describing the image type `jpeg'. */
6166 static struct image_type jpeg_type =
6168 &Qjpeg,
6169 jpeg_image_p,
6170 jpeg_load,
6171 x_clear_image,
6172 NULL
6175 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6177 static int
6178 jpeg_image_p (object)
6179 Lisp_Object object;
6181 struct image_keyword fmt[JPEG_LAST];
6183 bcopy (jpeg_format, fmt, sizeof fmt);
6185 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6186 return 0;
6188 /* Must specify either the :data or :file keyword. */
6189 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6192 #endif /* HAVE_JPEG || HAVE_NS */
6194 #ifdef HAVE_JPEG
6196 /* Work around a warning about HAVE_STDLIB_H being redefined in
6197 jconfig.h. */
6198 #ifdef HAVE_STDLIB_H
6199 #define HAVE_STDLIB_H_1
6200 #undef HAVE_STDLIB_H
6201 #endif /* HAVE_STLIB_H */
6203 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6204 /* In older releases of the jpeg library, jpeglib.h will define boolean
6205 differently depending on __WIN32__, so make sure it is defined. */
6206 #define __WIN32__ 1
6207 #endif
6209 #include <jpeglib.h>
6210 #include <jerror.h>
6212 #ifdef HAVE_STLIB_H_1
6213 #define HAVE_STDLIB_H 1
6214 #endif
6216 #ifdef HAVE_NTGUI
6218 /* JPEG library details. */
6219 DEF_IMGLIB_FN (void, jpeg_CreateDecompress);
6220 DEF_IMGLIB_FN (boolean, jpeg_start_decompress);
6221 DEF_IMGLIB_FN (boolean, jpeg_finish_decompress);
6222 DEF_IMGLIB_FN (void, jpeg_destroy_decompress);
6223 DEF_IMGLIB_FN (int, jpeg_read_header);
6224 DEF_IMGLIB_FN (JDIMENSION, jpeg_read_scanlines);
6225 DEF_IMGLIB_FN (struct jpeg_error_mgr *, jpeg_std_error);
6226 DEF_IMGLIB_FN (boolean, jpeg_resync_to_restart);
6228 static int
6229 init_jpeg_functions (Lisp_Object libraries)
6231 HMODULE library;
6233 if (!(library = w32_delayed_load (libraries, Qjpeg)))
6234 return 0;
6236 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6237 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6238 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6239 LOAD_IMGLIB_FN (library, jpeg_read_header);
6240 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6241 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6242 LOAD_IMGLIB_FN (library, jpeg_std_error);
6243 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6244 return 1;
6247 /* Wrapper since we can't directly assign the function pointer
6248 to another function pointer that was declared more completely easily. */
6249 static boolean
6250 jpeg_resync_to_restart_wrapper (cinfo, desired)
6251 j_decompress_ptr cinfo;
6252 int desired;
6254 return fn_jpeg_resync_to_restart (cinfo, desired);
6257 #else
6259 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6260 #define fn_jpeg_start_decompress jpeg_start_decompress
6261 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6262 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6263 #define fn_jpeg_read_header jpeg_read_header
6264 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6265 #define fn_jpeg_std_error jpeg_std_error
6266 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6268 #endif /* HAVE_NTGUI */
6270 struct my_jpeg_error_mgr
6272 struct jpeg_error_mgr pub;
6273 jmp_buf setjmp_buffer;
6277 static void
6278 my_error_exit (cinfo)
6279 j_common_ptr cinfo;
6281 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6282 longjmp (mgr->setjmp_buffer, 1);
6286 /* Init source method for JPEG data source manager. Called by
6287 jpeg_read_header() before any data is actually read. See
6288 libjpeg.doc from the JPEG lib distribution. */
6290 static void
6291 our_common_init_source (cinfo)
6292 j_decompress_ptr cinfo;
6297 /* Method to terminate data source. Called by
6298 jpeg_finish_decompress() after all data has been processed. */
6300 static void
6301 our_common_term_source (cinfo)
6302 j_decompress_ptr cinfo;
6307 /* Fill input buffer method for JPEG data source manager. Called
6308 whenever more data is needed. We read the whole image in one step,
6309 so this only adds a fake end of input marker at the end. */
6311 static JOCTET our_memory_buffer[2];
6313 static boolean
6314 our_memory_fill_input_buffer (cinfo)
6315 j_decompress_ptr cinfo;
6317 /* Insert a fake EOI marker. */
6318 struct jpeg_source_mgr *src = cinfo->src;
6320 our_memory_buffer[0] = (JOCTET) 0xFF;
6321 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
6323 src->next_input_byte = our_memory_buffer;
6324 src->bytes_in_buffer = 2;
6325 return 1;
6329 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6330 is the JPEG data source manager. */
6332 static void
6333 our_memory_skip_input_data (cinfo, num_bytes)
6334 j_decompress_ptr cinfo;
6335 long num_bytes;
6337 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6339 if (src)
6341 if (num_bytes > src->bytes_in_buffer)
6342 ERREXIT (cinfo, JERR_INPUT_EOF);
6344 src->bytes_in_buffer -= num_bytes;
6345 src->next_input_byte += num_bytes;
6350 /* Set up the JPEG lib for reading an image from DATA which contains
6351 LEN bytes. CINFO is the decompression info structure created for
6352 reading the image. */
6354 static void
6355 jpeg_memory_src (cinfo, data, len)
6356 j_decompress_ptr cinfo;
6357 JOCTET *data;
6358 unsigned int len;
6360 struct jpeg_source_mgr *src;
6362 if (cinfo->src == NULL)
6364 /* First time for this JPEG object? */
6365 cinfo->src = (struct jpeg_source_mgr *)
6366 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6367 sizeof (struct jpeg_source_mgr));
6368 src = (struct jpeg_source_mgr *) cinfo->src;
6369 src->next_input_byte = data;
6372 src = (struct jpeg_source_mgr *) cinfo->src;
6373 src->init_source = our_common_init_source;
6374 src->fill_input_buffer = our_memory_fill_input_buffer;
6375 src->skip_input_data = our_memory_skip_input_data;
6376 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6377 src->term_source = our_common_term_source;
6378 src->bytes_in_buffer = len;
6379 src->next_input_byte = data;
6383 struct jpeg_stdio_mgr
6385 struct jpeg_source_mgr mgr;
6386 boolean finished;
6387 FILE *file;
6388 JOCTET *buffer;
6392 /* Size of buffer to read JPEG from file.
6393 Not too big, as we want to use alloc_small. */
6394 #define JPEG_STDIO_BUFFER_SIZE 8192
6397 /* Fill input buffer method for JPEG data source manager. Called
6398 whenever more data is needed. The data is read from a FILE *. */
6400 static boolean
6401 our_stdio_fill_input_buffer (cinfo)
6402 j_decompress_ptr cinfo;
6404 struct jpeg_stdio_mgr *src;
6406 src = (struct jpeg_stdio_mgr *) cinfo->src;
6407 if (!src->finished)
6409 size_t bytes;
6411 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6412 if (bytes > 0)
6413 src->mgr.bytes_in_buffer = bytes;
6414 else
6416 WARNMS (cinfo, JWRN_JPEG_EOF);
6417 src->finished = 1;
6418 src->buffer[0] = (JOCTET) 0xFF;
6419 src->buffer[1] = (JOCTET) JPEG_EOI;
6420 src->mgr.bytes_in_buffer = 2;
6422 src->mgr.next_input_byte = src->buffer;
6425 return 1;
6429 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6430 is the JPEG data source manager. */
6432 static void
6433 our_stdio_skip_input_data (cinfo, num_bytes)
6434 j_decompress_ptr cinfo;
6435 long num_bytes;
6437 struct jpeg_stdio_mgr *src;
6438 src = (struct jpeg_stdio_mgr *) cinfo->src;
6440 while (num_bytes > 0 && !src->finished)
6442 if (num_bytes <= src->mgr.bytes_in_buffer)
6444 src->mgr.bytes_in_buffer -= num_bytes;
6445 src->mgr.next_input_byte += num_bytes;
6446 break;
6448 else
6450 num_bytes -= src->mgr.bytes_in_buffer;
6451 src->mgr.bytes_in_buffer = 0;
6452 src->mgr.next_input_byte = NULL;
6454 our_stdio_fill_input_buffer (cinfo);
6460 /* Set up the JPEG lib for reading an image from a FILE *.
6461 CINFO is the decompression info structure created for
6462 reading the image. */
6464 static void
6465 jpeg_file_src (cinfo, fp)
6466 j_decompress_ptr cinfo;
6467 FILE *fp;
6469 struct jpeg_stdio_mgr *src;
6471 if (cinfo->src != NULL)
6472 src = (struct jpeg_stdio_mgr *) cinfo->src;
6473 else
6475 /* First time for this JPEG object? */
6476 cinfo->src = (struct jpeg_source_mgr *)
6477 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6478 sizeof (struct jpeg_stdio_mgr));
6479 src = (struct jpeg_stdio_mgr *) cinfo->src;
6480 src->buffer = (JOCTET *)
6481 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6482 JPEG_STDIO_BUFFER_SIZE);
6485 src->file = fp;
6486 src->finished = 0;
6487 src->mgr.init_source = our_common_init_source;
6488 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6489 src->mgr.skip_input_data = our_stdio_skip_input_data;
6490 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6491 src->mgr.term_source = our_common_term_source;
6492 src->mgr.bytes_in_buffer = 0;
6493 src->mgr.next_input_byte = NULL;
6497 /* Load image IMG for use on frame F. Patterned after example.c
6498 from the JPEG lib. */
6500 static int
6501 jpeg_load (f, img)
6502 struct frame *f;
6503 struct image *img;
6505 struct jpeg_decompress_struct cinfo;
6506 struct my_jpeg_error_mgr mgr;
6507 Lisp_Object file, specified_file;
6508 Lisp_Object specified_data;
6509 FILE * volatile fp = NULL;
6510 JSAMPARRAY buffer;
6511 int row_stride, x, y;
6512 XImagePtr ximg = NULL;
6513 int rc;
6514 unsigned long *colors;
6515 int width, height;
6516 struct gcpro gcpro1;
6518 /* Open the JPEG file. */
6519 specified_file = image_spec_value (img->spec, QCfile, NULL);
6520 specified_data = image_spec_value (img->spec, QCdata, NULL);
6521 file = Qnil;
6522 GCPRO1 (file);
6524 if (NILP (specified_data))
6526 file = x_find_image_file (specified_file);
6527 if (!STRINGP (file))
6529 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6530 UNGCPRO;
6531 return 0;
6534 fp = fopen (SDATA (file), "rb");
6535 if (fp == NULL)
6537 image_error ("Cannot open `%s'", file, Qnil);
6538 UNGCPRO;
6539 return 0;
6543 /* Customize libjpeg's error handling to call my_error_exit when an
6544 error is detected. This function will perform a longjmp. */
6545 cinfo.err = fn_jpeg_std_error (&mgr.pub);
6546 mgr.pub.error_exit = my_error_exit;
6548 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6550 if (rc == 1)
6552 /* Called from my_error_exit. Display a JPEG error. */
6553 char buffer[JMSG_LENGTH_MAX];
6554 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6555 image_error ("Error reading JPEG image `%s': %s", img->spec,
6556 build_string (buffer));
6559 /* Close the input file and destroy the JPEG object. */
6560 if (fp)
6561 fclose ((FILE *) fp);
6562 fn_jpeg_destroy_decompress (&cinfo);
6564 /* If we already have an XImage, free that. */
6565 x_destroy_x_image (ximg);
6567 /* Free pixmap and colors. */
6568 x_clear_image (f, img);
6570 UNGCPRO;
6571 return 0;
6574 /* Create the JPEG decompression object. Let it read from fp.
6575 Read the JPEG image header. */
6576 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6578 if (NILP (specified_data))
6579 jpeg_file_src (&cinfo, (FILE *) fp);
6580 else
6581 jpeg_memory_src (&cinfo, SDATA (specified_data),
6582 SBYTES (specified_data));
6584 fn_jpeg_read_header (&cinfo, 1);
6586 /* Customize decompression so that color quantization will be used.
6587 Start decompression. */
6588 cinfo.quantize_colors = 1;
6589 fn_jpeg_start_decompress (&cinfo);
6590 width = img->width = cinfo.output_width;
6591 height = img->height = cinfo.output_height;
6593 if (!check_image_size (f, width, height))
6595 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
6596 longjmp (mgr.setjmp_buffer, 2);
6599 /* Create X image and pixmap. */
6600 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6601 longjmp (mgr.setjmp_buffer, 2);
6603 /* Allocate colors. When color quantization is used,
6604 cinfo.actual_number_of_colors has been set with the number of
6605 colors generated, and cinfo.colormap is a two-dimensional array
6606 of color indices in the range 0..cinfo.actual_number_of_colors.
6607 No more than 255 colors will be generated. */
6609 int i, ir, ig, ib;
6611 if (cinfo.out_color_components > 2)
6612 ir = 0, ig = 1, ib = 2;
6613 else if (cinfo.out_color_components > 1)
6614 ir = 0, ig = 1, ib = 0;
6615 else
6616 ir = 0, ig = 0, ib = 0;
6618 /* Use the color table mechanism because it handles colors that
6619 cannot be allocated nicely. Such colors will be replaced with
6620 a default color, and we don't have to care about which colors
6621 can be freed safely, and which can't. */
6622 init_color_table ();
6623 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6624 * sizeof *colors);
6626 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6628 /* Multiply RGB values with 255 because X expects RGB values
6629 in the range 0..0xffff. */
6630 int r = cinfo.colormap[ir][i] << 8;
6631 int g = cinfo.colormap[ig][i] << 8;
6632 int b = cinfo.colormap[ib][i] << 8;
6633 colors[i] = lookup_rgb_color (f, r, g, b);
6636 #ifdef COLOR_TABLE_SUPPORT
6637 /* Remember those colors actually allocated. */
6638 img->colors = colors_in_color_table (&img->ncolors);
6639 free_color_table ();
6640 #endif /* COLOR_TABLE_SUPPORT */
6643 /* Read pixels. */
6644 row_stride = width * cinfo.output_components;
6645 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6646 row_stride, 1);
6647 for (y = 0; y < height; ++y)
6649 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6650 for (x = 0; x < cinfo.output_width; ++x)
6651 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6654 /* Clean up. */
6655 fn_jpeg_finish_decompress (&cinfo);
6656 fn_jpeg_destroy_decompress (&cinfo);
6657 if (fp)
6658 fclose ((FILE *) fp);
6660 /* Maybe fill in the background field while we have ximg handy. */
6661 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6662 /* Casting avoids a GCC warning. */
6663 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6665 /* Put the image into the pixmap. */
6666 x_put_x_image (f, ximg, img->pixmap, width, height);
6667 x_destroy_x_image (ximg);
6668 UNGCPRO;
6669 return 1;
6672 #else /* HAVE_JPEG */
6674 #ifdef HAVE_NS
6675 static int
6676 jpeg_load (struct frame *f, struct image *img)
6678 return ns_load_image(f, img,
6679 image_spec_value (img->spec, QCfile, NULL),
6680 image_spec_value (img->spec, QCdata, NULL));
6682 #endif /* HAVE_NS */
6684 #endif /* !HAVE_JPEG */
6688 /***********************************************************************
6689 TIFF
6690 ***********************************************************************/
6692 #if defined (HAVE_TIFF) || defined (HAVE_NS)
6694 static int tiff_image_p P_ ((Lisp_Object object));
6695 static int tiff_load P_ ((struct frame *f, struct image *img));
6697 /* The symbol `tiff' identifying images of this type. */
6699 Lisp_Object Qtiff;
6701 /* Indices of image specification fields in tiff_format, below. */
6703 enum tiff_keyword_index
6705 TIFF_TYPE,
6706 TIFF_DATA,
6707 TIFF_FILE,
6708 TIFF_ASCENT,
6709 TIFF_MARGIN,
6710 TIFF_RELIEF,
6711 TIFF_ALGORITHM,
6712 TIFF_HEURISTIC_MASK,
6713 TIFF_MASK,
6714 TIFF_BACKGROUND,
6715 TIFF_INDEX,
6716 TIFF_LAST
6719 /* Vector of image_keyword structures describing the format
6720 of valid user-defined image specifications. */
6722 static const struct image_keyword tiff_format[TIFF_LAST] =
6724 {":type", IMAGE_SYMBOL_VALUE, 1},
6725 {":data", IMAGE_STRING_VALUE, 0},
6726 {":file", IMAGE_STRING_VALUE, 0},
6727 {":ascent", IMAGE_ASCENT_VALUE, 0},
6728 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6729 {":relief", IMAGE_INTEGER_VALUE, 0},
6730 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6731 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6732 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6733 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
6734 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
6737 /* Structure describing the image type `tiff'. */
6739 static struct image_type tiff_type =
6741 &Qtiff,
6742 tiff_image_p,
6743 tiff_load,
6744 x_clear_image,
6745 NULL
6748 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6750 static int
6751 tiff_image_p (object)
6752 Lisp_Object object;
6754 struct image_keyword fmt[TIFF_LAST];
6755 bcopy (tiff_format, fmt, sizeof fmt);
6757 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6758 return 0;
6760 /* Must specify either the :data or :file keyword. */
6761 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6764 #endif /* HAVE_TIFF || HAVE_NS */
6766 #ifdef HAVE_TIFF
6768 #include <tiffio.h>
6770 #ifdef HAVE_NTGUI
6772 /* TIFF library details. */
6773 DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetErrorHandler);
6774 DEF_IMGLIB_FN (TIFFErrorHandler, TIFFSetWarningHandler);
6775 DEF_IMGLIB_FN (TIFF *, TIFFOpen);
6776 DEF_IMGLIB_FN (TIFF *, TIFFClientOpen);
6777 DEF_IMGLIB_FN (int, TIFFGetField);
6778 DEF_IMGLIB_FN (int, TIFFReadRGBAImage);
6779 DEF_IMGLIB_FN (void, TIFFClose);
6780 DEF_IMGLIB_FN (int, TIFFSetDirectory);
6782 static int
6783 init_tiff_functions (Lisp_Object libraries)
6785 HMODULE library;
6787 if (!(library = w32_delayed_load (libraries, Qtiff)))
6788 return 0;
6790 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6791 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6792 LOAD_IMGLIB_FN (library, TIFFOpen);
6793 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6794 LOAD_IMGLIB_FN (library, TIFFGetField);
6795 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6796 LOAD_IMGLIB_FN (library, TIFFClose);
6797 LOAD_IMGLIB_FN (library, TIFFSetDirectory);
6798 return 1;
6801 #else
6803 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6804 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6805 #define fn_TIFFOpen TIFFOpen
6806 #define fn_TIFFClientOpen TIFFClientOpen
6807 #define fn_TIFFGetField TIFFGetField
6808 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6809 #define fn_TIFFClose TIFFClose
6810 #define fn_TIFFSetDirectory TIFFSetDirectory
6811 #endif /* HAVE_NTGUI */
6814 /* Reading from a memory buffer for TIFF images Based on the PNG
6815 memory source, but we have to provide a lot of extra functions.
6816 Blah.
6818 We really only need to implement read and seek, but I am not
6819 convinced that the TIFF library is smart enough not to destroy
6820 itself if we only hand it the function pointers we need to
6821 override. */
6823 typedef struct
6825 unsigned char *bytes;
6826 size_t len;
6827 int index;
6829 tiff_memory_source;
6831 static size_t
6832 tiff_read_from_memory (data, buf, size)
6833 thandle_t data;
6834 tdata_t buf;
6835 tsize_t size;
6837 tiff_memory_source *src = (tiff_memory_source *) data;
6839 if (size > src->len - src->index)
6840 return (size_t) -1;
6841 bcopy (src->bytes + src->index, buf, size);
6842 src->index += size;
6843 return size;
6846 static size_t
6847 tiff_write_from_memory (data, buf, size)
6848 thandle_t data;
6849 tdata_t buf;
6850 tsize_t size;
6852 return (size_t) -1;
6855 static toff_t
6856 tiff_seek_in_memory (data, off, whence)
6857 thandle_t data;
6858 toff_t off;
6859 int whence;
6861 tiff_memory_source *src = (tiff_memory_source *) data;
6862 int idx;
6864 switch (whence)
6866 case SEEK_SET: /* Go from beginning of source. */
6867 idx = off;
6868 break;
6870 case SEEK_END: /* Go from end of source. */
6871 idx = src->len + off;
6872 break;
6874 case SEEK_CUR: /* Go from current position. */
6875 idx = src->index + off;
6876 break;
6878 default: /* Invalid `whence'. */
6879 return -1;
6882 if (idx > src->len || idx < 0)
6883 return -1;
6885 src->index = idx;
6886 return src->index;
6889 static int
6890 tiff_close_memory (data)
6891 thandle_t data;
6893 /* NOOP */
6894 return 0;
6897 static int
6898 tiff_mmap_memory (data, pbase, psize)
6899 thandle_t data;
6900 tdata_t *pbase;
6901 toff_t *psize;
6903 /* It is already _IN_ memory. */
6904 return 0;
6907 static void
6908 tiff_unmap_memory (data, base, size)
6909 thandle_t data;
6910 tdata_t base;
6911 toff_t size;
6913 /* We don't need to do this. */
6916 static toff_t
6917 tiff_size_of_memory (data)
6918 thandle_t data;
6920 return ((tiff_memory_source *) data)->len;
6924 static void
6925 tiff_error_handler (title, format, ap)
6926 const char *title, *format;
6927 va_list ap;
6929 char buf[512];
6930 int len;
6932 len = sprintf (buf, "TIFF error: %s ", title);
6933 vsprintf (buf + len, format, ap);
6934 add_to_log (buf, Qnil, Qnil);
6938 static void
6939 tiff_warning_handler (title, format, ap)
6940 const char *title, *format;
6941 va_list ap;
6943 char buf[512];
6944 int len;
6946 len = sprintf (buf, "TIFF warning: %s ", title);
6947 vsprintf (buf + len, format, ap);
6948 add_to_log (buf, Qnil, Qnil);
6952 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6953 successful. */
6955 static int
6956 tiff_load (f, img)
6957 struct frame *f;
6958 struct image *img;
6960 Lisp_Object file, specified_file;
6961 Lisp_Object specified_data;
6962 TIFF *tiff;
6963 int width, height, x, y, count;
6964 uint32 *buf;
6965 int rc, rc2;
6966 XImagePtr ximg;
6967 struct gcpro gcpro1;
6968 tiff_memory_source memsrc;
6969 Lisp_Object image;
6971 specified_file = image_spec_value (img->spec, QCfile, NULL);
6972 specified_data = image_spec_value (img->spec, QCdata, NULL);
6973 file = Qnil;
6974 GCPRO1 (file);
6976 fn_TIFFSetErrorHandler (tiff_error_handler);
6977 fn_TIFFSetWarningHandler (tiff_warning_handler);
6979 if (NILP (specified_data))
6981 /* Read from a file */
6982 file = x_find_image_file (specified_file);
6983 if (!STRINGP (file))
6985 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6986 UNGCPRO;
6987 return 0;
6990 /* Try to open the image file. */
6991 tiff = fn_TIFFOpen (SDATA (file), "r");
6992 if (tiff == NULL)
6994 image_error ("Cannot open `%s'", file, Qnil);
6995 UNGCPRO;
6996 return 0;
6999 else
7001 /* Memory source! */
7002 memsrc.bytes = SDATA (specified_data);
7003 memsrc.len = SBYTES (specified_data);
7004 memsrc.index = 0;
7006 tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7007 (TIFFReadWriteProc) tiff_read_from_memory,
7008 (TIFFReadWriteProc) tiff_write_from_memory,
7009 tiff_seek_in_memory,
7010 tiff_close_memory,
7011 tiff_size_of_memory,
7012 tiff_mmap_memory,
7013 tiff_unmap_memory);
7015 if (!tiff)
7017 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7018 UNGCPRO;
7019 return 0;
7023 image = image_spec_value (img->spec, QCindex, NULL);
7024 if (INTEGERP (image))
7026 int ino = XFASTINT (image);
7027 if (!fn_TIFFSetDirectory (tiff, ino))
7029 image_error ("Invalid image number `%s' in image `%s'",
7030 image, img->spec);
7031 fn_TIFFClose (tiff);
7032 UNGCPRO;
7033 return 0;
7037 /* Get width and height of the image, and allocate a raster buffer
7038 of width x height 32-bit values. */
7039 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7040 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7042 if (!check_image_size (f, width, height))
7044 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7045 fn_TIFFClose (tiff);
7046 UNGCPRO;
7047 return 0;
7050 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7052 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7054 /* Count the number of images in the file. */
7055 for (count = 1, rc2 = 1; rc2; count++)
7056 rc2 = fn_TIFFSetDirectory (tiff, count);
7058 if (count > 1)
7059 img->data.lisp_val = Fcons (Qcount,
7060 Fcons (make_number (count),
7061 img->data.lisp_val));
7063 fn_TIFFClose (tiff);
7064 if (!rc)
7066 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7067 xfree (buf);
7068 UNGCPRO;
7069 return 0;
7072 /* Create the X image and pixmap. */
7073 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7075 xfree (buf);
7076 UNGCPRO;
7077 return 0;
7080 /* Initialize the color table. */
7081 init_color_table ();
7083 /* Process the pixel raster. Origin is in the lower-left corner. */
7084 for (y = 0; y < height; ++y)
7086 uint32 *row = buf + y * width;
7088 for (x = 0; x < width; ++x)
7090 uint32 abgr = row[x];
7091 int r = TIFFGetR (abgr) << 8;
7092 int g = TIFFGetG (abgr) << 8;
7093 int b = TIFFGetB (abgr) << 8;
7094 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7098 #ifdef COLOR_TABLE_SUPPORT
7099 /* Remember the colors allocated for the image. Free the color table. */
7100 img->colors = colors_in_color_table (&img->ncolors);
7101 free_color_table ();
7102 #endif /* COLOR_TABLE_SUPPORT */
7104 img->width = width;
7105 img->height = height;
7107 /* Maybe fill in the background field while we have ximg handy. */
7108 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7109 /* Casting avoids a GCC warning on W32. */
7110 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7112 /* Put the image into the pixmap, then free the X image and its buffer. */
7113 x_put_x_image (f, ximg, img->pixmap, width, height);
7114 x_destroy_x_image (ximg);
7115 xfree (buf);
7117 UNGCPRO;
7118 return 1;
7121 #else /* HAVE_TIFF */
7123 #ifdef HAVE_NS
7124 static int
7125 tiff_load (struct frame *f, struct image *img)
7127 return ns_load_image(f, img,
7128 image_spec_value (img->spec, QCfile, NULL),
7129 image_spec_value (img->spec, QCdata, NULL));
7131 #endif /* HAVE_NS */
7133 #endif /* !HAVE_TIFF */
7137 /***********************************************************************
7139 ***********************************************************************/
7141 #if defined (HAVE_GIF) || defined (HAVE_NS)
7143 static int gif_image_p P_ ((Lisp_Object object));
7144 static int gif_load P_ ((struct frame *f, struct image *img));
7145 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7147 /* The symbol `gif' identifying images of this type. */
7149 Lisp_Object Qgif;
7151 /* Indices of image specification fields in gif_format, below. */
7153 enum gif_keyword_index
7155 GIF_TYPE,
7156 GIF_DATA,
7157 GIF_FILE,
7158 GIF_ASCENT,
7159 GIF_MARGIN,
7160 GIF_RELIEF,
7161 GIF_ALGORITHM,
7162 GIF_HEURISTIC_MASK,
7163 GIF_MASK,
7164 GIF_IMAGE,
7165 GIF_BACKGROUND,
7166 GIF_LAST
7169 /* Vector of image_keyword structures describing the format
7170 of valid user-defined image specifications. */
7172 static const struct image_keyword gif_format[GIF_LAST] =
7174 {":type", IMAGE_SYMBOL_VALUE, 1},
7175 {":data", IMAGE_STRING_VALUE, 0},
7176 {":file", IMAGE_STRING_VALUE, 0},
7177 {":ascent", IMAGE_ASCENT_VALUE, 0},
7178 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7179 {":relief", IMAGE_INTEGER_VALUE, 0},
7180 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7181 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7182 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7183 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7184 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7187 /* Structure describing the image type `gif'. */
7189 static struct image_type gif_type =
7191 &Qgif,
7192 gif_image_p,
7193 gif_load,
7194 gif_clear_image,
7195 NULL
7198 /* Free X resources of GIF image IMG which is used on frame F. */
7200 static void
7201 gif_clear_image (f, img)
7202 struct frame *f;
7203 struct image *img;
7205 /* IMG->data.ptr_val may contain extension data. */
7206 img->data.lisp_val = Qnil;
7207 x_clear_image (f, img);
7210 /* Return non-zero if OBJECT is a valid GIF image specification. */
7212 static int
7213 gif_image_p (object)
7214 Lisp_Object object;
7216 struct image_keyword fmt[GIF_LAST];
7217 bcopy (gif_format, fmt, sizeof fmt);
7219 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7220 return 0;
7222 /* Must specify either the :data or :file keyword. */
7223 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7226 #endif /* HAVE_GIF */
7228 #ifdef HAVE_GIF
7230 #if defined (HAVE_NTGUI)
7231 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7232 Undefine before redefining to avoid a preprocessor warning. */
7233 #ifdef DrawText
7234 #undef DrawText
7235 #endif
7236 /* avoid conflict with QuickdrawText.h */
7237 #define DrawText gif_DrawText
7238 #include <gif_lib.h>
7239 #undef DrawText
7241 #else /* HAVE_NTGUI */
7243 #include <gif_lib.h>
7245 #endif /* HAVE_NTGUI */
7248 #ifdef HAVE_NTGUI
7250 /* GIF library details. */
7251 DEF_IMGLIB_FN (int, DGifCloseFile);
7252 DEF_IMGLIB_FN (int, DGifSlurp);
7253 DEF_IMGLIB_FN (GifFileType *, DGifOpen);
7254 DEF_IMGLIB_FN (GifFileType *, DGifOpenFileName);
7256 static int
7257 init_gif_functions (Lisp_Object libraries)
7259 HMODULE library;
7261 if (!(library = w32_delayed_load (libraries, Qgif)))
7262 return 0;
7264 LOAD_IMGLIB_FN (library, DGifCloseFile);
7265 LOAD_IMGLIB_FN (library, DGifSlurp);
7266 LOAD_IMGLIB_FN (library, DGifOpen);
7267 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7268 return 1;
7271 #else
7273 #define fn_DGifCloseFile DGifCloseFile
7274 #define fn_DGifSlurp DGifSlurp
7275 #define fn_DGifOpen DGifOpen
7276 #define fn_DGifOpenFileName DGifOpenFileName
7278 #endif /* HAVE_NTGUI */
7280 /* Reading a GIF image from memory
7281 Based on the PNG memory stuff to a certain extent. */
7283 typedef struct
7285 unsigned char *bytes;
7286 size_t len;
7287 int index;
7289 gif_memory_source;
7291 /* Make the current memory source available to gif_read_from_memory.
7292 It's done this way because not all versions of libungif support
7293 a UserData field in the GifFileType structure. */
7294 static gif_memory_source *current_gif_memory_src;
7296 static int
7297 gif_read_from_memory (file, buf, len)
7298 GifFileType *file;
7299 GifByteType *buf;
7300 int len;
7302 gif_memory_source *src = current_gif_memory_src;
7304 if (len > src->len - src->index)
7305 return -1;
7307 bcopy (src->bytes + src->index, buf, len);
7308 src->index += len;
7309 return len;
7313 /* Load GIF image IMG for use on frame F. Value is non-zero if
7314 successful. */
7316 static const int interlace_start[] = {0, 4, 2, 1};
7317 static const int interlace_increment[] = {8, 8, 4, 2};
7319 static int
7320 gif_load (f, img)
7321 struct frame *f;
7322 struct image *img;
7324 Lisp_Object file, specified_file;
7325 Lisp_Object specified_data;
7326 int rc, width, height, x, y, i;
7327 XImagePtr ximg;
7328 ColorMapObject *gif_color_map;
7329 unsigned long pixel_colors[256];
7330 GifFileType *gif;
7331 struct gcpro gcpro1;
7332 Lisp_Object image;
7333 int ino, image_height, image_width;
7334 gif_memory_source memsrc;
7335 unsigned char *raster;
7337 specified_file = image_spec_value (img->spec, QCfile, NULL);
7338 specified_data = image_spec_value (img->spec, QCdata, NULL);
7339 file = Qnil;
7340 GCPRO1 (file);
7342 if (NILP (specified_data))
7344 file = x_find_image_file (specified_file);
7345 if (!STRINGP (file))
7347 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7348 UNGCPRO;
7349 return 0;
7352 /* Open the GIF file. */
7353 gif = fn_DGifOpenFileName (SDATA (file));
7354 if (gif == NULL)
7356 image_error ("Cannot open `%s'", file, Qnil);
7357 UNGCPRO;
7358 return 0;
7361 else
7363 /* Read from memory! */
7364 current_gif_memory_src = &memsrc;
7365 memsrc.bytes = SDATA (specified_data);
7366 memsrc.len = SBYTES (specified_data);
7367 memsrc.index = 0;
7369 gif = fn_DGifOpen (&memsrc, gif_read_from_memory);
7370 if (!gif)
7372 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7373 UNGCPRO;
7374 return 0;
7378 /* Before reading entire contents, check the declared image size. */
7379 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7381 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7382 fn_DGifCloseFile (gif);
7383 UNGCPRO;
7384 return 0;
7387 /* Read entire contents. */
7388 rc = fn_DGifSlurp (gif);
7389 if (rc == GIF_ERROR)
7391 image_error ("Error reading `%s'", img->spec, Qnil);
7392 fn_DGifCloseFile (gif);
7393 UNGCPRO;
7394 return 0;
7397 image = image_spec_value (img->spec, QCindex, NULL);
7398 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7399 if (ino >= gif->ImageCount)
7401 image_error ("Invalid image number `%s' in image `%s'",
7402 image, img->spec);
7403 fn_DGifCloseFile (gif);
7404 UNGCPRO;
7405 return 0;
7408 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
7409 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
7410 image_height = gif->SavedImages[ino].ImageDesc.Height;
7411 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
7412 image_width = gif->SavedImages[ino].ImageDesc.Width;
7413 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
7415 width = img->width = max (gif->SWidth,
7416 max (gif->Image.Left + gif->Image.Width,
7417 img->corners[RIGHT_CORNER]));
7418 height = img->height = max (gif->SHeight,
7419 max (gif->Image.Top + gif->Image.Height,
7420 img->corners[BOT_CORNER]));
7422 if (!check_image_size (f, width, height))
7424 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7425 fn_DGifCloseFile (gif);
7426 UNGCPRO;
7427 return 0;
7430 /* Create the X image and pixmap. */
7431 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7433 fn_DGifCloseFile (gif);
7434 UNGCPRO;
7435 return 0;
7438 /* Allocate colors. */
7439 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7440 if (!gif_color_map)
7441 gif_color_map = gif->SColorMap;
7442 init_color_table ();
7443 bzero (pixel_colors, sizeof pixel_colors);
7445 if (gif_color_map)
7446 for (i = 0; i < gif_color_map->ColorCount; ++i)
7448 int r = gif_color_map->Colors[i].Red << 8;
7449 int g = gif_color_map->Colors[i].Green << 8;
7450 int b = gif_color_map->Colors[i].Blue << 8;
7451 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7454 #ifdef COLOR_TABLE_SUPPORT
7455 img->colors = colors_in_color_table (&img->ncolors);
7456 free_color_table ();
7457 #endif /* COLOR_TABLE_SUPPORT */
7459 /* Clear the part of the screen image that are not covered by
7460 the image from the GIF file. Full animated GIF support
7461 requires more than can be done here (see the gif89 spec,
7462 disposal methods). Let's simply assume that the part
7463 not covered by a sub-image is in the frame's background color. */
7464 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
7465 for (x = 0; x < width; ++x)
7466 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7468 for (y = img->corners[BOT_CORNER]; y < height; ++y)
7469 for (x = 0; x < width; ++x)
7470 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7472 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
7474 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
7475 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7476 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
7477 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7480 /* Read the GIF image into the X image. We use a local variable
7481 `raster' here because RasterBits below is a char *, and invites
7482 problems with bytes >= 0x80. */
7483 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7485 if (gif->SavedImages[ino].ImageDesc.Interlace)
7487 int pass;
7488 int row = interlace_start[0];
7490 pass = 0;
7492 for (y = 0; y < image_height; y++)
7494 if (row >= image_height)
7496 row = interlace_start[++pass];
7497 while (row >= image_height)
7498 row = interlace_start[++pass];
7501 for (x = 0; x < image_width; x++)
7503 int i = raster[(y * image_width) + x];
7504 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7505 row + img->corners[TOP_CORNER], pixel_colors[i]);
7508 row += interlace_increment[pass];
7511 else
7513 for (y = 0; y < image_height; ++y)
7514 for (x = 0; x < image_width; ++x)
7516 int i = raster[y * image_width + x];
7517 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7518 y + img->corners[TOP_CORNER], pixel_colors[i]);
7522 /* Save GIF image extension data for `image-extension-data'.
7523 Format is (count IMAGES FUNCTION "BYTES" ...). */
7524 img->data.lisp_val = Qnil;
7525 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
7527 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
7528 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
7529 /* Append (... FUNCTION "BYTES") */
7530 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7531 Fcons (make_number (ext->Function),
7532 img->data.lisp_val));
7533 img->data.lisp_val = Fnreverse (img->data.lisp_val);
7535 if (gif->ImageCount > 1)
7536 img->data.lisp_val = Fcons (Qcount,
7537 Fcons (make_number (gif->ImageCount),
7538 img->data.lisp_val));
7540 fn_DGifCloseFile (gif);
7542 /* Maybe fill in the background field while we have ximg handy. */
7543 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7544 /* Casting avoids a GCC warning. */
7545 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7547 /* Put the image into the pixmap, then free the X image and its buffer. */
7548 x_put_x_image (f, ximg, img->pixmap, width, height);
7549 x_destroy_x_image (ximg);
7551 UNGCPRO;
7552 return 1;
7555 #else /* !HAVE_GIF */
7557 #ifdef HAVE_NS
7558 static int
7559 gif_load (struct frame *f, struct image *img)
7561 return ns_load_image(f, img,
7562 image_spec_value (img->spec, QCfile, NULL),
7563 image_spec_value (img->spec, QCdata, NULL));
7565 #endif /* HAVE_NS */
7567 #endif /* HAVE_GIF */
7571 /***********************************************************************
7573 ***********************************************************************/
7575 #if defined (HAVE_RSVG)
7577 /* Function prototypes. */
7579 static int svg_image_p P_ ((Lisp_Object object));
7580 static int svg_load P_ ((struct frame *f, struct image *img));
7582 static int svg_load_image P_ ((struct frame *, struct image *,
7583 unsigned char *, unsigned int));
7585 /* The symbol `svg' identifying images of this type. */
7587 Lisp_Object Qsvg;
7589 /* Indices of image specification fields in svg_format, below. */
7591 enum svg_keyword_index
7593 SVG_TYPE,
7594 SVG_DATA,
7595 SVG_FILE,
7596 SVG_ASCENT,
7597 SVG_MARGIN,
7598 SVG_RELIEF,
7599 SVG_ALGORITHM,
7600 SVG_HEURISTIC_MASK,
7601 SVG_MASK,
7602 SVG_BACKGROUND,
7603 SVG_LAST
7606 /* Vector of image_keyword structures describing the format
7607 of valid user-defined image specifications. */
7609 static const struct image_keyword svg_format[SVG_LAST] =
7611 {":type", IMAGE_SYMBOL_VALUE, 1},
7612 {":data", IMAGE_STRING_VALUE, 0},
7613 {":file", IMAGE_STRING_VALUE, 0},
7614 {":ascent", IMAGE_ASCENT_VALUE, 0},
7615 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7616 {":relief", IMAGE_INTEGER_VALUE, 0},
7617 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7618 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7619 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7620 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7623 /* Structure describing the image type `svg'. Its the same type of
7624 structure defined for all image formats, handled by emacs image
7625 functions. See struct image_type in dispextern.h. */
7627 static struct image_type svg_type =
7629 /* An identifier showing that this is an image structure for the SVG format. */
7630 &Qsvg,
7631 /* Handle to a function that can be used to identify a SVG file. */
7632 svg_image_p,
7633 /* Handle to function used to load a SVG file. */
7634 svg_load,
7635 /* Handle to function to free sresources for SVG. */
7636 x_clear_image,
7637 /* An internal field to link to the next image type in a list of
7638 image types, will be filled in when registering the format. */
7639 NULL
7643 /* Return non-zero if OBJECT is a valid SVG image specification. Do
7644 this by calling parse_image_spec and supplying the keywords that
7645 identify the SVG format. */
7647 static int
7648 svg_image_p (object)
7649 Lisp_Object object;
7651 struct image_keyword fmt[SVG_LAST];
7652 bcopy (svg_format, fmt, sizeof fmt);
7654 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
7655 return 0;
7657 /* Must specify either the :data or :file keyword. */
7658 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
7661 #include <librsvg/rsvg.h>
7663 #ifdef HAVE_NTGUI
7665 /* SVG library functions. */
7666 DEF_IMGLIB_FN (RsvgHandle *, rsvg_handle_new);
7667 DEF_IMGLIB_FN (void, rsvg_handle_get_dimensions);
7668 DEF_IMGLIB_FN (gboolean, rsvg_handle_write);
7669 DEF_IMGLIB_FN (gboolean, rsvg_handle_close);
7670 DEF_IMGLIB_FN (GdkPixbuf *, rsvg_handle_get_pixbuf);
7671 DEF_IMGLIB_FN (void, rsvg_handle_free);
7673 DEF_IMGLIB_FN (int, gdk_pixbuf_get_width);
7674 DEF_IMGLIB_FN (int, gdk_pixbuf_get_height);
7675 DEF_IMGLIB_FN (guchar *, gdk_pixbuf_get_pixels);
7676 DEF_IMGLIB_FN (int, gdk_pixbuf_get_rowstride);
7677 DEF_IMGLIB_FN (GdkColorspace, gdk_pixbuf_get_colorspace);
7678 DEF_IMGLIB_FN (int, gdk_pixbuf_get_n_channels);
7679 DEF_IMGLIB_FN (gboolean, gdk_pixbuf_get_has_alpha);
7680 DEF_IMGLIB_FN (int, gdk_pixbuf_get_bits_per_sample);
7682 DEF_IMGLIB_FN (void, g_type_init);
7683 DEF_IMGLIB_FN (void, g_object_unref);
7684 DEF_IMGLIB_FN (void, g_error_free);
7686 Lisp_Object Qgdk_pixbuf, Qglib, Qgobject;
7688 static int
7689 init_svg_functions (Lisp_Object libraries)
7691 HMODULE library, gdklib, glib, gobject;
7693 if (!(glib = w32_delayed_load (libraries, Qglib))
7694 || !(gobject = w32_delayed_load (libraries, Qgobject))
7695 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
7696 || !(library = w32_delayed_load (libraries, Qsvg)))
7697 return 0;
7699 LOAD_IMGLIB_FN (library, rsvg_handle_new);
7700 LOAD_IMGLIB_FN (library, rsvg_handle_get_dimensions);
7701 LOAD_IMGLIB_FN (library, rsvg_handle_write);
7702 LOAD_IMGLIB_FN (library, rsvg_handle_close);
7703 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
7704 LOAD_IMGLIB_FN (library, rsvg_handle_free);
7706 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
7707 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
7708 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
7709 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
7710 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
7711 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
7712 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
7713 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
7715 LOAD_IMGLIB_FN (gobject, g_type_init);
7716 LOAD_IMGLIB_FN (gobject, g_object_unref);
7717 LOAD_IMGLIB_FN (glib, g_error_free);
7719 return 1;
7722 #else
7723 /* The following aliases for library functions allow dynamic loading
7724 to be used on some platforms. */
7725 #define fn_rsvg_handle_new rsvg_handle_new
7726 #define fn_rsvg_handle_get_dimensions rsvg_handle_get_dimensions
7727 #define fn_rsvg_handle_write rsvg_handle_write
7728 #define fn_rsvg_handle_close rsvg_handle_close
7729 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
7730 #define fn_rsvg_handle_free rsvg_handle_free
7732 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
7733 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
7734 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
7735 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
7736 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
7737 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
7738 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
7739 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
7741 #define fn_g_type_init g_type_init
7742 #define fn_g_object_unref g_object_unref
7743 #define fn_g_error_free g_error_free
7744 #endif /* !HAVE_NTGUI */
7746 /* Load SVG image IMG for use on frame F. Value is non-zero if
7747 successful. this function will go into the svg_type structure, and
7748 the prototype thus needs to be compatible with that structure. */
7750 static int
7751 svg_load (f, img)
7752 struct frame *f;
7753 struct image *img;
7755 int success_p = 0;
7756 Lisp_Object file_name;
7758 /* If IMG->spec specifies a file name, create a non-file spec from it. */
7759 file_name = image_spec_value (img->spec, QCfile, NULL);
7760 if (STRINGP (file_name))
7762 Lisp_Object file;
7763 unsigned char *contents;
7764 int size;
7765 struct gcpro gcpro1;
7767 file = x_find_image_file (file_name);
7768 GCPRO1 (file);
7769 if (!STRINGP (file))
7771 image_error ("Cannot find image file `%s'", file_name, Qnil);
7772 UNGCPRO;
7773 return 0;
7776 /* Read the entire file into memory. */
7777 contents = slurp_file (SDATA (file), &size);
7778 if (contents == NULL)
7780 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
7781 UNGCPRO;
7782 return 0;
7784 /* If the file was slurped into memory properly, parse it. */
7785 success_p = svg_load_image (f, img, contents, size);
7786 xfree (contents);
7787 UNGCPRO;
7789 /* Else its not a file, its a lisp object. Load the image from a
7790 lisp object rather than a file. */
7791 else
7793 Lisp_Object data;
7795 data = image_spec_value (img->spec, QCdata, NULL);
7796 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
7799 return success_p;
7802 /* svg_load_image is a helper function for svg_load, which does the
7803 actual loading given contents and size, apart from frame and image
7804 structures, passed from svg_load.
7806 Uses librsvg to do most of the image processing.
7808 Returns non-zero when successful. */
7809 static int
7810 svg_load_image (f, img, contents, size)
7811 /* Pointer to emacs frame structure. */
7812 struct frame *f;
7813 /* Pointer to emacs image structure. */
7814 struct image *img;
7815 /* String containing the SVG XML data to be parsed. */
7816 unsigned char *contents;
7817 /* Size of data in bytes. */
7818 unsigned int size;
7820 RsvgHandle *rsvg_handle;
7821 RsvgDimensionData dimension_data;
7822 GError *error = NULL;
7823 GdkPixbuf *pixbuf;
7824 int width;
7825 int height;
7826 const guint8 *pixels;
7827 int rowstride;
7828 XImagePtr ximg;
7829 Lisp_Object specified_bg;
7830 XColor background;
7831 int x;
7832 int y;
7834 /* g_type_init is a glib function that must be called prior to using
7835 gnome type library functions. */
7836 fn_g_type_init ();
7837 /* Make a handle to a new rsvg object. */
7838 rsvg_handle = fn_rsvg_handle_new ();
7840 /* Parse the contents argument and fill in the rsvg_handle. */
7841 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
7842 if (error) goto rsvg_error;
7844 /* The parsing is complete, rsvg_handle is ready to used, close it
7845 for further writes. */
7846 fn_rsvg_handle_close (rsvg_handle, &error);
7847 if (error) goto rsvg_error;
7849 fn_rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
7850 if (! check_image_size (f, dimension_data.width, dimension_data.height))
7852 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
7853 goto rsvg_error;
7856 /* We can now get a valid pixel buffer from the svg file, if all
7857 went ok. */
7858 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
7859 if (!pixbuf) goto rsvg_error;
7860 fn_g_object_unref (rsvg_handle);
7862 /* Extract some meta data from the svg handle. */
7863 width = fn_gdk_pixbuf_get_width (pixbuf);
7864 height = fn_gdk_pixbuf_get_height (pixbuf);
7865 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
7866 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
7868 /* Validate the svg meta data. */
7869 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
7870 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
7871 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
7872 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
7874 /* Try to create a x pixmap to hold the svg pixmap. */
7875 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7877 fn_g_object_unref (pixbuf);
7878 return 0;
7881 init_color_table ();
7883 /* Handle alpha channel by combining the image with a background
7884 color. */
7885 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7886 if (!STRINGP (specified_bg)
7887 || !x_defined_color (f, SDATA (specified_bg), &background, 0))
7889 #ifndef HAVE_NS
7890 background.pixel = FRAME_BACKGROUND_PIXEL (f);
7891 x_query_color (f, &background);
7892 #else
7893 ns_query_color(FRAME_BACKGROUND_COLOR (f), &background, 1);
7894 #endif
7897 /* SVG pixmaps specify transparency in the last byte, so right
7898 shift 8 bits to get rid of it, since emacs doesn't support
7899 transparency. */
7900 background.red >>= 8;
7901 background.green >>= 8;
7902 background.blue >>= 8;
7904 /* This loop handles opacity values, since Emacs assumes
7905 non-transparent images. Each pixel must be "flattened" by
7906 calculating the resulting color, given the transparency of the
7907 pixel, and the image background color. */
7908 for (y = 0; y < height; ++y)
7910 for (x = 0; x < width; ++x)
7912 unsigned red;
7913 unsigned green;
7914 unsigned blue;
7915 unsigned opacity;
7917 red = *pixels++;
7918 green = *pixels++;
7919 blue = *pixels++;
7920 opacity = *pixels++;
7922 red = ((red * opacity)
7923 + (background.red * ((1 << 8) - opacity)));
7924 green = ((green * opacity)
7925 + (background.green * ((1 << 8) - opacity)));
7926 blue = ((blue * opacity)
7927 + (background.blue * ((1 << 8) - opacity)));
7929 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
7932 pixels += rowstride - 4 * width;
7935 #ifdef COLOR_TABLE_SUPPORT
7936 /* Remember colors allocated for this image. */
7937 img->colors = colors_in_color_table (&img->ncolors);
7938 free_color_table ();
7939 #endif /* COLOR_TABLE_SUPPORT */
7941 fn_g_object_unref (pixbuf);
7943 img->width = width;
7944 img->height = height;
7946 /* Maybe fill in the background field while we have ximg handy.
7947 Casting avoids a GCC warning. */
7948 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7950 /* Put the image into the pixmap, then free the X image and its
7951 buffer. */
7952 x_put_x_image (f, ximg, img->pixmap, width, height);
7953 x_destroy_x_image (ximg);
7955 return 1;
7957 rsvg_error:
7958 fn_g_object_unref (rsvg_handle);
7959 /* FIXME: Use error->message so the user knows what is the actual
7960 problem with the image. */
7961 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
7962 fn_g_error_free (error);
7963 return 0;
7966 #endif /* defined (HAVE_RSVG) */
7971 /***********************************************************************
7972 Ghostscript
7973 ***********************************************************************/
7975 #ifdef HAVE_X_WINDOWS
7976 #define HAVE_GHOSTSCRIPT 1
7977 #endif /* HAVE_X_WINDOWS */
7979 /* The symbol `postscript' identifying images of this type. */
7981 Lisp_Object Qpostscript;
7983 #ifdef HAVE_GHOSTSCRIPT
7985 static int gs_image_p P_ ((Lisp_Object object));
7986 static int gs_load P_ ((struct frame *f, struct image *img));
7987 static void gs_clear_image P_ ((struct frame *f, struct image *img));
7989 /* Keyword symbols. */
7991 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
7993 /* Indices of image specification fields in gs_format, below. */
7995 enum gs_keyword_index
7997 GS_TYPE,
7998 GS_PT_WIDTH,
7999 GS_PT_HEIGHT,
8000 GS_FILE,
8001 GS_LOADER,
8002 GS_BOUNDING_BOX,
8003 GS_ASCENT,
8004 GS_MARGIN,
8005 GS_RELIEF,
8006 GS_ALGORITHM,
8007 GS_HEURISTIC_MASK,
8008 GS_MASK,
8009 GS_BACKGROUND,
8010 GS_LAST
8013 /* Vector of image_keyword structures describing the format
8014 of valid user-defined image specifications. */
8016 static const struct image_keyword gs_format[GS_LAST] =
8018 {":type", IMAGE_SYMBOL_VALUE, 1},
8019 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8020 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8021 {":file", IMAGE_STRING_VALUE, 1},
8022 {":loader", IMAGE_FUNCTION_VALUE, 0},
8023 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8024 {":ascent", IMAGE_ASCENT_VALUE, 0},
8025 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8026 {":relief", IMAGE_INTEGER_VALUE, 0},
8027 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8028 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8029 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8030 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8033 /* Structure describing the image type `ghostscript'. */
8035 static struct image_type gs_type =
8037 &Qpostscript,
8038 gs_image_p,
8039 gs_load,
8040 gs_clear_image,
8041 NULL
8045 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8047 static void
8048 gs_clear_image (f, img)
8049 struct frame *f;
8050 struct image *img;
8052 /* IMG->data.ptr_val may contain a recorded colormap. */
8053 xfree (img->data.ptr_val);
8054 x_clear_image (f, img);
8058 /* Return non-zero if OBJECT is a valid Ghostscript image
8059 specification. */
8061 static int
8062 gs_image_p (object)
8063 Lisp_Object object;
8065 struct image_keyword fmt[GS_LAST];
8066 Lisp_Object tem;
8067 int i;
8069 bcopy (gs_format, fmt, sizeof fmt);
8071 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8072 return 0;
8074 /* Bounding box must be a list or vector containing 4 integers. */
8075 tem = fmt[GS_BOUNDING_BOX].value;
8076 if (CONSP (tem))
8078 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8079 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8080 return 0;
8081 if (!NILP (tem))
8082 return 0;
8084 else if (VECTORP (tem))
8086 if (XVECTOR_SIZE (tem) != 4)
8087 return 0;
8088 for (i = 0; i < 4; ++i)
8089 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8090 return 0;
8092 else
8093 return 0;
8095 return 1;
8099 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8100 if successful. */
8102 static int
8103 gs_load (f, img)
8104 struct frame *f;
8105 struct image *img;
8107 char buffer[100];
8108 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8109 struct gcpro gcpro1, gcpro2;
8110 Lisp_Object frame;
8111 double in_width, in_height;
8112 Lisp_Object pixel_colors = Qnil;
8114 /* Compute pixel size of pixmap needed from the given size in the
8115 image specification. Sizes in the specification are in pt. 1 pt
8116 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8117 info. */
8118 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8119 in_width = XFASTINT (pt_width) / 72.0;
8120 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
8121 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8122 in_height = XFASTINT (pt_height) / 72.0;
8123 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
8125 if (!check_image_size (f, img->width, img->height))
8127 image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
8128 return 0;
8131 /* Create the pixmap. */
8132 xassert (img->pixmap == NO_PIXMAP);
8134 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8135 BLOCK_INPUT;
8136 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8137 img->width, img->height,
8138 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8139 UNBLOCK_INPUT;
8141 if (!img->pixmap)
8143 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8144 return 0;
8147 /* Call the loader to fill the pixmap. It returns a process object
8148 if successful. We do not record_unwind_protect here because
8149 other places in redisplay like calling window scroll functions
8150 don't either. Let the Lisp loader use `unwind-protect' instead. */
8151 GCPRO2 (window_and_pixmap_id, pixel_colors);
8153 sprintf (buffer, "%lu %lu",
8154 (unsigned long) FRAME_X_WINDOW (f),
8155 (unsigned long) img->pixmap);
8156 window_and_pixmap_id = build_string (buffer);
8158 sprintf (buffer, "%lu %lu",
8159 FRAME_FOREGROUND_PIXEL (f),
8160 FRAME_BACKGROUND_PIXEL (f));
8161 pixel_colors = build_string (buffer);
8163 XSETFRAME (frame, f);
8164 loader = image_spec_value (img->spec, QCloader, NULL);
8165 if (NILP (loader))
8166 loader = intern ("gs-load-image");
8168 img->data.lisp_val = call6 (loader, frame, img->spec,
8169 make_number (img->width),
8170 make_number (img->height),
8171 window_and_pixmap_id,
8172 pixel_colors);
8173 UNGCPRO;
8174 return PROCESSP (img->data.lisp_val);
8178 /* Kill the Ghostscript process that was started to fill PIXMAP on
8179 frame F. Called from XTread_socket when receiving an event
8180 telling Emacs that Ghostscript has finished drawing. */
8182 void
8183 x_kill_gs_process (pixmap, f)
8184 Pixmap pixmap;
8185 struct frame *f;
8187 struct image_cache *c = FRAME_IMAGE_CACHE (f);
8188 int class, i;
8189 struct image *img;
8191 /* Find the image containing PIXMAP. */
8192 for (i = 0; i < c->used; ++i)
8193 if (c->images[i]->pixmap == pixmap)
8194 break;
8196 /* Should someone in between have cleared the image cache, for
8197 instance, give up. */
8198 if (i == c->used)
8199 return;
8201 /* Kill the GS process. We should have found PIXMAP in the image
8202 cache and its image should contain a process object. */
8203 img = c->images[i];
8204 xassert (PROCESSP (img->data.lisp_val));
8205 Fkill_process (img->data.lisp_val, Qnil);
8206 img->data.lisp_val = Qnil;
8208 #if defined (HAVE_X_WINDOWS)
8210 /* On displays with a mutable colormap, figure out the colors
8211 allocated for the image by looking at the pixels of an XImage for
8212 img->pixmap. */
8213 class = FRAME_X_VISUAL (f)->class;
8214 if (class != StaticColor && class != StaticGray && class != TrueColor)
8216 XImagePtr ximg;
8218 BLOCK_INPUT;
8220 /* Try to get an XImage for img->pixmep. */
8221 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8222 0, 0, img->width, img->height, ~0, ZPixmap);
8223 if (ximg)
8225 int x, y;
8227 /* Initialize the color table. */
8228 init_color_table ();
8230 /* For each pixel of the image, look its color up in the
8231 color table. After having done so, the color table will
8232 contain an entry for each color used by the image. */
8233 for (y = 0; y < img->height; ++y)
8234 for (x = 0; x < img->width; ++x)
8236 unsigned long pixel = XGetPixel (ximg, x, y);
8237 lookup_pixel_color (f, pixel);
8240 /* Record colors in the image. Free color table and XImage. */
8241 #ifdef COLOR_TABLE_SUPPORT
8242 img->colors = colors_in_color_table (&img->ncolors);
8243 free_color_table ();
8244 #endif
8245 XDestroyImage (ximg);
8247 #if 0 /* This doesn't seem to be the case. If we free the colors
8248 here, we get a BadAccess later in x_clear_image when
8249 freeing the colors. */
8250 /* We have allocated colors once, but Ghostscript has also
8251 allocated colors on behalf of us. So, to get the
8252 reference counts right, free them once. */
8253 if (img->ncolors)
8254 x_free_colors (f, img->colors, img->ncolors);
8255 #endif
8257 else
8258 image_error ("Cannot get X image of `%s'; colors will not be freed",
8259 img->spec, Qnil);
8261 UNBLOCK_INPUT;
8263 #endif /* HAVE_X_WINDOWS */
8265 /* Now that we have the pixmap, compute mask and transform the
8266 image if requested. */
8267 BLOCK_INPUT;
8268 postprocess_image (f, img);
8269 UNBLOCK_INPUT;
8272 #endif /* HAVE_GHOSTSCRIPT */
8275 /***********************************************************************
8276 Tests
8277 ***********************************************************************/
8279 #if GLYPH_DEBUG
8281 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8282 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8283 (spec)
8284 Lisp_Object spec;
8286 return valid_image_p (spec) ? Qt : Qnil;
8290 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8291 (spec)
8292 Lisp_Object spec;
8294 int id = -1;
8296 if (valid_image_p (spec))
8297 id = lookup_image (SELECTED_FRAME (), spec);
8299 debug_print (spec);
8300 return make_number (id);
8303 #endif /* GLYPH_DEBUG != 0 */
8306 /***********************************************************************
8307 Initialization
8308 ***********************************************************************/
8310 #ifdef HAVE_NTGUI
8311 /* Image types that rely on external libraries are loaded dynamically
8312 if the library is available. */
8313 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8314 define_image_type (image_type, init_lib_fn (libraries))
8315 #else
8316 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8317 define_image_type (image_type, 1)
8318 #endif /* HAVE_NTGUI */
8320 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8321 doc: /* Initialize image library implementing image type TYPE.
8322 Return non-nil if TYPE is a supported image type.
8324 Image types pbm and xbm are prebuilt; other types are loaded here.
8325 Libraries to load are specified in alist LIBRARIES (usually, the value
8326 of `image-library-alist', which see). */)
8327 (type, libraries)
8328 Lisp_Object type, libraries;
8330 Lisp_Object tested;
8332 /* Don't try to reload the library. */
8333 tested = Fassq (type, Vimage_type_cache);
8334 if (CONSP (tested))
8335 return XCDR (tested);
8337 #if defined (HAVE_XPM) || defined (HAVE_NS)
8338 if (EQ (type, Qxpm))
8339 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8340 #endif
8342 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8343 if (EQ (type, Qjpeg))
8344 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8345 #endif
8347 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8348 if (EQ (type, Qtiff))
8349 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8350 #endif
8352 #if defined (HAVE_GIF) || defined (HAVE_NS)
8353 if (EQ (type, Qgif))
8354 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8355 #endif
8357 #if defined (HAVE_PNG) || defined (HAVE_NS)
8358 if (EQ (type, Qpng))
8359 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8360 #endif
8362 #if defined (HAVE_RSVG)
8363 if (EQ (type, Qsvg))
8364 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
8365 #endif
8367 #ifdef HAVE_GHOSTSCRIPT
8368 if (EQ (type, Qpostscript))
8369 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8370 #endif
8372 /* If the type is not recognized, avoid testing it ever again. */
8373 CACHE_IMAGE_TYPE (type, Qnil);
8374 return Qnil;
8377 void
8378 syms_of_image ()
8380 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8382 /* Initialize this only once, since that's what we do with Vimage_types
8383 and they are supposed to be in sync. Initializing here gives correct
8384 operation on GNU/Linux of calling dump-emacs after loading some images. */
8385 image_types = NULL;
8387 /* Must be defined now becase we're going to update it below, while
8388 defining the supported image types. */
8389 DEFVAR_LISP ("image-types", &Vimage_types,
8390 doc: /* List of potentially supported image types.
8391 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8392 To check whether it is really supported, use `image-type-available-p'. */);
8393 Vimage_types = Qnil;
8395 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8396 doc: /* Alist of image types vs external libraries needed to display them.
8398 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8399 representing a supported image type, and the rest are strings giving
8400 alternate filenames for the corresponding external libraries.
8402 Emacs tries to load the libraries in the order they appear on the
8403 list; if none is loaded, the running session of Emacs won't
8404 support the image type. Types 'pbm and 'xbm don't need to be
8405 listed; they are always supported. */);
8406 Vimage_library_alist = Qnil;
8407 Fput (intern_c_string ("image-library-alist"), Qrisky_local_variable, Qt);
8409 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8410 doc: /* Maximum size of images.
8411 Emacs will not load an image into memory if its pixel width or
8412 pixel height exceeds this limit.
8414 If the value is an integer, it directly specifies the maximum
8415 image height and width, measured in pixels. If it is a floating
8416 point number, it specifies the maximum image height and width
8417 as a ratio to the frame height and width. If the value is
8418 non-numeric, there is no explicit limit on the size of images. */);
8419 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8421 Vimage_type_cache = Qnil;
8422 staticpro (&Vimage_type_cache);
8424 Qpbm = intern_c_string ("pbm");
8425 staticpro (&Qpbm);
8426 ADD_IMAGE_TYPE (Qpbm);
8428 Qxbm = intern_c_string ("xbm");
8429 staticpro (&Qxbm);
8430 ADD_IMAGE_TYPE (Qxbm);
8432 define_image_type (&xbm_type, 1);
8433 define_image_type (&pbm_type, 1);
8435 Qcount = intern_c_string ("count");
8436 staticpro (&Qcount);
8438 QCascent = intern_c_string (":ascent");
8439 staticpro (&QCascent);
8440 QCmargin = intern_c_string (":margin");
8441 staticpro (&QCmargin);
8442 QCrelief = intern_c_string (":relief");
8443 staticpro (&QCrelief);
8444 QCconversion = intern_c_string (":conversion");
8445 staticpro (&QCconversion);
8446 QCcolor_symbols = intern_c_string (":color-symbols");
8447 staticpro (&QCcolor_symbols);
8448 QCheuristic_mask = intern_c_string (":heuristic-mask");
8449 staticpro (&QCheuristic_mask);
8450 QCindex = intern_c_string (":index");
8451 staticpro (&QCindex);
8452 QCmatrix = intern_c_string (":matrix");
8453 staticpro (&QCmatrix);
8454 QCcolor_adjustment = intern_c_string (":color-adjustment");
8455 staticpro (&QCcolor_adjustment);
8456 QCmask = intern_c_string (":mask");
8457 staticpro (&QCmask);
8459 Qlaplace = intern_c_string ("laplace");
8460 staticpro (&Qlaplace);
8461 Qemboss = intern_c_string ("emboss");
8462 staticpro (&Qemboss);
8463 Qedge_detection = intern_c_string ("edge-detection");
8464 staticpro (&Qedge_detection);
8465 Qheuristic = intern_c_string ("heuristic");
8466 staticpro (&Qheuristic);
8468 Qpostscript = intern_c_string ("postscript");
8469 staticpro (&Qpostscript);
8470 #ifdef HAVE_GHOSTSCRIPT
8471 ADD_IMAGE_TYPE (Qpostscript);
8472 QCloader = intern_c_string (":loader");
8473 staticpro (&QCloader);
8474 QCbounding_box = intern_c_string (":bounding-box");
8475 staticpro (&QCbounding_box);
8476 QCpt_width = intern_c_string (":pt-width");
8477 staticpro (&QCpt_width);
8478 QCpt_height = intern_c_string (":pt-height");
8479 staticpro (&QCpt_height);
8480 #endif /* HAVE_GHOSTSCRIPT */
8482 #ifdef HAVE_NTGUI
8483 Qlibpng_version = intern_c_string ("libpng-version");
8484 staticpro (&Qlibpng_version);
8485 Fset (Qlibpng_version,
8486 #if HAVE_PNG
8487 make_number (PNG_LIBPNG_VER)
8488 #else
8489 make_number (-1)
8490 #endif
8492 #endif
8494 #if defined (HAVE_XPM) || defined (HAVE_NS)
8495 Qxpm = intern_c_string ("xpm");
8496 staticpro (&Qxpm);
8497 ADD_IMAGE_TYPE (Qxpm);
8498 #endif
8500 #if defined (HAVE_JPEG) || defined (HAVE_NS)
8501 Qjpeg = intern_c_string ("jpeg");
8502 staticpro (&Qjpeg);
8503 ADD_IMAGE_TYPE (Qjpeg);
8504 #endif
8506 #if defined (HAVE_TIFF) || defined (HAVE_NS)
8507 Qtiff = intern_c_string ("tiff");
8508 staticpro (&Qtiff);
8509 ADD_IMAGE_TYPE (Qtiff);
8510 #endif
8512 #if defined (HAVE_GIF) || defined (HAVE_NS)
8513 Qgif = intern_c_string ("gif");
8514 staticpro (&Qgif);
8515 ADD_IMAGE_TYPE (Qgif);
8516 #endif
8518 #if defined (HAVE_PNG) || defined (HAVE_NS)
8519 Qpng = intern_c_string ("png");
8520 staticpro (&Qpng);
8521 ADD_IMAGE_TYPE (Qpng);
8522 #endif
8524 #if defined (HAVE_RSVG)
8525 Qsvg = intern_c_string ("svg");
8526 staticpro (&Qsvg);
8527 ADD_IMAGE_TYPE (Qsvg);
8528 #ifdef HAVE_NTGUI
8529 /* Other libraries used directly by svg code. */
8530 Qgdk_pixbuf = intern_c_string ("gdk-pixbuf");
8531 staticpro (&Qgdk_pixbuf);
8532 Qglib = intern_c_string ("glib");
8533 staticpro (&Qglib);
8534 Qgobject = intern_c_string ("gobject");
8535 staticpro (&Qgobject);
8536 #endif /* HAVE_NTGUI */
8537 #endif /* HAVE_RSVG */
8539 defsubr (&Sinit_image_library);
8540 defsubr (&Sclear_image_cache);
8541 defsubr (&Simage_refresh);
8542 defsubr (&Simage_size);
8543 defsubr (&Simage_mask_p);
8544 defsubr (&Simage_extension_data);
8546 #if GLYPH_DEBUG
8547 defsubr (&Simagep);
8548 defsubr (&Slookup_image);
8549 #endif
8551 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
8552 doc: /* Non-nil means always draw a cross over disabled images.
8553 Disabled images are those having a `:conversion disabled' property.
8554 A cross is always drawn on black & white displays. */);
8555 cross_disabled_images = 0;
8557 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8558 doc: /* List of directories to search for window system bitmap files. */);
8559 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8561 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8562 doc: /* Time after which cached images are removed from the cache.
8563 When an image has not been displayed this many seconds, remove it
8564 from the image cache. Value must be an integer or nil with nil
8565 meaning don't clear the cache. */);
8566 Vimage_cache_eviction_delay = make_number (30 * 60);
8569 void
8570 init_image ()
8574 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8575 (do not change this comment) */