Various changes in addition to:
[emacs.git] / src / image.c
blob34db5e53367d48a4d33e05564343601a8a834091
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 99, 2000,01,02,03,04
3 Free Software Foundation.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <math.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
31 /* This makes the fields of a Display accessible, in Xlib header files. */
33 #define XLIB_ILLEGAL_ACCESS
35 #include "lisp.h"
36 #include "frame.h"
37 #include "window.h"
38 #include "dispextern.h"
39 #include "blockinput.h"
40 #include "systime.h"
41 #include <epaths.h>
44 #ifdef HAVE_X_WINDOWS
45 #include "xterm.h"
46 #include <sys/types.h>
47 #include <sys/stat.h>
49 #define COLOR_TABLE_SUPPORT 1
51 typedef struct x_bitmap_record Bitmap_Record;
52 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
53 #define NO_PIXMAP None
54 #define PNG_BG_COLOR_SHIFT 0
56 #define RGB_PIXEL_COLOR unsigned long
58 #define PIX_MASK_RETAIN(f) 0
59 #define PIX_MASK_DRAW(f) 1
60 #endif /* HAVE_X_WINDOWS */
63 #ifdef HAVE_NTGUI
64 #include "w32term.h"
66 /* W32_TODO : Color tables on W32. */
67 #undef COLOR_TABLE_SUPPORT
69 typedef struct w32_bitmap_record Bitmap_Record;
70 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
71 #define NO_PIXMAP 0
72 #define PNG_BG_COLOR_SHIFT 0
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN(f) 0
77 #define PIX_MASK_DRAW(f) 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
85 #ifdef MAC_OS
86 #include "macterm.h"
87 #ifndef MAC_OSX
88 #include <alloca.h>
89 #endif
90 #ifdef MAC_OSX
91 #include <sys/stat.h>
92 #include <QuickTime/QuickTime.h>
93 #else /* not MAC_OSX */
94 #include <Windows.h>
95 #include <Gestalt.h>
96 #include <TextUtils.h>
97 #endif /* not MAC_OSX */
99 /* MAC_TODO : Color tables on Mac. */
100 #undef COLOR_TABLE_SUPPORT
102 #define ZPixmap 0 /* arbitrary */
103 typedef struct mac_bitmap_record Bitmap_Record;
105 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
106 #define NO_PIXMAP 0
107 #define PNG_BG_COLOR_SHIFT 8
109 #define RGB_PIXEL_COLOR unsigned long
111 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
112 #define x_defined_color mac_defined_color
113 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
114 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
115 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
117 #endif /* MAC_OS */
120 /* Search path for bitmap files. */
122 Lisp_Object Vx_bitmap_file_path;
125 static void x_disable_image P_ ((struct frame *, struct image *));
126 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
127 Lisp_Object));
129 static void init_color_table P_ ((void));
130 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
131 #ifdef COLOR_TABLE_SUPPORT
132 static void free_color_table P_ ((void));
133 static unsigned long *colors_in_color_table P_ ((int *n));
134 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
135 #endif
137 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
138 id, which is just an int that this section returns. Bitmaps are
139 reference counted so they can be shared among frames.
141 Bitmap indices are guaranteed to be > 0, so a negative number can
142 be used to indicate no bitmap.
144 If you use x_create_bitmap_from_data, then you must keep track of
145 the bitmaps yourself. That is, creating a bitmap from the same
146 data more than once will not be caught. */
148 #ifdef MAC_OS
150 static XImagePtr
151 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
152 Display *display; /* not used */
153 Pixmap pixmap;
154 int x, y; /* not used */
155 unsigned int width, height; /* not used */
156 unsigned long plane_mask; /* not used */
157 int format; /* not used */
159 #if GLYPH_DEBUG
160 xassert (x == 0 && y == 0);
162 Rect ri, rp;
163 SetRect (&ri, 0, 0, width, height);
164 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
166 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
167 #endif
169 LockPixels (GetGWorldPixMap (pixmap));
171 return pixmap;
174 static void
175 XPutPixel (ximage, x, y, pixel)
176 XImagePtr ximage;
177 int x, y;
178 unsigned long pixel;
180 RGBColor color;
182 SetGWorld (ximage, NULL);
184 color.red = RED16_FROM_ULONG (pixel);
185 color.green = GREEN16_FROM_ULONG (pixel);
186 color.blue = BLUE16_FROM_ULONG (pixel);
187 SetCPixel (x, y, &color);
190 static unsigned long
191 XGetPixel (ximage, x, y)
192 XImagePtr ximage;
193 int x, y;
195 RGBColor color;
197 SetGWorld (ximage, NULL);
199 GetCPixel (x, y, &color);
200 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
203 static void
204 XDestroyImage (ximg)
205 XImagePtr ximg;
207 UnlockPixels (GetGWorldPixMap (ximg));
209 #endif
212 /* Functions to access the contents of a bitmap, given an id. */
215 x_bitmap_height (f, id)
216 FRAME_PTR f;
217 int id;
219 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
223 x_bitmap_width (f, id)
224 FRAME_PTR f;
225 int id;
227 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
230 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
232 x_bitmap_pixmap (f, id)
233 FRAME_PTR f;
234 int id;
236 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
238 #endif
240 #ifdef HAVE_X_WINDOWS
242 x_bitmap_mask (f, id)
243 FRAME_PTR f;
244 int id;
246 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
248 #endif
250 /* Allocate a new bitmap record. Returns index of new record. */
252 static int
253 x_allocate_bitmap_record (f)
254 FRAME_PTR f;
256 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
257 int i;
259 if (dpyinfo->bitmaps == NULL)
261 dpyinfo->bitmaps_size = 10;
262 dpyinfo->bitmaps
263 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
264 dpyinfo->bitmaps_last = 1;
265 return 1;
268 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
269 return ++dpyinfo->bitmaps_last;
271 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
272 if (dpyinfo->bitmaps[i].refcount == 0)
273 return i + 1;
275 dpyinfo->bitmaps_size *= 2;
276 dpyinfo->bitmaps
277 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
278 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
279 return ++dpyinfo->bitmaps_last;
282 /* Add one reference to the reference count of the bitmap with id ID. */
284 void
285 x_reference_bitmap (f, id)
286 FRAME_PTR f;
287 int id;
289 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
292 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
295 x_create_bitmap_from_data (f, bits, width, height)
296 struct frame *f;
297 char *bits;
298 unsigned int width, height;
300 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
301 int id;
303 #ifdef HAVE_X_WINDOWS
304 Pixmap bitmap;
305 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
306 bits, width, height);
307 if (! bitmap)
308 return -1;
309 #endif /* HAVE_X_WINDOWS */
311 #ifdef HAVE_NTGUI
312 Pixmap bitmap;
313 bitmap = CreateBitmap (width, height,
314 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
315 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
316 bits);
317 if (! bitmap)
318 return -1;
319 #endif /* HAVE_NTGUI */
321 #ifdef MAC_OS
322 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
323 if (width % 16 != 0)
324 return -1;
325 #endif
327 id = x_allocate_bitmap_record (f);
328 #ifdef MAC_OS
329 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
330 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
331 return -1;
332 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
333 #endif /* MAC_OS */
335 dpyinfo->bitmaps[id - 1].file = NULL;
336 dpyinfo->bitmaps[id - 1].height = height;
337 dpyinfo->bitmaps[id - 1].width = width;
338 dpyinfo->bitmaps[id - 1].refcount = 1;
340 #ifdef HAVE_X_WINDOWS
341 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
342 dpyinfo->bitmaps[id - 1].have_mask = 0;
343 dpyinfo->bitmaps[id - 1].depth = 1;
344 #endif /* HAVE_X_WINDOWS */
346 #ifdef HAVE_NTGUI
347 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
348 dpyinfo->bitmaps[id - 1].hinst = NULL;
349 dpyinfo->bitmaps[id - 1].depth = 1;
350 #endif /* HAVE_NTGUI */
352 return id;
355 /* Create bitmap from file FILE for frame F. */
358 x_create_bitmap_from_file (f, file)
359 struct frame *f;
360 Lisp_Object file;
362 #ifdef MAC_OS
363 return -1; /* MAC_TODO : bitmap support */
364 #endif /* MAC_OS */
366 #ifdef HAVE_NTGUI
367 return -1; /* W32_TODO : bitmap support */
368 #endif /* HAVE_NTGUI */
370 #ifdef HAVE_X_WINDOWS
371 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
372 unsigned int width, height;
373 Pixmap bitmap;
374 int xhot, yhot, result, id;
375 Lisp_Object found;
376 int fd;
377 char *filename;
379 /* Look for an existing bitmap with the same name. */
380 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
382 if (dpyinfo->bitmaps[id].refcount
383 && dpyinfo->bitmaps[id].file
384 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
386 ++dpyinfo->bitmaps[id].refcount;
387 return id + 1;
391 /* Search bitmap-file-path for the file, if appropriate. */
392 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
393 if (fd < 0)
394 return -1;
395 emacs_close (fd);
397 filename = (char *) SDATA (found);
399 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
400 filename, &width, &height, &bitmap, &xhot, &yhot);
401 if (result != BitmapSuccess)
402 return -1;
404 id = x_allocate_bitmap_record (f);
405 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
406 dpyinfo->bitmaps[id - 1].have_mask = 0;
407 dpyinfo->bitmaps[id - 1].refcount = 1;
408 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
409 dpyinfo->bitmaps[id - 1].depth = 1;
410 dpyinfo->bitmaps[id - 1].height = height;
411 dpyinfo->bitmaps[id - 1].width = width;
412 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
414 return id;
415 #endif /* HAVE_X_WINDOWS */
418 /* Free bitmap B. */
420 static void
421 Free_Bitmap_Record (dpyinfo, bm)
422 Display_Info *dpyinfo;
423 Bitmap_Record *bm;
425 #ifdef HAVE_X_WINDOWS
426 XFreePixmap (dpyinfo->display, bm->pixmap);
427 if (bm->have_mask)
428 XFreePixmap (dpyinfo->display, bm->mask);
429 #endif /* HAVE_X_WINDOWS */
431 #ifdef HAVE_NTGUI
432 DeleteObject (bm->pixmap);
433 #endif /* HAVE_NTGUI */
435 #ifdef MAC_OS
436 xfree (bm->bitmap_data); /* Added ++kfs */
437 bm->bitmap_data = NULL;
438 #endif /* MAC_OS */
440 if (bm->file)
442 xfree (bm->file);
443 bm->file = NULL;
447 /* Remove reference to bitmap with id number ID. */
449 void
450 x_destroy_bitmap (f, id)
451 FRAME_PTR f;
452 int id;
454 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
456 if (id > 0)
458 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
460 if (--bm->refcount == 0)
462 BLOCK_INPUT;
463 Free_Bitmap_Record (dpyinfo, bm);
464 UNBLOCK_INPUT;
469 /* Free all the bitmaps for the display specified by DPYINFO. */
471 void
472 x_destroy_all_bitmaps (dpyinfo)
473 Display_Info *dpyinfo;
475 int i;
476 Bitmap_Record *bm = dpyinfo->bitmaps;
478 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
479 if (bm->refcount > 0)
480 Free_Bitmap_Record (dpyinfo, bm);
482 dpyinfo->bitmaps_last = 0;
486 #ifdef HAVE_X_WINDOWS
488 /* Useful functions defined in the section
489 `Image type independent image structures' below. */
491 static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
492 unsigned long height));
494 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
495 int depth, XImagePtr *ximg,
496 Pixmap *pixmap));
498 static void x_destroy_x_image P_ ((XImagePtr ximg));
501 /* Create a mask of a bitmap. Note is this not a perfect mask.
502 It's nicer with some borders in this context */
505 x_create_bitmap_mask (f, id)
506 struct frame *f;
507 int id;
509 Pixmap pixmap, mask;
510 XImagePtr ximg, mask_img;
511 unsigned long width, height;
512 int result;
513 unsigned long bg;
514 unsigned long x, y, xp, xm, yp, ym;
515 GC gc;
517 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
519 if (!(id > 0))
520 return -1;
522 pixmap = x_bitmap_pixmap (f, id);
523 width = x_bitmap_width (f, id);
524 height = x_bitmap_height (f, id);
526 BLOCK_INPUT;
527 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
528 ~0, ZPixmap);
530 if (!ximg)
532 UNBLOCK_INPUT;
533 return -1;
536 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
538 UNBLOCK_INPUT;
539 if (!result)
541 XDestroyImage (ximg);
542 return -1;
545 bg = four_corners_best (ximg, width, height);
547 for (y = 0; y < ximg->height; ++y)
549 for (x = 0; x < ximg->width; ++x)
551 xp = x != ximg->width - 1 ? x + 1 : 0;
552 xm = x != 0 ? x - 1 : ximg->width - 1;
553 yp = y != ximg->height - 1 ? y + 1 : 0;
554 ym = y != 0 ? y - 1 : ximg->height - 1;
555 if (XGetPixel (ximg, x, y) == bg
556 && XGetPixel (ximg, x, yp) == bg
557 && XGetPixel (ximg, x, ym) == bg
558 && XGetPixel (ximg, xp, y) == bg
559 && XGetPixel (ximg, xp, yp) == bg
560 && XGetPixel (ximg, xp, ym) == bg
561 && XGetPixel (ximg, xm, y) == bg
562 && XGetPixel (ximg, xm, yp) == bg
563 && XGetPixel (ximg, xm, ym) == bg)
564 XPutPixel (mask_img, x, y, 0);
565 else
566 XPutPixel (mask_img, x, y, 1);
570 xassert (interrupt_input_blocked);
571 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
572 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
573 width, height);
574 XFreeGC (FRAME_X_DISPLAY (f), gc);
576 dpyinfo->bitmaps[id - 1].have_mask = 1;
577 dpyinfo->bitmaps[id - 1].mask = mask;
579 XDestroyImage (ximg);
580 x_destroy_x_image (mask_img);
582 return 0;
585 #endif /* HAVE_X_WINDOWS */
588 /***********************************************************************
589 Image types
590 ***********************************************************************/
592 /* Value is the number of elements of vector VECTOR. */
594 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
596 /* List of supported image types. Use define_image_type to add new
597 types. Use lookup_image_type to find a type for a given symbol. */
599 static struct image_type *image_types;
601 /* The symbol `xbm' which is used as the type symbol for XBM images. */
603 Lisp_Object Qxbm;
605 /* Keywords. */
607 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
608 extern Lisp_Object QCdata, QCtype;
609 extern Lisp_Object Qcenter;
610 Lisp_Object QCascent, QCmargin, QCrelief;
611 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
612 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
614 /* Other symbols. */
616 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
618 /* Time in seconds after which images should be removed from the cache
619 if not displayed. */
621 Lisp_Object Vimage_cache_eviction_delay;
623 /* Function prototypes. */
625 static void define_image_type P_ ((struct image_type *type));
626 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
627 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
628 static void x_laplace P_ ((struct frame *, struct image *));
629 static void x_emboss P_ ((struct frame *, struct image *));
630 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
631 Lisp_Object));
634 /* Define a new image type from TYPE. This adds a copy of TYPE to
635 image_types and adds the symbol *TYPE->type to Vimage_types. */
637 static void
638 define_image_type (type)
639 struct image_type *type;
641 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
642 The initialized data segment is read-only. */
643 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
644 bcopy (type, p, sizeof *p);
645 p->next = image_types;
646 image_types = p;
647 Vimage_types = Fcons (*p->type, Vimage_types);
651 /* Look up image type SYMBOL, and return a pointer to its image_type
652 structure. Value is null if SYMBOL is not a known image type. */
654 static INLINE struct image_type *
655 lookup_image_type (symbol)
656 Lisp_Object symbol;
658 struct image_type *type;
660 for (type = image_types; type; type = type->next)
661 if (EQ (symbol, *type->type))
662 break;
664 return type;
668 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
669 valid image specification is a list whose car is the symbol
670 `image', and whose rest is a property list. The property list must
671 contain a value for key `:type'. That value must be the name of a
672 supported image type. The rest of the property list depends on the
673 image type. */
676 valid_image_p (object)
677 Lisp_Object object;
679 int valid_p = 0;
681 if (IMAGEP (object))
683 Lisp_Object tem;
685 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
686 if (EQ (XCAR (tem), QCtype))
688 tem = XCDR (tem);
689 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
691 struct image_type *type;
692 type = lookup_image_type (XCAR (tem));
693 if (type)
694 valid_p = type->valid_p (object);
697 break;
701 return valid_p;
705 /* Log error message with format string FORMAT and argument ARG.
706 Signaling an error, e.g. when an image cannot be loaded, is not a
707 good idea because this would interrupt redisplay, and the error
708 message display would lead to another redisplay. This function
709 therefore simply displays a message. */
711 static void
712 image_error (format, arg1, arg2)
713 char *format;
714 Lisp_Object arg1, arg2;
716 add_to_log (format, arg1, arg2);
721 /***********************************************************************
722 Image specifications
723 ***********************************************************************/
725 enum image_value_type
727 IMAGE_DONT_CHECK_VALUE_TYPE,
728 IMAGE_STRING_VALUE,
729 IMAGE_STRING_OR_NIL_VALUE,
730 IMAGE_SYMBOL_VALUE,
731 IMAGE_POSITIVE_INTEGER_VALUE,
732 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
733 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
734 IMAGE_ASCENT_VALUE,
735 IMAGE_INTEGER_VALUE,
736 IMAGE_FUNCTION_VALUE,
737 IMAGE_NUMBER_VALUE,
738 IMAGE_BOOL_VALUE
741 /* Structure used when parsing image specifications. */
743 struct image_keyword
745 /* Name of keyword. */
746 char *name;
748 /* The type of value allowed. */
749 enum image_value_type type;
751 /* Non-zero means key must be present. */
752 int mandatory_p;
754 /* Used to recognize duplicate keywords in a property list. */
755 int count;
757 /* The value that was found. */
758 Lisp_Object value;
762 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
763 int, Lisp_Object));
764 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
767 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
768 has the format (image KEYWORD VALUE ...). One of the keyword/
769 value pairs must be `:type TYPE'. KEYWORDS is a vector of
770 image_keywords structures of size NKEYWORDS describing other
771 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
773 static int
774 parse_image_spec (spec, keywords, nkeywords, type)
775 Lisp_Object spec;
776 struct image_keyword *keywords;
777 int nkeywords;
778 Lisp_Object type;
780 int i;
781 Lisp_Object plist;
783 if (!IMAGEP (spec))
784 return 0;
786 plist = XCDR (spec);
787 while (CONSP (plist))
789 Lisp_Object key, value;
791 /* First element of a pair must be a symbol. */
792 key = XCAR (plist);
793 plist = XCDR (plist);
794 if (!SYMBOLP (key))
795 return 0;
797 /* There must follow a value. */
798 if (!CONSP (plist))
799 return 0;
800 value = XCAR (plist);
801 plist = XCDR (plist);
803 /* Find key in KEYWORDS. Error if not found. */
804 for (i = 0; i < nkeywords; ++i)
805 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
806 break;
808 if (i == nkeywords)
809 continue;
811 /* Record that we recognized the keyword. If a keywords
812 was found more than once, it's an error. */
813 keywords[i].value = value;
814 ++keywords[i].count;
816 if (keywords[i].count > 1)
817 return 0;
819 /* Check type of value against allowed type. */
820 switch (keywords[i].type)
822 case IMAGE_STRING_VALUE:
823 if (!STRINGP (value))
824 return 0;
825 break;
827 case IMAGE_STRING_OR_NIL_VALUE:
828 if (!STRINGP (value) && !NILP (value))
829 return 0;
830 break;
832 case IMAGE_SYMBOL_VALUE:
833 if (!SYMBOLP (value))
834 return 0;
835 break;
837 case IMAGE_POSITIVE_INTEGER_VALUE:
838 if (!INTEGERP (value) || XINT (value) <= 0)
839 return 0;
840 break;
842 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
843 if (INTEGERP (value) && XINT (value) >= 0)
844 break;
845 if (CONSP (value)
846 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
847 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
848 break;
849 return 0;
851 case IMAGE_ASCENT_VALUE:
852 if (SYMBOLP (value) && EQ (value, Qcenter))
853 break;
854 else if (INTEGERP (value)
855 && XINT (value) >= 0
856 && XINT (value) <= 100)
857 break;
858 return 0;
860 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
861 if (!INTEGERP (value) || XINT (value) < 0)
862 return 0;
863 break;
865 case IMAGE_DONT_CHECK_VALUE_TYPE:
866 break;
868 case IMAGE_FUNCTION_VALUE:
869 value = indirect_function (value);
870 if (SUBRP (value)
871 || COMPILEDP (value)
872 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
873 break;
874 return 0;
876 case IMAGE_NUMBER_VALUE:
877 if (!INTEGERP (value) && !FLOATP (value))
878 return 0;
879 break;
881 case IMAGE_INTEGER_VALUE:
882 if (!INTEGERP (value))
883 return 0;
884 break;
886 case IMAGE_BOOL_VALUE:
887 if (!NILP (value) && !EQ (value, Qt))
888 return 0;
889 break;
891 default:
892 abort ();
893 break;
896 if (EQ (key, QCtype) && !EQ (type, value))
897 return 0;
900 /* Check that all mandatory fields are present. */
901 for (i = 0; i < nkeywords; ++i)
902 if (keywords[i].mandatory_p && keywords[i].count == 0)
903 return 0;
905 return NILP (plist);
909 /* Return the value of KEY in image specification SPEC. Value is nil
910 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
911 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
913 static Lisp_Object
914 image_spec_value (spec, key, found)
915 Lisp_Object spec, key;
916 int *found;
918 Lisp_Object tail;
920 xassert (valid_image_p (spec));
922 for (tail = XCDR (spec);
923 CONSP (tail) && CONSP (XCDR (tail));
924 tail = XCDR (XCDR (tail)))
926 if (EQ (XCAR (tail), key))
928 if (found)
929 *found = 1;
930 return XCAR (XCDR (tail));
934 if (found)
935 *found = 0;
936 return Qnil;
940 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
941 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
942 PIXELS non-nil means return the size in pixels, otherwise return the
943 size in canonical character units.
944 FRAME is the frame on which the image will be displayed. FRAME nil
945 or omitted means use the selected frame. */)
946 (spec, pixels, frame)
947 Lisp_Object spec, pixels, frame;
949 Lisp_Object size;
951 size = Qnil;
952 if (valid_image_p (spec))
954 struct frame *f = check_x_frame (frame);
955 int id = lookup_image (f, spec);
956 struct image *img = IMAGE_FROM_ID (f, id);
957 int width = img->width + 2 * img->hmargin;
958 int height = img->height + 2 * img->vmargin;
960 if (NILP (pixels))
961 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
962 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
963 else
964 size = Fcons (make_number (width), make_number (height));
966 else
967 error ("Invalid image specification");
969 return size;
973 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
974 doc: /* Return t if image SPEC has a mask bitmap.
975 FRAME is the frame on which the image will be displayed. FRAME nil
976 or omitted means use the selected frame. */)
977 (spec, frame)
978 Lisp_Object spec, frame;
980 Lisp_Object mask;
982 mask = Qnil;
983 if (valid_image_p (spec))
985 struct frame *f = check_x_frame (frame);
986 int id = lookup_image (f, spec);
987 struct image *img = IMAGE_FROM_ID (f, id);
988 if (img->mask)
989 mask = Qt;
991 else
992 error ("Invalid image specification");
994 return mask;
998 /***********************************************************************
999 Image type independent image structures
1000 ***********************************************************************/
1002 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1003 static void free_image P_ ((struct frame *f, struct image *img));
1006 /* Allocate and return a new image structure for image specification
1007 SPEC. SPEC has a hash value of HASH. */
1009 static struct image *
1010 make_image (spec, hash)
1011 Lisp_Object spec;
1012 unsigned hash;
1014 struct image *img = (struct image *) xmalloc (sizeof *img);
1016 xassert (valid_image_p (spec));
1017 bzero (img, sizeof *img);
1018 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1019 xassert (img->type != NULL);
1020 img->spec = spec;
1021 img->data.lisp_val = Qnil;
1022 img->ascent = DEFAULT_IMAGE_ASCENT;
1023 img->hash = hash;
1024 return img;
1028 /* Free image IMG which was used on frame F, including its resources. */
1030 static void
1031 free_image (f, img)
1032 struct frame *f;
1033 struct image *img;
1035 if (img)
1037 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1039 /* Remove IMG from the hash table of its cache. */
1040 if (img->prev)
1041 img->prev->next = img->next;
1042 else
1043 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1045 if (img->next)
1046 img->next->prev = img->prev;
1048 c->images[img->id] = NULL;
1050 /* Free resources, then free IMG. */
1051 img->type->free (f, img);
1052 xfree (img);
1057 /* Prepare image IMG for display on frame F. Must be called before
1058 drawing an image. */
1060 void
1061 prepare_image_for_display (f, img)
1062 struct frame *f;
1063 struct image *img;
1065 EMACS_TIME t;
1067 /* We're about to display IMG, so set its timestamp to `now'. */
1068 EMACS_GET_TIME (t);
1069 img->timestamp = EMACS_SECS (t);
1071 /* If IMG doesn't have a pixmap yet, load it now, using the image
1072 type dependent loader function. */
1073 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1074 img->load_failed_p = img->type->load (f, img) == 0;
1078 /* Value is the number of pixels for the ascent of image IMG when
1079 drawn in face FACE. */
1082 image_ascent (img, face)
1083 struct image *img;
1084 struct face *face;
1086 int height = img->height + img->vmargin;
1087 int ascent;
1089 if (img->ascent == CENTERED_IMAGE_ASCENT)
1091 if (face->font)
1093 #ifdef HAVE_NTGUI
1094 /* W32 specific version. Why?. ++kfs */
1095 ascent = height / 2 - (FONT_DESCENT(face->font)
1096 - FONT_BASE(face->font)) / 2;
1097 #else
1098 /* This expression is arranged so that if the image can't be
1099 exactly centered, it will be moved slightly up. This is
1100 because a typical font is `top-heavy' (due to the presence
1101 uppercase letters), so the image placement should err towards
1102 being top-heavy too. It also just generally looks better. */
1103 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1104 #endif /* HAVE_NTGUI */
1106 else
1107 ascent = height / 2;
1109 else
1110 ascent = (int) (height * img->ascent / 100.0);
1112 return ascent;
1116 /* Image background colors. */
1118 /* Find the "best" corner color of a bitmap.
1119 On W32, XIMG is assumed to a device context with the bitmap selected. */
1121 static RGB_PIXEL_COLOR
1122 four_corners_best (ximg, width, height)
1123 XImagePtr_or_DC ximg;
1124 unsigned long width, height;
1126 RGB_PIXEL_COLOR corners[4], best;
1127 int i, best_count;
1129 /* Get the colors at the corners of ximg. */
1130 corners[0] = GET_PIXEL (ximg, 0, 0);
1131 corners[1] = GET_PIXEL (ximg, width - 1, 0);
1132 corners[2] = GET_PIXEL (ximg, width - 1, height - 1);
1133 corners[3] = GET_PIXEL (ximg, 0, height - 1);
1135 /* Choose the most frequently found color as background. */
1136 for (i = best_count = 0; i < 4; ++i)
1138 int j, n;
1140 for (j = n = 0; j < 4; ++j)
1141 if (corners[i] == corners[j])
1142 ++n;
1144 if (n > best_count)
1145 best = corners[i], best_count = n;
1148 return best;
1151 /* Portability macros */
1153 #ifdef HAVE_NTGUI
1155 #define Destroy_Image(img_dc, prev) \
1156 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1158 #define Free_Pixmap(display, pixmap) \
1159 DeleteObject (pixmap)
1161 #else
1163 #define Destroy_Image(ximg, dummy) \
1164 XDestroyImage (ximg)
1166 #define Free_Pixmap(display, pixmap) \
1167 XFreePixmap (display, pixmap)
1169 #endif /* HAVE_NTGUI */
1172 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1173 it is guessed heuristically. If non-zero, XIMG is an existing
1174 XImage object (or device context with the image selected on W32) to
1175 use for the heuristic. */
1177 RGB_PIXEL_COLOR
1178 image_background (img, f, ximg)
1179 struct image *img;
1180 struct frame *f;
1181 XImagePtr_or_DC ximg;
1183 if (! img->background_valid)
1184 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1186 int free_ximg = !ximg;
1187 #ifdef HAVE_NTGUI
1188 HGDIOBJ prev;
1189 #endif /* HAVE_NTGUI */
1191 if (free_ximg)
1193 #ifndef HAVE_NTGUI
1194 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1195 0, 0, img->width, img->height, ~0, ZPixmap);
1196 #else
1197 HDC frame_dc = get_frame_dc (f);
1198 ximg = CreateCompatibleDC (frame_dc);
1199 release_frame_dc (f, frame_dc);
1200 prev = SelectObject (ximg, img->pixmap);
1201 #endif /* !HAVE_NTGUI */
1204 img->background = four_corners_best (ximg, img->width, img->height);
1206 if (free_ximg)
1207 Destroy_Image (ximg, prev);
1209 img->background_valid = 1;
1212 return img->background;
1215 /* Return the `background_transparent' field of IMG. If IMG doesn't
1216 have one yet, it is guessed heuristically. If non-zero, MASK is an
1217 existing XImage object to use for the heuristic. */
1220 image_background_transparent (img, f, mask)
1221 struct image *img;
1222 struct frame *f;
1223 XImagePtr_or_DC mask;
1225 if (! img->background_transparent_valid)
1226 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1228 if (img->mask)
1230 int free_mask = !mask;
1231 #ifdef HAVE_NTGUI
1232 HGDIOBJ prev;
1233 #endif /* HAVE_NTGUI */
1235 if (free_mask)
1237 #ifndef HAVE_NTGUI
1238 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1239 0, 0, img->width, img->height, ~0, ZPixmap);
1240 #else
1241 HDC frame_dc = get_frame_dc (f);
1242 mask = CreateCompatibleDC (frame_dc);
1243 release_frame_dc (f, frame_dc);
1244 prev = SelectObject (mask, img->mask);
1245 #endif /* HAVE_NTGUI */
1248 img->background_transparent
1249 = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN (f));
1251 if (free_mask)
1252 Destroy_Image (mask, prev);
1254 else
1255 img->background_transparent = 0;
1257 img->background_transparent_valid = 1;
1260 return img->background_transparent;
1264 /***********************************************************************
1265 Helper functions for X image types
1266 ***********************************************************************/
1268 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1269 int, int));
1270 static void x_clear_image P_ ((struct frame *f, struct image *img));
1271 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1272 struct image *img,
1273 Lisp_Object color_name,
1274 unsigned long dflt));
1277 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1278 free the pixmap if any. MASK_P non-zero means clear the mask
1279 pixmap if any. COLORS_P non-zero means free colors allocated for
1280 the image, if any. */
1282 static void
1283 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1284 struct frame *f;
1285 struct image *img;
1286 int pixmap_p, mask_p, colors_p;
1288 if (pixmap_p && img->pixmap)
1290 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1291 img->pixmap = NO_PIXMAP;
1292 img->background_valid = 0;
1295 if (mask_p && img->mask)
1297 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1298 img->mask = NO_PIXMAP;
1299 img->background_transparent_valid = 0;
1302 if (colors_p && img->ncolors)
1304 /* MAC_TODO: color table support. */
1305 /* W32_TODO: color table support. */
1306 #ifdef HAVE_X_WINDOWS
1307 x_free_colors (f, img->colors, img->ncolors);
1308 #endif /* HAVE_X_WINDOWS */
1309 xfree (img->colors);
1310 img->colors = NULL;
1311 img->ncolors = 0;
1315 /* Free X resources of image IMG which is used on frame F. */
1317 static void
1318 x_clear_image (f, img)
1319 struct frame *f;
1320 struct image *img;
1322 BLOCK_INPUT;
1323 x_clear_image_1 (f, img, 1, 1, 1);
1324 UNBLOCK_INPUT;
1328 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1329 cannot be allocated, use DFLT. Add a newly allocated color to
1330 IMG->colors, so that it can be freed again. Value is the pixel
1331 color. */
1333 static unsigned long
1334 x_alloc_image_color (f, img, color_name, dflt)
1335 struct frame *f;
1336 struct image *img;
1337 Lisp_Object color_name;
1338 unsigned long dflt;
1340 XColor color;
1341 unsigned long result;
1343 xassert (STRINGP (color_name));
1345 if (x_defined_color (f, SDATA (color_name), &color, 1))
1347 /* This isn't called frequently so we get away with simply
1348 reallocating the color vector to the needed size, here. */
1349 ++img->ncolors;
1350 img->colors =
1351 (unsigned long *) xrealloc (img->colors,
1352 img->ncolors * sizeof *img->colors);
1353 img->colors[img->ncolors - 1] = color.pixel;
1354 result = color.pixel;
1356 else
1357 result = dflt;
1359 return result;
1364 /***********************************************************************
1365 Image Cache
1366 ***********************************************************************/
1368 static void cache_image P_ ((struct frame *f, struct image *img));
1369 static void postprocess_image P_ ((struct frame *, struct image *));
1371 /* Return a new, initialized image cache that is allocated from the
1372 heap. Call free_image_cache to free an image cache. */
1374 struct image_cache *
1375 make_image_cache ()
1377 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1378 int size;
1380 bzero (c, sizeof *c);
1381 c->size = 50;
1382 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1383 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1384 c->buckets = (struct image **) xmalloc (size);
1385 bzero (c->buckets, size);
1386 return c;
1390 /* Free image cache of frame F. Be aware that X frames share images
1391 caches. */
1393 void
1394 free_image_cache (f)
1395 struct frame *f;
1397 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1398 if (c)
1400 int i;
1402 /* Cache should not be referenced by any frame when freed. */
1403 xassert (c->refcount == 0);
1405 for (i = 0; i < c->used; ++i)
1406 free_image (f, c->images[i]);
1407 xfree (c->images);
1408 xfree (c->buckets);
1409 xfree (c);
1410 FRAME_X_IMAGE_CACHE (f) = NULL;
1415 /* Clear image cache of frame F. FORCE_P non-zero means free all
1416 images. FORCE_P zero means clear only images that haven't been
1417 displayed for some time. Should be called from time to time to
1418 reduce the number of loaded images. If image-eviction-seconds is
1419 non-nil, this frees images in the cache which weren't displayed for
1420 at least that many seconds. */
1422 void
1423 clear_image_cache (f, force_p)
1424 struct frame *f;
1425 int force_p;
1427 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1429 if (c && INTEGERP (Vimage_cache_eviction_delay))
1431 EMACS_TIME t;
1432 unsigned long old;
1433 int i, nfreed;
1435 EMACS_GET_TIME (t);
1436 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1438 /* Block input so that we won't be interrupted by a SIGIO
1439 while being in an inconsistent state. */
1440 BLOCK_INPUT;
1442 for (i = nfreed = 0; i < c->used; ++i)
1444 struct image *img = c->images[i];
1445 if (img != NULL
1446 && (force_p || img->timestamp < old))
1448 free_image (f, img);
1449 ++nfreed;
1453 /* We may be clearing the image cache because, for example,
1454 Emacs was iconified for a longer period of time. In that
1455 case, current matrices may still contain references to
1456 images freed above. So, clear these matrices. */
1457 if (nfreed)
1459 Lisp_Object tail, frame;
1461 FOR_EACH_FRAME (tail, frame)
1463 struct frame *f = XFRAME (frame);
1464 if (FRAME_WINDOW_P (f)
1465 && FRAME_X_IMAGE_CACHE (f) == c)
1466 clear_current_matrices (f);
1469 ++windows_or_buffers_changed;
1472 UNBLOCK_INPUT;
1477 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1478 0, 1, 0,
1479 doc: /* Clear the image cache of FRAME.
1480 FRAME nil or omitted means use the selected frame.
1481 FRAME t means clear the image caches of all frames. */)
1482 (frame)
1483 Lisp_Object frame;
1485 if (EQ (frame, Qt))
1487 Lisp_Object tail;
1489 FOR_EACH_FRAME (tail, frame)
1490 if (FRAME_WINDOW_P (XFRAME (frame)))
1491 clear_image_cache (XFRAME (frame), 1);
1493 else
1494 clear_image_cache (check_x_frame (frame), 1);
1496 return Qnil;
1500 /* Compute masks and transform image IMG on frame F, as specified
1501 by the image's specification, */
1503 static void
1504 postprocess_image (f, img)
1505 struct frame *f;
1506 struct image *img;
1508 /* Manipulation of the image's mask. */
1509 if (img->pixmap)
1511 Lisp_Object conversion, spec;
1512 Lisp_Object mask;
1514 spec = img->spec;
1516 /* `:heuristic-mask t'
1517 `:mask heuristic'
1518 means build a mask heuristically.
1519 `:heuristic-mask (R G B)'
1520 `:mask (heuristic (R G B))'
1521 means build a mask from color (R G B) in the
1522 image.
1523 `:mask nil'
1524 means remove a mask, if any. */
1526 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1527 if (!NILP (mask))
1528 x_build_heuristic_mask (f, img, mask);
1529 else
1531 int found_p;
1533 mask = image_spec_value (spec, QCmask, &found_p);
1535 if (EQ (mask, Qheuristic))
1536 x_build_heuristic_mask (f, img, Qt);
1537 else if (CONSP (mask)
1538 && EQ (XCAR (mask), Qheuristic))
1540 if (CONSP (XCDR (mask)))
1541 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1542 else
1543 x_build_heuristic_mask (f, img, XCDR (mask));
1545 else if (NILP (mask) && found_p && img->mask)
1547 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1548 img->mask = NO_PIXMAP;
1553 /* Should we apply an image transformation algorithm? */
1554 conversion = image_spec_value (spec, QCconversion, NULL);
1555 if (EQ (conversion, Qdisabled))
1556 x_disable_image (f, img);
1557 else if (EQ (conversion, Qlaplace))
1558 x_laplace (f, img);
1559 else if (EQ (conversion, Qemboss))
1560 x_emboss (f, img);
1561 else if (CONSP (conversion)
1562 && EQ (XCAR (conversion), Qedge_detection))
1564 Lisp_Object tem;
1565 tem = XCDR (conversion);
1566 if (CONSP (tem))
1567 x_edge_detection (f, img,
1568 Fplist_get (tem, QCmatrix),
1569 Fplist_get (tem, QCcolor_adjustment));
1575 /* Return the id of image with Lisp specification SPEC on frame F.
1576 SPEC must be a valid Lisp image specification (see valid_image_p). */
1579 lookup_image (f, spec)
1580 struct frame *f;
1581 Lisp_Object spec;
1583 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1584 struct image *img;
1585 int i;
1586 unsigned hash;
1587 struct gcpro gcpro1;
1588 EMACS_TIME now;
1590 /* F must be a window-system frame, and SPEC must be a valid image
1591 specification. */
1592 xassert (FRAME_WINDOW_P (f));
1593 xassert (valid_image_p (spec));
1595 GCPRO1 (spec);
1597 /* Look up SPEC in the hash table of the image cache. */
1598 hash = sxhash (spec, 0);
1599 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1601 for (img = c->buckets[i]; img; img = img->next)
1602 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
1603 break;
1605 /* If not found, create a new image and cache it. */
1606 if (img == NULL)
1608 extern Lisp_Object Qpostscript;
1610 BLOCK_INPUT;
1611 img = make_image (spec, hash);
1612 cache_image (f, img);
1613 img->load_failed_p = img->type->load (f, img) == 0;
1615 /* If we can't load the image, and we don't have a width and
1616 height, use some arbitrary width and height so that we can
1617 draw a rectangle for it. */
1618 if (img->load_failed_p)
1620 Lisp_Object value;
1622 value = image_spec_value (spec, QCwidth, NULL);
1623 img->width = (INTEGERP (value)
1624 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1625 value = image_spec_value (spec, QCheight, NULL);
1626 img->height = (INTEGERP (value)
1627 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1629 else
1631 /* Handle image type independent image attributes
1632 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1633 `:background COLOR'. */
1634 Lisp_Object ascent, margin, relief, bg;
1636 ascent = image_spec_value (spec, QCascent, NULL);
1637 if (INTEGERP (ascent))
1638 img->ascent = XFASTINT (ascent);
1639 else if (EQ (ascent, Qcenter))
1640 img->ascent = CENTERED_IMAGE_ASCENT;
1642 margin = image_spec_value (spec, QCmargin, NULL);
1643 if (INTEGERP (margin) && XINT (margin) >= 0)
1644 img->vmargin = img->hmargin = XFASTINT (margin);
1645 else if (CONSP (margin) && INTEGERP (XCAR (margin))
1646 && INTEGERP (XCDR (margin)))
1648 if (XINT (XCAR (margin)) > 0)
1649 img->hmargin = XFASTINT (XCAR (margin));
1650 if (XINT (XCDR (margin)) > 0)
1651 img->vmargin = XFASTINT (XCDR (margin));
1654 relief = image_spec_value (spec, QCrelief, NULL);
1655 if (INTEGERP (relief))
1657 img->relief = XINT (relief);
1658 img->hmargin += abs (img->relief);
1659 img->vmargin += abs (img->relief);
1662 if (! img->background_valid)
1664 bg = image_spec_value (img->spec, QCbackground, NULL);
1665 if (!NILP (bg))
1667 img->background
1668 = x_alloc_image_color (f, img, bg,
1669 FRAME_BACKGROUND_PIXEL (f));
1670 img->background_valid = 1;
1674 /* Do image transformations and compute masks, unless we
1675 don't have the image yet. */
1676 if (!EQ (*img->type->type, Qpostscript))
1677 postprocess_image (f, img);
1680 UNBLOCK_INPUT;
1683 /* We're using IMG, so set its timestamp to `now'. */
1684 EMACS_GET_TIME (now);
1685 img->timestamp = EMACS_SECS (now);
1687 UNGCPRO;
1689 /* Value is the image id. */
1690 return img->id;
1694 /* Cache image IMG in the image cache of frame F. */
1696 static void
1697 cache_image (f, img)
1698 struct frame *f;
1699 struct image *img;
1701 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1702 int i;
1704 /* Find a free slot in c->images. */
1705 for (i = 0; i < c->used; ++i)
1706 if (c->images[i] == NULL)
1707 break;
1709 /* If no free slot found, maybe enlarge c->images. */
1710 if (i == c->used && c->used == c->size)
1712 c->size *= 2;
1713 c->images = (struct image **) xrealloc (c->images,
1714 c->size * sizeof *c->images);
1717 /* Add IMG to c->images, and assign IMG an id. */
1718 c->images[i] = img;
1719 img->id = i;
1720 if (i == c->used)
1721 ++c->used;
1723 /* Add IMG to the cache's hash table. */
1724 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1725 img->next = c->buckets[i];
1726 if (img->next)
1727 img->next->prev = img;
1728 img->prev = NULL;
1729 c->buckets[i] = img;
1733 /* Call FN on every image in the image cache of frame F. Used to mark
1734 Lisp Objects in the image cache. */
1736 void
1737 forall_images_in_image_cache (f, fn)
1738 struct frame *f;
1739 void (*fn) P_ ((struct image *img));
1741 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f))
1743 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1744 if (c)
1746 int i;
1747 for (i = 0; i < c->used; ++i)
1748 if (c->images[i])
1749 fn (c->images[i]);
1756 /***********************************************************************
1757 X / MAC / W32 support code
1758 ***********************************************************************/
1760 #ifdef HAVE_NTGUI
1762 /* Macro for defining functions that will be loaded from image DLLs. */
1763 #define DEF_IMGLIB_FN(func) FARPROC fn_##func
1765 /* Macro for loading those image functions from the library. */
1766 #define LOAD_IMGLIB_FN(lib,func) { \
1767 fn_##func = (void *) GetProcAddress (lib, #func); \
1768 if (!fn_##func) return 0; \
1771 #endif /* HAVE_NTGUI */
1773 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
1774 XImagePtr *, Pixmap *));
1775 static void x_destroy_x_image P_ ((XImagePtr));
1776 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
1779 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
1780 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
1781 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
1782 via xmalloc. Print error messages via image_error if an error
1783 occurs. Value is non-zero if successful.
1785 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
1786 should indicate the bit depth of the image. */
1788 static int
1789 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
1790 struct frame *f;
1791 int width, height, depth;
1792 XImagePtr *ximg;
1793 Pixmap *pixmap;
1795 #ifdef HAVE_X_WINDOWS
1796 Display *display = FRAME_X_DISPLAY (f);
1797 Window window = FRAME_X_WINDOW (f);
1798 Screen *screen = FRAME_X_SCREEN (f);
1800 xassert (interrupt_input_blocked);
1802 if (depth <= 0)
1803 depth = DefaultDepthOfScreen (screen);
1804 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
1805 depth, ZPixmap, 0, NULL, width, height,
1806 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
1807 if (*ximg == NULL)
1809 image_error ("Unable to allocate X image", Qnil, Qnil);
1810 return 0;
1813 /* Allocate image raster. */
1814 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
1816 /* Allocate a pixmap of the same size. */
1817 *pixmap = XCreatePixmap (display, window, width, height, depth);
1818 if (*pixmap == NO_PIXMAP)
1820 x_destroy_x_image (*ximg);
1821 *ximg = NULL;
1822 image_error ("Unable to create X pixmap", Qnil, Qnil);
1823 return 0;
1826 return 1;
1827 #endif /* HAVE_X_WINDOWS */
1829 #ifdef HAVE_NTGUI
1831 BITMAPINFOHEADER *header;
1832 HDC hdc;
1833 int scanline_width_bits;
1834 int remainder;
1835 int palette_colors = 0;
1837 if (depth == 0)
1838 depth = 24;
1840 if (depth != 1 && depth != 4 && depth != 8
1841 && depth != 16 && depth != 24 && depth != 32)
1843 image_error ("Invalid image bit depth specified", Qnil, Qnil);
1844 return 0;
1847 scanline_width_bits = width * depth;
1848 remainder = scanline_width_bits % 32;
1850 if (remainder)
1851 scanline_width_bits += 32 - remainder;
1853 /* Bitmaps with a depth less than 16 need a palette. */
1854 /* BITMAPINFO structure already contains the first RGBQUAD. */
1855 if (depth < 16)
1856 palette_colors = 1 << depth - 1;
1858 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
1859 if (*ximg == NULL)
1861 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
1862 return 0;
1865 header = &((*ximg)->info.bmiHeader);
1866 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
1867 header->biSize = sizeof (*header);
1868 header->biWidth = width;
1869 header->biHeight = -height; /* negative indicates a top-down bitmap. */
1870 header->biPlanes = 1;
1871 header->biBitCount = depth;
1872 header->biCompression = BI_RGB;
1873 header->biClrUsed = palette_colors;
1875 /* TODO: fill in palette. */
1876 if (depth == 1)
1878 (*ximg)->info.bmiColors[0].rgbBlue = 0;
1879 (*ximg)->info.bmiColors[0].rgbGreen = 0;
1880 (*ximg)->info.bmiColors[0].rgbRed = 0;
1881 (*ximg)->info.bmiColors[0].rgbReserved = 0;
1882 (*ximg)->info.bmiColors[1].rgbBlue = 255;
1883 (*ximg)->info.bmiColors[1].rgbGreen = 255;
1884 (*ximg)->info.bmiColors[1].rgbRed = 255;
1885 (*ximg)->info.bmiColors[1].rgbReserved = 0;
1888 hdc = get_frame_dc (f);
1890 /* Create a DIBSection and raster array for the bitmap,
1891 and store its handle in *pixmap. */
1892 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
1893 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
1894 &((*ximg)->data), NULL, 0);
1896 /* Realize display palette and garbage all frames. */
1897 release_frame_dc (f, hdc);
1899 if (*pixmap == NULL)
1901 DWORD err = GetLastError();
1902 Lisp_Object errcode;
1903 /* All system errors are < 10000, so the following is safe. */
1904 XSETINT (errcode, (int) err);
1905 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
1906 x_destroy_x_image (*ximg);
1907 return 0;
1910 return 1;
1912 #endif /* HAVE_NTGUI */
1914 #ifdef MAC_OS
1915 Display *display = FRAME_X_DISPLAY (f);
1916 Window window = FRAME_X_WINDOW (f);
1918 xassert (interrupt_input_blocked);
1920 /* Allocate a pixmap of the same size. */
1921 *pixmap = XCreatePixmap (display, window, width, height, depth);
1922 if (*pixmap == NO_PIXMAP)
1924 x_destroy_x_image (*ximg);
1925 *ximg = NULL;
1926 image_error ("Unable to create X pixmap", Qnil, Qnil);
1927 return 0;
1930 LockPixels (GetGWorldPixMap (*pixmap));
1931 *ximg = *pixmap;
1932 return 1;
1934 #endif /* MAC_OS */
1938 /* Destroy XImage XIMG. Free XIMG->data. */
1940 static void
1941 x_destroy_x_image (ximg)
1942 XImagePtr ximg;
1944 xassert (interrupt_input_blocked);
1945 if (ximg)
1947 #ifdef HAVE_X_WINDOWS
1948 xfree (ximg->data);
1949 ximg->data = NULL;
1950 XDestroyImage (ximg);
1951 #endif /* HAVE_X_WINDOWS */
1952 #ifdef HAVE_NTGUI
1953 /* Data will be freed by DestroyObject. */
1954 ximg->data = NULL;
1955 xfree (ximg);
1956 #endif /* HAVE_NTGUI */
1957 #ifdef MAC_OS
1958 XDestroyImage (ximg);
1959 #endif /* MAC_OS */
1964 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
1965 are width and height of both the image and pixmap. */
1967 static void
1968 x_put_x_image (f, ximg, pixmap, width, height)
1969 struct frame *f;
1970 XImagePtr ximg;
1971 Pixmap pixmap;
1972 int width, height;
1974 #ifdef HAVE_X_WINDOWS
1975 GC gc;
1977 xassert (interrupt_input_blocked);
1978 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
1979 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
1980 XFreeGC (FRAME_X_DISPLAY (f), gc);
1981 #endif /* HAVE_X_WINDOWS */
1983 #ifdef HAVE_NTGUI
1984 #if 0 /* I don't think this is necessary looking at where it is used. */
1985 HDC hdc = get_frame_dc (f);
1986 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
1987 release_frame_dc (f, hdc);
1988 #endif
1989 #endif /* HAVE_NTGUI */
1991 #ifdef MAC_OS
1992 xassert (ximg == pixmap);
1993 #endif /* MAC_OS */
1997 /***********************************************************************
1998 File Handling
1999 ***********************************************************************/
2001 static unsigned char *slurp_file P_ ((char *, int *));
2004 /* Find image file FILE. Look in data-directory, then
2005 x-bitmap-file-path. Value is the full name of the file found, or
2006 nil if not found. */
2008 Lisp_Object
2009 x_find_image_file (file)
2010 Lisp_Object file;
2012 Lisp_Object file_found, search_path;
2013 struct gcpro gcpro1, gcpro2;
2014 int fd;
2016 file_found = Qnil;
2017 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
2018 GCPRO2 (file_found, search_path);
2020 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2021 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2023 if (fd == -1)
2024 file_found = Qnil;
2025 else
2026 close (fd);
2028 UNGCPRO;
2029 return file_found;
2033 /* Read FILE into memory. Value is a pointer to a buffer allocated
2034 with xmalloc holding FILE's contents. Value is null if an error
2035 occurred. *SIZE is set to the size of the file. */
2037 static unsigned char *
2038 slurp_file (file, size)
2039 char *file;
2040 int *size;
2042 FILE *fp = NULL;
2043 unsigned char *buf = NULL;
2044 struct stat st;
2046 if (stat (file, &st) == 0
2047 && (fp = fopen (file, "rb")) != NULL
2048 && (buf = (char *) xmalloc (st.st_size),
2049 fread (buf, 1, st.st_size, fp) == st.st_size))
2051 *size = st.st_size;
2052 fclose (fp);
2054 else
2056 if (fp)
2057 fclose (fp);
2058 if (buf)
2060 xfree (buf);
2061 buf = NULL;
2065 return buf;
2070 #ifdef MAC_OS
2072 /***********************************************************************
2073 MAC Image Load Functions
2074 ***********************************************************************/
2076 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2077 OSType));
2078 #ifdef MAC_OSX
2079 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2080 #endif
2082 static OSErr
2083 find_image_fsspec (specified_file, file, fss)
2084 Lisp_Object specified_file, *file;
2085 FSSpec *fss;
2087 #if TARGET_API_MAC_CARBON
2088 FSRef fsr;
2089 #else
2090 Str255 mac_pathname;
2091 #endif
2092 OSErr err;
2094 *file = x_find_image_file (specified_file);
2095 if (!STRINGP (*file))
2096 return fnfErr; /* file or directory not found;
2097 incomplete pathname */
2098 /* Try to open the image file. */
2099 #if TARGET_API_MAC_CARBON
2100 err = FSPathMakeRef (SDATA (*file), &fsr, NULL);
2101 if (err == noErr)
2102 err = FSGetCatalogInfo (&fsr, kFSCatInfoNone, NULL, NULL, fss, NULL);
2103 #else
2104 if (posix_to_mac_pathname (SDATA (*file), mac_pathname, MAXPATHLEN+1) == 0)
2105 return fnfErr;
2106 c2pstr (mac_pathname);
2107 err = FSMakeFSSpec (0, 0, mac_pathname, fss);
2108 #endif
2109 return err;
2112 static int
2113 image_load_qt_1 (f, img, type, fss, dh)
2114 struct frame *f;
2115 struct image *img;
2116 OSType type;
2117 FSSpec *fss;
2118 Handle dh;
2120 OSErr err;
2121 GraphicsImportComponent gi;
2122 Rect rect;
2123 int width, height;
2124 short draw_all_pixels;
2125 Lisp_Object specified_bg;
2126 XColor color;
2127 XImagePtr ximg;
2128 RGBColor bg_color;
2130 err = OpenADefaultComponent (GraphicsImporterComponentType,
2131 type, &gi);
2132 if (err != noErr)
2134 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2135 return 0;
2137 if (dh == NULL)
2139 /* read from file system spec */
2140 err = GraphicsImportSetDataFile (gi, fss);
2141 if (err != noErr)
2143 image_error ("Cannot set fsspec to graphics importer for '%s'",
2144 img->spec, Qnil);
2145 goto error;
2148 else
2150 /* read from data handle */
2151 err = GraphicsImportSetDataHandle (gi, dh);
2152 if (err != noErr)
2154 image_error ("Cannot set data handle to graphics importer for `%s'",
2155 img->spec, Qnil);
2156 goto error;
2159 err = GraphicsImportGetNaturalBounds (gi, &rect);
2160 if (err != noErr)
2162 image_error ("Error reading `%s'", img->spec, Qnil);
2163 goto error;
2165 width = img->width = rect.right - rect.left;
2166 height = img->height = rect.bottom - rect.top;
2167 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2168 #if 0
2169 /* Don't check the error code here. It may have an undocumented
2170 value -32766. */
2171 if (err != noErr)
2173 image_error ("Error reading `%s'", img->spec, Qnil);
2174 goto error;
2176 #endif
2177 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2179 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2180 if (!STRINGP (specified_bg) ||
2181 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2183 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2184 color.red = RED16_FROM_ULONG (color.pixel);
2185 color.green = GREEN16_FROM_ULONG (color.pixel);
2186 color.blue = BLUE16_FROM_ULONG (color.pixel);
2190 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2191 goto error;
2192 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2194 SetGWorld (ximg, NULL);
2195 bg_color.red = color.red;
2196 bg_color.green = color.green;
2197 bg_color.blue = color.blue;
2198 RGBBackColor (&bg_color);
2199 #if TARGET_API_MAC_CARBON
2200 GetPortBounds (ximg, &rect);
2201 EraseRect (&rect);
2202 #else
2203 EraseRect (&(ximg->portRect));
2204 #endif
2206 GraphicsImportSetGWorld (gi, ximg, NULL);
2207 GraphicsImportDraw (gi);
2208 CloseComponent (gi);
2210 /* Maybe fill in the background field while we have ximg handy. */
2211 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2212 IMAGE_BACKGROUND (img, f, ximg);
2214 /* Put the image into the pixmap. */
2215 x_put_x_image (f, ximg, img->pixmap, width, height);
2216 x_destroy_x_image (ximg);
2217 return 1;
2219 error:
2220 CloseComponent (gi);
2221 return 0;
2225 /* Load an image using the QuickTime Graphics Importer.
2226 Note: The alpha channel does not work for PNG images. */
2227 static int
2228 image_load_quicktime (f, img, type)
2229 struct frame *f;
2230 struct image *img;
2231 OSType type;
2233 Lisp_Object specified_file;
2234 Lisp_Object specified_data;
2235 OSErr err;
2237 specified_file = image_spec_value (img->spec, QCfile, NULL);
2238 specified_data = image_spec_value (img->spec, QCdata, NULL);
2240 if (NILP (specified_data))
2242 /* Read from a file */
2243 Lisp_Object file;
2244 FSSpec fss;
2246 err = find_image_fsspec (specified_file, &file, &fss);
2247 if (err != noErr)
2249 if (err == fnfErr)
2250 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2251 else
2252 image_error ("Cannot open `%s'", file, Qnil);
2253 return 0;
2255 return image_load_qt_1 (f, img, type, &fss, NULL);
2257 else
2259 /* Memory source! */
2260 int success_p;
2261 Handle dh;
2263 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2264 if (err != noErr)
2266 image_error ("Cannot allocate data handle for `%s'",
2267 img->spec, Qnil);
2268 return 0;
2270 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2271 DisposeHandle (dh);
2272 return success_p;
2277 #ifdef MAC_OSX
2278 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2279 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2280 So don't use this function directly but determine at runtime
2281 whether it exists. */
2282 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
2283 (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
2284 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
2287 static void
2288 init_image_func_pointer ()
2290 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2292 MyCGImageCreateWithPNGDataProvider
2293 = (CGImageCreateWithPNGDataProviderProcType)
2294 NSAddressOfSymbol (NSLookupAndBindSymbol
2295 ("_CGImageCreateWithPNGDataProvider"));
2297 else
2298 MyCGImageCreateWithPNGDataProvider = NULL;
2302 static int
2303 image_load_quartz2d (f, img, png_p)
2304 struct frame *f;
2305 struct image *img;
2306 int png_p;
2308 Lisp_Object file, specified_file;
2309 Lisp_Object specified_data, specified_bg;
2310 struct gcpro gcpro1;
2311 CGDataProviderRef source;
2312 CGImageRef image;
2313 int width, height;
2314 XColor color;
2315 XImagePtr ximg = NULL;
2316 CGContextRef context;
2317 CGRect rectangle;
2319 /* Open the file. */
2320 specified_file = image_spec_value (img->spec, QCfile, NULL);
2321 specified_data = image_spec_value (img->spec, QCdata, NULL);
2323 file = Qnil;
2324 GCPRO1 (file);
2326 if (NILP (specified_data))
2328 CFStringRef path;
2329 CFURLRef url;
2331 file = x_find_image_file (specified_file);
2332 if (!STRINGP (file))
2334 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2335 UNGCPRO;
2336 return 0;
2338 path = CFStringCreateWithCString (NULL, SDATA (file),
2339 kCFStringEncodingUTF8);
2340 url = CFURLCreateWithFileSystemPath (NULL, path,
2341 kCFURLPOSIXPathStyle, 0);
2342 CFRelease (path);
2343 source = CGDataProviderCreateWithURL (url);
2344 CFRelease (url);
2346 else
2347 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
2348 SBYTES (specified_data), NULL);
2350 if (png_p)
2351 image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
2352 kCGRenderingIntentDefault);
2353 else
2354 image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
2355 kCGRenderingIntentDefault);
2357 CGDataProviderRelease (source);
2358 if (image == NULL)
2360 UNGCPRO;
2361 image_error ("Error reading image `%s'", img->spec, Qnil);
2362 return 0;
2365 if (png_p)
2367 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2368 if (!STRINGP (specified_bg) ||
2369 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2371 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2372 color.red = RED16_FROM_ULONG (color.pixel);
2373 color.green = GREEN16_FROM_ULONG (color.pixel);
2374 color.blue = BLUE16_FROM_ULONG (color.pixel);
2377 width = img->width = CGImageGetWidth (image);
2378 height = img->height = CGImageGetHeight (image);
2379 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2381 CGImageRelease (image);
2382 UNGCPRO;
2383 return 0;
2385 rectangle = CGRectMake (0, 0, width, height);
2386 QDBeginCGContext (ximg, &context);
2387 if (png_p)
2389 CGContextSetRGBFillColor (context, color.red / 65535.0,
2390 color.green / 65535.0,
2391 color.blue / 65535.0, 1.0);
2392 CGContextFillRect (context, rectangle);
2394 CGContextDrawImage (context, rectangle, image);
2395 QDEndCGContext (ximg, &context);
2396 CGImageRelease (image);
2398 /* Maybe fill in the background field while we have ximg handy. */
2399 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2400 IMAGE_BACKGROUND (img, f, ximg);
2402 /* Put the image into the pixmap. */
2403 x_put_x_image (f, ximg, img->pixmap, width, height);
2404 x_destroy_x_image (ximg);
2405 UNGCPRO;
2406 return 1;
2408 #endif
2410 #endif /* MAC_OS */
2413 /***********************************************************************
2414 XBM images
2415 ***********************************************************************/
2417 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
2418 static int xbm_load P_ ((struct frame *f, struct image *img));
2419 static int xbm_load_image P_ ((struct frame *f, struct image *img,
2420 unsigned char *, unsigned char *));
2421 static int xbm_image_p P_ ((Lisp_Object object));
2422 static int xbm_read_bitmap_data P_ ((unsigned char *, unsigned char *,
2423 int *, int *, unsigned char **));
2424 static int xbm_file_p P_ ((Lisp_Object));
2427 /* Indices of image specification fields in xbm_format, below. */
2429 enum xbm_keyword_index
2431 XBM_TYPE,
2432 XBM_FILE,
2433 XBM_WIDTH,
2434 XBM_HEIGHT,
2435 XBM_DATA,
2436 XBM_FOREGROUND,
2437 XBM_BACKGROUND,
2438 XBM_ASCENT,
2439 XBM_MARGIN,
2440 XBM_RELIEF,
2441 XBM_ALGORITHM,
2442 XBM_HEURISTIC_MASK,
2443 XBM_MASK,
2444 XBM_LAST
2447 /* Vector of image_keyword structures describing the format
2448 of valid XBM image specifications. */
2450 static struct image_keyword xbm_format[XBM_LAST] =
2452 {":type", IMAGE_SYMBOL_VALUE, 1},
2453 {":file", IMAGE_STRING_VALUE, 0},
2454 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2455 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2456 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2457 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2458 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2459 {":ascent", IMAGE_ASCENT_VALUE, 0},
2460 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2461 {":relief", IMAGE_INTEGER_VALUE, 0},
2462 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2463 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2464 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2467 /* Structure describing the image type XBM. */
2469 static struct image_type xbm_type =
2471 &Qxbm,
2472 xbm_image_p,
2473 xbm_load,
2474 x_clear_image,
2475 NULL
2478 /* Tokens returned from xbm_scan. */
2480 enum xbm_token
2482 XBM_TK_IDENT = 256,
2483 XBM_TK_NUMBER
2487 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2488 A valid specification is a list starting with the symbol `image'
2489 The rest of the list is a property list which must contain an
2490 entry `:type xbm..
2492 If the specification specifies a file to load, it must contain
2493 an entry `:file FILENAME' where FILENAME is a string.
2495 If the specification is for a bitmap loaded from memory it must
2496 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2497 WIDTH and HEIGHT are integers > 0. DATA may be:
2499 1. a string large enough to hold the bitmap data, i.e. it must
2500 have a size >= (WIDTH + 7) / 8 * HEIGHT
2502 2. a bool-vector of size >= WIDTH * HEIGHT
2504 3. a vector of strings or bool-vectors, one for each line of the
2505 bitmap.
2507 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2508 may not be specified in this case because they are defined in the
2509 XBM file.
2511 Both the file and data forms may contain the additional entries
2512 `:background COLOR' and `:foreground COLOR'. If not present,
2513 foreground and background of the frame on which the image is
2514 displayed is used. */
2516 static int
2517 xbm_image_p (object)
2518 Lisp_Object object;
2520 struct image_keyword kw[XBM_LAST];
2522 bcopy (xbm_format, kw, sizeof kw);
2523 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2524 return 0;
2526 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2528 if (kw[XBM_FILE].count)
2530 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2531 return 0;
2533 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2535 /* In-memory XBM file. */
2536 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2537 return 0;
2539 else
2541 Lisp_Object data;
2542 int width, height;
2544 /* Entries for `:width', `:height' and `:data' must be present. */
2545 if (!kw[XBM_WIDTH].count
2546 || !kw[XBM_HEIGHT].count
2547 || !kw[XBM_DATA].count)
2548 return 0;
2550 data = kw[XBM_DATA].value;
2551 width = XFASTINT (kw[XBM_WIDTH].value);
2552 height = XFASTINT (kw[XBM_HEIGHT].value);
2554 /* Check type of data, and width and height against contents of
2555 data. */
2556 if (VECTORP (data))
2558 int i;
2560 /* Number of elements of the vector must be >= height. */
2561 if (XVECTOR (data)->size < height)
2562 return 0;
2564 /* Each string or bool-vector in data must be large enough
2565 for one line of the image. */
2566 for (i = 0; i < height; ++i)
2568 Lisp_Object elt = XVECTOR (data)->contents[i];
2570 if (STRINGP (elt))
2572 if (SCHARS (elt)
2573 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2574 return 0;
2576 else if (BOOL_VECTOR_P (elt))
2578 if (XBOOL_VECTOR (elt)->size < width)
2579 return 0;
2581 else
2582 return 0;
2585 else if (STRINGP (data))
2587 if (SCHARS (data)
2588 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2589 return 0;
2591 else if (BOOL_VECTOR_P (data))
2593 if (XBOOL_VECTOR (data)->size < width * height)
2594 return 0;
2596 else
2597 return 0;
2600 return 1;
2604 /* Scan a bitmap file. FP is the stream to read from. Value is
2605 either an enumerator from enum xbm_token, or a character for a
2606 single-character token, or 0 at end of file. If scanning an
2607 identifier, store the lexeme of the identifier in SVAL. If
2608 scanning a number, store its value in *IVAL. */
2610 static int
2611 xbm_scan (s, end, sval, ival)
2612 unsigned char **s, *end;
2613 char *sval;
2614 int *ival;
2616 unsigned int c;
2618 loop:
2620 /* Skip white space. */
2621 while (*s < end && (c = *(*s)++, isspace (c)))
2624 if (*s >= end)
2625 c = 0;
2626 else if (isdigit (c))
2628 int value = 0, digit;
2630 if (c == '0' && *s < end)
2632 c = *(*s)++;
2633 if (c == 'x' || c == 'X')
2635 while (*s < end)
2637 c = *(*s)++;
2638 if (isdigit (c))
2639 digit = c - '0';
2640 else if (c >= 'a' && c <= 'f')
2641 digit = c - 'a' + 10;
2642 else if (c >= 'A' && c <= 'F')
2643 digit = c - 'A' + 10;
2644 else
2645 break;
2646 value = 16 * value + digit;
2649 else if (isdigit (c))
2651 value = c - '0';
2652 while (*s < end
2653 && (c = *(*s)++, isdigit (c)))
2654 value = 8 * value + c - '0';
2657 else
2659 value = c - '0';
2660 while (*s < end
2661 && (c = *(*s)++, isdigit (c)))
2662 value = 10 * value + c - '0';
2665 if (*s < end)
2666 *s = *s - 1;
2667 *ival = value;
2668 c = XBM_TK_NUMBER;
2670 else if (isalpha (c) || c == '_')
2672 *sval++ = c;
2673 while (*s < end
2674 && (c = *(*s)++, (isalnum (c) || c == '_')))
2675 *sval++ = c;
2676 *sval = 0;
2677 if (*s < end)
2678 *s = *s - 1;
2679 c = XBM_TK_IDENT;
2681 else if (c == '/' && **s == '*')
2683 /* C-style comment. */
2684 ++*s;
2685 while (**s && (**s != '*' || *(*s + 1) != '/'))
2686 ++*s;
2687 if (**s)
2689 *s += 2;
2690 goto loop;
2694 return c;
2697 #ifdef HAVE_NTGUI
2699 /* Create a Windows bitmap from X bitmap data. */
2700 static HBITMAP
2701 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2703 static unsigned char swap_nibble[16]
2704 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2705 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2706 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2707 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2708 int i, j, w1, w2;
2709 unsigned char *bits, *p;
2710 HBITMAP bmp;
2712 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2713 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2714 bits = (unsigned char *) alloca (height * w2);
2715 bzero (bits, height * w2);
2716 for (i = 0; i < height; i++)
2718 p = bits + i*w2;
2719 for (j = 0; j < w1; j++)
2721 /* Bitswap XBM bytes to match how Windows does things. */
2722 unsigned char c = *data++;
2723 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2724 | (swap_nibble[(c>>4) & 0xf]));
2727 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2729 return bmp;
2732 static void convert_mono_to_color_image (f, img, foreground, background)
2733 struct frame *f;
2734 struct image *img;
2735 COLORREF foreground, background;
2737 HDC hdc, old_img_dc, new_img_dc;
2738 HGDIOBJ old_prev, new_prev;
2739 HBITMAP new_pixmap;
2741 hdc = get_frame_dc (f);
2742 old_img_dc = CreateCompatibleDC (hdc);
2743 new_img_dc = CreateCompatibleDC (hdc);
2744 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
2745 release_frame_dc (f, hdc);
2746 old_prev = SelectObject (old_img_dc, img->pixmap);
2747 new_prev = SelectObject (new_img_dc, new_pixmap);
2748 SetTextColor (new_img_dc, foreground);
2749 SetBkColor (new_img_dc, background);
2751 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
2752 0, 0, SRCCOPY);
2754 SelectObject (old_img_dc, old_prev);
2755 SelectObject (new_img_dc, new_prev);
2756 DeleteDC (old_img_dc);
2757 DeleteDC (new_img_dc);
2758 DeleteObject (img->pixmap);
2759 if (new_pixmap == 0)
2760 fprintf (stderr, "Failed to convert image to color.\n");
2761 else
2762 img->pixmap = new_pixmap;
2765 #define XBM_BIT_SHUFFLE(b) (~(b))
2767 #else
2769 #define XBM_BIT_SHUFFLE(b) (b)
2771 #endif /* HAVE_NTGUI */
2774 static void
2775 Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
2776 struct frame *f;
2777 struct image *img;
2778 char *data;
2779 RGB_PIXEL_COLOR fg, bg;
2780 int non_default_colors;
2782 #ifdef HAVE_NTGUI
2783 img->pixmap
2784 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
2786 /* If colors were specified, transfer the bitmap to a color one. */
2787 if (non_default_colors)
2788 convert_mono_to_color_image (f, img, fg, bg);
2789 #else
2790 img->pixmap
2791 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
2792 FRAME_X_WINDOW (f),
2793 data,
2794 img->width, img->height,
2795 fg, bg,
2796 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
2797 #endif /* HAVE_NTGUI */
2802 /* Replacement for XReadBitmapFileData which isn't available under old
2803 X versions. CONTENTS is a pointer to a buffer to parse; END is the
2804 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
2805 the image. Return in *DATA the bitmap data allocated with xmalloc.
2806 Value is non-zero if successful. DATA null means just test if
2807 CONTENTS looks like an in-memory XBM file. */
2809 static int
2810 xbm_read_bitmap_data (contents, end, width, height, data)
2811 unsigned char *contents, *end;
2812 int *width, *height;
2813 unsigned char **data;
2815 unsigned char *s = contents;
2816 char buffer[BUFSIZ];
2817 int padding_p = 0;
2818 int v10 = 0;
2819 int bytes_per_line, i, nbytes;
2820 unsigned char *p;
2821 int value;
2822 int LA1;
2824 #define match() \
2825 LA1 = xbm_scan (&s, end, buffer, &value)
2827 #define expect(TOKEN) \
2828 if (LA1 != (TOKEN)) \
2829 goto failure; \
2830 else \
2831 match ()
2833 #define expect_ident(IDENT) \
2834 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
2835 match (); \
2836 else \
2837 goto failure
2839 *width = *height = -1;
2840 if (data)
2841 *data = NULL;
2842 LA1 = xbm_scan (&s, end, buffer, &value);
2844 /* Parse defines for width, height and hot-spots. */
2845 while (LA1 == '#')
2847 match ();
2848 expect_ident ("define");
2849 expect (XBM_TK_IDENT);
2851 if (LA1 == XBM_TK_NUMBER);
2853 char *p = strrchr (buffer, '_');
2854 p = p ? p + 1 : buffer;
2855 if (strcmp (p, "width") == 0)
2856 *width = value;
2857 else if (strcmp (p, "height") == 0)
2858 *height = value;
2860 expect (XBM_TK_NUMBER);
2863 if (*width < 0 || *height < 0)
2864 goto failure;
2865 else if (data == NULL)
2866 goto success;
2868 /* Parse bits. Must start with `static'. */
2869 expect_ident ("static");
2870 if (LA1 == XBM_TK_IDENT)
2872 if (strcmp (buffer, "unsigned") == 0)
2874 match ();
2875 expect_ident ("char");
2877 else if (strcmp (buffer, "short") == 0)
2879 match ();
2880 v10 = 1;
2881 if (*width % 16 && *width % 16 < 9)
2882 padding_p = 1;
2884 else if (strcmp (buffer, "char") == 0)
2885 match ();
2886 else
2887 goto failure;
2889 else
2890 goto failure;
2892 expect (XBM_TK_IDENT);
2893 expect ('[');
2894 expect (']');
2895 expect ('=');
2896 expect ('{');
2898 bytes_per_line = (*width + 7) / 8 + padding_p;
2899 nbytes = bytes_per_line * *height;
2900 p = *data = (char *) xmalloc (nbytes);
2902 if (v10)
2904 for (i = 0; i < nbytes; i += 2)
2906 int val = value;
2907 expect (XBM_TK_NUMBER);
2909 *p++ = XBM_BIT_SHUFFLE (val);
2910 if (!padding_p || ((i + 2) % bytes_per_line))
2911 *p++ = XBM_BIT_SHUFFLE (value >> 8);
2913 if (LA1 == ',' || LA1 == '}')
2914 match ();
2915 else
2916 goto failure;
2919 else
2921 for (i = 0; i < nbytes; ++i)
2923 int val = value;
2924 expect (XBM_TK_NUMBER);
2926 *p++ = XBM_BIT_SHUFFLE (val);
2928 if (LA1 == ',' || LA1 == '}')
2929 match ();
2930 else
2931 goto failure;
2935 success:
2936 return 1;
2938 failure:
2940 if (data && *data)
2942 xfree (*data);
2943 *data = NULL;
2945 return 0;
2947 #undef match
2948 #undef expect
2949 #undef expect_ident
2953 /* Load XBM image IMG which will be displayed on frame F from buffer
2954 CONTENTS. END is the end of the buffer. Value is non-zero if
2955 successful. */
2957 static int
2958 xbm_load_image (f, img, contents, end)
2959 struct frame *f;
2960 struct image *img;
2961 unsigned char *contents, *end;
2963 int rc;
2964 unsigned char *data;
2965 int success_p = 0;
2967 rc = xbm_read_bitmap_data (contents, end, &img->width, &img->height, &data);
2968 if (rc)
2970 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
2971 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
2972 int non_default_colors = 0;
2973 Lisp_Object value;
2975 xassert (img->width > 0 && img->height > 0);
2977 /* Get foreground and background colors, maybe allocate colors. */
2978 value = image_spec_value (img->spec, QCforeground, NULL);
2979 if (!NILP (value))
2981 foreground = x_alloc_image_color (f, img, value, foreground);
2982 non_default_colors = 1;
2984 value = image_spec_value (img->spec, QCbackground, NULL);
2985 if (!NILP (value))
2987 background = x_alloc_image_color (f, img, value, background);
2988 img->background = background;
2989 img->background_valid = 1;
2990 non_default_colors = 1;
2993 Create_Pixmap_From_Bitmap_Data (f, img, data,
2994 foreground, background,
2995 non_default_colors);
2996 xfree (data);
2998 if (img->pixmap == NO_PIXMAP)
3000 x_clear_image (f, img);
3001 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3003 else
3004 success_p = 1;
3006 else
3007 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3009 return success_p;
3013 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3015 static int
3016 xbm_file_p (data)
3017 Lisp_Object data;
3019 int w, h;
3020 return (STRINGP (data)
3021 && xbm_read_bitmap_data (SDATA (data),
3022 (SDATA (data)
3023 + SBYTES (data)),
3024 &w, &h, NULL));
3028 /* Fill image IMG which is used on frame F with pixmap data. Value is
3029 non-zero if successful. */
3031 static int
3032 xbm_load (f, img)
3033 struct frame *f;
3034 struct image *img;
3036 int success_p = 0;
3037 Lisp_Object file_name;
3039 xassert (xbm_image_p (img->spec));
3041 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3042 file_name = image_spec_value (img->spec, QCfile, NULL);
3043 if (STRINGP (file_name))
3045 Lisp_Object file;
3046 unsigned char *contents;
3047 int size;
3048 struct gcpro gcpro1;
3050 file = x_find_image_file (file_name);
3051 GCPRO1 (file);
3052 if (!STRINGP (file))
3054 image_error ("Cannot find image file `%s'", file_name, Qnil);
3055 UNGCPRO;
3056 return 0;
3059 contents = slurp_file (SDATA (file), &size);
3060 if (contents == NULL)
3062 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3063 UNGCPRO;
3064 return 0;
3067 success_p = xbm_load_image (f, img, contents, contents + size);
3068 UNGCPRO;
3070 else
3072 struct image_keyword fmt[XBM_LAST];
3073 Lisp_Object data;
3074 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3075 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3076 int non_default_colors = 0;
3077 char *bits;
3078 int parsed_p;
3079 int in_memory_file_p = 0;
3081 /* See if data looks like an in-memory XBM file. */
3082 data = image_spec_value (img->spec, QCdata, NULL);
3083 in_memory_file_p = xbm_file_p (data);
3085 /* Parse the image specification. */
3086 bcopy (xbm_format, fmt, sizeof fmt);
3087 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3088 xassert (parsed_p);
3090 /* Get specified width, and height. */
3091 if (!in_memory_file_p)
3093 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3094 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3095 xassert (img->width > 0 && img->height > 0);
3098 /* Get foreground and background colors, maybe allocate colors. */
3099 if (fmt[XBM_FOREGROUND].count
3100 && STRINGP (fmt[XBM_FOREGROUND].value))
3102 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3103 foreground);
3104 non_default_colors = 1;
3107 if (fmt[XBM_BACKGROUND].count
3108 && STRINGP (fmt[XBM_BACKGROUND].value))
3110 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3111 background);
3112 non_default_colors = 1;
3115 if (in_memory_file_p)
3116 success_p = xbm_load_image (f, img, SDATA (data),
3117 (SDATA (data)
3118 + SBYTES (data)));
3119 else
3121 if (VECTORP (data))
3123 int i;
3124 char *p;
3125 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3127 p = bits = (char *) alloca (nbytes * img->height);
3128 for (i = 0; i < img->height; ++i, p += nbytes)
3130 Lisp_Object line = XVECTOR (data)->contents[i];
3131 if (STRINGP (line))
3132 bcopy (SDATA (line), p, nbytes);
3133 else
3134 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3137 else if (STRINGP (data))
3138 bits = SDATA (data);
3139 else
3140 bits = XBOOL_VECTOR (data)->data;
3142 /* Create the pixmap. */
3144 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3145 foreground, background,
3146 non_default_colors);
3147 if (img->pixmap)
3148 success_p = 1;
3149 else
3151 image_error ("Unable to create pixmap for XBM image `%s'",
3152 img->spec, Qnil);
3153 x_clear_image (f, img);
3158 return success_p;
3163 /***********************************************************************
3164 XPM images
3165 ***********************************************************************/
3167 #ifdef HAVE_XPM
3169 static int xpm_image_p P_ ((Lisp_Object object));
3170 static int xpm_load P_ ((struct frame *f, struct image *img));
3171 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3173 #ifdef HAVE_NTGUI
3174 /* Indicate to xpm.h that we don't have Xlib. */
3175 #define FOR_MSW
3176 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3177 #define XColor xpm_XColor
3178 #define XImage xpm_XImage
3179 #define PIXEL_ALREADY_TYPEDEFED
3180 #include "X11/xpm.h"
3181 #undef FOR_MSW
3182 #undef XColor
3183 #undef XImage
3184 #undef PIXEL_ALREADY_TYPEDEFED
3185 #else
3186 #include "X11/xpm.h"
3187 #endif /* HAVE_NTGUI */
3189 /* The symbol `xpm' identifying XPM-format images. */
3191 Lisp_Object Qxpm;
3193 /* Indices of image specification fields in xpm_format, below. */
3195 enum xpm_keyword_index
3197 XPM_TYPE,
3198 XPM_FILE,
3199 XPM_DATA,
3200 XPM_ASCENT,
3201 XPM_MARGIN,
3202 XPM_RELIEF,
3203 XPM_ALGORITHM,
3204 XPM_HEURISTIC_MASK,
3205 XPM_MASK,
3206 XPM_COLOR_SYMBOLS,
3207 XPM_BACKGROUND,
3208 XPM_LAST
3211 /* Vector of image_keyword structures describing the format
3212 of valid XPM image specifications. */
3214 static struct image_keyword xpm_format[XPM_LAST] =
3216 {":type", IMAGE_SYMBOL_VALUE, 1},
3217 {":file", IMAGE_STRING_VALUE, 0},
3218 {":data", IMAGE_STRING_VALUE, 0},
3219 {":ascent", IMAGE_ASCENT_VALUE, 0},
3220 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3221 {":relief", IMAGE_INTEGER_VALUE, 0},
3222 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3223 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3224 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3225 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3226 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3229 /* Structure describing the image type XPM. */
3231 static struct image_type xpm_type =
3233 &Qxpm,
3234 xpm_image_p,
3235 xpm_load,
3236 x_clear_image,
3237 NULL
3240 #ifdef HAVE_X_WINDOWS
3242 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3243 functions for allocating image colors. Our own functions handle
3244 color allocation failures more gracefully than the ones on the XPM
3245 lib. */
3247 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3248 #define ALLOC_XPM_COLORS
3249 #endif
3250 #endif /* HAVE_X_WINDOWS */
3252 #ifdef ALLOC_XPM_COLORS
3254 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3255 static void xpm_free_color_cache P_ ((void));
3256 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3257 static int xpm_color_bucket P_ ((char *));
3258 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3259 XColor *, int));
3261 /* An entry in a hash table used to cache color definitions of named
3262 colors. This cache is necessary to speed up XPM image loading in
3263 case we do color allocations ourselves. Without it, we would need
3264 a call to XParseColor per pixel in the image. */
3266 struct xpm_cached_color
3268 /* Next in collision chain. */
3269 struct xpm_cached_color *next;
3271 /* Color definition (RGB and pixel color). */
3272 XColor color;
3274 /* Color name. */
3275 char name[1];
3278 /* The hash table used for the color cache, and its bucket vector
3279 size. */
3281 #define XPM_COLOR_CACHE_BUCKETS 1001
3282 struct xpm_cached_color **xpm_color_cache;
3284 /* Initialize the color cache. */
3286 static void
3287 xpm_init_color_cache (f, attrs)
3288 struct frame *f;
3289 XpmAttributes *attrs;
3291 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3292 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3293 memset (xpm_color_cache, 0, nbytes);
3294 init_color_table ();
3296 if (attrs->valuemask & XpmColorSymbols)
3298 int i;
3299 XColor color;
3301 for (i = 0; i < attrs->numsymbols; ++i)
3302 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3303 attrs->colorsymbols[i].value, &color))
3305 color.pixel = lookup_rgb_color (f, color.red, color.green,
3306 color.blue);
3307 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3312 /* Free the color cache. */
3314 static void
3315 xpm_free_color_cache ()
3317 struct xpm_cached_color *p, *next;
3318 int i;
3320 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3321 for (p = xpm_color_cache[i]; p; p = next)
3323 next = p->next;
3324 xfree (p);
3327 xfree (xpm_color_cache);
3328 xpm_color_cache = NULL;
3329 free_color_table ();
3332 /* Return the bucket index for color named COLOR_NAME in the color
3333 cache. */
3335 static int
3336 xpm_color_bucket (color_name)
3337 char *color_name;
3339 unsigned h = 0;
3340 char *s;
3342 for (s = color_name; *s; ++s)
3343 h = (h << 2) ^ *s;
3344 return h %= XPM_COLOR_CACHE_BUCKETS;
3348 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3349 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3350 entry added. */
3352 static struct xpm_cached_color *
3353 xpm_cache_color (f, color_name, color, bucket)
3354 struct frame *f;
3355 char *color_name;
3356 XColor *color;
3357 int bucket;
3359 size_t nbytes;
3360 struct xpm_cached_color *p;
3362 if (bucket < 0)
3363 bucket = xpm_color_bucket (color_name);
3365 nbytes = sizeof *p + strlen (color_name);
3366 p = (struct xpm_cached_color *) xmalloc (nbytes);
3367 strcpy (p->name, color_name);
3368 p->color = *color;
3369 p->next = xpm_color_cache[bucket];
3370 xpm_color_cache[bucket] = p;
3371 return p;
3374 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3375 return the cached definition in *COLOR. Otherwise, make a new
3376 entry in the cache and allocate the color. Value is zero if color
3377 allocation failed. */
3379 static int
3380 xpm_lookup_color (f, color_name, color)
3381 struct frame *f;
3382 char *color_name;
3383 XColor *color;
3385 struct xpm_cached_color *p;
3386 int h = xpm_color_bucket (color_name);
3388 for (p = xpm_color_cache[h]; p; p = p->next)
3389 if (strcmp (p->name, color_name) == 0)
3390 break;
3392 if (p != NULL)
3393 *color = p->color;
3394 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3395 color_name, color))
3397 color->pixel = lookup_rgb_color (f, color->red, color->green,
3398 color->blue);
3399 p = xpm_cache_color (f, color_name, color, h);
3401 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3402 with transparency, and it's useful. */
3403 else if (strcmp ("opaque", color_name) == 0)
3405 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
3406 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3407 p = xpm_cache_color (f, color_name, color, h);
3410 return p != NULL;
3414 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3415 CLOSURE is a pointer to the frame on which we allocate the
3416 color. Return in *COLOR the allocated color. Value is non-zero
3417 if successful. */
3419 static int
3420 xpm_alloc_color (dpy, cmap, color_name, color, closure)
3421 Display *dpy;
3422 Colormap cmap;
3423 char *color_name;
3424 XColor *color;
3425 void *closure;
3427 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3431 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3432 is a pointer to the frame on which we allocate the color. Value is
3433 non-zero if successful. */
3435 static int
3436 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
3437 Display *dpy;
3438 Colormap cmap;
3439 Pixel *pixels;
3440 int npixels;
3441 void *closure;
3443 return 1;
3446 #endif /* ALLOC_XPM_COLORS */
3449 #ifdef HAVE_NTGUI
3451 /* XPM library details. */
3453 DEF_IMGLIB_FN (XpmFreeAttributes);
3454 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
3455 DEF_IMGLIB_FN (XpmReadFileToImage);
3456 DEF_IMGLIB_FN (XImageFree);
3459 static int
3460 init_xpm_functions (void)
3462 HMODULE library;
3464 if (!(library = LoadLibrary ("libXpm.dll")))
3465 return 0;
3467 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3468 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3469 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3470 LOAD_IMGLIB_FN (library, XImageFree);
3471 return 1;
3474 #endif /* HAVE_NTGUI */
3477 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3478 for XPM images. Such a list must consist of conses whose car and
3479 cdr are strings. */
3481 static int
3482 xpm_valid_color_symbols_p (color_symbols)
3483 Lisp_Object color_symbols;
3485 while (CONSP (color_symbols))
3487 Lisp_Object sym = XCAR (color_symbols);
3488 if (!CONSP (sym)
3489 || !STRINGP (XCAR (sym))
3490 || !STRINGP (XCDR (sym)))
3491 break;
3492 color_symbols = XCDR (color_symbols);
3495 return NILP (color_symbols);
3499 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3501 static int
3502 xpm_image_p (object)
3503 Lisp_Object object;
3505 struct image_keyword fmt[XPM_LAST];
3506 bcopy (xpm_format, fmt, sizeof fmt);
3507 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3508 /* Either `:file' or `:data' must be present. */
3509 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3510 /* Either no `:color-symbols' or it's a list of conses
3511 whose car and cdr are strings. */
3512 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3513 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3517 /* Load image IMG which will be displayed on frame F. Value is
3518 non-zero if successful. */
3520 static int
3521 xpm_load (f, img)
3522 struct frame *f;
3523 struct image *img;
3525 int rc;
3526 XpmAttributes attrs;
3527 Lisp_Object specified_file, color_symbols;
3528 #ifdef HAVE_NTGUI
3529 HDC hdc;
3530 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3531 #endif /* HAVE_NTGUI */
3533 /* Configure the XPM lib. Use the visual of frame F. Allocate
3534 close colors. Return colors allocated. */
3535 bzero (&attrs, sizeof attrs);
3537 #ifndef HAVE_NTGUI
3538 attrs.visual = FRAME_X_VISUAL (f);
3539 attrs.colormap = FRAME_X_COLORMAP (f);
3540 attrs.valuemask |= XpmVisual;
3541 attrs.valuemask |= XpmColormap;
3542 #endif /* HAVE_NTGUI */
3544 #ifdef ALLOC_XPM_COLORS
3545 /* Allocate colors with our own functions which handle
3546 failing color allocation more gracefully. */
3547 attrs.color_closure = f;
3548 attrs.alloc_color = xpm_alloc_color;
3549 attrs.free_colors = xpm_free_colors;
3550 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3551 #else /* not ALLOC_XPM_COLORS */
3552 /* Let the XPM lib allocate colors. */
3553 attrs.valuemask |= XpmReturnAllocPixels;
3554 #ifdef XpmAllocCloseColors
3555 attrs.alloc_close_colors = 1;
3556 attrs.valuemask |= XpmAllocCloseColors;
3557 #else /* not XpmAllocCloseColors */
3558 attrs.closeness = 600;
3559 attrs.valuemask |= XpmCloseness;
3560 #endif /* not XpmAllocCloseColors */
3561 #endif /* ALLOC_XPM_COLORS */
3563 /* If image specification contains symbolic color definitions, add
3564 these to `attrs'. */
3565 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3566 if (CONSP (color_symbols))
3568 Lisp_Object tail;
3569 XpmColorSymbol *xpm_syms;
3570 int i, size;
3572 attrs.valuemask |= XpmColorSymbols;
3574 /* Count number of symbols. */
3575 attrs.numsymbols = 0;
3576 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3577 ++attrs.numsymbols;
3579 /* Allocate an XpmColorSymbol array. */
3580 size = attrs.numsymbols * sizeof *xpm_syms;
3581 xpm_syms = (XpmColorSymbol *) alloca (size);
3582 bzero (xpm_syms, size);
3583 attrs.colorsymbols = xpm_syms;
3585 /* Fill the color symbol array. */
3586 for (tail = color_symbols, i = 0;
3587 CONSP (tail);
3588 ++i, tail = XCDR (tail))
3590 Lisp_Object name = XCAR (XCAR (tail));
3591 Lisp_Object color = XCDR (XCAR (tail));
3592 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3593 strcpy (xpm_syms[i].name, SDATA (name));
3594 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3595 strcpy (xpm_syms[i].value, SDATA (color));
3599 /* Create a pixmap for the image, either from a file, or from a
3600 string buffer containing data in the same format as an XPM file. */
3601 #ifdef ALLOC_XPM_COLORS
3602 xpm_init_color_cache (f, &attrs);
3603 #endif
3605 specified_file = image_spec_value (img->spec, QCfile, NULL);
3607 #ifdef HAVE_NTGUI
3609 HDC frame_dc = get_frame_dc (f);
3610 hdc = CreateCompatibleDC (frame_dc);
3611 release_frame_dc (f, frame_dc);
3613 #endif /* HAVE_NTGUI */
3615 if (STRINGP (specified_file))
3617 Lisp_Object file = x_find_image_file (specified_file);
3618 if (!STRINGP (file))
3620 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3621 return 0;
3624 #ifdef HAVE_NTGUI
3625 /* XpmReadFileToPixmap is not available in the Windows port of
3626 libxpm. But XpmReadFileToImage almost does what we want. */
3627 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3628 &xpm_image, &xpm_mask,
3629 &attrs);
3630 #else
3631 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3632 SDATA (file), &img->pixmap, &img->mask,
3633 &attrs);
3634 #endif /* HAVE_NTGUI */
3636 else
3638 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3639 #ifdef HAVE_NTGUI
3640 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3641 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3642 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3643 &xpm_image, &xpm_mask,
3644 &attrs);
3645 #else
3646 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3647 SDATA (buffer),
3648 &img->pixmap, &img->mask,
3649 &attrs);
3650 #endif /* HAVE_NTGUI */
3653 if (rc == XpmSuccess)
3655 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3656 img->colors = colors_in_color_table (&img->ncolors);
3657 #else /* not ALLOC_XPM_COLORS */
3658 int i;
3660 #ifdef HAVE_NTGUI
3661 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3662 plus some duplicate attributes. */
3663 if (xpm_image && xpm_image->bitmap)
3665 img->pixmap = xpm_image->bitmap;
3666 /* XImageFree in libXpm frees XImage struct without destroying
3667 the bitmap, which is what we want. */
3668 fn_XImageFree (xpm_image);
3670 if (xpm_mask && xpm_mask->bitmap)
3672 /* The mask appears to be inverted compared with what we expect.
3673 TODO: invert our expectations. See other places where we
3674 have to invert bits because our idea of masks is backwards. */
3675 HGDIOBJ old_obj;
3676 old_obj = SelectObject (hdc, xpm_mask->bitmap);
3678 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
3679 SelectObject (hdc, old_obj);
3681 img->mask = xpm_mask->bitmap;
3682 fn_XImageFree (xpm_mask);
3683 DeleteDC (hdc);
3686 DeleteDC (hdc);
3687 #endif /* HAVE_NTGUI */
3689 /* Remember allocated colors. */
3690 img->ncolors = attrs.nalloc_pixels;
3691 img->colors = (unsigned long *) xmalloc (img->ncolors
3692 * sizeof *img->colors);
3693 for (i = 0; i < attrs.nalloc_pixels; ++i)
3695 img->colors[i] = attrs.alloc_pixels[i];
3696 #ifdef DEBUG_X_COLORS
3697 register_color (img->colors[i]);
3698 #endif
3700 #endif /* not ALLOC_XPM_COLORS */
3702 img->width = attrs.width;
3703 img->height = attrs.height;
3704 xassert (img->width > 0 && img->height > 0);
3706 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
3707 #ifdef HAVE_NTGUI
3708 fn_XpmFreeAttributes (&attrs);
3709 #else
3710 XpmFreeAttributes (&attrs);
3711 #endif /* HAVE_NTGUI */
3713 else
3715 #ifdef HAVE_NTGUI
3716 DeleteDC (hdc);
3717 #endif /* HAVE_NTGUI */
3719 switch (rc)
3721 case XpmOpenFailed:
3722 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
3723 break;
3725 case XpmFileInvalid:
3726 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
3727 break;
3729 case XpmNoMemory:
3730 image_error ("Out of memory (%s)", img->spec, Qnil);
3731 break;
3733 case XpmColorFailed:
3734 image_error ("Color allocation error (%s)", img->spec, Qnil);
3735 break;
3737 default:
3738 image_error ("Unknown error (%s)", img->spec, Qnil);
3739 break;
3743 #ifdef ALLOC_XPM_COLORS
3744 xpm_free_color_cache ();
3745 #endif
3746 return rc == XpmSuccess;
3749 #endif /* HAVE_XPM */
3752 /***********************************************************************
3753 Color table
3754 ***********************************************************************/
3756 #ifdef COLOR_TABLE_SUPPORT
3758 /* An entry in the color table mapping an RGB color to a pixel color. */
3760 struct ct_color
3762 int r, g, b;
3763 unsigned long pixel;
3765 /* Next in color table collision list. */
3766 struct ct_color *next;
3769 /* The bucket vector size to use. Must be prime. */
3771 #define CT_SIZE 101
3773 /* Value is a hash of the RGB color given by R, G, and B. */
3775 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
3777 /* The color hash table. */
3779 struct ct_color **ct_table;
3781 /* Number of entries in the color table. */
3783 int ct_colors_allocated;
3785 /* Initialize the color table. */
3787 static void
3788 init_color_table ()
3790 int size = CT_SIZE * sizeof (*ct_table);
3791 ct_table = (struct ct_color **) xmalloc (size);
3792 bzero (ct_table, size);
3793 ct_colors_allocated = 0;
3797 /* Free memory associated with the color table. */
3799 static void
3800 free_color_table ()
3802 int i;
3803 struct ct_color *p, *next;
3805 for (i = 0; i < CT_SIZE; ++i)
3806 for (p = ct_table[i]; p; p = next)
3808 next = p->next;
3809 xfree (p);
3812 xfree (ct_table);
3813 ct_table = NULL;
3817 /* Value is a pixel color for RGB color R, G, B on frame F. If an
3818 entry for that color already is in the color table, return the
3819 pixel color of that entry. Otherwise, allocate a new color for R,
3820 G, B, and make an entry in the color table. */
3822 static unsigned long
3823 lookup_rgb_color (f, r, g, b)
3824 struct frame *f;
3825 int r, g, b;
3827 unsigned hash = CT_HASH_RGB (r, g, b);
3828 int i = hash % CT_SIZE;
3829 struct ct_color *p;
3830 Display_Info *dpyinfo;
3832 /* Handle TrueColor visuals specially, which improves performance by
3833 two orders of magnitude. Freeing colors on TrueColor visuals is
3834 a nop, and pixel colors specify RGB values directly. See also
3835 the Xlib spec, chapter 3.1. */
3836 dpyinfo = FRAME_X_DISPLAY_INFO (f);
3837 if (dpyinfo->red_bits > 0)
3839 unsigned long pr, pg, pb;
3841 /* Apply gamma-correction like normal color allocation does. */
3842 if (f->gamma)
3844 XColor color;
3845 color.red = r, color.green = g, color.blue = b;
3846 gamma_correct (f, &color);
3847 r = color.red, g = color.green, b = color.blue;
3850 /* Scale down RGB values to the visual's bits per RGB, and shift
3851 them to the right position in the pixel color. Note that the
3852 original RGB values are 16-bit values, as usual in X. */
3853 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
3854 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
3855 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
3857 /* Assemble the pixel color. */
3858 return pr | pg | pb;
3861 for (p = ct_table[i]; p; p = p->next)
3862 if (p->r == r && p->g == g && p->b == b)
3863 break;
3865 if (p == NULL)
3868 #ifdef HAVE_X_WINDOWS
3869 XColor color;
3870 Colormap cmap;
3871 int rc;
3873 color.red = r;
3874 color.green = g;
3875 color.blue = b;
3877 cmap = FRAME_X_COLORMAP (f);
3878 rc = x_alloc_nearest_color (f, cmap, &color);
3879 if (rc)
3881 ++ct_colors_allocated;
3882 p = (struct ct_color *) xmalloc (sizeof *p);
3883 p->r = r;
3884 p->g = g;
3885 p->b = b;
3886 p->pixel = color.pixel;
3887 p->next = ct_table[i];
3888 ct_table[i] = p;
3890 else
3891 return FRAME_FOREGROUND_PIXEL (f);
3893 #else
3894 COLORREF color;
3895 #ifdef HAVE_NTGUI
3896 color = PALETTERGB (r, g, b);
3897 #else
3898 color = RGB_TO_ULONG (r, g, b);
3899 #endif /* HAVE_NTGUI */
3900 ++ct_colors_allocated;
3901 p = (struct ct_color *) xmalloc (sizeof *p);
3902 p->r = r;
3903 p->g = g;
3904 p->b = b;
3905 p->pixel = color;
3906 p->next = ct_table[i];
3907 ct_table[i] = p;
3908 #endif /* HAVE_X_WINDOWS */
3912 return p->pixel;
3916 /* Look up pixel color PIXEL which is used on frame F in the color
3917 table. If not already present, allocate it. Value is PIXEL. */
3919 static unsigned long
3920 lookup_pixel_color (f, pixel)
3921 struct frame *f;
3922 unsigned long pixel;
3924 int i = pixel % CT_SIZE;
3925 struct ct_color *p;
3927 for (p = ct_table[i]; p; p = p->next)
3928 if (p->pixel == pixel)
3929 break;
3931 if (p == NULL)
3933 XColor color;
3934 Colormap cmap;
3935 int rc;
3937 #ifdef HAVE_X_WINDOWS
3938 cmap = FRAME_X_COLORMAP (f);
3939 color.pixel = pixel;
3940 x_query_color (f, &color);
3941 rc = x_alloc_nearest_color (f, cmap, &color);
3942 #else
3943 BLOCK_INPUT;
3944 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
3945 color.pixel = pixel;
3946 XQueryColor (NULL, cmap, &color);
3947 rc = x_alloc_nearest_color (f, cmap, &color);
3948 UNBLOCK_INPUT;
3949 #endif /* HAVE_X_WINDOWS */
3951 if (rc)
3953 ++ct_colors_allocated;
3955 p = (struct ct_color *) xmalloc (sizeof *p);
3956 p->r = color.red;
3957 p->g = color.green;
3958 p->b = color.blue;
3959 p->pixel = pixel;
3960 p->next = ct_table[i];
3961 ct_table[i] = p;
3963 else
3964 return FRAME_FOREGROUND_PIXEL (f);
3966 return p->pixel;
3970 /* Value is a vector of all pixel colors contained in the color table,
3971 allocated via xmalloc. Set *N to the number of colors. */
3973 static unsigned long *
3974 colors_in_color_table (n)
3975 int *n;
3977 int i, j;
3978 struct ct_color *p;
3979 unsigned long *colors;
3981 if (ct_colors_allocated == 0)
3983 *n = 0;
3984 colors = NULL;
3986 else
3988 colors = (unsigned long *) xmalloc (ct_colors_allocated
3989 * sizeof *colors);
3990 *n = ct_colors_allocated;
3992 for (i = j = 0; i < CT_SIZE; ++i)
3993 for (p = ct_table[i]; p; p = p->next)
3994 colors[j++] = p->pixel;
3997 return colors;
4000 #else /* COLOR_TABLE_SUPPORT */
4002 static unsigned long
4003 lookup_rgb_color (f, r, g, b)
4004 struct frame *f;
4005 int r, g, b;
4007 unsigned long pixel;
4009 #ifdef MAC_OS
4010 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4011 gamma_correct (f, &pixel);
4012 #endif /* MAC_OS */
4014 #ifdef HAVE_NTGUI
4015 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4016 #endif /* HAVE_NTGUI */
4018 return pixel;
4021 static void
4022 init_color_table ()
4025 #endif /* COLOR_TABLE_SUPPORT */
4028 /***********************************************************************
4029 Algorithms
4030 ***********************************************************************/
4032 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
4033 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
4034 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
4036 #ifdef HAVE_NTGUI
4037 static void XPutPixel (XImagePtr , int, int, COLORREF);
4038 #endif /* HAVE_NTGUI */
4040 /* Non-zero means draw a cross on images having `:conversion
4041 disabled'. */
4043 int cross_disabled_images;
4045 /* Edge detection matrices for different edge-detection
4046 strategies. */
4048 static int emboss_matrix[9] = {
4049 /* x - 1 x x + 1 */
4050 2, -1, 0, /* y - 1 */
4051 -1, 0, 1, /* y */
4052 0, 1, -2 /* y + 1 */
4055 static int laplace_matrix[9] = {
4056 /* x - 1 x x + 1 */
4057 1, 0, 0, /* y - 1 */
4058 0, 0, 0, /* y */
4059 0, 0, -1 /* y + 1 */
4062 /* Value is the intensity of the color whose red/green/blue values
4063 are R, G, and B. */
4065 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4068 /* On frame F, return an array of XColor structures describing image
4069 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4070 non-zero means also fill the red/green/blue members of the XColor
4071 structures. Value is a pointer to the array of XColors structures,
4072 allocated with xmalloc; it must be freed by the caller. */
4074 static XColor *
4075 x_to_xcolors (f, img, rgb_p)
4076 struct frame *f;
4077 struct image *img;
4078 int rgb_p;
4080 int x, y;
4081 XColor *colors, *p;
4082 XImagePtr_or_DC ximg;
4083 #ifdef HAVE_NTGUI
4084 HDC hdc;
4085 HGDIOBJ prev;
4086 #endif /* HAVE_NTGUI */
4088 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4090 #ifndef HAVE_NTGUI
4091 /* Get the X image IMG->pixmap. */
4092 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4093 0, 0, img->width, img->height, ~0, ZPixmap);
4094 #else
4095 /* Load the image into a memory device context. */
4096 hdc = get_frame_dc (f);
4097 ximg = CreateCompatibleDC (hdc);
4098 release_frame_dc (f, hdc);
4099 prev = SelectObject (ximg, img->pixmap);
4100 #endif /* HAVE_NTGUI */
4102 /* Fill the `pixel' members of the XColor array. I wished there
4103 were an easy and portable way to circumvent XGetPixel. */
4104 p = colors;
4105 for (y = 0; y < img->height; ++y)
4107 XColor *row = p;
4109 #ifdef HAVE_X_WINDOWS
4110 for (x = 0; x < img->width; ++x, ++p)
4111 p->pixel = XGetPixel (ximg, x, y);
4112 if (rgb_p)
4113 x_query_colors (f, row, img->width);
4115 #else
4117 for (x = 0; x < img->width; ++x, ++p)
4119 /* W32_TODO: palette support needed here? */
4120 p->pixel = GET_PIXEL (ximg, x, y);
4121 if (rgb_p)
4123 #ifdef MAC_OS
4124 p->red = RED16_FROM_ULONG (p->pixel);
4125 p->green = GREEN16_FROM_ULONG (p->pixel);
4126 p->blue = BLUE16_FROM_ULONG (p->pixel);
4127 #endif /* MAC_OS */
4128 #ifdef HAVE_NTGUI
4129 p->red = 256 * GetRValue (p->pixel);
4130 p->green = 256 * GetGValue (p->pixel);
4131 p->blue = 256 * GetBValue (p->pixel);
4132 #endif /* HAVE_NTGUI */
4135 #endif /* HAVE_X_WINDOWS */
4138 Destroy_Image (ximg, prev);
4140 return colors;
4143 #ifdef HAVE_NTGUI
4145 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4146 created with CreateDIBSection, with the pointer to the bit values
4147 stored in ximg->data. */
4149 static void XPutPixel (ximg, x, y, color)
4150 XImagePtr ximg;
4151 int x, y;
4152 COLORREF color;
4154 int width = ximg->info.bmiHeader.biWidth;
4155 int height = ximg->info.bmiHeader.biHeight;
4156 unsigned char * pixel;
4158 /* True color images. */
4159 if (ximg->info.bmiHeader.biBitCount == 24)
4161 int rowbytes = width * 3;
4162 /* Ensure scanlines are aligned on 4 byte boundaries. */
4163 if (rowbytes % 4)
4164 rowbytes += 4 - (rowbytes % 4);
4166 pixel = ximg->data + y * rowbytes + x * 3;
4167 /* Windows bitmaps are in BGR order. */
4168 *pixel = GetBValue (color);
4169 *(pixel + 1) = GetGValue (color);
4170 *(pixel + 2) = GetRValue (color);
4172 /* Monochrome images. */
4173 else if (ximg->info.bmiHeader.biBitCount == 1)
4175 int rowbytes = width / 8;
4176 /* Ensure scanlines are aligned on 4 byte boundaries. */
4177 if (rowbytes % 4)
4178 rowbytes += 4 - (rowbytes % 4);
4179 pixel = ximg->data + y * rowbytes + x / 8;
4180 /* Filter out palette info. */
4181 if (color & 0x00ffffff)
4182 *pixel = *pixel | (1 << x % 8);
4183 else
4184 *pixel = *pixel & ~(1 << x % 8);
4186 else
4187 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4190 #endif /* HAVE_NTGUI */
4192 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4193 RGB members are set. F is the frame on which this all happens.
4194 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4196 static void
4197 x_from_xcolors (f, img, colors)
4198 struct frame *f;
4199 struct image *img;
4200 XColor *colors;
4202 int x, y;
4203 XImagePtr oimg;
4204 Pixmap pixmap;
4205 XColor *p;
4207 init_color_table ();
4209 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
4210 &oimg, &pixmap);
4211 p = colors;
4212 for (y = 0; y < img->height; ++y)
4213 for (x = 0; x < img->width; ++x, ++p)
4215 unsigned long pixel;
4216 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
4217 XPutPixel (oimg, x, y, pixel);
4220 xfree (colors);
4221 x_clear_image_1 (f, img, 1, 0, 1);
4223 x_put_x_image (f, oimg, pixmap, img->width, img->height);
4224 x_destroy_x_image (oimg);
4225 img->pixmap = pixmap;
4226 #ifdef COLOR_TABLE_SUPPORT
4227 img->colors = colors_in_color_table (&img->ncolors);
4228 free_color_table ();
4229 #endif /* COLOR_TABLE_SUPPORT */
4233 /* On frame F, perform edge-detection on image IMG.
4235 MATRIX is a nine-element array specifying the transformation
4236 matrix. See emboss_matrix for an example.
4238 COLOR_ADJUST is a color adjustment added to each pixel of the
4239 outgoing image. */
4241 static void
4242 x_detect_edges (f, img, matrix, color_adjust)
4243 struct frame *f;
4244 struct image *img;
4245 int matrix[9], color_adjust;
4247 XColor *colors = x_to_xcolors (f, img, 1);
4248 XColor *new, *p;
4249 int x, y, i, sum;
4251 for (i = sum = 0; i < 9; ++i)
4252 sum += abs (matrix[i]);
4254 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
4256 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
4258 for (y = 0; y < img->height; ++y)
4260 p = COLOR (new, 0, y);
4261 p->red = p->green = p->blue = 0xffff/2;
4262 p = COLOR (new, img->width - 1, y);
4263 p->red = p->green = p->blue = 0xffff/2;
4266 for (x = 1; x < img->width - 1; ++x)
4268 p = COLOR (new, x, 0);
4269 p->red = p->green = p->blue = 0xffff/2;
4270 p = COLOR (new, x, img->height - 1);
4271 p->red = p->green = p->blue = 0xffff/2;
4274 for (y = 1; y < img->height - 1; ++y)
4276 p = COLOR (new, 1, y);
4278 for (x = 1; x < img->width - 1; ++x, ++p)
4280 int r, g, b, y1, x1;
4282 r = g = b = i = 0;
4283 for (y1 = y - 1; y1 < y + 2; ++y1)
4284 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
4285 if (matrix[i])
4287 XColor *t = COLOR (colors, x1, y1);
4288 r += matrix[i] * t->red;
4289 g += matrix[i] * t->green;
4290 b += matrix[i] * t->blue;
4293 r = (r / sum + color_adjust) & 0xffff;
4294 g = (g / sum + color_adjust) & 0xffff;
4295 b = (b / sum + color_adjust) & 0xffff;
4296 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
4300 xfree (colors);
4301 x_from_xcolors (f, img, new);
4303 #undef COLOR
4307 /* Perform the pre-defined `emboss' edge-detection on image IMG
4308 on frame F. */
4310 static void
4311 x_emboss (f, img)
4312 struct frame *f;
4313 struct image *img;
4315 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
4319 /* Transform image IMG which is used on frame F with a Laplace
4320 edge-detection algorithm. The result is an image that can be used
4321 to draw disabled buttons, for example. */
4323 static void
4324 x_laplace (f, img)
4325 struct frame *f;
4326 struct image *img;
4328 x_detect_edges (f, img, laplace_matrix, 45000);
4332 /* Perform edge-detection on image IMG on frame F, with specified
4333 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
4335 MATRIX must be either
4337 - a list of at least 9 numbers in row-major form
4338 - a vector of at least 9 numbers
4340 COLOR_ADJUST nil means use a default; otherwise it must be a
4341 number. */
4343 static void
4344 x_edge_detection (f, img, matrix, color_adjust)
4345 struct frame *f;
4346 struct image *img;
4347 Lisp_Object matrix, color_adjust;
4349 int i = 0;
4350 int trans[9];
4352 if (CONSP (matrix))
4354 for (i = 0;
4355 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
4356 ++i, matrix = XCDR (matrix))
4357 trans[i] = XFLOATINT (XCAR (matrix));
4359 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
4361 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
4362 trans[i] = XFLOATINT (AREF (matrix, i));
4365 if (NILP (color_adjust))
4366 color_adjust = make_number (0xffff / 2);
4368 if (i == 9 && NUMBERP (color_adjust))
4369 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
4373 /* Transform image IMG on frame F so that it looks disabled. */
4375 static void
4376 x_disable_image (f, img)
4377 struct frame *f;
4378 struct image *img;
4380 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4381 #ifdef HAVE_NTGUI
4382 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
4383 #else
4384 int n_planes = dpyinfo->n_planes;
4385 #endif /* HAVE_NTGUI */
4387 if (n_planes >= 2)
4389 /* Color (or grayscale). Convert to gray, and equalize. Just
4390 drawing such images with a stipple can look very odd, so
4391 we're using this method instead. */
4392 XColor *colors = x_to_xcolors (f, img, 1);
4393 XColor *p, *end;
4394 const int h = 15000;
4395 const int l = 30000;
4397 for (p = colors, end = colors + img->width * img->height;
4398 p < end;
4399 ++p)
4401 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
4402 int i2 = (0xffff - h - l) * i / 0xffff + l;
4403 p->red = p->green = p->blue = i2;
4406 x_from_xcolors (f, img, colors);
4409 /* Draw a cross over the disabled image, if we must or if we
4410 should. */
4411 if (n_planes < 2 || cross_disabled_images)
4413 #ifndef HAVE_NTGUI
4414 Display *dpy = FRAME_X_DISPLAY (f);
4415 GC gc;
4417 #ifdef MAC_OS
4418 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
4419 #define MaskForeground(f) PIX_MASK_DRAW (f)
4420 #else
4421 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
4422 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4423 #endif
4425 gc = XCreateGC_pixmap (dpy, img->pixmap);
4426 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4427 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4428 img->width - 1, img->height - 1);
4429 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
4430 img->width - 1, 0);
4431 XFreeGC (dpy, gc);
4433 if (img->mask)
4435 gc = XCreateGC_pixmap (dpy, img->mask);
4436 XSetForeground (dpy, gc, MaskForeground (f));
4437 XDrawLine (dpy, img->mask, gc, 0, 0,
4438 img->width - 1, img->height - 1);
4439 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
4440 img->width - 1, 0);
4441 XFreeGC (dpy, gc);
4443 #else
4444 HDC hdc, bmpdc;
4445 HGDIOBJ prev;
4447 hdc = get_frame_dc (f);
4448 bmpdc = CreateCompatibleDC (hdc);
4449 release_frame_dc (f, hdc);
4451 prev = SelectObject (bmpdc, img->pixmap);
4453 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
4454 MoveToEx (bmpdc, 0, 0, NULL);
4455 LineTo (bmpdc, img->width - 1, img->height - 1);
4456 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4457 LineTo (bmpdc, img->width - 1, 0);
4459 if (img->mask)
4461 SelectObject (bmpdc, img->mask);
4462 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
4463 MoveToEx (bmpdc, 0, 0, NULL);
4464 LineTo (bmpdc, img->width - 1, img->height - 1);
4465 MoveToEx (bmpdc, 0, img->height - 1, NULL);
4466 LineTo (bmpdc, img->width - 1, 0);
4468 SelectObject (bmpdc, prev);
4469 DeleteDC (bmpdc);
4470 #endif /* HAVE_NTGUI */
4475 /* Build a mask for image IMG which is used on frame F. FILE is the
4476 name of an image file, for error messages. HOW determines how to
4477 determine the background color of IMG. If it is a list '(R G B)',
4478 with R, G, and B being integers >= 0, take that as the color of the
4479 background. Otherwise, determine the background color of IMG
4480 heuristically. Value is non-zero if successful. */
4482 static int
4483 x_build_heuristic_mask (f, img, how)
4484 struct frame *f;
4485 struct image *img;
4486 Lisp_Object how;
4488 XImagePtr_or_DC ximg;
4489 #ifndef HAVE_NTGUI
4490 XImagePtr mask_img;
4491 #else
4492 HDC frame_dc;
4493 HGDIOBJ prev;
4494 char *mask_img;
4495 int row_width;
4496 #endif /* HAVE_NTGUI */
4497 int x, y, rc, use_img_background;
4498 unsigned long bg = 0;
4500 if (img->mask)
4502 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4503 img->mask = NO_PIXMAP;
4504 img->background_transparent_valid = 0;
4507 #ifndef HAVE_NTGUI
4508 /* Create an image and pixmap serving as mask. */
4509 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
4510 &mask_img, &img->mask);
4511 if (!rc)
4512 return 0;
4514 /* Get the X image of IMG->pixmap. */
4515 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4516 img->width, img->height,
4517 ~0, ZPixmap);
4518 #else
4519 /* Create the bit array serving as mask. */
4520 row_width = (img->width + 7) / 8;
4521 mask_img = xmalloc (row_width * img->height);
4522 bzero (mask_img, row_width * img->height);
4524 /* Create a memory device context for IMG->pixmap. */
4525 frame_dc = get_frame_dc (f);
4526 ximg = CreateCompatibleDC (frame_dc);
4527 release_frame_dc (f, frame_dc);
4528 prev = SelectObject (ximg, img->pixmap);
4529 #endif /* HAVE_NTGUI */
4531 /* Determine the background color of ximg. If HOW is `(R G B)'
4532 take that as color. Otherwise, use the image's background color. */
4533 use_img_background = 1;
4535 if (CONSP (how))
4537 int rgb[3], i;
4539 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
4541 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
4542 how = XCDR (how);
4545 if (i == 3 && NILP (how))
4547 char color_name[30];
4548 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
4549 bg = (
4550 #ifdef HAVE_NTGUI
4551 0x00ffffff & /* Filter out palette info. */
4552 #endif /* HAVE_NTGUI */
4553 x_alloc_image_color (f, img, build_string (color_name), 0));
4554 use_img_background = 0;
4558 if (use_img_background)
4559 bg = four_corners_best (ximg, img->width, img->height);
4561 /* Set all bits in mask_img to 1 whose color in ximg is different
4562 from the background color bg. */
4563 #ifndef HAVE_NTGUI
4564 for (y = 0; y < img->height; ++y)
4565 for (x = 0; x < img->width; ++x)
4566 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
4567 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f)));
4569 /* Fill in the background_transparent field while we have the mask handy. */
4570 image_background_transparent (img, f, mask_img);
4572 /* Put mask_img into img->mask. */
4573 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
4574 x_destroy_x_image (mask_img);
4576 #else
4577 for (y = 0; y < img->height; ++y)
4578 for (x = 0; x < img->width; ++x)
4580 COLORREF p = GetPixel (ximg, x, y);
4581 if (p != bg)
4582 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
4585 /* Create the mask image. */
4586 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
4587 mask_img);
4588 /* Fill in the background_transparent field while we have the mask handy. */
4589 SelectObject (ximg, img->mask);
4590 image_background_transparent (img, f, ximg);
4592 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
4593 xfree (mask_img);
4594 #endif /* HAVE_NTGUI */
4596 Destroy_Image (ximg, prev);
4598 return 1;
4602 /***********************************************************************
4603 PBM (mono, gray, color)
4604 ***********************************************************************/
4606 static int pbm_image_p P_ ((Lisp_Object object));
4607 static int pbm_load P_ ((struct frame *f, struct image *img));
4608 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
4610 /* The symbol `pbm' identifying images of this type. */
4612 Lisp_Object Qpbm;
4614 /* Indices of image specification fields in gs_format, below. */
4616 enum pbm_keyword_index
4618 PBM_TYPE,
4619 PBM_FILE,
4620 PBM_DATA,
4621 PBM_ASCENT,
4622 PBM_MARGIN,
4623 PBM_RELIEF,
4624 PBM_ALGORITHM,
4625 PBM_HEURISTIC_MASK,
4626 PBM_MASK,
4627 PBM_FOREGROUND,
4628 PBM_BACKGROUND,
4629 PBM_LAST
4632 /* Vector of image_keyword structures describing the format
4633 of valid user-defined image specifications. */
4635 static struct image_keyword pbm_format[PBM_LAST] =
4637 {":type", IMAGE_SYMBOL_VALUE, 1},
4638 {":file", IMAGE_STRING_VALUE, 0},
4639 {":data", IMAGE_STRING_VALUE, 0},
4640 {":ascent", IMAGE_ASCENT_VALUE, 0},
4641 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
4642 {":relief", IMAGE_INTEGER_VALUE, 0},
4643 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4644 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4645 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
4646 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
4647 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
4650 /* Structure describing the image type `pbm'. */
4652 static struct image_type pbm_type =
4654 &Qpbm,
4655 pbm_image_p,
4656 pbm_load,
4657 x_clear_image,
4658 NULL
4662 /* Return non-zero if OBJECT is a valid PBM image specification. */
4664 static int
4665 pbm_image_p (object)
4666 Lisp_Object object;
4668 struct image_keyword fmt[PBM_LAST];
4670 bcopy (pbm_format, fmt, sizeof fmt);
4672 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
4673 return 0;
4675 /* Must specify either :data or :file. */
4676 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
4680 /* Scan a decimal number from *S and return it. Advance *S while
4681 reading the number. END is the end of the string. Value is -1 at
4682 end of input. */
4684 static int
4685 pbm_scan_number (s, end)
4686 unsigned char **s, *end;
4688 int c = 0, val = -1;
4690 while (*s < end)
4692 /* Skip white-space. */
4693 while (*s < end && (c = *(*s)++, isspace (c)))
4696 if (c == '#')
4698 /* Skip comment to end of line. */
4699 while (*s < end && (c = *(*s)++, c != '\n'))
4702 else if (isdigit (c))
4704 /* Read decimal number. */
4705 val = c - '0';
4706 while (*s < end && (c = *(*s)++, isdigit (c)))
4707 val = 10 * val + c - '0';
4708 break;
4710 else
4711 break;
4714 return val;
4718 #ifdef HAVE_NTGUI
4719 #if 0 /* Unused. ++kfs */
4721 /* Read FILE into memory. Value is a pointer to a buffer allocated
4722 with xmalloc holding FILE's contents. Value is null if an error
4723 occurred. *SIZE is set to the size of the file. */
4725 static char *
4726 pbm_read_file (file, size)
4727 Lisp_Object file;
4728 int *size;
4730 FILE *fp = NULL;
4731 char *buf = NULL;
4732 struct stat st;
4734 if (stat (SDATA (file), &st) == 0
4735 && (fp = fopen (SDATA (file), "rb")) != NULL
4736 && (buf = (char *) xmalloc (st.st_size),
4737 fread (buf, 1, st.st_size, fp) == st.st_size))
4739 *size = st.st_size;
4740 fclose (fp);
4742 else
4744 if (fp)
4745 fclose (fp);
4746 if (buf)
4748 xfree (buf);
4749 buf = NULL;
4753 return buf;
4755 #endif
4756 #endif /* HAVE_NTGUI */
4758 /* Load PBM image IMG for use on frame F. */
4760 static int
4761 pbm_load (f, img)
4762 struct frame *f;
4763 struct image *img;
4765 int raw_p, x, y;
4766 int width, height, max_color_idx = 0;
4767 XImagePtr ximg;
4768 Lisp_Object file, specified_file;
4769 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
4770 struct gcpro gcpro1;
4771 unsigned char *contents = NULL;
4772 unsigned char *end, *p;
4773 int size;
4775 specified_file = image_spec_value (img->spec, QCfile, NULL);
4776 file = Qnil;
4777 GCPRO1 (file);
4779 if (STRINGP (specified_file))
4781 file = x_find_image_file (specified_file);
4782 if (!STRINGP (file))
4784 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4785 UNGCPRO;
4786 return 0;
4789 contents = slurp_file (SDATA (file), &size);
4790 if (contents == NULL)
4792 image_error ("Error reading `%s'", file, Qnil);
4793 UNGCPRO;
4794 return 0;
4797 p = contents;
4798 end = contents + size;
4800 else
4802 Lisp_Object data;
4803 data = image_spec_value (img->spec, QCdata, NULL);
4804 p = SDATA (data);
4805 end = p + SBYTES (data);
4808 /* Check magic number. */
4809 if (end - p < 2 || *p++ != 'P')
4811 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
4812 error:
4813 xfree (contents);
4814 UNGCPRO;
4815 return 0;
4818 switch (*p++)
4820 case '1':
4821 raw_p = 0, type = PBM_MONO;
4822 break;
4824 case '2':
4825 raw_p = 0, type = PBM_GRAY;
4826 break;
4828 case '3':
4829 raw_p = 0, type = PBM_COLOR;
4830 break;
4832 case '4':
4833 raw_p = 1, type = PBM_MONO;
4834 break;
4836 case '5':
4837 raw_p = 1, type = PBM_GRAY;
4838 break;
4840 case '6':
4841 raw_p = 1, type = PBM_COLOR;
4842 break;
4844 default:
4845 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
4846 goto error;
4849 /* Read width, height, maximum color-component. Characters
4850 starting with `#' up to the end of a line are ignored. */
4851 width = pbm_scan_number (&p, end);
4852 height = pbm_scan_number (&p, end);
4854 if (type != PBM_MONO)
4856 max_color_idx = pbm_scan_number (&p, end);
4857 if (raw_p && max_color_idx > 255)
4858 max_color_idx = 255;
4861 if (width < 0
4862 || height < 0
4863 || (type != PBM_MONO && max_color_idx < 0))
4864 goto error;
4866 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4867 &ximg, &img->pixmap))
4868 goto error;
4870 /* Initialize the color hash table. */
4871 init_color_table ();
4873 if (type == PBM_MONO)
4875 int c = 0, g;
4876 struct image_keyword fmt[PBM_LAST];
4877 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
4878 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
4880 /* Parse the image specification. */
4881 bcopy (pbm_format, fmt, sizeof fmt);
4882 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
4884 /* Get foreground and background colors, maybe allocate colors. */
4885 if (fmt[PBM_FOREGROUND].count
4886 && STRINGP (fmt[PBM_FOREGROUND].value))
4887 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
4888 if (fmt[PBM_BACKGROUND].count
4889 && STRINGP (fmt[PBM_BACKGROUND].value))
4891 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
4892 img->background = bg;
4893 img->background_valid = 1;
4896 for (y = 0; y < height; ++y)
4897 for (x = 0; x < width; ++x)
4899 if (raw_p)
4901 if ((x & 7) == 0)
4902 c = *p++;
4903 g = c & 0x80;
4904 c <<= 1;
4906 else
4907 g = pbm_scan_number (&p, end);
4909 XPutPixel (ximg, x, y, g ? fg : bg);
4912 else
4914 for (y = 0; y < height; ++y)
4915 for (x = 0; x < width; ++x)
4917 int r, g, b;
4919 if (type == PBM_GRAY)
4920 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
4921 else if (raw_p)
4923 r = *p++;
4924 g = *p++;
4925 b = *p++;
4927 else
4929 r = pbm_scan_number (&p, end);
4930 g = pbm_scan_number (&p, end);
4931 b = pbm_scan_number (&p, end);
4934 if (r < 0 || g < 0 || b < 0)
4936 x_destroy_x_image (ximg);
4937 image_error ("Invalid pixel value in image `%s'",
4938 img->spec, Qnil);
4939 goto error;
4942 /* RGB values are now in the range 0..max_color_idx.
4943 Scale this to the range 0..0xffff supported by X. */
4944 r = (double) r * 65535 / max_color_idx;
4945 g = (double) g * 65535 / max_color_idx;
4946 b = (double) b * 65535 / max_color_idx;
4947 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
4951 #ifdef COLOR_TABLE_SUPPORT
4952 /* Store in IMG->colors the colors allocated for the image, and
4953 free the color table. */
4954 img->colors = colors_in_color_table (&img->ncolors);
4955 free_color_table ();
4956 #endif /* COLOR_TABLE_SUPPORT */
4958 img->width = width;
4959 img->height = height;
4961 /* Maybe fill in the background field while we have ximg handy. */
4963 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4964 IMAGE_BACKGROUND (img, f, ximg);
4966 /* Put the image into a pixmap. */
4967 x_put_x_image (f, ximg, img->pixmap, width, height);
4968 x_destroy_x_image (ximg);
4970 /* X and W32 versions did it here, MAC version above. ++kfs
4971 img->width = width;
4972 img->height = height; */
4974 UNGCPRO;
4975 xfree (contents);
4976 return 1;
4980 /***********************************************************************
4982 ***********************************************************************/
4984 #if defined (HAVE_PNG) || defined (MAC_OS)
4986 /* Function prototypes. */
4988 static int png_image_p P_ ((Lisp_Object object));
4989 static int png_load P_ ((struct frame *f, struct image *img));
4991 /* The symbol `png' identifying images of this type. */
4993 Lisp_Object Qpng;
4995 /* Indices of image specification fields in png_format, below. */
4997 enum png_keyword_index
4999 PNG_TYPE,
5000 PNG_DATA,
5001 PNG_FILE,
5002 PNG_ASCENT,
5003 PNG_MARGIN,
5004 PNG_RELIEF,
5005 PNG_ALGORITHM,
5006 PNG_HEURISTIC_MASK,
5007 PNG_MASK,
5008 PNG_BACKGROUND,
5009 PNG_LAST
5012 /* Vector of image_keyword structures describing the format
5013 of valid user-defined image specifications. */
5015 static struct image_keyword png_format[PNG_LAST] =
5017 {":type", IMAGE_SYMBOL_VALUE, 1},
5018 {":data", IMAGE_STRING_VALUE, 0},
5019 {":file", IMAGE_STRING_VALUE, 0},
5020 {":ascent", IMAGE_ASCENT_VALUE, 0},
5021 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5022 {":relief", IMAGE_INTEGER_VALUE, 0},
5023 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5024 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5025 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5026 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5029 /* Structure describing the image type `png'. */
5031 static struct image_type png_type =
5033 &Qpng,
5034 png_image_p,
5035 png_load,
5036 x_clear_image,
5037 NULL
5040 /* Return non-zero if OBJECT is a valid PNG image specification. */
5042 static int
5043 png_image_p (object)
5044 Lisp_Object object;
5046 struct image_keyword fmt[PNG_LAST];
5047 bcopy (png_format, fmt, sizeof fmt);
5049 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5050 return 0;
5052 /* Must specify either the :data or :file keyword. */
5053 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5056 #endif /* HAVE_PNG || MAC_OS */
5059 #ifdef HAVE_PNG
5061 #if defined HAVE_LIBPNG_PNG_H
5062 # include <libpng/png.h>
5063 #else
5064 # include <png.h>
5065 #endif
5067 #ifdef HAVE_NTGUI
5068 /* PNG library details. */
5070 DEF_IMGLIB_FN (png_get_io_ptr);
5071 DEF_IMGLIB_FN (png_check_sig);
5072 DEF_IMGLIB_FN (png_create_read_struct);
5073 DEF_IMGLIB_FN (png_create_info_struct);
5074 DEF_IMGLIB_FN (png_destroy_read_struct);
5075 DEF_IMGLIB_FN (png_set_read_fn);
5076 DEF_IMGLIB_FN (png_init_io);
5077 DEF_IMGLIB_FN (png_set_sig_bytes);
5078 DEF_IMGLIB_FN (png_read_info);
5079 DEF_IMGLIB_FN (png_get_IHDR);
5080 DEF_IMGLIB_FN (png_get_valid);
5081 DEF_IMGLIB_FN (png_set_strip_16);
5082 DEF_IMGLIB_FN (png_set_expand);
5083 DEF_IMGLIB_FN (png_set_gray_to_rgb);
5084 DEF_IMGLIB_FN (png_set_background);
5085 DEF_IMGLIB_FN (png_get_bKGD);
5086 DEF_IMGLIB_FN (png_read_update_info);
5087 DEF_IMGLIB_FN (png_get_channels);
5088 DEF_IMGLIB_FN (png_get_rowbytes);
5089 DEF_IMGLIB_FN (png_read_image);
5090 DEF_IMGLIB_FN (png_read_end);
5091 DEF_IMGLIB_FN (png_error);
5093 static int
5094 init_png_functions (void)
5096 HMODULE library;
5098 /* Ensure zlib is loaded. Try debug version first. */
5099 if (!LoadLibrary ("zlibd.dll")
5100 && !LoadLibrary ("zlib.dll"))
5101 return 0;
5103 /* Try loading libpng under probable names. */
5104 if (!(library = LoadLibrary ("libpng13d.dll"))
5105 && !(library = LoadLibrary ("libpng13.dll"))
5106 && !(library = LoadLibrary ("libpng12d.dll"))
5107 && !(library = LoadLibrary ("libpng12.dll"))
5108 && !(library = LoadLibrary ("libpng.dll")))
5109 return 0;
5111 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5112 LOAD_IMGLIB_FN (library, png_check_sig);
5113 LOAD_IMGLIB_FN (library, png_create_read_struct);
5114 LOAD_IMGLIB_FN (library, png_create_info_struct);
5115 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5116 LOAD_IMGLIB_FN (library, png_set_read_fn);
5117 LOAD_IMGLIB_FN (library, png_init_io);
5118 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5119 LOAD_IMGLIB_FN (library, png_read_info);
5120 LOAD_IMGLIB_FN (library, png_get_IHDR);
5121 LOAD_IMGLIB_FN (library, png_get_valid);
5122 LOAD_IMGLIB_FN (library, png_set_strip_16);
5123 LOAD_IMGLIB_FN (library, png_set_expand);
5124 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5125 LOAD_IMGLIB_FN (library, png_set_background);
5126 LOAD_IMGLIB_FN (library, png_get_bKGD);
5127 LOAD_IMGLIB_FN (library, png_read_update_info);
5128 LOAD_IMGLIB_FN (library, png_get_channels);
5129 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5130 LOAD_IMGLIB_FN (library, png_read_image);
5131 LOAD_IMGLIB_FN (library, png_read_end);
5132 LOAD_IMGLIB_FN (library, png_error);
5133 return 1;
5135 #else
5137 #define fn_png_get_io_ptr png_get_io_ptr
5138 #define fn_png_check_sig png_check_sig
5139 #define fn_png_create_read_struct png_create_read_struct
5140 #define fn_png_create_info_struct png_create_info_struct
5141 #define fn_png_destroy_read_struct png_destroy_read_struct
5142 #define fn_png_set_read_fn png_set_read_fn
5143 #define fn_png_init_io png_init_io
5144 #define fn_png_set_sig_bytes png_set_sig_bytes
5145 #define fn_png_read_info png_read_info
5146 #define fn_png_get_IHDR png_get_IHDR
5147 #define fn_png_get_valid png_get_valid
5148 #define fn_png_set_strip_16 png_set_strip_16
5149 #define fn_png_set_expand png_set_expand
5150 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5151 #define fn_png_set_background png_set_background
5152 #define fn_png_get_bKGD png_get_bKGD
5153 #define fn_png_read_update_info png_read_update_info
5154 #define fn_png_get_channels png_get_channels
5155 #define fn_png_get_rowbytes png_get_rowbytes
5156 #define fn_png_read_image png_read_image
5157 #define fn_png_read_end png_read_end
5158 #define fn_png_error png_error
5160 #endif /* HAVE_NTGUI */
5162 /* Error and warning handlers installed when the PNG library
5163 is initialized. */
5165 static void
5166 my_png_error (png_ptr, msg)
5167 png_struct *png_ptr;
5168 char *msg;
5170 xassert (png_ptr != NULL);
5171 image_error ("PNG error: %s", build_string (msg), Qnil);
5172 longjmp (png_ptr->jmpbuf, 1);
5176 static void
5177 my_png_warning (png_ptr, msg)
5178 png_struct *png_ptr;
5179 char *msg;
5181 xassert (png_ptr != NULL);
5182 image_error ("PNG warning: %s", build_string (msg), Qnil);
5185 /* Memory source for PNG decoding. */
5187 struct png_memory_storage
5189 unsigned char *bytes; /* The data */
5190 size_t len; /* How big is it? */
5191 int index; /* Where are we? */
5195 /* Function set as reader function when reading PNG image from memory.
5196 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5197 bytes from the input to DATA. */
5199 static void
5200 png_read_from_memory (png_ptr, data, length)
5201 png_structp png_ptr;
5202 png_bytep data;
5203 png_size_t length;
5205 struct png_memory_storage *tbr
5206 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5208 if (length > tbr->len - tbr->index)
5209 fn_png_error (png_ptr, "Read error");
5211 bcopy (tbr->bytes + tbr->index, data, length);
5212 tbr->index = tbr->index + length;
5215 /* Load PNG image IMG for use on frame F. Value is non-zero if
5216 successful. */
5218 static int
5219 png_load (f, img)
5220 struct frame *f;
5221 struct image *img;
5223 Lisp_Object file, specified_file;
5224 Lisp_Object specified_data;
5225 int x, y, i;
5226 XImagePtr ximg, mask_img = NULL;
5227 struct gcpro gcpro1;
5228 png_struct *png_ptr = NULL;
5229 png_info *info_ptr = NULL, *end_info = NULL;
5230 FILE *volatile fp = NULL;
5231 png_byte sig[8];
5232 png_byte * volatile pixels = NULL;
5233 png_byte ** volatile rows = NULL;
5234 png_uint_32 width, height;
5235 int bit_depth, color_type, interlace_type;
5236 png_byte channels;
5237 png_uint_32 row_bytes;
5238 int transparent_p;
5239 double screen_gamma;
5240 struct png_memory_storage tbr; /* Data to be read */
5242 /* Find out what file to load. */
5243 specified_file = image_spec_value (img->spec, QCfile, NULL);
5244 specified_data = image_spec_value (img->spec, QCdata, NULL);
5245 file = Qnil;
5246 GCPRO1 (file);
5248 if (NILP (specified_data))
5250 file = x_find_image_file (specified_file);
5251 if (!STRINGP (file))
5253 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5254 UNGCPRO;
5255 return 0;
5258 /* Open the image file. */
5259 fp = fopen (SDATA (file), "rb");
5260 if (!fp)
5262 image_error ("Cannot open image file `%s'", file, Qnil);
5263 UNGCPRO;
5264 fclose (fp);
5265 return 0;
5268 /* Check PNG signature. */
5269 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
5270 || !fn_png_check_sig (sig, sizeof sig))
5272 image_error ("Not a PNG file: `%s'", file, Qnil);
5273 UNGCPRO;
5274 fclose (fp);
5275 return 0;
5278 else
5280 /* Read from memory. */
5281 tbr.bytes = SDATA (specified_data);
5282 tbr.len = SBYTES (specified_data);
5283 tbr.index = 0;
5285 /* Check PNG signature. */
5286 if (tbr.len < sizeof sig
5287 || !fn_png_check_sig (tbr.bytes, sizeof sig))
5289 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
5290 UNGCPRO;
5291 return 0;
5294 /* Need to skip past the signature. */
5295 tbr.bytes += sizeof (sig);
5298 /* Initialize read and info structs for PNG lib. */
5299 png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
5300 my_png_error, my_png_warning);
5301 if (!png_ptr)
5303 if (fp) fclose (fp);
5304 UNGCPRO;
5305 return 0;
5308 info_ptr = fn_png_create_info_struct (png_ptr);
5309 if (!info_ptr)
5311 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
5312 if (fp) fclose (fp);
5313 UNGCPRO;
5314 return 0;
5317 end_info = fn_png_create_info_struct (png_ptr);
5318 if (!end_info)
5320 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
5321 if (fp) fclose (fp);
5322 UNGCPRO;
5323 return 0;
5326 /* Set error jump-back. We come back here when the PNG library
5327 detects an error. */
5328 if (setjmp (png_ptr->jmpbuf))
5330 error:
5331 if (png_ptr)
5332 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5333 xfree (pixels);
5334 xfree (rows);
5335 if (fp) fclose (fp);
5336 UNGCPRO;
5337 return 0;
5340 /* Read image info. */
5341 if (!NILP (specified_data))
5342 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
5343 else
5344 fn_png_init_io (png_ptr, fp);
5346 fn_png_set_sig_bytes (png_ptr, sizeof sig);
5347 fn_png_read_info (png_ptr, info_ptr);
5348 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
5349 &interlace_type, NULL, NULL);
5351 /* If image contains simply transparency data, we prefer to
5352 construct a clipping mask. */
5353 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
5354 transparent_p = 1;
5355 else
5356 transparent_p = 0;
5358 /* This function is easier to write if we only have to handle
5359 one data format: RGB or RGBA with 8 bits per channel. Let's
5360 transform other formats into that format. */
5362 /* Strip more than 8 bits per channel. */
5363 if (bit_depth == 16)
5364 fn_png_set_strip_16 (png_ptr);
5366 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
5367 if available. */
5368 fn_png_set_expand (png_ptr);
5370 /* Convert grayscale images to RGB. */
5371 if (color_type == PNG_COLOR_TYPE_GRAY
5372 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5373 fn_png_set_gray_to_rgb (png_ptr);
5375 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
5377 #if 0 /* Avoid double gamma correction for PNG images. */
5378 { /* Tell the PNG lib to handle gamma correction for us. */
5379 int intent;
5380 double image_gamma;
5381 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
5382 if (png_get_sRGB (png_ptr, info_ptr, &intent))
5383 /* The libpng documentation says this is right in this case. */
5384 png_set_gamma (png_ptr, screen_gamma, 0.45455);
5385 else
5386 #endif
5387 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
5388 /* Image contains gamma information. */
5389 png_set_gamma (png_ptr, screen_gamma, image_gamma);
5390 else
5391 /* Use the standard default for the image gamma. */
5392 png_set_gamma (png_ptr, screen_gamma, 0.45455);
5394 #endif /* if 0 */
5396 /* Handle alpha channel by combining the image with a background
5397 color. Do this only if a real alpha channel is supplied. For
5398 simple transparency, we prefer a clipping mask. */
5399 if (!transparent_p)
5401 png_color_16 *image_bg;
5402 Lisp_Object specified_bg
5403 = image_spec_value (img->spec, QCbackground, NULL);
5405 if (STRINGP (specified_bg))
5406 /* The user specified `:background', use that. */
5408 /* W32 version incorrectly used COLORREF here!! ++kfs */
5409 XColor color;
5410 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
5412 png_color_16 user_bg;
5414 bzero (&user_bg, sizeof user_bg);
5415 user_bg.red = color.red >> PNG_BG_COLOR_SHIFT;
5416 user_bg.green = color.green >> PNG_BG_COLOR_SHIFT;
5417 user_bg.blue = color.blue >> PNG_BG_COLOR_SHIFT;
5419 fn_png_set_background (png_ptr, &user_bg,
5420 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5423 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
5424 /* Image contains a background color with which to
5425 combine the image. */
5426 fn_png_set_background (png_ptr, image_bg,
5427 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
5428 else
5430 /* Image does not contain a background color with which
5431 to combine the image data via an alpha channel. Use
5432 the frame's background instead. */
5433 #ifdef HAVE_X_WINDOWS
5434 XColor color;
5435 png_color_16 frame_background;
5437 color.pixel = FRAME_BACKGROUND_PIXEL (f);
5438 x_query_color (f, &color);
5440 bzero (&frame_background, sizeof frame_background);
5441 frame_background.red = color.red;
5442 frame_background.green = color.green;
5443 frame_background.blue = color.blue;
5444 #endif /* HAVE_X_WINDOWS */
5446 #ifdef HAVE_NTGUI
5447 COLORREF color;
5448 png_color_16 frame_background;
5449 color = FRAME_BACKGROUND_PIXEL (f);
5450 #if 0 /* W32 TODO : Colormap support. */
5451 x_query_color (f, &color);
5452 #endif
5453 bzero (&frame_background, sizeof frame_background);
5454 frame_background.red = 256 * GetRValue (color);
5455 frame_background.green = 256 * GetGValue (color);
5456 frame_background.blue = 256 * GetBValue (color);
5457 #endif /* HAVE_NTGUI */
5459 #ifdef MAC_OS
5460 unsigned long color;
5461 png_color_16 frame_background;
5462 color = FRAME_BACKGROUND_PIXEL (f);
5463 #if 0 /* MAC/W32 TODO : Colormap support. */
5464 x_query_color (f, &color);
5465 #endif
5466 bzero (&frame_background, sizeof frame_background);
5467 frame_background.red = RED_FROM_ULONG (color);
5468 frame_background.green = GREEN_FROM_ULONG (color);
5469 frame_background.blue = BLUE_FROM_ULONG (color);
5470 #endif /* MAC_OS */
5472 fn_png_set_background (png_ptr, &frame_background,
5473 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
5477 /* Update info structure. */
5478 fn_png_read_update_info (png_ptr, info_ptr);
5480 /* Get number of channels. Valid values are 1 for grayscale images
5481 and images with a palette, 2 for grayscale images with transparency
5482 information (alpha channel), 3 for RGB images, and 4 for RGB
5483 images with alpha channel, i.e. RGBA. If conversions above were
5484 sufficient we should only have 3 or 4 channels here. */
5485 channels = fn_png_get_channels (png_ptr, info_ptr);
5486 xassert (channels == 3 || channels == 4);
5488 /* Number of bytes needed for one row of the image. */
5489 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
5491 /* Allocate memory for the image. */
5492 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
5493 rows = (png_byte **) xmalloc (height * sizeof *rows);
5494 for (i = 0; i < height; ++i)
5495 rows[i] = pixels + i * row_bytes;
5497 /* Read the entire image. */
5498 fn_png_read_image (png_ptr, rows);
5499 fn_png_read_end (png_ptr, info_ptr);
5500 if (fp)
5502 fclose (fp);
5503 fp = NULL;
5506 /* Create the X image and pixmap. */
5507 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
5508 &img->pixmap))
5509 goto error;
5511 /* Create an image and pixmap serving as mask if the PNG image
5512 contains an alpha channel. */
5513 if (channels == 4
5514 && !transparent_p
5515 && !x_create_x_image_and_pixmap (f, width, height, 1,
5516 &mask_img, &img->mask))
5518 x_destroy_x_image (ximg);
5519 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
5520 img->pixmap = NO_PIXMAP;
5521 goto error;
5524 /* Fill the X image and mask from PNG data. */
5525 init_color_table ();
5527 for (y = 0; y < height; ++y)
5529 png_byte *p = rows[y];
5531 for (x = 0; x < width; ++x)
5533 unsigned r, g, b;
5535 r = *p++ << 8;
5536 g = *p++ << 8;
5537 b = *p++ << 8;
5538 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5539 /* An alpha channel, aka mask channel, associates variable
5540 transparency with an image. Where other image formats
5541 support binary transparency---fully transparent or fully
5542 opaque---PNG allows up to 254 levels of partial transparency.
5543 The PNG library implements partial transparency by combining
5544 the image with a specified background color.
5546 I'm not sure how to handle this here nicely: because the
5547 background on which the image is displayed may change, for
5548 real alpha channel support, it would be necessary to create
5549 a new image for each possible background.
5551 What I'm doing now is that a mask is created if we have
5552 boolean transparency information. Otherwise I'm using
5553 the frame's background color to combine the image with. */
5555 if (channels == 4)
5557 if (mask_img)
5558 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW (f) : PIX_MASK_RETAIN (f));
5559 ++p;
5564 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5565 /* Set IMG's background color from the PNG image, unless the user
5566 overrode it. */
5568 png_color_16 *bg;
5569 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
5571 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
5572 img->background_valid = 1;
5576 #ifdef COLOR_TABLE_SUPPORT
5577 /* Remember colors allocated for this image. */
5578 img->colors = colors_in_color_table (&img->ncolors);
5579 free_color_table ();
5580 #endif /* COLOR_TABLE_SUPPORT */
5582 /* Clean up. */
5583 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
5584 xfree (rows);
5585 xfree (pixels);
5587 img->width = width;
5588 img->height = height;
5590 /* Maybe fill in the background field while we have ximg handy. */
5591 IMAGE_BACKGROUND (img, f, ximg);
5593 /* Put the image into the pixmap, then free the X image and its buffer. */
5594 x_put_x_image (f, ximg, img->pixmap, width, height);
5595 x_destroy_x_image (ximg);
5597 /* Same for the mask. */
5598 if (mask_img)
5600 /* Fill in the background_transparent field while we have the mask
5601 handy. */
5602 image_background_transparent (img, f, mask_img);
5604 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5605 x_destroy_x_image (mask_img);
5608 UNGCPRO;
5609 return 1;
5612 #else /* HAVE_PNG */
5614 #ifdef MAC_OS
5615 static int
5616 png_load (f, img)
5617 struct frame *f;
5618 struct image *img;
5620 #ifdef MAC_OSX
5621 if (MyCGImageCreateWithPNGDataProvider)
5622 return image_load_quartz2d (f, img, 1);
5623 else
5624 #endif
5625 return image_load_quicktime (f, img, kQTFileTypePNG);
5627 #endif /* MAC_OS */
5629 #endif /* !HAVE_PNG */
5633 /***********************************************************************
5634 JPEG
5635 ***********************************************************************/
5637 #if defined (HAVE_JPEG) || defined (MAC_OS)
5639 static int jpeg_image_p P_ ((Lisp_Object object));
5640 static int jpeg_load P_ ((struct frame *f, struct image *img));
5642 /* The symbol `jpeg' identifying images of this type. */
5644 Lisp_Object Qjpeg;
5646 /* Indices of image specification fields in gs_format, below. */
5648 enum jpeg_keyword_index
5650 JPEG_TYPE,
5651 JPEG_DATA,
5652 JPEG_FILE,
5653 JPEG_ASCENT,
5654 JPEG_MARGIN,
5655 JPEG_RELIEF,
5656 JPEG_ALGORITHM,
5657 JPEG_HEURISTIC_MASK,
5658 JPEG_MASK,
5659 JPEG_BACKGROUND,
5660 JPEG_LAST
5663 /* Vector of image_keyword structures describing the format
5664 of valid user-defined image specifications. */
5666 static struct image_keyword jpeg_format[JPEG_LAST] =
5668 {":type", IMAGE_SYMBOL_VALUE, 1},
5669 {":data", IMAGE_STRING_VALUE, 0},
5670 {":file", IMAGE_STRING_VALUE, 0},
5671 {":ascent", IMAGE_ASCENT_VALUE, 0},
5672 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5673 {":relief", IMAGE_INTEGER_VALUE, 0},
5674 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5675 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5676 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5677 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5680 /* Structure describing the image type `jpeg'. */
5682 static struct image_type jpeg_type =
5684 &Qjpeg,
5685 jpeg_image_p,
5686 jpeg_load,
5687 x_clear_image,
5688 NULL
5691 /* Return non-zero if OBJECT is a valid JPEG image specification. */
5693 static int
5694 jpeg_image_p (object)
5695 Lisp_Object object;
5697 struct image_keyword fmt[JPEG_LAST];
5699 bcopy (jpeg_format, fmt, sizeof fmt);
5701 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
5702 return 0;
5704 /* Must specify either the :data or :file keyword. */
5705 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
5708 #endif /* HAVE_JPEG || MAC_OS */
5710 #ifdef HAVE_JPEG
5712 /* Work around a warning about HAVE_STDLIB_H being redefined in
5713 jconfig.h. */
5714 #ifdef HAVE_STDLIB_H
5715 #define HAVE_STDLIB_H_1
5716 #undef HAVE_STDLIB_H
5717 #endif /* HAVE_STLIB_H */
5719 #include <jpeglib.h>
5720 #include <jerror.h>
5721 #include <setjmp.h>
5723 #ifdef HAVE_STLIB_H_1
5724 #define HAVE_STDLIB_H 1
5725 #endif
5727 #ifdef HAVE_NTGUI
5729 /* JPEG library details. */
5730 DEF_IMGLIB_FN (jpeg_CreateDecompress);
5731 DEF_IMGLIB_FN (jpeg_start_decompress);
5732 DEF_IMGLIB_FN (jpeg_finish_decompress);
5733 DEF_IMGLIB_FN (jpeg_destroy_decompress);
5734 DEF_IMGLIB_FN (jpeg_read_header);
5735 DEF_IMGLIB_FN (jpeg_read_scanlines);
5736 DEF_IMGLIB_FN (jpeg_stdio_src);
5737 DEF_IMGLIB_FN (jpeg_std_error);
5738 DEF_IMGLIB_FN (jpeg_resync_to_restart);
5740 static int
5741 init_jpeg_functions (void)
5743 HMODULE library;
5745 if (!(library = LoadLibrary ("libjpeg.dll"))
5746 && !(library = LoadLibrary ("jpeg-62.dll"))
5747 && !(library = LoadLibrary ("jpeg.dll")))
5748 return 0;
5750 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
5751 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
5752 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
5753 LOAD_IMGLIB_FN (library, jpeg_read_header);
5754 LOAD_IMGLIB_FN (library, jpeg_stdio_src);
5755 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
5756 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
5757 LOAD_IMGLIB_FN (library, jpeg_std_error);
5758 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
5759 return 1;
5762 /* Wrapper since we can't directly assign the function pointer
5763 to another function pointer that was declared more completely easily. */
5764 static boolean
5765 jpeg_resync_to_restart_wrapper(cinfo, desired)
5766 j_decompress_ptr cinfo;
5767 int desired;
5769 return fn_jpeg_resync_to_restart (cinfo, desired);
5772 #else
5774 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
5775 #define fn_jpeg_start_decompress jpeg_start_decompress
5776 #define fn_jpeg_finish_decompress jpeg_finish_decompress
5777 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
5778 #define fn_jpeg_read_header jpeg_read_header
5779 #define fn_jpeg_read_scanlines jpeg_read_scanlines
5780 #define fn_jpeg_stdio_src jpeg_stdio_src
5781 #define fn_jpeg_std_error jpeg_std_error
5782 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
5784 #endif /* HAVE_NTGUI */
5786 struct my_jpeg_error_mgr
5788 struct jpeg_error_mgr pub;
5789 jmp_buf setjmp_buffer;
5793 static void
5794 my_error_exit (cinfo)
5795 j_common_ptr cinfo;
5797 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
5798 longjmp (mgr->setjmp_buffer, 1);
5802 /* Init source method for JPEG data source manager. Called by
5803 jpeg_read_header() before any data is actually read. See
5804 libjpeg.doc from the JPEG lib distribution. */
5806 static void
5807 our_init_source (cinfo)
5808 j_decompress_ptr cinfo;
5813 /* Fill input buffer method for JPEG data source manager. Called
5814 whenever more data is needed. We read the whole image in one step,
5815 so this only adds a fake end of input marker at the end. */
5817 static boolean
5818 our_fill_input_buffer (cinfo)
5819 j_decompress_ptr cinfo;
5821 /* Insert a fake EOI marker. */
5822 struct jpeg_source_mgr *src = cinfo->src;
5823 static JOCTET buffer[2];
5825 buffer[0] = (JOCTET) 0xFF;
5826 buffer[1] = (JOCTET) JPEG_EOI;
5828 src->next_input_byte = buffer;
5829 src->bytes_in_buffer = 2;
5830 return TRUE;
5834 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
5835 is the JPEG data source manager. */
5837 static void
5838 our_skip_input_data (cinfo, num_bytes)
5839 j_decompress_ptr cinfo;
5840 long num_bytes;
5842 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
5844 if (src)
5846 if (num_bytes > src->bytes_in_buffer)
5847 ERREXIT (cinfo, JERR_INPUT_EOF);
5849 src->bytes_in_buffer -= num_bytes;
5850 src->next_input_byte += num_bytes;
5855 /* Method to terminate data source. Called by
5856 jpeg_finish_decompress() after all data has been processed. */
5858 static void
5859 our_term_source (cinfo)
5860 j_decompress_ptr cinfo;
5865 /* Set up the JPEG lib for reading an image from DATA which contains
5866 LEN bytes. CINFO is the decompression info structure created for
5867 reading the image. */
5869 static void
5870 jpeg_memory_src (cinfo, data, len)
5871 j_decompress_ptr cinfo;
5872 JOCTET *data;
5873 unsigned int len;
5875 struct jpeg_source_mgr *src;
5877 if (cinfo->src == NULL)
5879 /* First time for this JPEG object? */
5880 cinfo->src = (struct jpeg_source_mgr *)
5881 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
5882 sizeof (struct jpeg_source_mgr));
5883 src = (struct jpeg_source_mgr *) cinfo->src;
5884 src->next_input_byte = data;
5887 src = (struct jpeg_source_mgr *) cinfo->src;
5888 src->init_source = our_init_source;
5889 src->fill_input_buffer = our_fill_input_buffer;
5890 src->skip_input_data = our_skip_input_data;
5891 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
5892 src->term_source = our_term_source;
5893 src->bytes_in_buffer = len;
5894 src->next_input_byte = data;
5898 /* Load image IMG for use on frame F. Patterned after example.c
5899 from the JPEG lib. */
5901 static int
5902 jpeg_load (f, img)
5903 struct frame *f;
5904 struct image *img;
5906 struct jpeg_decompress_struct cinfo;
5907 struct my_jpeg_error_mgr mgr;
5908 Lisp_Object file, specified_file;
5909 Lisp_Object specified_data;
5910 FILE * volatile fp = NULL;
5911 JSAMPARRAY buffer;
5912 int row_stride, x, y;
5913 XImagePtr ximg = NULL;
5914 int rc;
5915 unsigned long *colors;
5916 int width, height;
5917 struct gcpro gcpro1;
5919 /* Open the JPEG file. */
5920 specified_file = image_spec_value (img->spec, QCfile, NULL);
5921 specified_data = image_spec_value (img->spec, QCdata, NULL);
5922 file = Qnil;
5923 GCPRO1 (file);
5925 if (NILP (specified_data))
5927 file = x_find_image_file (specified_file);
5928 if (!STRINGP (file))
5930 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5931 UNGCPRO;
5932 return 0;
5935 fp = fopen (SDATA (file), "rb");
5936 if (fp == NULL)
5938 image_error ("Cannot open `%s'", file, Qnil);
5939 UNGCPRO;
5940 return 0;
5944 /* Customize libjpeg's error handling to call my_error_exit when an
5945 error is detected. This function will perform a longjmp. */
5946 cinfo.err = fn_jpeg_std_error (&mgr.pub);
5947 mgr.pub.error_exit = my_error_exit;
5949 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
5951 if (rc == 1)
5953 /* Called from my_error_exit. Display a JPEG error. */
5954 char buffer[JMSG_LENGTH_MAX];
5955 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
5956 image_error ("Error reading JPEG image `%s': %s", img->spec,
5957 build_string (buffer));
5960 /* Close the input file and destroy the JPEG object. */
5961 if (fp)
5962 fclose ((FILE *) fp);
5963 fn_jpeg_destroy_decompress (&cinfo);
5965 /* If we already have an XImage, free that. */
5966 x_destroy_x_image (ximg);
5968 /* Free pixmap and colors. */
5969 x_clear_image (f, img);
5971 UNGCPRO;
5972 return 0;
5975 /* Create the JPEG decompression object. Let it read from fp.
5976 Read the JPEG image header. */
5977 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
5979 if (NILP (specified_data))
5980 fn_jpeg_stdio_src (&cinfo, (FILE *) fp);
5981 else
5982 jpeg_memory_src (&cinfo, SDATA (specified_data),
5983 SBYTES (specified_data));
5985 fn_jpeg_read_header (&cinfo, TRUE);
5987 /* Customize decompression so that color quantization will be used.
5988 Start decompression. */
5989 cinfo.quantize_colors = TRUE;
5990 fn_jpeg_start_decompress (&cinfo);
5991 width = img->width = cinfo.output_width;
5992 height = img->height = cinfo.output_height;
5994 /* Create X image and pixmap. */
5995 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
5996 longjmp (mgr.setjmp_buffer, 2);
5998 /* Allocate colors. When color quantization is used,
5999 cinfo.actual_number_of_colors has been set with the number of
6000 colors generated, and cinfo.colormap is a two-dimensional array
6001 of color indices in the range 0..cinfo.actual_number_of_colors.
6002 No more than 255 colors will be generated. */
6004 int i, ir, ig, ib;
6006 if (cinfo.out_color_components > 2)
6007 ir = 0, ig = 1, ib = 2;
6008 else if (cinfo.out_color_components > 1)
6009 ir = 0, ig = 1, ib = 0;
6010 else
6011 ir = 0, ig = 0, ib = 0;
6013 /* Use the color table mechanism because it handles colors that
6014 cannot be allocated nicely. Such colors will be replaced with
6015 a default color, and we don't have to care about which colors
6016 can be freed safely, and which can't. */
6017 init_color_table ();
6018 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6019 * sizeof *colors);
6021 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6023 /* Multiply RGB values with 255 because X expects RGB values
6024 in the range 0..0xffff. */
6025 int r = cinfo.colormap[ir][i] << 8;
6026 int g = cinfo.colormap[ig][i] << 8;
6027 int b = cinfo.colormap[ib][i] << 8;
6028 colors[i] = lookup_rgb_color (f, r, g, b);
6031 #ifdef COLOR_TABLE_SUPPORT
6032 /* Remember those colors actually allocated. */
6033 img->colors = colors_in_color_table (&img->ncolors);
6034 free_color_table ();
6035 #endif /* COLOR_TABLE_SUPPORT */
6038 /* Read pixels. */
6039 row_stride = width * cinfo.output_components;
6040 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6041 row_stride, 1);
6042 for (y = 0; y < height; ++y)
6044 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6045 for (x = 0; x < cinfo.output_width; ++x)
6046 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6049 /* Clean up. */
6050 fn_jpeg_finish_decompress (&cinfo);
6051 fn_jpeg_destroy_decompress (&cinfo);
6052 if (fp)
6053 fclose ((FILE *) fp);
6055 /* Maybe fill in the background field while we have ximg handy. */
6056 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6057 IMAGE_BACKGROUND (img, f, ximg);
6059 /* Put the image into the pixmap. */
6060 x_put_x_image (f, ximg, img->pixmap, width, height);
6061 x_destroy_x_image (ximg);
6062 UNGCPRO;
6063 return 1;
6066 #else /* HAVE_JPEG */
6068 #ifdef MAC_OS
6069 static int
6070 jpeg_load (f, img)
6071 struct frame *f;
6072 struct image *img;
6074 #ifdef MAC_OSX
6075 return image_load_quartz2d (f, img, 0);
6076 #else
6077 return image_load_quicktime (f, img, kQTFileTypeJPEG);
6078 #endif
6080 #endif /* MAC_OS */
6082 #endif /* !HAVE_JPEG */
6086 /***********************************************************************
6087 TIFF
6088 ***********************************************************************/
6090 #if defined (HAVE_TIFF) || defined (MAC_OS)
6092 static int tiff_image_p P_ ((Lisp_Object object));
6093 static int tiff_load P_ ((struct frame *f, struct image *img));
6095 /* The symbol `tiff' identifying images of this type. */
6097 Lisp_Object Qtiff;
6099 /* Indices of image specification fields in tiff_format, below. */
6101 enum tiff_keyword_index
6103 TIFF_TYPE,
6104 TIFF_DATA,
6105 TIFF_FILE,
6106 TIFF_ASCENT,
6107 TIFF_MARGIN,
6108 TIFF_RELIEF,
6109 TIFF_ALGORITHM,
6110 TIFF_HEURISTIC_MASK,
6111 TIFF_MASK,
6112 TIFF_BACKGROUND,
6113 TIFF_LAST
6116 /* Vector of image_keyword structures describing the format
6117 of valid user-defined image specifications. */
6119 static struct image_keyword tiff_format[TIFF_LAST] =
6121 {":type", IMAGE_SYMBOL_VALUE, 1},
6122 {":data", IMAGE_STRING_VALUE, 0},
6123 {":file", IMAGE_STRING_VALUE, 0},
6124 {":ascent", IMAGE_ASCENT_VALUE, 0},
6125 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6126 {":relief", IMAGE_INTEGER_VALUE, 0},
6127 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6128 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6129 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6130 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6133 /* Structure describing the image type `tiff'. */
6135 static struct image_type tiff_type =
6137 &Qtiff,
6138 tiff_image_p,
6139 tiff_load,
6140 x_clear_image,
6141 NULL
6144 /* Return non-zero if OBJECT is a valid TIFF image specification. */
6146 static int
6147 tiff_image_p (object)
6148 Lisp_Object object;
6150 struct image_keyword fmt[TIFF_LAST];
6151 bcopy (tiff_format, fmt, sizeof fmt);
6153 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
6154 return 0;
6156 /* Must specify either the :data or :file keyword. */
6157 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
6160 #endif /* HAVE_TIFF || MAC_OS */
6162 #ifdef HAVE_TIFF
6164 #include <tiffio.h>
6166 #ifdef HAVE_NTGUI
6168 /* TIFF library details. */
6169 DEF_IMGLIB_FN (TIFFSetErrorHandler);
6170 DEF_IMGLIB_FN (TIFFSetWarningHandler);
6171 DEF_IMGLIB_FN (TIFFOpen);
6172 DEF_IMGLIB_FN (TIFFClientOpen);
6173 DEF_IMGLIB_FN (TIFFGetField);
6174 DEF_IMGLIB_FN (TIFFReadRGBAImage);
6175 DEF_IMGLIB_FN (TIFFClose);
6177 static int
6178 init_tiff_functions (void)
6180 HMODULE library;
6182 if (!(library = LoadLibrary ("libtiff.dll")))
6183 return 0;
6185 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
6186 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
6187 LOAD_IMGLIB_FN (library, TIFFOpen);
6188 LOAD_IMGLIB_FN (library, TIFFClientOpen);
6189 LOAD_IMGLIB_FN (library, TIFFGetField);
6190 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
6191 LOAD_IMGLIB_FN (library, TIFFClose);
6192 return 1;
6195 #else
6197 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
6198 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
6199 #define fn_TIFFOpen TIFFOpen
6200 #define fn_TIFFClientOpen TIFFClientOpen
6201 #define fn_TIFFGetField TIFFGetField
6202 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
6203 #define fn_TIFFClose TIFFClose
6205 #endif /* HAVE_NTGUI */
6208 /* Reading from a memory buffer for TIFF images Based on the PNG
6209 memory source, but we have to provide a lot of extra functions.
6210 Blah.
6212 We really only need to implement read and seek, but I am not
6213 convinced that the TIFF library is smart enough not to destroy
6214 itself if we only hand it the function pointers we need to
6215 override. */
6217 typedef struct
6219 unsigned char *bytes;
6220 size_t len;
6221 int index;
6223 tiff_memory_source;
6225 static size_t
6226 tiff_read_from_memory (data, buf, size)
6227 thandle_t data;
6228 tdata_t buf;
6229 tsize_t size;
6231 tiff_memory_source *src = (tiff_memory_source *) data;
6233 if (size > src->len - src->index)
6234 return (size_t) -1;
6235 bcopy (src->bytes + src->index, buf, size);
6236 src->index += size;
6237 return size;
6240 static size_t
6241 tiff_write_from_memory (data, buf, size)
6242 thandle_t data;
6243 tdata_t buf;
6244 tsize_t size;
6246 return (size_t) -1;
6249 static toff_t
6250 tiff_seek_in_memory (data, off, whence)
6251 thandle_t data;
6252 toff_t off;
6253 int whence;
6255 tiff_memory_source *src = (tiff_memory_source *) data;
6256 int idx;
6258 switch (whence)
6260 case SEEK_SET: /* Go from beginning of source. */
6261 idx = off;
6262 break;
6264 case SEEK_END: /* Go from end of source. */
6265 idx = src->len + off;
6266 break;
6268 case SEEK_CUR: /* Go from current position. */
6269 idx = src->index + off;
6270 break;
6272 default: /* Invalid `whence'. */
6273 return -1;
6276 if (idx > src->len || idx < 0)
6277 return -1;
6279 src->index = idx;
6280 return src->index;
6283 static int
6284 tiff_close_memory (data)
6285 thandle_t data;
6287 /* NOOP */
6288 return 0;
6291 static int
6292 tiff_mmap_memory (data, pbase, psize)
6293 thandle_t data;
6294 tdata_t *pbase;
6295 toff_t *psize;
6297 /* It is already _IN_ memory. */
6298 return 0;
6301 static void
6302 tiff_unmap_memory (data, base, size)
6303 thandle_t data;
6304 tdata_t base;
6305 toff_t size;
6307 /* We don't need to do this. */
6310 static toff_t
6311 tiff_size_of_memory (data)
6312 thandle_t data;
6314 return ((tiff_memory_source *) data)->len;
6318 static void
6319 tiff_error_handler (title, format, ap)
6320 const char *title, *format;
6321 va_list ap;
6323 char buf[512];
6324 int len;
6326 len = sprintf (buf, "TIFF error: %s ", title);
6327 vsprintf (buf + len, format, ap);
6328 add_to_log (buf, Qnil, Qnil);
6332 static void
6333 tiff_warning_handler (title, format, ap)
6334 const char *title, *format;
6335 va_list ap;
6337 char buf[512];
6338 int len;
6340 len = sprintf (buf, "TIFF warning: %s ", title);
6341 vsprintf (buf + len, format, ap);
6342 add_to_log (buf, Qnil, Qnil);
6346 /* Load TIFF image IMG for use on frame F. Value is non-zero if
6347 successful. */
6349 static int
6350 tiff_load (f, img)
6351 struct frame *f;
6352 struct image *img;
6354 Lisp_Object file, specified_file;
6355 Lisp_Object specified_data;
6356 TIFF *tiff;
6357 int width, height, x, y;
6358 uint32 *buf;
6359 int rc;
6360 XImagePtr ximg;
6361 struct gcpro gcpro1;
6362 tiff_memory_source memsrc;
6364 specified_file = image_spec_value (img->spec, QCfile, NULL);
6365 specified_data = image_spec_value (img->spec, QCdata, NULL);
6366 file = Qnil;
6367 GCPRO1 (file);
6369 fn_TIFFSetErrorHandler (tiff_error_handler);
6370 fn_TIFFSetWarningHandler (tiff_warning_handler);
6372 if (NILP (specified_data))
6374 /* Read from a file */
6375 file = x_find_image_file (specified_file);
6376 if (!STRINGP (file))
6378 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6379 UNGCPRO;
6380 return 0;
6383 /* Try to open the image file. */
6384 tiff = fn_TIFFOpen (SDATA (file), "r");
6385 if (tiff == NULL)
6387 image_error ("Cannot open `%s'", file, Qnil);
6388 UNGCPRO;
6389 return 0;
6392 else
6394 /* Memory source! */
6395 memsrc.bytes = SDATA (specified_data);
6396 memsrc.len = SBYTES (specified_data);
6397 memsrc.index = 0;
6399 tiff = fn_TIFFClientOpen ("memory_source", "r", &memsrc,
6400 (TIFFReadWriteProc) tiff_read_from_memory,
6401 (TIFFReadWriteProc) tiff_write_from_memory,
6402 tiff_seek_in_memory,
6403 tiff_close_memory,
6404 tiff_size_of_memory,
6405 tiff_mmap_memory,
6406 tiff_unmap_memory);
6408 if (!tiff)
6410 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
6411 UNGCPRO;
6412 return 0;
6416 /* Get width and height of the image, and allocate a raster buffer
6417 of width x height 32-bit values. */
6418 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
6419 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
6420 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
6422 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
6423 fn_TIFFClose (tiff);
6424 if (!rc)
6426 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
6427 xfree (buf);
6428 UNGCPRO;
6429 return 0;
6432 /* Create the X image and pixmap. */
6433 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6435 xfree (buf);
6436 UNGCPRO;
6437 return 0;
6440 /* Initialize the color table. */
6441 init_color_table ();
6443 /* Process the pixel raster. Origin is in the lower-left corner. */
6444 for (y = 0; y < height; ++y)
6446 uint32 *row = buf + y * width;
6448 for (x = 0; x < width; ++x)
6450 uint32 abgr = row[x];
6451 int r = TIFFGetR (abgr) << 8;
6452 int g = TIFFGetG (abgr) << 8;
6453 int b = TIFFGetB (abgr) << 8;
6454 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
6458 #ifdef COLOR_TABLE_SUPPORT
6459 /* Remember the colors allocated for the image. Free the color table. */
6460 img->colors = colors_in_color_table (&img->ncolors);
6461 free_color_table ();
6462 #endif /* COLOR_TABLE_SUPPORT */
6464 img->width = width;
6465 img->height = height;
6467 /* Maybe fill in the background field while we have ximg handy. */
6468 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6469 IMAGE_BACKGROUND (img, f, ximg);
6471 /* Put the image into the pixmap, then free the X image and its buffer. */
6472 x_put_x_image (f, ximg, img->pixmap, width, height);
6473 x_destroy_x_image (ximg);
6474 xfree (buf);
6476 UNGCPRO;
6477 return 1;
6480 #else /* HAVE_TIFF */
6482 #ifdef MAC_OS
6483 static int
6484 tiff_load (f, img)
6485 struct frame *f;
6486 struct image *img;
6488 return image_load_quicktime (f, img, kQTFileTypeTIFF);
6490 #endif /* MAC_OS */
6492 #endif /* !HAVE_TIFF */
6496 /***********************************************************************
6498 ***********************************************************************/
6500 #if defined (HAVE_GIF) || defined (MAC_OS)
6502 static int gif_image_p P_ ((Lisp_Object object));
6503 static int gif_load P_ ((struct frame *f, struct image *img));
6505 /* The symbol `gif' identifying images of this type. */
6507 Lisp_Object Qgif;
6509 /* Indices of image specification fields in gif_format, below. */
6511 enum gif_keyword_index
6513 GIF_TYPE,
6514 GIF_DATA,
6515 GIF_FILE,
6516 GIF_ASCENT,
6517 GIF_MARGIN,
6518 GIF_RELIEF,
6519 GIF_ALGORITHM,
6520 GIF_HEURISTIC_MASK,
6521 GIF_MASK,
6522 GIF_IMAGE,
6523 GIF_BACKGROUND,
6524 GIF_LAST
6527 /* Vector of image_keyword structures describing the format
6528 of valid user-defined image specifications. */
6530 static struct image_keyword gif_format[GIF_LAST] =
6532 {":type", IMAGE_SYMBOL_VALUE, 1},
6533 {":data", IMAGE_STRING_VALUE, 0},
6534 {":file", IMAGE_STRING_VALUE, 0},
6535 {":ascent", IMAGE_ASCENT_VALUE, 0},
6536 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6537 {":relief", IMAGE_INTEGER_VALUE, 0},
6538 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6539 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6540 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6541 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
6542 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6545 /* Structure describing the image type `gif'. */
6547 static struct image_type gif_type =
6549 &Qgif,
6550 gif_image_p,
6551 gif_load,
6552 x_clear_image,
6553 NULL
6556 /* Return non-zero if OBJECT is a valid GIF image specification. */
6558 static int
6559 gif_image_p (object)
6560 Lisp_Object object;
6562 struct image_keyword fmt[GIF_LAST];
6563 bcopy (gif_format, fmt, sizeof fmt);
6565 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
6566 return 0;
6568 /* Must specify either the :data or :file keyword. */
6569 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
6572 #endif /* HAVE_GIF || MAC_OS */
6574 #ifdef HAVE_GIF
6576 #if defined (HAVE_NTGUI) || defined (MAC_OS)
6577 /* avoid conflict with QuickdrawText.h */
6578 #define DrawText gif_DrawText
6579 #include <gif_lib.h>
6580 #undef DrawText
6582 #else /* HAVE_NTGUI || MAC_OS */
6584 #include <gif_lib.h>
6586 #endif /* HAVE_NTGUI || MAC_OS */
6589 #ifdef HAVE_NTGUI
6591 /* GIF library details. */
6592 DEF_IMGLIB_FN (DGifCloseFile);
6593 DEF_IMGLIB_FN (DGifSlurp);
6594 DEF_IMGLIB_FN (DGifOpen);
6595 DEF_IMGLIB_FN (DGifOpenFileName);
6597 static int
6598 init_gif_functions (void)
6600 HMODULE library;
6602 if (!(library = LoadLibrary ("libungif.dll")))
6603 return 0;
6605 LOAD_IMGLIB_FN (library, DGifCloseFile);
6606 LOAD_IMGLIB_FN (library, DGifSlurp);
6607 LOAD_IMGLIB_FN (library, DGifOpen);
6608 LOAD_IMGLIB_FN (library, DGifOpenFileName);
6609 return 1;
6612 #else
6614 #define fn_DGifCloseFile DGifCloseFile
6615 #define fn_DGifSlurp DGifSlurp
6616 #define fn_DGifOpen DGifOpen
6617 #define fn_DGifOpenFileName DGifOpenFileName
6619 #endif /* HAVE_NTGUI */
6621 /* Reading a GIF image from memory
6622 Based on the PNG memory stuff to a certain extent. */
6624 typedef struct
6626 unsigned char *bytes;
6627 size_t len;
6628 int index;
6630 gif_memory_source;
6632 /* Make the current memory source available to gif_read_from_memory.
6633 It's done this way because not all versions of libungif support
6634 a UserData field in the GifFileType structure. */
6635 static gif_memory_source *current_gif_memory_src;
6637 static int
6638 gif_read_from_memory (file, buf, len)
6639 GifFileType *file;
6640 GifByteType *buf;
6641 int len;
6643 gif_memory_source *src = current_gif_memory_src;
6645 if (len > src->len - src->index)
6646 return -1;
6648 bcopy (src->bytes + src->index, buf, len);
6649 src->index += len;
6650 return len;
6654 /* Load GIF image IMG for use on frame F. Value is non-zero if
6655 successful. */
6657 static int
6658 gif_load (f, img)
6659 struct frame *f;
6660 struct image *img;
6662 Lisp_Object file, specified_file;
6663 Lisp_Object specified_data;
6664 int rc, width, height, x, y, i;
6665 XImagePtr ximg;
6666 ColorMapObject *gif_color_map;
6667 unsigned long pixel_colors[256];
6668 GifFileType *gif;
6669 struct gcpro gcpro1;
6670 Lisp_Object image;
6671 int ino, image_left, image_top, image_width, image_height;
6672 gif_memory_source memsrc;
6673 unsigned char *raster;
6675 specified_file = image_spec_value (img->spec, QCfile, NULL);
6676 specified_data = image_spec_value (img->spec, QCdata, NULL);
6677 file = Qnil;
6678 GCPRO1 (file);
6680 if (NILP (specified_data))
6682 file = x_find_image_file (specified_file);
6683 if (!STRINGP (file))
6685 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6686 UNGCPRO;
6687 return 0;
6690 /* Open the GIF file. */
6691 gif = fn_DGifOpenFileName (SDATA (file));
6692 if (gif == NULL)
6694 image_error ("Cannot open `%s'", file, Qnil);
6695 UNGCPRO;
6696 return 0;
6699 else
6701 /* Read from memory! */
6702 current_gif_memory_src = &memsrc;
6703 memsrc.bytes = SDATA (specified_data);
6704 memsrc.len = SBYTES (specified_data);
6705 memsrc.index = 0;
6707 gif = fn_DGifOpen(&memsrc, gif_read_from_memory);
6708 if (!gif)
6710 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
6711 UNGCPRO;
6712 return 0;
6716 /* Read entire contents. */
6717 rc = fn_DGifSlurp (gif);
6718 if (rc == GIF_ERROR)
6720 image_error ("Error reading `%s'", img->spec, Qnil);
6721 fn_DGifCloseFile (gif);
6722 UNGCPRO;
6723 return 0;
6726 image = image_spec_value (img->spec, QCindex, NULL);
6727 ino = INTEGERP (image) ? XFASTINT (image) : 0;
6728 if (ino >= gif->ImageCount)
6730 image_error ("Invalid image number `%s' in image `%s'",
6731 image, img->spec);
6732 fn_DGifCloseFile (gif);
6733 UNGCPRO;
6734 return 0;
6737 width = img->width = max (gif->SWidth, gif->Image.Left + gif->Image.Width);
6738 height = img->height = max (gif->SHeight, gif->Image.Top + gif->Image.Height);
6740 /* Create the X image and pixmap. */
6741 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6743 fn_DGifCloseFile (gif);
6744 UNGCPRO;
6745 return 0;
6748 /* Allocate colors. */
6749 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
6750 if (!gif_color_map)
6751 gif_color_map = gif->SColorMap;
6752 init_color_table ();
6753 bzero (pixel_colors, sizeof pixel_colors);
6755 for (i = 0; i < gif_color_map->ColorCount; ++i)
6757 int r = gif_color_map->Colors[i].Red << 8;
6758 int g = gif_color_map->Colors[i].Green << 8;
6759 int b = gif_color_map->Colors[i].Blue << 8;
6760 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
6763 #ifdef COLOR_TABLE_SUPPORT
6764 img->colors = colors_in_color_table (&img->ncolors);
6765 free_color_table ();
6766 #endif /* COLOR_TABLE_SUPPORT */
6768 /* Clear the part of the screen image that are not covered by
6769 the image from the GIF file. Full animated GIF support
6770 requires more than can be done here (see the gif89 spec,
6771 disposal methods). Let's simply assume that the part
6772 not covered by a sub-image is in the frame's background color. */
6773 image_top = gif->SavedImages[ino].ImageDesc.Top;
6774 image_left = gif->SavedImages[ino].ImageDesc.Left;
6775 image_width = gif->SavedImages[ino].ImageDesc.Width;
6776 image_height = gif->SavedImages[ino].ImageDesc.Height;
6778 for (y = 0; y < image_top; ++y)
6779 for (x = 0; x < width; ++x)
6780 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6782 for (y = image_top + image_height; y < height; ++y)
6783 for (x = 0; x < width; ++x)
6784 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6786 for (y = image_top; y < image_top + image_height; ++y)
6788 for (x = 0; x < image_left; ++x)
6789 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6790 for (x = image_left + image_width; x < width; ++x)
6791 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
6794 /* Read the GIF image into the X image. We use a local variable
6795 `raster' here because RasterBits below is a char *, and invites
6796 problems with bytes >= 0x80. */
6797 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
6799 if (gif->SavedImages[ino].ImageDesc.Interlace)
6801 static int interlace_start[] = {0, 4, 2, 1};
6802 static int interlace_increment[] = {8, 8, 4, 2};
6803 int pass;
6804 int row = interlace_start[0];
6806 pass = 0;
6808 for (y = 0; y < image_height; y++)
6810 if (row >= image_height)
6812 row = interlace_start[++pass];
6813 while (row >= image_height)
6814 row = interlace_start[++pass];
6817 for (x = 0; x < image_width; x++)
6819 int i = raster[(y * image_width) + x];
6820 XPutPixel (ximg, x + image_left, row + image_top,
6821 pixel_colors[i]);
6824 row += interlace_increment[pass];
6827 else
6829 for (y = 0; y < image_height; ++y)
6830 for (x = 0; x < image_width; ++x)
6832 int i = raster[y * image_width + x];
6833 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
6837 fn_DGifCloseFile (gif);
6839 /* Maybe fill in the background field while we have ximg handy. */
6840 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6841 IMAGE_BACKGROUND (img, f, ximg);
6843 /* Put the image into the pixmap, then free the X image and its buffer. */
6844 x_put_x_image (f, ximg, img->pixmap, width, height);
6845 x_destroy_x_image (ximg);
6847 UNGCPRO;
6848 return 1;
6851 #else
6853 #ifdef MAC_OS
6854 static int
6855 gif_load (f, img)
6856 struct frame *f;
6857 struct image *img;
6859 Lisp_Object specified_file, file;
6860 Lisp_Object specified_data;
6861 OSErr err;
6862 Boolean graphic_p, movie_p, prefer_graphic_p;
6863 Handle dh = NULL;
6864 Movie movie = NULL;
6865 Lisp_Object image;
6866 Track track = NULL;
6867 Media media = NULL;
6868 long nsamples;
6869 Rect rect;
6870 Lisp_Object specified_bg;
6871 XColor color;
6872 RGBColor bg_color;
6873 int width, height;
6874 XImagePtr ximg;
6875 TimeValue time;
6876 struct gcpro gcpro1;
6877 int ino;
6879 specified_file = image_spec_value (img->spec, QCfile, NULL);
6880 specified_data = image_spec_value (img->spec, QCdata, NULL);
6882 if (NILP (specified_data))
6884 /* Read from a file */
6885 FSSpec fss;
6886 short refnum;
6888 err = find_image_fsspec (specified_file, &file, &fss);
6889 if (err != noErr)
6891 if (err == fnfErr)
6892 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6893 else
6894 goto open_error;
6897 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
6898 &graphic_p, &movie_p, &prefer_graphic_p, 0);
6899 if (err != noErr)
6900 goto open_error;
6902 if (!graphic_p && !movie_p)
6903 goto open_error;
6904 if (prefer_graphic_p)
6905 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
6906 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
6907 if (err != noErr)
6908 goto open_error;
6909 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
6910 CloseMovieFile (refnum);
6911 if (err != noErr)
6913 image_error ("Error reading `%s'", file, Qnil);
6914 return 0;
6917 else
6919 /* Memory source! */
6920 Handle dref = NULL;
6921 long file_type_atom[3];
6923 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
6924 if (err != noErr)
6926 image_error ("Cannot allocate data handle for `%s'",
6927 img->spec, Qnil);
6928 goto error;
6931 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
6932 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
6933 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
6934 err = PtrToHand (&dh, &dref, sizeof (Handle));
6935 if (err == noErr)
6936 /* no file name */
6937 err = PtrAndHand ("\p", dref, 1);
6938 if (err == noErr)
6939 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
6940 if (err != noErr)
6942 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
6943 goto error;
6945 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
6946 &movie_p, &prefer_graphic_p, 0);
6947 if (err != noErr)
6948 goto open_error;
6950 if (!graphic_p && !movie_p)
6951 goto open_error;
6952 if (prefer_graphic_p)
6954 int success_p;
6956 DisposeHandle (dref);
6957 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
6958 DisposeHandle (dh);
6959 return success_p;
6961 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
6962 HandleDataHandlerSubType);
6963 DisposeHandle (dref);
6964 if (err != noErr)
6965 goto open_error;
6968 image = image_spec_value (img->spec, QCindex, NULL);
6969 ino = INTEGERP (image) ? XFASTINT (image) : 0;
6970 track = GetMovieIndTrack (movie, 1);
6971 media = GetTrackMedia (track);
6972 nsamples = GetMediaSampleCount (media);
6973 if (ino >= nsamples)
6975 image_error ("Invalid image number `%s' in image `%s'",
6976 image, img->spec);
6977 goto error;
6980 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
6981 if (!STRINGP (specified_bg) ||
6982 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
6984 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6985 color.red = RED16_FROM_ULONG (color.pixel);
6986 color.green = GREEN16_FROM_ULONG (color.pixel);
6987 color.blue = BLUE16_FROM_ULONG (color.pixel);
6989 GetMovieBox (movie, &rect);
6990 width = img->width = rect.right - rect.left;
6991 height = img->height = rect.bottom - rect.top;
6992 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6993 goto error;
6995 SetGWorld (ximg, NULL);
6996 bg_color.red = color.red;
6997 bg_color.green = color.green;
6998 bg_color.blue = color.blue;
6999 RGBBackColor (&bg_color);
7000 SetMovieActive (movie, TRUE);
7001 SetMovieGWorld (movie, ximg, NULL);
7002 SampleNumToMediaTime (media, ino + 1, &time, NULL);
7003 SetMovieTimeValue (movie, time);
7004 MoviesTask (movie, 0L);
7005 DisposeTrackMedia (media);
7006 DisposeMovieTrack (track);
7007 DisposeMovie (movie);
7008 if (dh)
7009 DisposeHandle (dh);
7010 /* Maybe fill in the background field while we have ximg handy. */
7011 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7012 IMAGE_BACKGROUND (img, f, ximg);
7014 /* Put the image into the pixmap. */
7015 x_put_x_image (f, ximg, img->pixmap, width, height);
7016 x_destroy_x_image (ximg);
7017 return 1;
7019 open_error:
7020 image_error ("Cannot open `%s'", file, Qnil);
7021 error:
7022 if (media)
7023 DisposeTrackMedia (media);
7024 if (track)
7025 DisposeMovieTrack (track);
7026 if (movie)
7027 DisposeMovie (movie);
7028 if (dh)
7029 DisposeHandle (dh);
7030 return 0;
7032 #endif /* MAC_OS */
7034 #endif /* HAVE_GIF */
7038 /***********************************************************************
7039 Ghostscript
7040 ***********************************************************************/
7042 #ifdef HAVE_X_WINDOWS
7043 #define HAVE_GHOSTSCRIPT 1
7044 #endif /* HAVE_X_WINDOWS */
7046 /* The symbol `postscript' identifying images of this type. */
7048 Lisp_Object Qpostscript;
7050 #ifdef HAVE_GHOSTSCRIPT
7052 static int gs_image_p P_ ((Lisp_Object object));
7053 static int gs_load P_ ((struct frame *f, struct image *img));
7054 static void gs_clear_image P_ ((struct frame *f, struct image *img));
7056 /* Keyword symbols. */
7058 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
7060 /* Indices of image specification fields in gs_format, below. */
7062 enum gs_keyword_index
7064 GS_TYPE,
7065 GS_PT_WIDTH,
7066 GS_PT_HEIGHT,
7067 GS_FILE,
7068 GS_LOADER,
7069 GS_BOUNDING_BOX,
7070 GS_ASCENT,
7071 GS_MARGIN,
7072 GS_RELIEF,
7073 GS_ALGORITHM,
7074 GS_HEURISTIC_MASK,
7075 GS_MASK,
7076 GS_BACKGROUND,
7077 GS_LAST
7080 /* Vector of image_keyword structures describing the format
7081 of valid user-defined image specifications. */
7083 static struct image_keyword gs_format[GS_LAST] =
7085 {":type", IMAGE_SYMBOL_VALUE, 1},
7086 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7087 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
7088 {":file", IMAGE_STRING_VALUE, 1},
7089 {":loader", IMAGE_FUNCTION_VALUE, 0},
7090 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
7091 {":ascent", IMAGE_ASCENT_VALUE, 0},
7092 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7093 {":relief", IMAGE_INTEGER_VALUE, 0},
7094 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7095 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7096 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7097 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7100 /* Structure describing the image type `ghostscript'. */
7102 static struct image_type gs_type =
7104 &Qpostscript,
7105 gs_image_p,
7106 gs_load,
7107 gs_clear_image,
7108 NULL
7112 /* Free X resources of Ghostscript image IMG which is used on frame F. */
7114 static void
7115 gs_clear_image (f, img)
7116 struct frame *f;
7117 struct image *img;
7119 /* IMG->data.ptr_val may contain a recorded colormap. */
7120 xfree (img->data.ptr_val);
7121 x_clear_image (f, img);
7125 /* Return non-zero if OBJECT is a valid Ghostscript image
7126 specification. */
7128 static int
7129 gs_image_p (object)
7130 Lisp_Object object;
7132 struct image_keyword fmt[GS_LAST];
7133 Lisp_Object tem;
7134 int i;
7136 bcopy (gs_format, fmt, sizeof fmt);
7138 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
7139 return 0;
7141 /* Bounding box must be a list or vector containing 4 integers. */
7142 tem = fmt[GS_BOUNDING_BOX].value;
7143 if (CONSP (tem))
7145 for (i = 0; i < 4; ++i, tem = XCDR (tem))
7146 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
7147 return 0;
7148 if (!NILP (tem))
7149 return 0;
7151 else if (VECTORP (tem))
7153 if (XVECTOR (tem)->size != 4)
7154 return 0;
7155 for (i = 0; i < 4; ++i)
7156 if (!INTEGERP (XVECTOR (tem)->contents[i]))
7157 return 0;
7159 else
7160 return 0;
7162 return 1;
7166 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
7167 if successful. */
7169 static int
7170 gs_load (f, img)
7171 struct frame *f;
7172 struct image *img;
7174 char buffer[100];
7175 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
7176 struct gcpro gcpro1, gcpro2;
7177 Lisp_Object frame;
7178 double in_width, in_height;
7179 Lisp_Object pixel_colors = Qnil;
7181 /* Compute pixel size of pixmap needed from the given size in the
7182 image specification. Sizes in the specification are in pt. 1 pt
7183 = 1/72 in, xdpi and ydpi are stored in the frame's X display
7184 info. */
7185 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
7186 in_width = XFASTINT (pt_width) / 72.0;
7187 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
7188 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
7189 in_height = XFASTINT (pt_height) / 72.0;
7190 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
7192 /* Create the pixmap. */
7193 xassert (img->pixmap == NO_PIXMAP);
7195 /* Only W32 version did BLOCK_INPUT here. ++kfs */
7196 BLOCK_INPUT;
7197 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7198 img->width, img->height,
7199 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
7200 UNBLOCK_INPUT;
7202 if (!img->pixmap)
7204 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
7205 return 0;
7208 /* Call the loader to fill the pixmap. It returns a process object
7209 if successful. We do not record_unwind_protect here because
7210 other places in redisplay like calling window scroll functions
7211 don't either. Let the Lisp loader use `unwind-protect' instead. */
7212 GCPRO2 (window_and_pixmap_id, pixel_colors);
7214 sprintf (buffer, "%lu %lu",
7215 (unsigned long) FRAME_X_WINDOW (f),
7216 (unsigned long) img->pixmap);
7217 window_and_pixmap_id = build_string (buffer);
7219 sprintf (buffer, "%lu %lu",
7220 FRAME_FOREGROUND_PIXEL (f),
7221 FRAME_BACKGROUND_PIXEL (f));
7222 pixel_colors = build_string (buffer);
7224 XSETFRAME (frame, f);
7225 loader = image_spec_value (img->spec, QCloader, NULL);
7226 if (NILP (loader))
7227 loader = intern ("gs-load-image");
7229 img->data.lisp_val = call6 (loader, frame, img->spec,
7230 make_number (img->width),
7231 make_number (img->height),
7232 window_and_pixmap_id,
7233 pixel_colors);
7234 UNGCPRO;
7235 return PROCESSP (img->data.lisp_val);
7239 /* Kill the Ghostscript process that was started to fill PIXMAP on
7240 frame F. Called from XTread_socket when receiving an event
7241 telling Emacs that Ghostscript has finished drawing. */
7243 void
7244 x_kill_gs_process (pixmap, f)
7245 Pixmap pixmap;
7246 struct frame *f;
7248 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
7249 int class, i;
7250 struct image *img;
7252 /* Find the image containing PIXMAP. */
7253 for (i = 0; i < c->used; ++i)
7254 if (c->images[i]->pixmap == pixmap)
7255 break;
7257 /* Should someone in between have cleared the image cache, for
7258 instance, give up. */
7259 if (i == c->used)
7260 return;
7262 /* Kill the GS process. We should have found PIXMAP in the image
7263 cache and its image should contain a process object. */
7264 img = c->images[i];
7265 xassert (PROCESSP (img->data.lisp_val));
7266 Fkill_process (img->data.lisp_val, Qnil);
7267 img->data.lisp_val = Qnil;
7269 #if defined (HAVE_X_WINDOWS)
7271 /* On displays with a mutable colormap, figure out the colors
7272 allocated for the image by looking at the pixels of an XImage for
7273 img->pixmap. */
7274 class = FRAME_X_VISUAL (f)->class;
7275 if (class != StaticColor && class != StaticGray && class != TrueColor)
7277 XImagePtr ximg;
7279 BLOCK_INPUT;
7281 /* Try to get an XImage for img->pixmep. */
7282 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
7283 0, 0, img->width, img->height, ~0, ZPixmap);
7284 if (ximg)
7286 int x, y;
7288 /* Initialize the color table. */
7289 init_color_table ();
7291 /* For each pixel of the image, look its color up in the
7292 color table. After having done so, the color table will
7293 contain an entry for each color used by the image. */
7294 for (y = 0; y < img->height; ++y)
7295 for (x = 0; x < img->width; ++x)
7297 unsigned long pixel = XGetPixel (ximg, x, y);
7298 lookup_pixel_color (f, pixel);
7301 /* Record colors in the image. Free color table and XImage. */
7302 #ifdef COLOR_TABLE_SUPPORT
7303 img->colors = colors_in_color_table (&img->ncolors);
7304 free_color_table ();
7305 #endif
7306 XDestroyImage (ximg);
7308 #if 0 /* This doesn't seem to be the case. If we free the colors
7309 here, we get a BadAccess later in x_clear_image when
7310 freeing the colors. */
7311 /* We have allocated colors once, but Ghostscript has also
7312 allocated colors on behalf of us. So, to get the
7313 reference counts right, free them once. */
7314 if (img->ncolors)
7315 x_free_colors (f, img->colors, img->ncolors);
7316 #endif
7318 else
7319 image_error ("Cannot get X image of `%s'; colors will not be freed",
7320 img->spec, Qnil);
7322 UNBLOCK_INPUT;
7324 #endif /* HAVE_X_WINDOWS */
7326 /* Now that we have the pixmap, compute mask and transform the
7327 image if requested. */
7328 BLOCK_INPUT;
7329 postprocess_image (f, img);
7330 UNBLOCK_INPUT;
7333 #endif /* HAVE_GHOSTSCRIPT */
7336 /***********************************************************************
7337 Tests
7338 ***********************************************************************/
7340 #if GLYPH_DEBUG
7342 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
7343 doc: /* Value is non-nil if SPEC is a valid image specification. */)
7344 (spec)
7345 Lisp_Object spec;
7347 return valid_image_p (spec) ? Qt : Qnil;
7351 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
7352 (spec)
7353 Lisp_Object spec;
7355 int id = -1;
7357 if (valid_image_p (spec))
7358 id = lookup_image (SELECTED_FRAME (), spec);
7360 debug_print (spec);
7361 return make_number (id);
7364 #endif /* GLYPH_DEBUG != 0 */
7367 /***********************************************************************
7368 Initialization
7369 ***********************************************************************/
7371 void
7372 syms_of_image ()
7374 QCascent = intern (":ascent");
7375 staticpro (&QCascent);
7376 QCmargin = intern (":margin");
7377 staticpro (&QCmargin);
7378 QCrelief = intern (":relief");
7379 staticpro (&QCrelief);
7380 QCconversion = intern (":conversion");
7381 staticpro (&QCconversion);
7382 QCcolor_symbols = intern (":color-symbols");
7383 staticpro (&QCcolor_symbols);
7384 QCheuristic_mask = intern (":heuristic-mask");
7385 staticpro (&QCheuristic_mask);
7386 QCindex = intern (":index");
7387 staticpro (&QCindex);
7388 QCmatrix = intern (":matrix");
7389 staticpro (&QCmatrix);
7390 QCcolor_adjustment = intern (":color-adjustment");
7391 staticpro (&QCcolor_adjustment);
7392 QCmask = intern (":mask");
7393 staticpro (&QCmask);
7395 Qlaplace = intern ("laplace");
7396 staticpro (&Qlaplace);
7397 Qemboss = intern ("emboss");
7398 staticpro (&Qemboss);
7399 Qedge_detection = intern ("edge-detection");
7400 staticpro (&Qedge_detection);
7401 Qheuristic = intern ("heuristic");
7402 staticpro (&Qheuristic);
7404 Qpostscript = intern ("postscript");
7405 staticpro (&Qpostscript);
7406 #ifdef HAVE_GHOSTSCRIPT
7407 QCloader = intern (":loader");
7408 staticpro (&QCloader);
7409 QCbounding_box = intern (":bounding-box");
7410 staticpro (&QCbounding_box);
7411 QCpt_width = intern (":pt-width");
7412 staticpro (&QCpt_width);
7413 QCpt_height = intern (":pt-height");
7414 staticpro (&QCpt_height);
7415 #endif /* HAVE_GHOSTSCRIPT */
7417 Qpbm = intern ("pbm");
7418 staticpro (&Qpbm);
7420 Qxbm = intern ("xbm");
7421 staticpro (&Qxbm);
7423 #ifdef HAVE_XPM
7424 Qxpm = intern ("xpm");
7425 staticpro (&Qxpm);
7426 #endif
7428 #if defined (HAVE_JPEG) || defined (MAC_OS)
7429 Qjpeg = intern ("jpeg");
7430 staticpro (&Qjpeg);
7431 #endif
7433 #if defined (HAVE_TIFF) || defined (MAC_OS)
7434 Qtiff = intern ("tiff");
7435 staticpro (&Qtiff);
7436 #endif
7438 #if defined (HAVE_GIF) || defined (MAC_OS)
7439 Qgif = intern ("gif");
7440 staticpro (&Qgif);
7441 #endif
7443 #if defined (HAVE_PNG) || defined (MAC_OS)
7444 Qpng = intern ("png");
7445 staticpro (&Qpng);
7446 #endif
7448 defsubr (&Sclear_image_cache);
7449 defsubr (&Simage_size);
7450 defsubr (&Simage_mask_p);
7452 #if GLYPH_DEBUG
7453 defsubr (&Simagep);
7454 defsubr (&Slookup_image);
7455 #endif
7457 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
7458 doc: /* Non-nil means always draw a cross over disabled images.
7459 Disabled images are those having an `:conversion disabled' property.
7460 A cross is always drawn on black & white displays. */);
7461 cross_disabled_images = 0;
7463 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
7464 doc: /* List of directories to search for window system bitmap files. */);
7465 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
7467 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
7468 doc: /* Time after which cached images are removed from the cache.
7469 When an image has not been displayed this many seconds, remove it
7470 from the image cache. Value must be an integer or nil with nil
7471 meaning don't clear the cache. */);
7472 Vimage_cache_eviction_delay = make_number (30 * 60);
7476 #ifdef HAVE_NTGUI
7477 /* Image types that rely on external libraries are loaded dynamically
7478 if the library is available. */
7479 #define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn())
7480 #else
7481 #define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */
7482 #endif /* HAVE_NTGUI */
7484 void
7485 init_image ()
7487 image_types = NULL;
7488 Vimage_types = Qnil;
7490 define_image_type (&xbm_type);
7491 define_image_type (&pbm_type);
7493 #ifdef HAVE_XPM
7494 IF_LIB_AVAILABLE(init_xpm_functions)
7495 define_image_type (&xpm_type);
7496 #endif
7498 #if defined (HAVE_JPEG) || defined (MAC_OS)
7499 IF_LIB_AVAILABLE(init_jpeg_functions)
7500 define_image_type (&jpeg_type);
7501 #endif
7503 #if defined (HAVE_TIFF) || defined (MAC_OS)
7504 IF_LIB_AVAILABLE(init_tiff_functions)
7505 define_image_type (&tiff_type);
7506 #endif
7508 #if defined (HAVE_GIF) || defined (MAC_OS)
7509 IF_LIB_AVAILABLE(init_gif_functions)
7510 define_image_type (&gif_type);
7511 #endif
7513 #if defined (HAVE_PNG) || defined (MAC_OS)
7514 IF_LIB_AVAILABLE(init_png_functions)
7515 define_image_type (&png_type);
7516 #endif
7518 #ifdef HAVE_GHOSTSCRIPT
7519 define_image_type (&gs_type);
7520 #endif
7522 #ifdef MAC_OS
7523 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7524 EnterMovies ();
7525 #ifdef MAC_OSX
7526 init_image_func_pointer ();
7527 #endif
7528 #endif
7531 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
7532 (do not change this comment) */