(picture-mode-exit): Run picture-mode-exit-hook.
[emacs.git] / src / image.c
blob6f2e93a591a5e7c05f9a2e5e5a064b92f1c1139c
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
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., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <ctype.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>
42 #include "charset.h"
43 #include "coding.h"
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #include <sys/types.h>
49 #include <sys/stat.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
64 #ifdef HAVE_NTGUI
65 #include "w32term.h"
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define NO_PIXMAP 0
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 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 #include <sys/stat.h>
88 #ifndef MAC_OSX
89 #include <alloca.h>
90 #include <sys/param.h>
91 #endif
92 #if TARGET_API_MAC_CARBON
93 #ifdef MAC_OSX
94 #include <QuickTime/QuickTime.h>
95 #else /* not MAC_OSX */
96 #include <QuickTime.h>
97 #endif /* not MAC_OSX */
98 #else /* not TARGET_API_MAC_CARBON */
99 #include <Windows.h>
100 #include <Gestalt.h>
101 #include <TextUtils.h>
102 #include <ImageCompression.h>
103 #include <QuickTimeComponents.h>
104 #endif /* not TARGET_API_MAC_CARBON */
106 /* MAC_TODO : Color tables on Mac. */
107 #undef COLOR_TABLE_SUPPORT
109 #define ZPixmap 0 /* arbitrary */
110 typedef struct mac_bitmap_record Bitmap_Record;
112 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
113 #define NO_PIXMAP 0
115 #define RGB_PIXEL_COLOR unsigned long
117 /* A black pixel in a mask bitmap/pixmap means ``draw a source
118 pixel''. A white pixel means ``retain the current pixel''. */
119 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
120 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
122 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
123 #define x_defined_color mac_defined_color
124 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
125 #define XDrawLine(display, w, gc, x1, y1, x2, y2) \
126 mac_draw_line_to_pixmap(display, w, gc, x1, y1, x2, y2)
128 #endif /* MAC_OS */
131 /* Search path for bitmap files. */
133 Lisp_Object Vx_bitmap_file_path;
136 static void x_disable_image P_ ((struct frame *, struct image *));
137 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
138 Lisp_Object));
140 static void init_color_table P_ ((void));
141 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
142 #ifdef COLOR_TABLE_SUPPORT
143 static void free_color_table P_ ((void));
144 static unsigned long *colors_in_color_table P_ ((int *n));
145 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
146 #endif
148 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
149 id, which is just an int that this section returns. Bitmaps are
150 reference counted so they can be shared among frames.
152 Bitmap indices are guaranteed to be > 0, so a negative number can
153 be used to indicate no bitmap.
155 If you use x_create_bitmap_from_data, then you must keep track of
156 the bitmaps yourself. That is, creating a bitmap from the same
157 data more than once will not be caught. */
159 #ifdef MAC_OS
161 static XImagePtr
162 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
163 Display *display; /* not used */
164 Pixmap pixmap;
165 int x, y; /* not used */
166 unsigned int width, height; /* not used */
167 unsigned long plane_mask; /* not used */
168 int format; /* not used */
170 #if GLYPH_DEBUG
171 xassert (x == 0 && y == 0);
173 Rect ri, rp;
174 SetRect (&ri, 0, 0, width, height);
175 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
177 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
178 #endif
180 LockPixels (GetGWorldPixMap (pixmap));
182 return pixmap;
185 static void
186 XPutPixel (ximage, x, y, pixel)
187 XImagePtr ximage;
188 int x, y;
189 unsigned long pixel;
191 PixMapHandle pixmap = GetGWorldPixMap (ximage);
192 short depth = GetPixDepth (pixmap);
194 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
195 if (depth == 32)
197 char *base_addr = GetPixBaseAddr (pixmap);
198 short row_bytes = GetPixRowBytes (pixmap);
200 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
202 else
203 #endif
204 if (depth == 1)
206 char *base_addr = GetPixBaseAddr (pixmap);
207 short row_bytes = GetPixRowBytes (pixmap);
209 if (pixel == PIX_MASK_DRAW)
210 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
211 else
212 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
214 else
216 CGrafPtr old_port;
217 GDHandle old_gdh;
218 RGBColor color;
220 GetGWorld (&old_port, &old_gdh);
221 SetGWorld (ximage, NULL);
223 color.red = RED16_FROM_ULONG (pixel);
224 color.green = GREEN16_FROM_ULONG (pixel);
225 color.blue = BLUE16_FROM_ULONG (pixel);
227 SetCPixel (x, y, &color);
229 SetGWorld (old_port, old_gdh);
233 static unsigned long
234 XGetPixel (ximage, x, y)
235 XImagePtr ximage;
236 int x, y;
238 PixMapHandle pixmap = GetGWorldPixMap (ximage);
239 short depth = GetPixDepth (pixmap);
241 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
242 if (depth == 32)
244 char *base_addr = GetPixBaseAddr (pixmap);
245 short row_bytes = GetPixRowBytes (pixmap);
247 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
249 else
250 #endif
251 if (depth == 1)
253 char *base_addr = GetPixBaseAddr (pixmap);
254 short row_bytes = GetPixRowBytes (pixmap);
256 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
257 return PIX_MASK_DRAW;
258 else
259 return PIX_MASK_RETAIN;
261 else
263 CGrafPtr old_port;
264 GDHandle old_gdh;
265 RGBColor color;
267 GetGWorld (&old_port, &old_gdh);
268 SetGWorld (ximage, NULL);
270 GetCPixel (x, y, &color);
272 SetGWorld (old_port, old_gdh);
273 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
277 static void
278 XDestroyImage (ximg)
279 XImagePtr ximg;
281 UnlockPixels (GetGWorldPixMap (ximg));
284 #if USE_CG_DRAWING
285 static CGImageRef
286 mac_create_cg_image_from_image (f, img)
287 struct frame *f;
288 struct image *img;
290 Pixmap mask;
291 CGImageRef result = NULL;
293 BLOCK_INPUT;
294 if (img->mask)
295 mask = img->mask;
296 else
298 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
299 img->width, img->height, 1);
300 if (mask)
302 CGrafPtr old_port;
303 GDHandle old_gdh;
304 Rect r;
306 GetGWorld (&old_port, &old_gdh);
307 SetGWorld (mask, NULL);
308 BackColor (blackColor); /* Don't mask. */
309 SetRect (&r, 0, 0, img->width, img->height);
310 EraseRect (&r);
311 SetGWorld (old_port, old_gdh);
314 if (mask)
316 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
317 GetGWorldPixMap (mask), &result);
318 if (mask != img->mask)
319 XFreePixmap (FRAME_X_DISPLAY (f), mask);
321 UNBLOCK_INPUT;
323 return result;
325 #endif /* USE_CG_DRAWING */
326 #endif /* MAC_OS */
329 /* Functions to access the contents of a bitmap, given an id. */
332 x_bitmap_height (f, id)
333 FRAME_PTR f;
334 int id;
336 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
340 x_bitmap_width (f, id)
341 FRAME_PTR f;
342 int id;
344 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
347 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
349 x_bitmap_pixmap (f, id)
350 FRAME_PTR f;
351 int id;
353 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
355 #endif
357 #ifdef HAVE_X_WINDOWS
359 x_bitmap_mask (f, id)
360 FRAME_PTR f;
361 int id;
363 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
365 #endif
367 /* Allocate a new bitmap record. Returns index of new record. */
369 static int
370 x_allocate_bitmap_record (f)
371 FRAME_PTR f;
373 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
374 int i;
376 if (dpyinfo->bitmaps == NULL)
378 dpyinfo->bitmaps_size = 10;
379 dpyinfo->bitmaps
380 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
381 dpyinfo->bitmaps_last = 1;
382 return 1;
385 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
386 return ++dpyinfo->bitmaps_last;
388 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
389 if (dpyinfo->bitmaps[i].refcount == 0)
390 return i + 1;
392 dpyinfo->bitmaps_size *= 2;
393 dpyinfo->bitmaps
394 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
395 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
396 return ++dpyinfo->bitmaps_last;
399 /* Add one reference to the reference count of the bitmap with id ID. */
401 void
402 x_reference_bitmap (f, id)
403 FRAME_PTR f;
404 int id;
406 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
409 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
412 x_create_bitmap_from_data (f, bits, width, height)
413 struct frame *f;
414 char *bits;
415 unsigned int width, height;
417 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
418 int id;
420 #ifdef HAVE_X_WINDOWS
421 Pixmap bitmap;
422 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
423 bits, width, height);
424 if (! bitmap)
425 return -1;
426 #endif /* HAVE_X_WINDOWS */
428 #ifdef HAVE_NTGUI
429 Pixmap bitmap;
430 bitmap = CreateBitmap (width, height,
431 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
432 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
433 bits);
434 if (! bitmap)
435 return -1;
436 #endif /* HAVE_NTGUI */
438 #ifdef MAC_OS
439 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
440 if (width % 16 != 0)
441 return -1;
442 #endif
444 id = x_allocate_bitmap_record (f);
445 #ifdef MAC_OS
446 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
447 if (! dpyinfo->bitmaps[id - 1].bitmap_data)
448 return -1;
449 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
450 #endif /* MAC_OS */
452 dpyinfo->bitmaps[id - 1].file = NULL;
453 dpyinfo->bitmaps[id - 1].height = height;
454 dpyinfo->bitmaps[id - 1].width = width;
455 dpyinfo->bitmaps[id - 1].refcount = 1;
457 #ifdef HAVE_X_WINDOWS
458 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
459 dpyinfo->bitmaps[id - 1].have_mask = 0;
460 dpyinfo->bitmaps[id - 1].depth = 1;
461 #endif /* HAVE_X_WINDOWS */
463 #ifdef HAVE_NTGUI
464 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
465 dpyinfo->bitmaps[id - 1].hinst = NULL;
466 dpyinfo->bitmaps[id - 1].depth = 1;
467 #endif /* HAVE_NTGUI */
469 return id;
472 /* Create bitmap from file FILE for frame F. */
475 x_create_bitmap_from_file (f, file)
476 struct frame *f;
477 Lisp_Object file;
479 #ifdef MAC_OS
480 return -1; /* MAC_TODO : bitmap support */
481 #endif /* MAC_OS */
483 #ifdef HAVE_NTGUI
484 return -1; /* W32_TODO : bitmap support */
485 #endif /* HAVE_NTGUI */
487 #ifdef HAVE_X_WINDOWS
488 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
489 unsigned int width, height;
490 Pixmap bitmap;
491 int xhot, yhot, result, id;
492 Lisp_Object found;
493 int fd;
494 char *filename;
496 /* Look for an existing bitmap with the same name. */
497 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
499 if (dpyinfo->bitmaps[id].refcount
500 && dpyinfo->bitmaps[id].file
501 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
503 ++dpyinfo->bitmaps[id].refcount;
504 return id + 1;
508 /* Search bitmap-file-path for the file, if appropriate. */
509 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
510 if (fd < 0)
511 return -1;
512 emacs_close (fd);
514 filename = (char *) SDATA (found);
516 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
517 filename, &width, &height, &bitmap, &xhot, &yhot);
518 if (result != BitmapSuccess)
519 return -1;
521 id = x_allocate_bitmap_record (f);
522 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
523 dpyinfo->bitmaps[id - 1].have_mask = 0;
524 dpyinfo->bitmaps[id - 1].refcount = 1;
525 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
526 dpyinfo->bitmaps[id - 1].depth = 1;
527 dpyinfo->bitmaps[id - 1].height = height;
528 dpyinfo->bitmaps[id - 1].width = width;
529 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
531 return id;
532 #endif /* HAVE_X_WINDOWS */
535 /* Free bitmap B. */
537 static void
538 Free_Bitmap_Record (dpyinfo, bm)
539 Display_Info *dpyinfo;
540 Bitmap_Record *bm;
542 #ifdef HAVE_X_WINDOWS
543 XFreePixmap (dpyinfo->display, bm->pixmap);
544 if (bm->have_mask)
545 XFreePixmap (dpyinfo->display, bm->mask);
546 #endif /* HAVE_X_WINDOWS */
548 #ifdef HAVE_NTGUI
549 DeleteObject (bm->pixmap);
550 #endif /* HAVE_NTGUI */
552 #ifdef MAC_OS
553 xfree (bm->bitmap_data); /* Added ++kfs */
554 bm->bitmap_data = NULL;
555 #endif /* MAC_OS */
557 if (bm->file)
559 xfree (bm->file);
560 bm->file = NULL;
564 /* Remove reference to bitmap with id number ID. */
566 void
567 x_destroy_bitmap (f, id)
568 FRAME_PTR f;
569 int id;
571 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
573 if (id > 0)
575 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
577 if (--bm->refcount == 0)
579 BLOCK_INPUT;
580 Free_Bitmap_Record (dpyinfo, bm);
581 UNBLOCK_INPUT;
586 /* Free all the bitmaps for the display specified by DPYINFO. */
588 void
589 x_destroy_all_bitmaps (dpyinfo)
590 Display_Info *dpyinfo;
592 int i;
593 Bitmap_Record *bm = dpyinfo->bitmaps;
595 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
596 if (bm->refcount > 0)
597 Free_Bitmap_Record (dpyinfo, bm);
599 dpyinfo->bitmaps_last = 0;
603 #ifdef HAVE_X_WINDOWS
605 /* Useful functions defined in the section
606 `Image type independent image structures' below. */
608 static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width,
609 unsigned long height));
611 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
612 int depth, XImagePtr *ximg,
613 Pixmap *pixmap));
615 static void x_destroy_x_image P_ ((XImagePtr ximg));
618 /* Create a mask of a bitmap. Note is this not a perfect mask.
619 It's nicer with some borders in this context */
622 x_create_bitmap_mask (f, id)
623 struct frame *f;
624 int id;
626 Pixmap pixmap, mask;
627 XImagePtr ximg, mask_img;
628 unsigned long width, height;
629 int result;
630 unsigned long bg;
631 unsigned long x, y, xp, xm, yp, ym;
632 GC gc;
634 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
636 if (!(id > 0))
637 return -1;
639 pixmap = x_bitmap_pixmap (f, id);
640 width = x_bitmap_width (f, id);
641 height = x_bitmap_height (f, id);
643 BLOCK_INPUT;
644 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
645 ~0, ZPixmap);
647 if (!ximg)
649 UNBLOCK_INPUT;
650 return -1;
653 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
655 UNBLOCK_INPUT;
656 if (!result)
658 XDestroyImage (ximg);
659 return -1;
662 bg = four_corners_best (ximg, width, height);
664 for (y = 0; y < ximg->height; ++y)
666 for (x = 0; x < ximg->width; ++x)
668 xp = x != ximg->width - 1 ? x + 1 : 0;
669 xm = x != 0 ? x - 1 : ximg->width - 1;
670 yp = y != ximg->height - 1 ? y + 1 : 0;
671 ym = y != 0 ? y - 1 : ximg->height - 1;
672 if (XGetPixel (ximg, x, y) == bg
673 && XGetPixel (ximg, x, yp) == bg
674 && XGetPixel (ximg, x, ym) == bg
675 && XGetPixel (ximg, xp, y) == bg
676 && XGetPixel (ximg, xp, yp) == bg
677 && XGetPixel (ximg, xp, ym) == bg
678 && XGetPixel (ximg, xm, y) == bg
679 && XGetPixel (ximg, xm, yp) == bg
680 && XGetPixel (ximg, xm, ym) == bg)
681 XPutPixel (mask_img, x, y, 0);
682 else
683 XPutPixel (mask_img, x, y, 1);
687 xassert (interrupt_input_blocked);
688 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
689 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
690 width, height);
691 XFreeGC (FRAME_X_DISPLAY (f), gc);
693 dpyinfo->bitmaps[id - 1].have_mask = 1;
694 dpyinfo->bitmaps[id - 1].mask = mask;
696 XDestroyImage (ximg);
697 x_destroy_x_image (mask_img);
699 return 0;
702 #endif /* HAVE_X_WINDOWS */
705 /***********************************************************************
706 Image types
707 ***********************************************************************/
709 /* Value is the number of elements of vector VECTOR. */
711 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
713 /* List of supported image types. Use define_image_type to add new
714 types. Use lookup_image_type to find a type for a given symbol. */
716 static struct image_type *image_types;
718 /* A list of symbols, one for each supported image type. */
720 Lisp_Object Vimage_types;
722 /* An alist of image types and libraries that implement the type. */
724 Lisp_Object Vimage_library_alist;
726 /* Cache for delayed-loading image types. */
728 static Lisp_Object Vimage_type_cache;
730 /* The symbol `xbm' which is used as the type symbol for XBM images. */
732 Lisp_Object Qxbm;
734 /* Keywords. */
736 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
737 extern Lisp_Object QCdata, QCtype;
738 extern Lisp_Object Qcenter;
739 Lisp_Object QCascent, QCmargin, QCrelief;
740 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
741 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
743 /* Other symbols. */
745 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
747 /* Time in seconds after which images should be removed from the cache
748 if not displayed. */
750 Lisp_Object Vimage_cache_eviction_delay;
752 /* Function prototypes. */
754 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
755 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
756 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
757 static void x_laplace P_ ((struct frame *, struct image *));
758 static void x_emboss P_ ((struct frame *, struct image *));
759 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
760 Lisp_Object));
762 #define CACHE_IMAGE_TYPE(type, status) \
763 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
765 #define ADD_IMAGE_TYPE(type) \
766 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
768 /* Define a new image type from TYPE. This adds a copy of TYPE to
769 image_types and caches the loading status of TYPE. */
771 static Lisp_Object
772 define_image_type (type, loaded)
773 struct image_type *type;
774 int loaded;
776 Lisp_Object success;
778 if (!loaded)
779 success = Qnil;
780 else
782 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
783 The initialized data segment is read-only. */
784 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
785 bcopy (type, p, sizeof *p);
786 p->next = image_types;
787 image_types = p;
788 success = Qt;
791 CACHE_IMAGE_TYPE (*type->type, success);
792 return success;
796 /* Look up image type SYMBOL, and return a pointer to its image_type
797 structure. Value is null if SYMBOL is not a known image type. */
799 static INLINE struct image_type *
800 lookup_image_type (symbol)
801 Lisp_Object symbol;
803 struct image_type *type;
805 /* We must initialize the image-type if it hasn't been already. */
806 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
807 return 0; /* unimplemented */
809 for (type = image_types; type; type = type->next)
810 if (EQ (symbol, *type->type))
811 break;
813 return type;
817 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
818 valid image specification is a list whose car is the symbol
819 `image', and whose rest is a property list. The property list must
820 contain a value for key `:type'. That value must be the name of a
821 supported image type. The rest of the property list depends on the
822 image type. */
825 valid_image_p (object)
826 Lisp_Object object;
828 int valid_p = 0;
830 if (IMAGEP (object))
832 Lisp_Object tem;
834 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
835 if (EQ (XCAR (tem), QCtype))
837 tem = XCDR (tem);
838 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
840 struct image_type *type;
841 type = lookup_image_type (XCAR (tem));
842 if (type)
843 valid_p = type->valid_p (object);
846 break;
850 return valid_p;
854 /* Log error message with format string FORMAT and argument ARG.
855 Signaling an error, e.g. when an image cannot be loaded, is not a
856 good idea because this would interrupt redisplay, and the error
857 message display would lead to another redisplay. This function
858 therefore simply displays a message. */
860 static void
861 image_error (format, arg1, arg2)
862 char *format;
863 Lisp_Object arg1, arg2;
865 add_to_log (format, arg1, arg2);
870 /***********************************************************************
871 Image specifications
872 ***********************************************************************/
874 enum image_value_type
876 IMAGE_DONT_CHECK_VALUE_TYPE,
877 IMAGE_STRING_VALUE,
878 IMAGE_STRING_OR_NIL_VALUE,
879 IMAGE_SYMBOL_VALUE,
880 IMAGE_POSITIVE_INTEGER_VALUE,
881 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
882 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
883 IMAGE_ASCENT_VALUE,
884 IMAGE_INTEGER_VALUE,
885 IMAGE_FUNCTION_VALUE,
886 IMAGE_NUMBER_VALUE,
887 IMAGE_BOOL_VALUE
890 /* Structure used when parsing image specifications. */
892 struct image_keyword
894 /* Name of keyword. */
895 char *name;
897 /* The type of value allowed. */
898 enum image_value_type type;
900 /* Non-zero means key must be present. */
901 int mandatory_p;
903 /* Used to recognize duplicate keywords in a property list. */
904 int count;
906 /* The value that was found. */
907 Lisp_Object value;
911 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
912 int, Lisp_Object));
913 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
916 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
917 has the format (image KEYWORD VALUE ...). One of the keyword/
918 value pairs must be `:type TYPE'. KEYWORDS is a vector of
919 image_keywords structures of size NKEYWORDS describing other
920 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
922 static int
923 parse_image_spec (spec, keywords, nkeywords, type)
924 Lisp_Object spec;
925 struct image_keyword *keywords;
926 int nkeywords;
927 Lisp_Object type;
929 int i;
930 Lisp_Object plist;
932 if (!IMAGEP (spec))
933 return 0;
935 plist = XCDR (spec);
936 while (CONSP (plist))
938 Lisp_Object key, value;
940 /* First element of a pair must be a symbol. */
941 key = XCAR (plist);
942 plist = XCDR (plist);
943 if (!SYMBOLP (key))
944 return 0;
946 /* There must follow a value. */
947 if (!CONSP (plist))
948 return 0;
949 value = XCAR (plist);
950 plist = XCDR (plist);
952 /* Find key in KEYWORDS. Error if not found. */
953 for (i = 0; i < nkeywords; ++i)
954 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
955 break;
957 if (i == nkeywords)
958 continue;
960 /* Record that we recognized the keyword. If a keywords
961 was found more than once, it's an error. */
962 keywords[i].value = value;
963 ++keywords[i].count;
965 if (keywords[i].count > 1)
966 return 0;
968 /* Check type of value against allowed type. */
969 switch (keywords[i].type)
971 case IMAGE_STRING_VALUE:
972 if (!STRINGP (value))
973 return 0;
974 break;
976 case IMAGE_STRING_OR_NIL_VALUE:
977 if (!STRINGP (value) && !NILP (value))
978 return 0;
979 break;
981 case IMAGE_SYMBOL_VALUE:
982 if (!SYMBOLP (value))
983 return 0;
984 break;
986 case IMAGE_POSITIVE_INTEGER_VALUE:
987 if (!INTEGERP (value) || XINT (value) <= 0)
988 return 0;
989 break;
991 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
992 if (INTEGERP (value) && XINT (value) >= 0)
993 break;
994 if (CONSP (value)
995 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
996 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
997 break;
998 return 0;
1000 case IMAGE_ASCENT_VALUE:
1001 if (SYMBOLP (value) && EQ (value, Qcenter))
1002 break;
1003 else if (INTEGERP (value)
1004 && XINT (value) >= 0
1005 && XINT (value) <= 100)
1006 break;
1007 return 0;
1009 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1010 if (!INTEGERP (value) || XINT (value) < 0)
1011 return 0;
1012 break;
1014 case IMAGE_DONT_CHECK_VALUE_TYPE:
1015 break;
1017 case IMAGE_FUNCTION_VALUE:
1018 value = indirect_function (value);
1019 if (SUBRP (value)
1020 || COMPILEDP (value)
1021 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1022 break;
1023 return 0;
1025 case IMAGE_NUMBER_VALUE:
1026 if (!INTEGERP (value) && !FLOATP (value))
1027 return 0;
1028 break;
1030 case IMAGE_INTEGER_VALUE:
1031 if (!INTEGERP (value))
1032 return 0;
1033 break;
1035 case IMAGE_BOOL_VALUE:
1036 if (!NILP (value) && !EQ (value, Qt))
1037 return 0;
1038 break;
1040 default:
1041 abort ();
1042 break;
1045 if (EQ (key, QCtype) && !EQ (type, value))
1046 return 0;
1049 /* Check that all mandatory fields are present. */
1050 for (i = 0; i < nkeywords; ++i)
1051 if (keywords[i].mandatory_p && keywords[i].count == 0)
1052 return 0;
1054 return NILP (plist);
1058 /* Return the value of KEY in image specification SPEC. Value is nil
1059 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1060 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1062 static Lisp_Object
1063 image_spec_value (spec, key, found)
1064 Lisp_Object spec, key;
1065 int *found;
1067 Lisp_Object tail;
1069 xassert (valid_image_p (spec));
1071 for (tail = XCDR (spec);
1072 CONSP (tail) && CONSP (XCDR (tail));
1073 tail = XCDR (XCDR (tail)))
1075 if (EQ (XCAR (tail), key))
1077 if (found)
1078 *found = 1;
1079 return XCAR (XCDR (tail));
1083 if (found)
1084 *found = 0;
1085 return Qnil;
1089 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1090 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1091 PIXELS non-nil means return the size in pixels, otherwise return the
1092 size in canonical character units.
1093 FRAME is the frame on which the image will be displayed. FRAME nil
1094 or omitted means use the selected frame. */)
1095 (spec, pixels, frame)
1096 Lisp_Object spec, pixels, frame;
1098 Lisp_Object size;
1100 size = Qnil;
1101 if (valid_image_p (spec))
1103 struct frame *f = check_x_frame (frame);
1104 int id = lookup_image (f, spec);
1105 struct image *img = IMAGE_FROM_ID (f, id);
1106 int width = img->width + 2 * img->hmargin;
1107 int height = img->height + 2 * img->vmargin;
1109 if (NILP (pixels))
1110 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1111 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1112 else
1113 size = Fcons (make_number (width), make_number (height));
1115 else
1116 error ("Invalid image specification");
1118 return size;
1122 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1123 doc: /* Return t if image SPEC has a mask bitmap.
1124 FRAME is the frame on which the image will be displayed. FRAME nil
1125 or omitted means use the selected frame. */)
1126 (spec, frame)
1127 Lisp_Object spec, frame;
1129 Lisp_Object mask;
1131 mask = Qnil;
1132 if (valid_image_p (spec))
1134 struct frame *f = check_x_frame (frame);
1135 int id = lookup_image (f, spec);
1136 struct image *img = IMAGE_FROM_ID (f, id);
1137 if (img->mask)
1138 mask = Qt;
1140 else
1141 error ("Invalid image specification");
1143 return mask;
1147 /***********************************************************************
1148 Image type independent image structures
1149 ***********************************************************************/
1151 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1152 static void free_image P_ ((struct frame *f, struct image *img));
1153 static int check_image_size P_ ((struct frame *f, int width, int height));
1155 #define MAX_IMAGE_SIZE 6.0
1156 Lisp_Object Vmax_image_size;
1158 /* Allocate and return a new image structure for image specification
1159 SPEC. SPEC has a hash value of HASH. */
1161 static struct image *
1162 make_image (spec, hash)
1163 Lisp_Object spec;
1164 unsigned hash;
1166 struct image *img = (struct image *) xmalloc (sizeof *img);
1168 xassert (valid_image_p (spec));
1169 bzero (img, sizeof *img);
1170 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1171 xassert (img->type != NULL);
1172 img->spec = spec;
1173 img->data.lisp_val = Qnil;
1174 img->ascent = DEFAULT_IMAGE_ASCENT;
1175 img->hash = hash;
1176 return img;
1180 /* Free image IMG which was used on frame F, including its resources. */
1182 static void
1183 free_image (f, img)
1184 struct frame *f;
1185 struct image *img;
1187 if (img)
1189 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1191 /* Remove IMG from the hash table of its cache. */
1192 if (img->prev)
1193 img->prev->next = img->next;
1194 else
1195 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1197 if (img->next)
1198 img->next->prev = img->prev;
1200 c->images[img->id] = NULL;
1202 /* Free resources, then free IMG. */
1203 img->type->free (f, img);
1204 xfree (img);
1208 /* Return 1 if the given widths and heights are valid for display;
1209 otherwise, return 0. */
1212 check_image_size (f, width, height)
1213 struct frame *f;
1214 int width;
1215 int height;
1217 int w, h;
1219 if (width <= 0 || height <= 0)
1220 return 0;
1222 if (INTEGERP (Vmax_image_size))
1223 w = h = XINT (Vmax_image_size);
1224 else if (FLOATP (Vmax_image_size))
1226 if (f != NULL)
1228 w = FRAME_PIXEL_WIDTH (f);
1229 h = FRAME_PIXEL_HEIGHT (f);
1231 else
1232 w = h = 1024; /* Arbitrary size for unknown frame. */
1233 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1234 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1236 else
1237 return 1;
1239 return (width <= w && height <= h);
1242 /* Prepare image IMG for display on frame F. Must be called before
1243 drawing an image. */
1245 void
1246 prepare_image_for_display (f, img)
1247 struct frame *f;
1248 struct image *img;
1250 EMACS_TIME t;
1252 /* We're about to display IMG, so set its timestamp to `now'. */
1253 EMACS_GET_TIME (t);
1254 img->timestamp = EMACS_SECS (t);
1256 /* If IMG doesn't have a pixmap yet, load it now, using the image
1257 type dependent loader function. */
1258 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1259 img->load_failed_p = img->type->load (f, img) == 0;
1261 #if defined (MAC_OS) && USE_CG_DRAWING
1262 if (!img->load_failed_p && img->data.ptr_val == NULL)
1264 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1265 if (img->data.ptr_val == NULL)
1267 img->load_failed_p = 1;
1268 img->type->free (f, img);
1271 #endif
1275 /* Value is the number of pixels for the ascent of image IMG when
1276 drawn in face FACE. */
1279 image_ascent (img, face, slice)
1280 struct image *img;
1281 struct face *face;
1282 struct glyph_slice *slice;
1284 int height;
1285 int ascent;
1287 if (slice->height == img->height)
1288 height = img->height + img->vmargin;
1289 else if (slice->y == 0)
1290 height = slice->height + img->vmargin;
1291 else
1292 height = slice->height;
1294 if (img->ascent == CENTERED_IMAGE_ASCENT)
1296 if (face->font)
1298 #ifdef HAVE_NTGUI
1299 /* W32 specific version. Why?. ++kfs */
1300 ascent = height / 2 - (FONT_DESCENT(face->font)
1301 - FONT_BASE(face->font)) / 2;
1302 #else
1303 /* This expression is arranged so that if the image can't be
1304 exactly centered, it will be moved slightly up. This is
1305 because a typical font is `top-heavy' (due to the presence
1306 uppercase letters), so the image placement should err towards
1307 being top-heavy too. It also just generally looks better. */
1308 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1309 #endif /* HAVE_NTGUI */
1311 else
1312 ascent = height / 2;
1314 else
1315 ascent = (int) (height * img->ascent / 100.0);
1317 return ascent;
1321 /* Image background colors. */
1323 /* Find the "best" corner color of a bitmap.
1324 On W32, XIMG is assumed to a device context with the bitmap selected. */
1326 static RGB_PIXEL_COLOR
1327 four_corners_best (ximg, width, height)
1328 XImagePtr_or_DC ximg;
1329 unsigned long width, height;
1331 RGB_PIXEL_COLOR corners[4], best;
1332 int i, best_count;
1334 /* Get the colors at the corners of ximg. */
1335 corners[0] = GET_PIXEL (ximg, 0, 0);
1336 corners[1] = GET_PIXEL (ximg, width - 1, 0);
1337 corners[2] = GET_PIXEL (ximg, width - 1, height - 1);
1338 corners[3] = GET_PIXEL (ximg, 0, height - 1);
1340 /* Choose the most frequently found color as background. */
1341 for (i = best_count = 0; i < 4; ++i)
1343 int j, n;
1345 for (j = n = 0; j < 4; ++j)
1346 if (corners[i] == corners[j])
1347 ++n;
1349 if (n > best_count)
1350 best = corners[i], best_count = n;
1353 return best;
1356 /* Portability macros */
1358 #ifdef HAVE_NTGUI
1360 #define Destroy_Image(img_dc, prev) \
1361 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1363 #define Free_Pixmap(display, pixmap) \
1364 DeleteObject (pixmap)
1366 #else
1368 #define Destroy_Image(ximg, dummy) \
1369 XDestroyImage (ximg)
1371 #define Free_Pixmap(display, pixmap) \
1372 XFreePixmap (display, pixmap)
1374 #endif /* HAVE_NTGUI */
1377 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1378 it is guessed heuristically. If non-zero, XIMG is an existing
1379 XImage object (or device context with the image selected on W32) to
1380 use for the heuristic. */
1382 RGB_PIXEL_COLOR
1383 image_background (img, f, ximg)
1384 struct image *img;
1385 struct frame *f;
1386 XImagePtr_or_DC ximg;
1388 if (! img->background_valid)
1389 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1391 int free_ximg = !ximg;
1392 #ifdef HAVE_NTGUI
1393 HGDIOBJ prev;
1394 #endif /* HAVE_NTGUI */
1396 if (free_ximg)
1398 #ifndef HAVE_NTGUI
1399 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1400 0, 0, img->width, img->height, ~0, ZPixmap);
1401 #else
1402 HDC frame_dc = get_frame_dc (f);
1403 ximg = CreateCompatibleDC (frame_dc);
1404 release_frame_dc (f, frame_dc);
1405 prev = SelectObject (ximg, img->pixmap);
1406 #endif /* !HAVE_NTGUI */
1409 img->background = four_corners_best (ximg, img->width, img->height);
1411 if (free_ximg)
1412 Destroy_Image (ximg, prev);
1414 img->background_valid = 1;
1417 return img->background;
1420 /* Return the `background_transparent' field of IMG. If IMG doesn't
1421 have one yet, it is guessed heuristically. If non-zero, MASK is an
1422 existing XImage object to use for the heuristic. */
1425 image_background_transparent (img, f, mask)
1426 struct image *img;
1427 struct frame *f;
1428 XImagePtr_or_DC mask;
1430 if (! img->background_transparent_valid)
1431 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1433 if (img->mask)
1435 int free_mask = !mask;
1436 #ifdef HAVE_NTGUI
1437 HGDIOBJ prev;
1438 #endif /* HAVE_NTGUI */
1440 if (free_mask)
1442 #ifndef HAVE_NTGUI
1443 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1444 0, 0, img->width, img->height, ~0, ZPixmap);
1445 #else
1446 HDC frame_dc = get_frame_dc (f);
1447 mask = CreateCompatibleDC (frame_dc);
1448 release_frame_dc (f, frame_dc);
1449 prev = SelectObject (mask, img->mask);
1450 #endif /* HAVE_NTGUI */
1453 img->background_transparent
1454 = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN);
1456 if (free_mask)
1457 Destroy_Image (mask, prev);
1459 else
1460 img->background_transparent = 0;
1462 img->background_transparent_valid = 1;
1465 return img->background_transparent;
1469 /***********************************************************************
1470 Helper functions for X image types
1471 ***********************************************************************/
1473 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1474 int, int));
1475 static void x_clear_image P_ ((struct frame *f, struct image *img));
1476 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1477 struct image *img,
1478 Lisp_Object color_name,
1479 unsigned long dflt));
1482 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1483 free the pixmap if any. MASK_P non-zero means clear the mask
1484 pixmap if any. COLORS_P non-zero means free colors allocated for
1485 the image, if any. */
1487 static void
1488 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1489 struct frame *f;
1490 struct image *img;
1491 int pixmap_p, mask_p, colors_p;
1493 if (pixmap_p && img->pixmap)
1495 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1496 img->pixmap = NO_PIXMAP;
1497 img->background_valid = 0;
1500 if (mask_p && img->mask)
1502 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1503 img->mask = NO_PIXMAP;
1504 img->background_transparent_valid = 0;
1507 if (colors_p && img->ncolors)
1509 /* MAC_TODO: color table support. */
1510 /* W32_TODO: color table support. */
1511 #ifdef HAVE_X_WINDOWS
1512 x_free_colors (f, img->colors, img->ncolors);
1513 #endif /* HAVE_X_WINDOWS */
1514 xfree (img->colors);
1515 img->colors = NULL;
1516 img->ncolors = 0;
1519 #if defined (MAC_OS) && USE_CG_DRAWING
1520 if (img->data.ptr_val)
1522 CGImageRelease (img->data.ptr_val);
1523 img->data.ptr_val = NULL;
1525 #endif
1528 /* Free X resources of image IMG which is used on frame F. */
1530 static void
1531 x_clear_image (f, img)
1532 struct frame *f;
1533 struct image *img;
1535 BLOCK_INPUT;
1536 x_clear_image_1 (f, img, 1, 1, 1);
1537 UNBLOCK_INPUT;
1541 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1542 cannot be allocated, use DFLT. Add a newly allocated color to
1543 IMG->colors, so that it can be freed again. Value is the pixel
1544 color. */
1546 static unsigned long
1547 x_alloc_image_color (f, img, color_name, dflt)
1548 struct frame *f;
1549 struct image *img;
1550 Lisp_Object color_name;
1551 unsigned long dflt;
1553 XColor color;
1554 unsigned long result;
1556 xassert (STRINGP (color_name));
1558 if (x_defined_color (f, SDATA (color_name), &color, 1))
1560 /* This isn't called frequently so we get away with simply
1561 reallocating the color vector to the needed size, here. */
1562 ++img->ncolors;
1563 img->colors =
1564 (unsigned long *) xrealloc (img->colors,
1565 img->ncolors * sizeof *img->colors);
1566 img->colors[img->ncolors - 1] = color.pixel;
1567 result = color.pixel;
1569 else
1570 result = dflt;
1572 return result;
1577 /***********************************************************************
1578 Image Cache
1579 ***********************************************************************/
1581 static void cache_image P_ ((struct frame *f, struct image *img));
1582 static void postprocess_image P_ ((struct frame *, struct image *));
1584 /* Return a new, initialized image cache that is allocated from the
1585 heap. Call free_image_cache to free an image cache. */
1587 struct image_cache *
1588 make_image_cache ()
1590 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1591 int size;
1593 bzero (c, sizeof *c);
1594 c->size = 50;
1595 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1596 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1597 c->buckets = (struct image **) xmalloc (size);
1598 bzero (c->buckets, size);
1599 return c;
1603 /* Free image cache of frame F. Be aware that X frames share images
1604 caches. */
1606 void
1607 free_image_cache (f)
1608 struct frame *f;
1610 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1611 if (c)
1613 int i;
1615 /* Cache should not be referenced by any frame when freed. */
1616 xassert (c->refcount == 0);
1618 for (i = 0; i < c->used; ++i)
1619 free_image (f, c->images[i]);
1620 xfree (c->images);
1621 xfree (c->buckets);
1622 xfree (c);
1623 FRAME_X_IMAGE_CACHE (f) = NULL;
1628 /* Clear image cache of frame F. FORCE_P non-zero means free all
1629 images. FORCE_P zero means clear only images that haven't been
1630 displayed for some time. Should be called from time to time to
1631 reduce the number of loaded images. If image-eviction-seconds is
1632 non-nil, this frees images in the cache which weren't displayed for
1633 at least that many seconds. */
1635 void
1636 clear_image_cache (f, force_p)
1637 struct frame *f;
1638 int force_p;
1640 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1642 if (c && INTEGERP (Vimage_cache_eviction_delay))
1644 EMACS_TIME t;
1645 unsigned long old;
1646 int i, nfreed;
1648 EMACS_GET_TIME (t);
1649 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1651 /* Block input so that we won't be interrupted by a SIGIO
1652 while being in an inconsistent state. */
1653 BLOCK_INPUT;
1655 for (i = nfreed = 0; i < c->used; ++i)
1657 struct image *img = c->images[i];
1658 if (img != NULL
1659 && (force_p || img->timestamp < old))
1661 free_image (f, img);
1662 ++nfreed;
1666 /* We may be clearing the image cache because, for example,
1667 Emacs was iconified for a longer period of time. In that
1668 case, current matrices may still contain references to
1669 images freed above. So, clear these matrices. */
1670 if (nfreed)
1672 Lisp_Object tail, frame;
1674 FOR_EACH_FRAME (tail, frame)
1676 struct frame *f = XFRAME (frame);
1677 if (FRAME_WINDOW_P (f)
1678 && FRAME_X_IMAGE_CACHE (f) == c)
1679 clear_current_matrices (f);
1682 ++windows_or_buffers_changed;
1685 UNBLOCK_INPUT;
1690 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1691 0, 1, 0,
1692 doc: /* Clear the image cache of FRAME.
1693 FRAME nil or omitted means use the selected frame.
1694 FRAME t means clear the image caches of all frames. */)
1695 (frame)
1696 Lisp_Object frame;
1698 if (EQ (frame, Qt))
1700 Lisp_Object tail;
1702 FOR_EACH_FRAME (tail, frame)
1703 if (FRAME_WINDOW_P (XFRAME (frame)))
1704 clear_image_cache (XFRAME (frame), 1);
1706 else
1707 clear_image_cache (check_x_frame (frame), 1);
1709 return Qnil;
1713 /* Compute masks and transform image IMG on frame F, as specified
1714 by the image's specification, */
1716 static void
1717 postprocess_image (f, img)
1718 struct frame *f;
1719 struct image *img;
1721 /* Manipulation of the image's mask. */
1722 if (img->pixmap)
1724 Lisp_Object conversion, spec;
1725 Lisp_Object mask;
1727 spec = img->spec;
1729 /* `:heuristic-mask t'
1730 `:mask heuristic'
1731 means build a mask heuristically.
1732 `:heuristic-mask (R G B)'
1733 `:mask (heuristic (R G B))'
1734 means build a mask from color (R G B) in the
1735 image.
1736 `:mask nil'
1737 means remove a mask, if any. */
1739 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1740 if (!NILP (mask))
1741 x_build_heuristic_mask (f, img, mask);
1742 else
1744 int found_p;
1746 mask = image_spec_value (spec, QCmask, &found_p);
1748 if (EQ (mask, Qheuristic))
1749 x_build_heuristic_mask (f, img, Qt);
1750 else if (CONSP (mask)
1751 && EQ (XCAR (mask), Qheuristic))
1753 if (CONSP (XCDR (mask)))
1754 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1755 else
1756 x_build_heuristic_mask (f, img, XCDR (mask));
1758 else if (NILP (mask) && found_p && img->mask)
1760 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1761 img->mask = NO_PIXMAP;
1766 /* Should we apply an image transformation algorithm? */
1767 conversion = image_spec_value (spec, QCconversion, NULL);
1768 if (EQ (conversion, Qdisabled))
1769 x_disable_image (f, img);
1770 else if (EQ (conversion, Qlaplace))
1771 x_laplace (f, img);
1772 else if (EQ (conversion, Qemboss))
1773 x_emboss (f, img);
1774 else if (CONSP (conversion)
1775 && EQ (XCAR (conversion), Qedge_detection))
1777 Lisp_Object tem;
1778 tem = XCDR (conversion);
1779 if (CONSP (tem))
1780 x_edge_detection (f, img,
1781 Fplist_get (tem, QCmatrix),
1782 Fplist_get (tem, QCcolor_adjustment));
1788 /* Return the id of image with Lisp specification SPEC on frame F.
1789 SPEC must be a valid Lisp image specification (see valid_image_p). */
1792 lookup_image (f, spec)
1793 struct frame *f;
1794 Lisp_Object spec;
1796 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1797 struct image *img;
1798 int i;
1799 unsigned hash;
1800 struct gcpro gcpro1;
1801 EMACS_TIME now;
1803 /* F must be a window-system frame, and SPEC must be a valid image
1804 specification. */
1805 xassert (FRAME_WINDOW_P (f));
1806 xassert (valid_image_p (spec));
1808 GCPRO1 (spec);
1810 /* Look up SPEC in the hash table of the image cache. */
1811 hash = sxhash (spec, 0);
1812 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1814 for (img = c->buckets[i]; img; img = img->next)
1815 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
1816 break;
1818 if (img && img->load_failed_p)
1820 free_image (f, img);
1821 img = NULL;
1824 /* If not found, create a new image and cache it. */
1825 if (img == NULL)
1827 extern Lisp_Object Qpostscript;
1829 BLOCK_INPUT;
1830 img = make_image (spec, hash);
1831 cache_image (f, img);
1832 img->load_failed_p = img->type->load (f, img) == 0;
1834 /* If we can't load the image, and we don't have a width and
1835 height, use some arbitrary width and height so that we can
1836 draw a rectangle for it. */
1837 if (img->load_failed_p)
1839 Lisp_Object value;
1841 value = image_spec_value (spec, QCwidth, NULL);
1842 img->width = (INTEGERP (value)
1843 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1844 value = image_spec_value (spec, QCheight, NULL);
1845 img->height = (INTEGERP (value)
1846 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1848 else
1850 /* Handle image type independent image attributes
1851 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1852 `:background COLOR'. */
1853 Lisp_Object ascent, margin, relief, bg;
1855 ascent = image_spec_value (spec, QCascent, NULL);
1856 if (INTEGERP (ascent))
1857 img->ascent = XFASTINT (ascent);
1858 else if (EQ (ascent, Qcenter))
1859 img->ascent = CENTERED_IMAGE_ASCENT;
1861 margin = image_spec_value (spec, QCmargin, NULL);
1862 if (INTEGERP (margin) && XINT (margin) >= 0)
1863 img->vmargin = img->hmargin = XFASTINT (margin);
1864 else if (CONSP (margin) && INTEGERP (XCAR (margin))
1865 && INTEGERP (XCDR (margin)))
1867 if (XINT (XCAR (margin)) > 0)
1868 img->hmargin = XFASTINT (XCAR (margin));
1869 if (XINT (XCDR (margin)) > 0)
1870 img->vmargin = XFASTINT (XCDR (margin));
1873 relief = image_spec_value (spec, QCrelief, NULL);
1874 if (INTEGERP (relief))
1876 img->relief = XINT (relief);
1877 img->hmargin += abs (img->relief);
1878 img->vmargin += abs (img->relief);
1881 if (! img->background_valid)
1883 bg = image_spec_value (img->spec, QCbackground, NULL);
1884 if (!NILP (bg))
1886 img->background
1887 = x_alloc_image_color (f, img, bg,
1888 FRAME_BACKGROUND_PIXEL (f));
1889 img->background_valid = 1;
1893 /* Do image transformations and compute masks, unless we
1894 don't have the image yet. */
1895 if (!EQ (*img->type->type, Qpostscript))
1896 postprocess_image (f, img);
1899 UNBLOCK_INPUT;
1902 /* We're using IMG, so set its timestamp to `now'. */
1903 EMACS_GET_TIME (now);
1904 img->timestamp = EMACS_SECS (now);
1906 UNGCPRO;
1908 /* Value is the image id. */
1909 return img->id;
1913 /* Cache image IMG in the image cache of frame F. */
1915 static void
1916 cache_image (f, img)
1917 struct frame *f;
1918 struct image *img;
1920 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1921 int i;
1923 /* Find a free slot in c->images. */
1924 for (i = 0; i < c->used; ++i)
1925 if (c->images[i] == NULL)
1926 break;
1928 /* If no free slot found, maybe enlarge c->images. */
1929 if (i == c->used && c->used == c->size)
1931 c->size *= 2;
1932 c->images = (struct image **) xrealloc (c->images,
1933 c->size * sizeof *c->images);
1936 /* Add IMG to c->images, and assign IMG an id. */
1937 c->images[i] = img;
1938 img->id = i;
1939 if (i == c->used)
1940 ++c->used;
1942 /* Add IMG to the cache's hash table. */
1943 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1944 img->next = c->buckets[i];
1945 if (img->next)
1946 img->next->prev = img;
1947 img->prev = NULL;
1948 c->buckets[i] = img;
1952 /* Call FN on every image in the image cache of frame F. Used to mark
1953 Lisp Objects in the image cache. */
1955 void
1956 forall_images_in_image_cache (f, fn)
1957 struct frame *f;
1958 void (*fn) P_ ((struct image *img));
1960 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f))
1962 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1963 if (c)
1965 int i;
1966 for (i = 0; i < c->used; ++i)
1967 if (c->images[i])
1968 fn (c->images[i]);
1975 /***********************************************************************
1976 X / MAC / W32 support code
1977 ***********************************************************************/
1979 #ifdef HAVE_NTGUI
1981 /* Macro for defining functions that will be loaded from image DLLs. */
1982 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
1984 /* Macro for loading those image functions from the library. */
1985 #define LOAD_IMGLIB_FN(lib,func) { \
1986 fn_##func = (void *) GetProcAddress (lib, #func); \
1987 if (!fn_##func) return 0; \
1990 /* Load a DLL implementing an image type.
1991 The `image-library-alist' variable associates a symbol,
1992 identifying an image type, to a list of possible filenames.
1993 The function returns NULL if no library could be loaded for
1994 the given image type, or if the library was previously loaded;
1995 else the handle of the DLL. */
1996 static HMODULE
1997 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
1999 HMODULE library = NULL;
2001 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2003 Lisp_Object dlls = Fassq (type, libraries);
2005 if (CONSP (dlls))
2006 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2008 CHECK_STRING_CAR (dlls);
2009 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2010 break;
2014 return library;
2017 #endif /* HAVE_NTGUI */
2019 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2020 XImagePtr *, Pixmap *));
2021 static void x_destroy_x_image P_ ((XImagePtr));
2022 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2025 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2026 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2027 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2028 via xmalloc. Print error messages via image_error if an error
2029 occurs. Value is non-zero if successful.
2031 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2032 should indicate the bit depth of the image. */
2034 static int
2035 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2036 struct frame *f;
2037 int width, height, depth;
2038 XImagePtr *ximg;
2039 Pixmap *pixmap;
2041 #ifdef HAVE_X_WINDOWS
2042 Display *display = FRAME_X_DISPLAY (f);
2043 Window window = FRAME_X_WINDOW (f);
2044 Screen *screen = FRAME_X_SCREEN (f);
2046 xassert (interrupt_input_blocked);
2048 if (depth <= 0)
2049 depth = DefaultDepthOfScreen (screen);
2050 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2051 depth, ZPixmap, 0, NULL, width, height,
2052 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2053 if (*ximg == NULL)
2055 image_error ("Unable to allocate X image", Qnil, Qnil);
2056 return 0;
2059 /* Allocate image raster. */
2060 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2062 /* Allocate a pixmap of the same size. */
2063 *pixmap = XCreatePixmap (display, window, width, height, depth);
2064 if (*pixmap == NO_PIXMAP)
2066 x_destroy_x_image (*ximg);
2067 *ximg = NULL;
2068 image_error ("Unable to create X pixmap", Qnil, Qnil);
2069 return 0;
2072 return 1;
2073 #endif /* HAVE_X_WINDOWS */
2075 #ifdef HAVE_NTGUI
2077 BITMAPINFOHEADER *header;
2078 HDC hdc;
2079 int scanline_width_bits;
2080 int remainder;
2081 int palette_colors = 0;
2083 if (depth == 0)
2084 depth = 24;
2086 if (depth != 1 && depth != 4 && depth != 8
2087 && depth != 16 && depth != 24 && depth != 32)
2089 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2090 return 0;
2093 scanline_width_bits = width * depth;
2094 remainder = scanline_width_bits % 32;
2096 if (remainder)
2097 scanline_width_bits += 32 - remainder;
2099 /* Bitmaps with a depth less than 16 need a palette. */
2100 /* BITMAPINFO structure already contains the first RGBQUAD. */
2101 if (depth < 16)
2102 palette_colors = 1 << depth - 1;
2104 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2105 if (*ximg == NULL)
2107 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2108 return 0;
2111 header = &((*ximg)->info.bmiHeader);
2112 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2113 header->biSize = sizeof (*header);
2114 header->biWidth = width;
2115 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2116 header->biPlanes = 1;
2117 header->biBitCount = depth;
2118 header->biCompression = BI_RGB;
2119 header->biClrUsed = palette_colors;
2121 /* TODO: fill in palette. */
2122 if (depth == 1)
2124 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2125 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2126 (*ximg)->info.bmiColors[0].rgbRed = 0;
2127 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2128 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2129 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2130 (*ximg)->info.bmiColors[1].rgbRed = 255;
2131 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2134 hdc = get_frame_dc (f);
2136 /* Create a DIBSection and raster array for the bitmap,
2137 and store its handle in *pixmap. */
2138 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2139 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2140 /* casting avoids a GCC warning */
2141 (void **)&((*ximg)->data), NULL, 0);
2143 /* Realize display palette and garbage all frames. */
2144 release_frame_dc (f, hdc);
2146 if (*pixmap == NULL)
2148 DWORD err = GetLastError();
2149 Lisp_Object errcode;
2150 /* All system errors are < 10000, so the following is safe. */
2151 XSETINT (errcode, (int) err);
2152 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2153 x_destroy_x_image (*ximg);
2154 return 0;
2157 return 1;
2159 #endif /* HAVE_NTGUI */
2161 #ifdef MAC_OS
2162 Display *display = FRAME_X_DISPLAY (f);
2163 Window window = FRAME_X_WINDOW (f);
2165 xassert (interrupt_input_blocked);
2167 /* Allocate a pixmap of the same size. */
2168 *pixmap = XCreatePixmap (display, window, width, height, depth);
2169 if (*pixmap == NO_PIXMAP)
2171 *ximg = NULL;
2172 image_error ("Unable to create X pixmap", Qnil, Qnil);
2173 return 0;
2176 LockPixels (GetGWorldPixMap (*pixmap));
2177 *ximg = *pixmap;
2178 return 1;
2180 #endif /* MAC_OS */
2184 /* Destroy XImage XIMG. Free XIMG->data. */
2186 static void
2187 x_destroy_x_image (ximg)
2188 XImagePtr ximg;
2190 xassert (interrupt_input_blocked);
2191 if (ximg)
2193 #ifdef HAVE_X_WINDOWS
2194 xfree (ximg->data);
2195 ximg->data = NULL;
2196 XDestroyImage (ximg);
2197 #endif /* HAVE_X_WINDOWS */
2198 #ifdef HAVE_NTGUI
2199 /* Data will be freed by DestroyObject. */
2200 ximg->data = NULL;
2201 xfree (ximg);
2202 #endif /* HAVE_NTGUI */
2203 #ifdef MAC_OS
2204 XDestroyImage (ximg);
2205 #endif /* MAC_OS */
2210 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2211 are width and height of both the image and pixmap. */
2213 static void
2214 x_put_x_image (f, ximg, pixmap, width, height)
2215 struct frame *f;
2216 XImagePtr ximg;
2217 Pixmap pixmap;
2218 int width, height;
2220 #ifdef HAVE_X_WINDOWS
2221 GC gc;
2223 xassert (interrupt_input_blocked);
2224 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2225 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2226 XFreeGC (FRAME_X_DISPLAY (f), gc);
2227 #endif /* HAVE_X_WINDOWS */
2229 #ifdef HAVE_NTGUI
2230 #if 0 /* I don't think this is necessary looking at where it is used. */
2231 HDC hdc = get_frame_dc (f);
2232 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2233 release_frame_dc (f, hdc);
2234 #endif
2235 #endif /* HAVE_NTGUI */
2237 #ifdef MAC_OS
2238 xassert (ximg == pixmap);
2239 #endif /* MAC_OS */
2243 /***********************************************************************
2244 File Handling
2245 ***********************************************************************/
2247 static unsigned char *slurp_file P_ ((char *, int *));
2250 /* Find image file FILE. Look in data-directory, then
2251 x-bitmap-file-path. Value is the encoded full name of the file
2252 found, or nil if not found. */
2254 Lisp_Object
2255 x_find_image_file (file)
2256 Lisp_Object file;
2258 Lisp_Object file_found, search_path;
2259 struct gcpro gcpro1, gcpro2;
2260 int fd;
2262 file_found = Qnil;
2263 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
2264 GCPRO2 (file_found, search_path);
2266 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2267 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2269 if (fd == -1)
2270 file_found = Qnil;
2271 else
2273 file_found = ENCODE_FILE (file_found);
2274 close (fd);
2277 UNGCPRO;
2278 return file_found;
2282 /* Read FILE into memory. Value is a pointer to a buffer allocated
2283 with xmalloc holding FILE's contents. Value is null if an error
2284 occurred. *SIZE is set to the size of the file. */
2286 static unsigned char *
2287 slurp_file (file, size)
2288 char *file;
2289 int *size;
2291 FILE *fp = NULL;
2292 unsigned char *buf = NULL;
2293 struct stat st;
2295 if (stat (file, &st) == 0
2296 && (fp = fopen (file, "rb")) != NULL
2297 && (buf = (unsigned char *) xmalloc (st.st_size),
2298 fread (buf, 1, st.st_size, fp) == st.st_size))
2300 *size = st.st_size;
2301 fclose (fp);
2303 else
2305 if (fp)
2306 fclose (fp);
2307 if (buf)
2309 xfree (buf);
2310 buf = NULL;
2314 return buf;
2319 #ifdef MAC_OS
2321 /***********************************************************************
2322 MAC Image Load Functions
2323 ***********************************************************************/
2325 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2326 OSType));
2327 #ifdef MAC_OSX
2328 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2329 #endif
2331 static OSErr
2332 find_image_fsspec (specified_file, file, fss)
2333 Lisp_Object specified_file, *file;
2334 FSSpec *fss;
2336 OSErr err;
2337 AEDesc desc;
2339 *file = x_find_image_file (specified_file);
2340 if (!STRINGP (*file))
2341 return fnfErr; /* file or directory not found;
2342 incomplete pathname */
2343 /* Try to open the image file. */
2344 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2345 SBYTES (*file), typeFSS, &desc);
2346 if (err == noErr)
2348 #if TARGET_API_MAC_CARBON
2349 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2350 #else
2351 *fss = *(FSSpec *)(*(desc.dataHandle));
2352 #endif
2353 AEDisposeDesc (&desc);
2355 return err;
2358 static int
2359 image_load_qt_1 (f, img, type, fss, dh)
2360 struct frame *f;
2361 struct image *img;
2362 OSType type;
2363 FSSpec *fss;
2364 Handle dh;
2366 OSErr err;
2367 GraphicsImportComponent gi;
2368 Rect rect;
2369 int width, height;
2370 ImageDescriptionHandle desc_handle;
2371 short draw_all_pixels;
2372 Lisp_Object specified_bg;
2373 XColor color;
2374 XImagePtr ximg;
2375 RGBColor bg_color;
2377 err = OpenADefaultComponent (GraphicsImporterComponentType,
2378 type, &gi);
2379 if (err != noErr)
2381 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2382 return 0;
2384 if (dh == NULL)
2386 /* read from file system spec */
2387 err = GraphicsImportSetDataFile (gi, fss);
2388 if (err != noErr)
2390 image_error ("Cannot set fsspec to graphics importer for '%s'",
2391 img->spec, Qnil);
2392 goto error;
2395 else
2397 /* read from data handle */
2398 err = GraphicsImportSetDataHandle (gi, dh);
2399 if (err != noErr)
2401 image_error ("Cannot set data handle to graphics importer for `%s'",
2402 img->spec, Qnil);
2403 goto error;
2406 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2407 if (err != noErr || desc_handle == NULL)
2409 image_error ("Error reading `%s'", img->spec, Qnil);
2410 goto error;
2412 width = img->width = (*desc_handle)->width;
2413 height = img->height = (*desc_handle)->height;
2414 DisposeHandle ((Handle)desc_handle);
2416 if (!check_image_size (f, width, height))
2418 image_error ("Invalid image size", Qnil, Qnil);
2419 goto error;
2422 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2423 #if 0
2424 /* Don't check the error code here. It may have an undocumented
2425 value -32766. */
2426 if (err != noErr)
2428 image_error ("Error reading `%s'", img->spec, Qnil);
2429 goto error;
2431 #endif
2432 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2434 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2435 if (!STRINGP (specified_bg) ||
2436 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2438 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2439 color.red = RED16_FROM_ULONG (color.pixel);
2440 color.green = GREEN16_FROM_ULONG (color.pixel);
2441 color.blue = BLUE16_FROM_ULONG (color.pixel);
2445 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2446 goto error;
2447 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2449 CGrafPtr old_port;
2450 GDHandle old_gdh;
2452 GetGWorld (&old_port, &old_gdh);
2453 SetGWorld (ximg, NULL);
2454 bg_color.red = color.red;
2455 bg_color.green = color.green;
2456 bg_color.blue = color.blue;
2457 RGBBackColor (&bg_color);
2458 #if TARGET_API_MAC_CARBON
2459 GetPortBounds (ximg, &rect);
2460 EraseRect (&rect);
2461 #else
2462 EraseRect (&(ximg->portRect));
2463 #endif
2464 SetGWorld (old_port, old_gdh);
2466 GraphicsImportSetGWorld (gi, ximg, NULL);
2467 GraphicsImportDraw (gi);
2468 CloseComponent (gi);
2470 /* Maybe fill in the background field while we have ximg handy. */
2471 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2472 IMAGE_BACKGROUND (img, f, ximg);
2474 /* Put the image into the pixmap. */
2475 x_put_x_image (f, ximg, img->pixmap, width, height);
2476 x_destroy_x_image (ximg);
2477 return 1;
2479 error:
2480 CloseComponent (gi);
2481 return 0;
2485 /* Load an image using the QuickTime Graphics Importer.
2486 Note: The alpha channel does not work for PNG images. */
2487 static int
2488 image_load_quicktime (f, img, type)
2489 struct frame *f;
2490 struct image *img;
2491 OSType type;
2493 Lisp_Object specified_file;
2494 Lisp_Object specified_data;
2495 OSErr err;
2497 specified_file = image_spec_value (img->spec, QCfile, NULL);
2498 specified_data = image_spec_value (img->spec, QCdata, NULL);
2500 if (NILP (specified_data))
2502 /* Read from a file */
2503 Lisp_Object file;
2504 FSSpec fss;
2506 err = find_image_fsspec (specified_file, &file, &fss);
2507 if (err != noErr)
2509 if (err == fnfErr)
2510 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2511 else
2512 image_error ("Cannot open `%s'", file, Qnil);
2513 return 0;
2515 return image_load_qt_1 (f, img, type, &fss, NULL);
2517 else
2519 /* Memory source! */
2520 int success_p;
2521 Handle dh;
2523 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2524 if (err != noErr)
2526 image_error ("Cannot allocate data handle for `%s'",
2527 img->spec, Qnil);
2528 return 0;
2530 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2531 DisposeHandle (dh);
2532 return success_p;
2537 #ifdef MAC_OSX
2538 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2539 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2540 So don't use this function directly but determine at runtime
2541 whether it exists. */
2542 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
2543 (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
2544 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
2547 static void
2548 init_image_func_pointer ()
2550 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2552 MyCGImageCreateWithPNGDataProvider
2553 = (CGImageCreateWithPNGDataProviderProcType)
2554 NSAddressOfSymbol (NSLookupAndBindSymbol
2555 ("_CGImageCreateWithPNGDataProvider"));
2557 else
2558 MyCGImageCreateWithPNGDataProvider = NULL;
2562 static int
2563 image_load_quartz2d (f, img, png_p)
2564 struct frame *f;
2565 struct image *img;
2566 int png_p;
2568 Lisp_Object file, specified_file;
2569 Lisp_Object specified_data, specified_bg;
2570 struct gcpro gcpro1;
2571 CGDataProviderRef source;
2572 CGImageRef image;
2573 int width, height;
2574 XColor color;
2575 XImagePtr ximg = NULL;
2576 CGContextRef context;
2577 CGRect rectangle;
2579 /* Open the file. */
2580 specified_file = image_spec_value (img->spec, QCfile, NULL);
2581 specified_data = image_spec_value (img->spec, QCdata, NULL);
2583 file = Qnil;
2584 GCPRO1 (file);
2586 if (NILP (specified_data))
2588 CFStringRef path;
2589 CFURLRef url;
2591 file = x_find_image_file (specified_file);
2592 if (!STRINGP (file))
2594 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2595 UNGCPRO;
2596 return 0;
2598 path = cfstring_create_with_string (file);
2599 url = CFURLCreateWithFileSystemPath (NULL, path,
2600 kCFURLPOSIXPathStyle, 0);
2601 CFRelease (path);
2602 source = CGDataProviderCreateWithURL (url);
2603 CFRelease (url);
2605 else
2606 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
2607 SBYTES (specified_data), NULL);
2609 if (png_p)
2610 image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
2611 kCGRenderingIntentDefault);
2612 else
2613 image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
2614 kCGRenderingIntentDefault);
2616 CGDataProviderRelease (source);
2617 if (image == NULL)
2619 UNGCPRO;
2620 image_error ("Error reading image `%s'", img->spec, Qnil);
2621 return 0;
2623 width = img->width = CGImageGetWidth (image);
2624 height = img->height = CGImageGetHeight (image);
2626 if (!check_image_size (f, width, height))
2628 CGImageRelease (image);
2629 UNGCPRO;
2630 image_error ("Invalid image size", Qnil, Qnil);
2631 return 0;
2634 if (png_p)
2636 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2637 if (!STRINGP (specified_bg) ||
2638 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2640 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2641 color.red = RED16_FROM_ULONG (color.pixel);
2642 color.green = GREEN16_FROM_ULONG (color.pixel);
2643 color.blue = BLUE16_FROM_ULONG (color.pixel);
2647 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2649 CGImageRelease (image);
2650 UNGCPRO;
2651 return 0;
2653 rectangle = CGRectMake (0, 0, width, height);
2654 QDBeginCGContext (ximg, &context);
2655 if (png_p)
2657 CGContextSetRGBFillColor (context, color.red / 65535.0,
2658 color.green / 65535.0,
2659 color.blue / 65535.0, 1.0);
2660 CGContextFillRect (context, rectangle);
2662 CGContextDrawImage (context, rectangle, image);
2663 QDEndCGContext (ximg, &context);
2664 CGImageRelease (image);
2666 /* Maybe fill in the background field while we have ximg handy. */
2667 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2668 IMAGE_BACKGROUND (img, f, ximg);
2670 /* Put the image into the pixmap. */
2671 x_put_x_image (f, ximg, img->pixmap, width, height);
2672 x_destroy_x_image (ximg);
2673 UNGCPRO;
2674 return 1;
2676 #endif
2678 #endif /* MAC_OS */
2681 /***********************************************************************
2682 XBM images
2683 ***********************************************************************/
2685 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
2686 static int xbm_load P_ ((struct frame *f, struct image *img));
2687 static int xbm_load_image P_ ((struct frame *f, struct image *img,
2688 unsigned char *, unsigned char *));
2689 static int xbm_image_p P_ ((Lisp_Object object));
2690 static int xbm_read_bitmap_data P_ ((struct frame *f,
2691 unsigned char *, unsigned char *,
2692 int *, int *, unsigned char **));
2693 static int xbm_file_p P_ ((Lisp_Object));
2696 /* Indices of image specification fields in xbm_format, below. */
2698 enum xbm_keyword_index
2700 XBM_TYPE,
2701 XBM_FILE,
2702 XBM_WIDTH,
2703 XBM_HEIGHT,
2704 XBM_DATA,
2705 XBM_FOREGROUND,
2706 XBM_BACKGROUND,
2707 XBM_ASCENT,
2708 XBM_MARGIN,
2709 XBM_RELIEF,
2710 XBM_ALGORITHM,
2711 XBM_HEURISTIC_MASK,
2712 XBM_MASK,
2713 XBM_LAST
2716 /* Vector of image_keyword structures describing the format
2717 of valid XBM image specifications. */
2719 static struct image_keyword xbm_format[XBM_LAST] =
2721 {":type", IMAGE_SYMBOL_VALUE, 1},
2722 {":file", IMAGE_STRING_VALUE, 0},
2723 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2724 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2725 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2726 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2727 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2728 {":ascent", IMAGE_ASCENT_VALUE, 0},
2729 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2730 {":relief", IMAGE_INTEGER_VALUE, 0},
2731 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2732 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2733 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2736 /* Structure describing the image type XBM. */
2738 static struct image_type xbm_type =
2740 &Qxbm,
2741 xbm_image_p,
2742 xbm_load,
2743 x_clear_image,
2744 NULL
2747 /* Tokens returned from xbm_scan. */
2749 enum xbm_token
2751 XBM_TK_IDENT = 256,
2752 XBM_TK_NUMBER
2756 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2757 A valid specification is a list starting with the symbol `image'
2758 The rest of the list is a property list which must contain an
2759 entry `:type xbm..
2761 If the specification specifies a file to load, it must contain
2762 an entry `:file FILENAME' where FILENAME is a string.
2764 If the specification is for a bitmap loaded from memory it must
2765 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2766 WIDTH and HEIGHT are integers > 0. DATA may be:
2768 1. a string large enough to hold the bitmap data, i.e. it must
2769 have a size >= (WIDTH + 7) / 8 * HEIGHT
2771 2. a bool-vector of size >= WIDTH * HEIGHT
2773 3. a vector of strings or bool-vectors, one for each line of the
2774 bitmap.
2776 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2777 may not be specified in this case because they are defined in the
2778 XBM file.
2780 Both the file and data forms may contain the additional entries
2781 `:background COLOR' and `:foreground COLOR'. If not present,
2782 foreground and background of the frame on which the image is
2783 displayed is used. */
2785 static int
2786 xbm_image_p (object)
2787 Lisp_Object object;
2789 struct image_keyword kw[XBM_LAST];
2791 bcopy (xbm_format, kw, sizeof kw);
2792 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2793 return 0;
2795 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2797 if (kw[XBM_FILE].count)
2799 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2800 return 0;
2802 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2804 /* In-memory XBM file. */
2805 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2806 return 0;
2808 else
2810 Lisp_Object data;
2811 int width, height;
2813 /* Entries for `:width', `:height' and `:data' must be present. */
2814 if (!kw[XBM_WIDTH].count
2815 || !kw[XBM_HEIGHT].count
2816 || !kw[XBM_DATA].count)
2817 return 0;
2819 data = kw[XBM_DATA].value;
2820 width = XFASTINT (kw[XBM_WIDTH].value);
2821 height = XFASTINT (kw[XBM_HEIGHT].value);
2823 /* Check type of data, and width and height against contents of
2824 data. */
2825 if (VECTORP (data))
2827 int i;
2829 /* Number of elements of the vector must be >= height. */
2830 if (XVECTOR (data)->size < height)
2831 return 0;
2833 /* Each string or bool-vector in data must be large enough
2834 for one line of the image. */
2835 for (i = 0; i < height; ++i)
2837 Lisp_Object elt = XVECTOR (data)->contents[i];
2839 if (STRINGP (elt))
2841 if (SCHARS (elt)
2842 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2843 return 0;
2845 else if (BOOL_VECTOR_P (elt))
2847 if (XBOOL_VECTOR (elt)->size < width)
2848 return 0;
2850 else
2851 return 0;
2854 else if (STRINGP (data))
2856 if (SCHARS (data)
2857 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2858 return 0;
2860 else if (BOOL_VECTOR_P (data))
2862 if (XBOOL_VECTOR (data)->size < width * height)
2863 return 0;
2865 else
2866 return 0;
2869 return 1;
2873 /* Scan a bitmap file. FP is the stream to read from. Value is
2874 either an enumerator from enum xbm_token, or a character for a
2875 single-character token, or 0 at end of file. If scanning an
2876 identifier, store the lexeme of the identifier in SVAL. If
2877 scanning a number, store its value in *IVAL. */
2879 static int
2880 xbm_scan (s, end, sval, ival)
2881 unsigned char **s, *end;
2882 char *sval;
2883 int *ival;
2885 unsigned int c;
2887 loop:
2889 /* Skip white space. */
2890 while (*s < end && (c = *(*s)++, isspace (c)))
2893 if (*s >= end)
2894 c = 0;
2895 else if (isdigit (c))
2897 int value = 0, digit;
2899 if (c == '0' && *s < end)
2901 c = *(*s)++;
2902 if (c == 'x' || c == 'X')
2904 while (*s < end)
2906 c = *(*s)++;
2907 if (isdigit (c))
2908 digit = c - '0';
2909 else if (c >= 'a' && c <= 'f')
2910 digit = c - 'a' + 10;
2911 else if (c >= 'A' && c <= 'F')
2912 digit = c - 'A' + 10;
2913 else
2914 break;
2915 value = 16 * value + digit;
2918 else if (isdigit (c))
2920 value = c - '0';
2921 while (*s < end
2922 && (c = *(*s)++, isdigit (c)))
2923 value = 8 * value + c - '0';
2926 else
2928 value = c - '0';
2929 while (*s < end
2930 && (c = *(*s)++, isdigit (c)))
2931 value = 10 * value + c - '0';
2934 if (*s < end)
2935 *s = *s - 1;
2936 *ival = value;
2937 c = XBM_TK_NUMBER;
2939 else if (isalpha (c) || c == '_')
2941 *sval++ = c;
2942 while (*s < end
2943 && (c = *(*s)++, (isalnum (c) || c == '_')))
2944 *sval++ = c;
2945 *sval = 0;
2946 if (*s < end)
2947 *s = *s - 1;
2948 c = XBM_TK_IDENT;
2950 else if (c == '/' && **s == '*')
2952 /* C-style comment. */
2953 ++*s;
2954 while (**s && (**s != '*' || *(*s + 1) != '/'))
2955 ++*s;
2956 if (**s)
2958 *s += 2;
2959 goto loop;
2963 return c;
2966 #ifdef HAVE_NTGUI
2968 /* Create a Windows bitmap from X bitmap data. */
2969 static HBITMAP
2970 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
2972 static unsigned char swap_nibble[16]
2973 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
2974 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
2975 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
2976 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
2977 int i, j, w1, w2;
2978 unsigned char *bits, *p;
2979 HBITMAP bmp;
2981 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
2982 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
2983 bits = (unsigned char *) alloca (height * w2);
2984 bzero (bits, height * w2);
2985 for (i = 0; i < height; i++)
2987 p = bits + i*w2;
2988 for (j = 0; j < w1; j++)
2990 /* Bitswap XBM bytes to match how Windows does things. */
2991 unsigned char c = *data++;
2992 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
2993 | (swap_nibble[(c>>4) & 0xf]));
2996 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
2998 return bmp;
3001 static void convert_mono_to_color_image (f, img, foreground, background)
3002 struct frame *f;
3003 struct image *img;
3004 COLORREF foreground, background;
3006 HDC hdc, old_img_dc, new_img_dc;
3007 HGDIOBJ old_prev, new_prev;
3008 HBITMAP new_pixmap;
3010 hdc = get_frame_dc (f);
3011 old_img_dc = CreateCompatibleDC (hdc);
3012 new_img_dc = CreateCompatibleDC (hdc);
3013 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3014 release_frame_dc (f, hdc);
3015 old_prev = SelectObject (old_img_dc, img->pixmap);
3016 new_prev = SelectObject (new_img_dc, new_pixmap);
3017 SetTextColor (new_img_dc, foreground);
3018 SetBkColor (new_img_dc, background);
3020 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3021 0, 0, SRCCOPY);
3023 SelectObject (old_img_dc, old_prev);
3024 SelectObject (new_img_dc, new_prev);
3025 DeleteDC (old_img_dc);
3026 DeleteDC (new_img_dc);
3027 DeleteObject (img->pixmap);
3028 if (new_pixmap == 0)
3029 fprintf (stderr, "Failed to convert image to color.\n");
3030 else
3031 img->pixmap = new_pixmap;
3034 #define XBM_BIT_SHUFFLE(b) (~(b))
3036 #else
3038 #define XBM_BIT_SHUFFLE(b) (b)
3040 #endif /* HAVE_NTGUI */
3043 static void
3044 Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
3045 struct frame *f;
3046 struct image *img;
3047 char *data;
3048 RGB_PIXEL_COLOR fg, bg;
3049 int non_default_colors;
3051 #ifdef HAVE_NTGUI
3052 img->pixmap
3053 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3055 /* If colors were specified, transfer the bitmap to a color one. */
3056 if (non_default_colors)
3057 convert_mono_to_color_image (f, img, fg, bg);
3058 #else
3059 img->pixmap
3060 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3061 FRAME_X_WINDOW (f),
3062 data,
3063 img->width, img->height,
3064 fg, bg,
3065 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3066 #endif /* HAVE_NTGUI */
3071 /* Replacement for XReadBitmapFileData which isn't available under old
3072 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3073 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3074 the image. Return in *DATA the bitmap data allocated with xmalloc.
3075 Value is non-zero if successful. DATA null means just test if
3076 CONTENTS looks like an in-memory XBM file. */
3078 static int
3079 xbm_read_bitmap_data (f, contents, end, width, height, data)
3080 struct frame *f;
3081 unsigned char *contents, *end;
3082 int *width, *height;
3083 unsigned char **data;
3085 unsigned char *s = contents;
3086 char buffer[BUFSIZ];
3087 int padding_p = 0;
3088 int v10 = 0;
3089 int bytes_per_line, i, nbytes;
3090 unsigned char *p;
3091 int value;
3092 int LA1;
3094 #define match() \
3095 LA1 = xbm_scan (&s, end, buffer, &value)
3097 #define expect(TOKEN) \
3098 if (LA1 != (TOKEN)) \
3099 goto failure; \
3100 else \
3101 match ()
3103 #define expect_ident(IDENT) \
3104 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3105 match (); \
3106 else \
3107 goto failure
3109 *width = *height = -1;
3110 if (data)
3111 *data = NULL;
3112 LA1 = xbm_scan (&s, end, buffer, &value);
3114 /* Parse defines for width, height and hot-spots. */
3115 while (LA1 == '#')
3117 match ();
3118 expect_ident ("define");
3119 expect (XBM_TK_IDENT);
3121 if (LA1 == XBM_TK_NUMBER);
3123 char *p = strrchr (buffer, '_');
3124 p = p ? p + 1 : buffer;
3125 if (strcmp (p, "width") == 0)
3126 *width = value;
3127 else if (strcmp (p, "height") == 0)
3128 *height = value;
3130 expect (XBM_TK_NUMBER);
3133 if (!check_image_size (f, *width, *height))
3134 goto failure;
3135 else if (data == NULL)
3136 goto success;
3138 /* Parse bits. Must start with `static'. */
3139 expect_ident ("static");
3140 if (LA1 == XBM_TK_IDENT)
3142 if (strcmp (buffer, "unsigned") == 0)
3144 match ();
3145 expect_ident ("char");
3147 else if (strcmp (buffer, "short") == 0)
3149 match ();
3150 v10 = 1;
3151 if (*width % 16 && *width % 16 < 9)
3152 padding_p = 1;
3154 else if (strcmp (buffer, "char") == 0)
3155 match ();
3156 else
3157 goto failure;
3159 else
3160 goto failure;
3162 expect (XBM_TK_IDENT);
3163 expect ('[');
3164 expect (']');
3165 expect ('=');
3166 expect ('{');
3168 bytes_per_line = (*width + 7) / 8 + padding_p;
3169 nbytes = bytes_per_line * *height;
3170 p = *data = (unsigned char *) xmalloc (nbytes);
3172 if (v10)
3174 for (i = 0; i < nbytes; i += 2)
3176 int val = value;
3177 expect (XBM_TK_NUMBER);
3179 *p++ = XBM_BIT_SHUFFLE (val);
3180 if (!padding_p || ((i + 2) % bytes_per_line))
3181 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3183 if (LA1 == ',' || LA1 == '}')
3184 match ();
3185 else
3186 goto failure;
3189 else
3191 for (i = 0; i < nbytes; ++i)
3193 int val = value;
3194 expect (XBM_TK_NUMBER);
3196 *p++ = XBM_BIT_SHUFFLE (val);
3198 if (LA1 == ',' || LA1 == '}')
3199 match ();
3200 else
3201 goto failure;
3205 success:
3206 return 1;
3208 failure:
3210 if (data && *data)
3212 xfree (*data);
3213 *data = NULL;
3215 return 0;
3217 #undef match
3218 #undef expect
3219 #undef expect_ident
3223 /* Load XBM image IMG which will be displayed on frame F from buffer
3224 CONTENTS. END is the end of the buffer. Value is non-zero if
3225 successful. */
3227 static int
3228 xbm_load_image (f, img, contents, end)
3229 struct frame *f;
3230 struct image *img;
3231 unsigned char *contents, *end;
3233 int rc;
3234 unsigned char *data;
3235 int success_p = 0;
3237 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3238 if (rc)
3240 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3241 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3242 int non_default_colors = 0;
3243 Lisp_Object value;
3245 xassert (img->width > 0 && img->height > 0);
3247 /* Get foreground and background colors, maybe allocate colors. */
3248 value = image_spec_value (img->spec, QCforeground, NULL);
3249 if (!NILP (value))
3251 foreground = x_alloc_image_color (f, img, value, foreground);
3252 non_default_colors = 1;
3254 value = image_spec_value (img->spec, QCbackground, NULL);
3255 if (!NILP (value))
3257 background = x_alloc_image_color (f, img, value, background);
3258 img->background = background;
3259 img->background_valid = 1;
3260 non_default_colors = 1;
3263 Create_Pixmap_From_Bitmap_Data (f, img, data,
3264 foreground, background,
3265 non_default_colors);
3266 xfree (data);
3268 if (img->pixmap == NO_PIXMAP)
3270 x_clear_image (f, img);
3271 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3273 else
3274 success_p = 1;
3276 else
3277 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3279 return success_p;
3283 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3285 static int
3286 xbm_file_p (data)
3287 Lisp_Object data;
3289 int w, h;
3290 return (STRINGP (data)
3291 && xbm_read_bitmap_data (NULL, SDATA (data),
3292 (SDATA (data)
3293 + SBYTES (data)),
3294 &w, &h, NULL));
3298 /* Fill image IMG which is used on frame F with pixmap data. Value is
3299 non-zero if successful. */
3301 static int
3302 xbm_load (f, img)
3303 struct frame *f;
3304 struct image *img;
3306 int success_p = 0;
3307 Lisp_Object file_name;
3309 xassert (xbm_image_p (img->spec));
3311 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3312 file_name = image_spec_value (img->spec, QCfile, NULL);
3313 if (STRINGP (file_name))
3315 Lisp_Object file;
3316 unsigned char *contents;
3317 int size;
3318 struct gcpro gcpro1;
3320 file = x_find_image_file (file_name);
3321 GCPRO1 (file);
3322 if (!STRINGP (file))
3324 image_error ("Cannot find image file `%s'", file_name, Qnil);
3325 UNGCPRO;
3326 return 0;
3329 contents = slurp_file (SDATA (file), &size);
3330 if (contents == NULL)
3332 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3333 UNGCPRO;
3334 return 0;
3337 success_p = xbm_load_image (f, img, contents, contents + size);
3338 UNGCPRO;
3340 else
3342 struct image_keyword fmt[XBM_LAST];
3343 Lisp_Object data;
3344 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3345 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3346 int non_default_colors = 0;
3347 char *bits;
3348 int parsed_p;
3349 int in_memory_file_p = 0;
3351 /* See if data looks like an in-memory XBM file. */
3352 data = image_spec_value (img->spec, QCdata, NULL);
3353 in_memory_file_p = xbm_file_p (data);
3355 /* Parse the image specification. */
3356 bcopy (xbm_format, fmt, sizeof fmt);
3357 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3358 xassert (parsed_p);
3360 /* Get specified width, and height. */
3361 if (!in_memory_file_p)
3363 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3364 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3365 xassert (img->width > 0 && img->height > 0);
3368 /* Get foreground and background colors, maybe allocate colors. */
3369 if (fmt[XBM_FOREGROUND].count
3370 && STRINGP (fmt[XBM_FOREGROUND].value))
3372 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3373 foreground);
3374 non_default_colors = 1;
3377 if (fmt[XBM_BACKGROUND].count
3378 && STRINGP (fmt[XBM_BACKGROUND].value))
3380 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3381 background);
3382 non_default_colors = 1;
3385 if (in_memory_file_p)
3386 success_p = xbm_load_image (f, img, SDATA (data),
3387 (SDATA (data)
3388 + SBYTES (data)));
3389 else
3391 if (VECTORP (data))
3393 int i;
3394 char *p;
3395 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3397 p = bits = (char *) alloca (nbytes * img->height);
3398 for (i = 0; i < img->height; ++i, p += nbytes)
3400 Lisp_Object line = XVECTOR (data)->contents[i];
3401 if (STRINGP (line))
3402 bcopy (SDATA (line), p, nbytes);
3403 else
3404 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3407 else if (STRINGP (data))
3408 bits = SDATA (data);
3409 else
3410 bits = XBOOL_VECTOR (data)->data;
3412 /* Create the pixmap. */
3414 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3415 foreground, background,
3416 non_default_colors);
3417 if (img->pixmap)
3418 success_p = 1;
3419 else
3421 image_error ("Unable to create pixmap for XBM image `%s'",
3422 img->spec, Qnil);
3423 x_clear_image (f, img);
3428 return success_p;
3433 /***********************************************************************
3434 XPM images
3435 ***********************************************************************/
3437 #if defined (HAVE_XPM) || defined (MAC_OS)
3439 static int xpm_image_p P_ ((Lisp_Object object));
3440 static int xpm_load P_ ((struct frame *f, struct image *img));
3441 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3443 #endif /* HAVE_XPM || MAC_OS */
3445 #ifdef HAVE_XPM
3446 #ifdef HAVE_NTGUI
3447 /* Indicate to xpm.h that we don't have Xlib. */
3448 #define FOR_MSW
3449 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3450 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3451 #define XColor xpm_XColor
3452 #define XImage xpm_XImage
3453 #define Display xpm_Display
3454 #define PIXEL_ALREADY_TYPEDEFED
3455 #include "X11/xpm.h"
3456 #undef FOR_MSW
3457 #undef XColor
3458 #undef XImage
3459 #undef Display
3460 #undef PIXEL_ALREADY_TYPEDEFED
3461 #else
3462 #include "X11/xpm.h"
3463 #endif /* HAVE_NTGUI */
3464 #endif /* HAVE_XPM */
3466 #if defined (HAVE_XPM) || defined (MAC_OS)
3467 /* The symbol `xpm' identifying XPM-format images. */
3469 Lisp_Object Qxpm;
3471 /* Indices of image specification fields in xpm_format, below. */
3473 enum xpm_keyword_index
3475 XPM_TYPE,
3476 XPM_FILE,
3477 XPM_DATA,
3478 XPM_ASCENT,
3479 XPM_MARGIN,
3480 XPM_RELIEF,
3481 XPM_ALGORITHM,
3482 XPM_HEURISTIC_MASK,
3483 XPM_MASK,
3484 XPM_COLOR_SYMBOLS,
3485 XPM_BACKGROUND,
3486 XPM_LAST
3489 /* Vector of image_keyword structures describing the format
3490 of valid XPM image specifications. */
3492 static struct image_keyword xpm_format[XPM_LAST] =
3494 {":type", IMAGE_SYMBOL_VALUE, 1},
3495 {":file", IMAGE_STRING_VALUE, 0},
3496 {":data", IMAGE_STRING_VALUE, 0},
3497 {":ascent", IMAGE_ASCENT_VALUE, 0},
3498 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3499 {":relief", IMAGE_INTEGER_VALUE, 0},
3500 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3501 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3502 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3503 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3504 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3507 /* Structure describing the image type XPM. */
3509 static struct image_type xpm_type =
3511 &Qxpm,
3512 xpm_image_p,
3513 xpm_load,
3514 x_clear_image,
3515 NULL
3518 #ifdef HAVE_X_WINDOWS
3520 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3521 functions for allocating image colors. Our own functions handle
3522 color allocation failures more gracefully than the ones on the XPM
3523 lib. */
3525 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3526 #define ALLOC_XPM_COLORS
3527 #endif
3528 #endif /* HAVE_X_WINDOWS */
3530 #ifdef ALLOC_XPM_COLORS
3532 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3533 static void xpm_free_color_cache P_ ((void));
3534 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3535 static int xpm_color_bucket P_ ((char *));
3536 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3537 XColor *, int));
3539 /* An entry in a hash table used to cache color definitions of named
3540 colors. This cache is necessary to speed up XPM image loading in
3541 case we do color allocations ourselves. Without it, we would need
3542 a call to XParseColor per pixel in the image. */
3544 struct xpm_cached_color
3546 /* Next in collision chain. */
3547 struct xpm_cached_color *next;
3549 /* Color definition (RGB and pixel color). */
3550 XColor color;
3552 /* Color name. */
3553 char name[1];
3556 /* The hash table used for the color cache, and its bucket vector
3557 size. */
3559 #define XPM_COLOR_CACHE_BUCKETS 1001
3560 struct xpm_cached_color **xpm_color_cache;
3562 /* Initialize the color cache. */
3564 static void
3565 xpm_init_color_cache (f, attrs)
3566 struct frame *f;
3567 XpmAttributes *attrs;
3569 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3570 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3571 memset (xpm_color_cache, 0, nbytes);
3572 init_color_table ();
3574 if (attrs->valuemask & XpmColorSymbols)
3576 int i;
3577 XColor color;
3579 for (i = 0; i < attrs->numsymbols; ++i)
3580 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3581 attrs->colorsymbols[i].value, &color))
3583 color.pixel = lookup_rgb_color (f, color.red, color.green,
3584 color.blue);
3585 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3590 /* Free the color cache. */
3592 static void
3593 xpm_free_color_cache ()
3595 struct xpm_cached_color *p, *next;
3596 int i;
3598 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3599 for (p = xpm_color_cache[i]; p; p = next)
3601 next = p->next;
3602 xfree (p);
3605 xfree (xpm_color_cache);
3606 xpm_color_cache = NULL;
3607 free_color_table ();
3610 /* Return the bucket index for color named COLOR_NAME in the color
3611 cache. */
3613 static int
3614 xpm_color_bucket (color_name)
3615 char *color_name;
3617 unsigned h = 0;
3618 char *s;
3620 for (s = color_name; *s; ++s)
3621 h = (h << 2) ^ *s;
3622 return h %= XPM_COLOR_CACHE_BUCKETS;
3626 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3627 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3628 entry added. */
3630 static struct xpm_cached_color *
3631 xpm_cache_color (f, color_name, color, bucket)
3632 struct frame *f;
3633 char *color_name;
3634 XColor *color;
3635 int bucket;
3637 size_t nbytes;
3638 struct xpm_cached_color *p;
3640 if (bucket < 0)
3641 bucket = xpm_color_bucket (color_name);
3643 nbytes = sizeof *p + strlen (color_name);
3644 p = (struct xpm_cached_color *) xmalloc (nbytes);
3645 strcpy (p->name, color_name);
3646 p->color = *color;
3647 p->next = xpm_color_cache[bucket];
3648 xpm_color_cache[bucket] = p;
3649 return p;
3652 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3653 return the cached definition in *COLOR. Otherwise, make a new
3654 entry in the cache and allocate the color. Value is zero if color
3655 allocation failed. */
3657 static int
3658 xpm_lookup_color (f, color_name, color)
3659 struct frame *f;
3660 char *color_name;
3661 XColor *color;
3663 struct xpm_cached_color *p;
3664 int h = xpm_color_bucket (color_name);
3666 for (p = xpm_color_cache[h]; p; p = p->next)
3667 if (strcmp (p->name, color_name) == 0)
3668 break;
3670 if (p != NULL)
3671 *color = p->color;
3672 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3673 color_name, color))
3675 color->pixel = lookup_rgb_color (f, color->red, color->green,
3676 color->blue);
3677 p = xpm_cache_color (f, color_name, color, h);
3679 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3680 with transparency, and it's useful. */
3681 else if (strcmp ("opaque", color_name) == 0)
3683 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
3684 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3685 p = xpm_cache_color (f, color_name, color, h);
3688 return p != NULL;
3692 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3693 CLOSURE is a pointer to the frame on which we allocate the
3694 color. Return in *COLOR the allocated color. Value is non-zero
3695 if successful. */
3697 static int
3698 xpm_alloc_color (dpy, cmap, color_name, color, closure)
3699 Display *dpy;
3700 Colormap cmap;
3701 char *color_name;
3702 XColor *color;
3703 void *closure;
3705 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3709 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3710 is a pointer to the frame on which we allocate the color. Value is
3711 non-zero if successful. */
3713 static int
3714 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
3715 Display *dpy;
3716 Colormap cmap;
3717 Pixel *pixels;
3718 int npixels;
3719 void *closure;
3721 return 1;
3724 #endif /* ALLOC_XPM_COLORS */
3727 #ifdef HAVE_NTGUI
3729 /* XPM library details. */
3731 DEF_IMGLIB_FN (XpmFreeAttributes);
3732 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
3733 DEF_IMGLIB_FN (XpmReadFileToImage);
3734 DEF_IMGLIB_FN (XImageFree);
3736 static int
3737 init_xpm_functions (Lisp_Object libraries)
3739 HMODULE library;
3741 if (!(library = w32_delayed_load (libraries, Qxpm)))
3742 return 0;
3744 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3745 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3746 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3747 LOAD_IMGLIB_FN (library, XImageFree);
3748 return 1;
3751 #endif /* HAVE_NTGUI */
3754 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3755 for XPM images. Such a list must consist of conses whose car and
3756 cdr are strings. */
3758 static int
3759 xpm_valid_color_symbols_p (color_symbols)
3760 Lisp_Object color_symbols;
3762 while (CONSP (color_symbols))
3764 Lisp_Object sym = XCAR (color_symbols);
3765 if (!CONSP (sym)
3766 || !STRINGP (XCAR (sym))
3767 || !STRINGP (XCDR (sym)))
3768 break;
3769 color_symbols = XCDR (color_symbols);
3772 return NILP (color_symbols);
3776 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3778 static int
3779 xpm_image_p (object)
3780 Lisp_Object object;
3782 struct image_keyword fmt[XPM_LAST];
3783 bcopy (xpm_format, fmt, sizeof fmt);
3784 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3785 /* Either `:file' or `:data' must be present. */
3786 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3787 /* Either no `:color-symbols' or it's a list of conses
3788 whose car and cdr are strings. */
3789 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3790 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3793 #endif /* HAVE_XPM || MAC_OS */
3795 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3797 x_create_bitmap_from_xpm_data (f, bits)
3798 struct frame *f;
3799 char **bits;
3801 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3802 int id, rc;
3803 XpmAttributes attrs;
3804 Pixmap bitmap, mask;
3806 bzero (&attrs, sizeof attrs);
3808 attrs.visual = FRAME_X_VISUAL (f);
3809 attrs.colormap = FRAME_X_COLORMAP (f);
3810 attrs.valuemask |= XpmVisual;
3811 attrs.valuemask |= XpmColormap;
3813 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3814 bits, &bitmap, &mask, &attrs);
3815 if (rc != XpmSuccess)
3817 XpmFreeAttributes (&attrs);
3818 return -1;
3821 id = x_allocate_bitmap_record (f);
3822 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3823 dpyinfo->bitmaps[id - 1].have_mask = 1;
3824 dpyinfo->bitmaps[id - 1].mask = mask;
3825 dpyinfo->bitmaps[id - 1].file = NULL;
3826 dpyinfo->bitmaps[id - 1].height = attrs.height;
3827 dpyinfo->bitmaps[id - 1].width = attrs.width;
3828 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3829 dpyinfo->bitmaps[id - 1].refcount = 1;
3831 XpmFreeAttributes (&attrs);
3832 return id;
3834 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3836 /* Load image IMG which will be displayed on frame F. Value is
3837 non-zero if successful. */
3839 #ifdef HAVE_XPM
3841 static int
3842 xpm_load (f, img)
3843 struct frame *f;
3844 struct image *img;
3846 int rc;
3847 XpmAttributes attrs;
3848 Lisp_Object specified_file, color_symbols;
3849 #ifdef HAVE_NTGUI
3850 HDC hdc;
3851 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3852 #endif /* HAVE_NTGUI */
3854 /* Configure the XPM lib. Use the visual of frame F. Allocate
3855 close colors. Return colors allocated. */
3856 bzero (&attrs, sizeof attrs);
3858 #ifndef HAVE_NTGUI
3859 attrs.visual = FRAME_X_VISUAL (f);
3860 attrs.colormap = FRAME_X_COLORMAP (f);
3861 attrs.valuemask |= XpmVisual;
3862 attrs.valuemask |= XpmColormap;
3863 #endif /* HAVE_NTGUI */
3865 #ifdef ALLOC_XPM_COLORS
3866 /* Allocate colors with our own functions which handle
3867 failing color allocation more gracefully. */
3868 attrs.color_closure = f;
3869 attrs.alloc_color = xpm_alloc_color;
3870 attrs.free_colors = xpm_free_colors;
3871 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3872 #else /* not ALLOC_XPM_COLORS */
3873 /* Let the XPM lib allocate colors. */
3874 attrs.valuemask |= XpmReturnAllocPixels;
3875 #ifdef XpmAllocCloseColors
3876 attrs.alloc_close_colors = 1;
3877 attrs.valuemask |= XpmAllocCloseColors;
3878 #else /* not XpmAllocCloseColors */
3879 attrs.closeness = 600;
3880 attrs.valuemask |= XpmCloseness;
3881 #endif /* not XpmAllocCloseColors */
3882 #endif /* ALLOC_XPM_COLORS */
3883 #ifdef ALLOC_XPM_COLORS
3884 xpm_init_color_cache (f, &attrs);
3885 #endif
3887 /* If image specification contains symbolic color definitions, add
3888 these to `attrs'. */
3889 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3890 if (CONSP (color_symbols))
3892 Lisp_Object tail;
3893 XpmColorSymbol *xpm_syms;
3894 int i, size;
3896 attrs.valuemask |= XpmColorSymbols;
3898 /* Count number of symbols. */
3899 attrs.numsymbols = 0;
3900 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3901 ++attrs.numsymbols;
3903 /* Allocate an XpmColorSymbol array. */
3904 size = attrs.numsymbols * sizeof *xpm_syms;
3905 xpm_syms = (XpmColorSymbol *) alloca (size);
3906 bzero (xpm_syms, size);
3907 attrs.colorsymbols = xpm_syms;
3909 /* Fill the color symbol array. */
3910 for (tail = color_symbols, i = 0;
3911 CONSP (tail);
3912 ++i, tail = XCDR (tail))
3914 Lisp_Object name = XCAR (XCAR (tail));
3915 Lisp_Object color = XCDR (XCAR (tail));
3916 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3917 strcpy (xpm_syms[i].name, SDATA (name));
3918 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3919 strcpy (xpm_syms[i].value, SDATA (color));
3923 /* Create a pixmap for the image, either from a file, or from a
3924 string buffer containing data in the same format as an XPM file. */
3925 #ifdef ALLOC_XPM_COLORS
3926 xpm_init_color_cache (f, &attrs);
3927 #endif
3929 specified_file = image_spec_value (img->spec, QCfile, NULL);
3931 #ifdef HAVE_NTGUI
3933 HDC frame_dc = get_frame_dc (f);
3934 hdc = CreateCompatibleDC (frame_dc);
3935 release_frame_dc (f, frame_dc);
3937 #endif /* HAVE_NTGUI */
3939 if (STRINGP (specified_file))
3941 Lisp_Object file = x_find_image_file (specified_file);
3942 if (!STRINGP (file))
3944 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3945 return 0;
3948 #ifdef HAVE_NTGUI
3949 /* XpmReadFileToPixmap is not available in the Windows port of
3950 libxpm. But XpmReadFileToImage almost does what we want. */
3951 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3952 &xpm_image, &xpm_mask,
3953 &attrs);
3954 #else
3955 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3956 SDATA (file), &img->pixmap, &img->mask,
3957 &attrs);
3958 #endif /* HAVE_NTGUI */
3960 else
3962 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3963 #ifdef HAVE_NTGUI
3964 /* XpmCreatePixmapFromBuffer is not available in the Windows port
3965 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
3966 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
3967 &xpm_image, &xpm_mask,
3968 &attrs);
3969 #else
3970 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3971 SDATA (buffer),
3972 &img->pixmap, &img->mask,
3973 &attrs);
3974 #endif /* HAVE_NTGUI */
3977 if (rc == XpmSuccess)
3979 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
3980 img->colors = colors_in_color_table (&img->ncolors);
3981 #else /* not ALLOC_XPM_COLORS */
3982 int i;
3984 #ifdef HAVE_NTGUI
3985 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
3986 plus some duplicate attributes. */
3987 if (xpm_image && xpm_image->bitmap)
3989 img->pixmap = xpm_image->bitmap;
3990 /* XImageFree in libXpm frees XImage struct without destroying
3991 the bitmap, which is what we want. */
3992 fn_XImageFree (xpm_image);
3994 if (xpm_mask && xpm_mask->bitmap)
3996 /* The mask appears to be inverted compared with what we expect.
3997 TODO: invert our expectations. See other places where we
3998 have to invert bits because our idea of masks is backwards. */
3999 HGDIOBJ old_obj;
4000 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4002 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4003 SelectObject (hdc, old_obj);
4005 img->mask = xpm_mask->bitmap;
4006 fn_XImageFree (xpm_mask);
4007 DeleteDC (hdc);
4010 DeleteDC (hdc);
4011 #endif /* HAVE_NTGUI */
4013 /* Remember allocated colors. */
4014 img->ncolors = attrs.nalloc_pixels;
4015 img->colors = (unsigned long *) xmalloc (img->ncolors
4016 * sizeof *img->colors);
4017 for (i = 0; i < attrs.nalloc_pixels; ++i)
4019 img->colors[i] = attrs.alloc_pixels[i];
4020 #ifdef DEBUG_X_COLORS
4021 register_color (img->colors[i]);
4022 #endif
4024 #endif /* not ALLOC_XPM_COLORS */
4026 img->width = attrs.width;
4027 img->height = attrs.height;
4028 xassert (img->width > 0 && img->height > 0);
4030 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4031 #ifdef HAVE_NTGUI
4032 fn_XpmFreeAttributes (&attrs);
4033 #else
4034 XpmFreeAttributes (&attrs);
4035 #endif /* HAVE_NTGUI */
4037 else
4039 #ifdef HAVE_NTGUI
4040 DeleteDC (hdc);
4041 #endif /* HAVE_NTGUI */
4043 switch (rc)
4045 case XpmOpenFailed:
4046 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4047 break;
4049 case XpmFileInvalid:
4050 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4051 break;
4053 case XpmNoMemory:
4054 image_error ("Out of memory (%s)", img->spec, Qnil);
4055 break;
4057 case XpmColorFailed:
4058 image_error ("Color allocation error (%s)", img->spec, Qnil);
4059 break;
4061 default:
4062 image_error ("Unknown error (%s)", img->spec, Qnil);
4063 break;
4067 #ifdef ALLOC_XPM_COLORS
4068 xpm_free_color_cache ();
4069 #endif
4070 return rc == XpmSuccess;
4073 #endif /* HAVE_XPM */
4075 #ifdef MAC_OS
4077 /* XPM support functions for Mac OS where libxpm is not available.
4078 Only XPM version 3 (without any extensions) is supported. */
4080 static int xpm_scan P_ ((unsigned char **, unsigned char *,
4081 unsigned char **, int *));
4082 static Lisp_Object xpm_make_color_table_v
4083 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
4084 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
4085 static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
4086 int, Lisp_Object));
4087 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4088 unsigned char *, int));
4089 static Lisp_Object xpm_make_color_table_h
4090 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
4091 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
4092 static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
4093 int, Lisp_Object));
4094 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4095 unsigned char *, int));
4096 static int xpm_str_to_color_key P_ ((char *));
4097 static int xpm_load_image P_ ((struct frame *, struct image *,
4098 unsigned char *, unsigned char *));
4100 /* Tokens returned from xpm_scan. */
4102 enum xpm_token
4104 XPM_TK_IDENT = 256,
4105 XPM_TK_STRING,
4106 XPM_TK_EOF
4109 /* Scan an XPM data and return a character (< 256) or a token defined
4110 by enum xpm_token above. *S and END are the start (inclusive) and
4111 the end (exclusive) addresses of the data, respectively. Advance
4112 *S while scanning. If token is either XPM_TK_IDENT or
4113 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4114 length of the corresponding token, respectively. */
4116 static int
4117 xpm_scan (s, end, beg, len)
4118 unsigned char **s, *end, **beg;
4119 int *len;
4121 int c;
4123 while (*s < end)
4125 /* Skip white-space. */
4126 while (*s < end && (c = *(*s)++, isspace (c)))
4129 /* gnus-pointer.xpm uses '-' in its identifier.
4130 sb-dir-plus.xpm uses '+' in its identifier. */
4131 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4133 *beg = *s - 1;
4134 while (*s < end &&
4135 (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4136 ++*s;
4137 *len = *s - *beg;
4138 return XPM_TK_IDENT;
4140 else if (c == '"')
4142 *beg = *s;
4143 while (*s < end && **s != '"')
4144 ++*s;
4145 *len = *s - *beg;
4146 if (*s < end)
4147 ++*s;
4148 return XPM_TK_STRING;
4150 else if (c == '/')
4152 if (*s < end && **s == '*')
4154 /* C-style comment. */
4155 ++*s;
4158 while (*s < end && *(*s)++ != '*')
4161 while (*s < end && **s != '/');
4162 if (*s < end)
4163 ++*s;
4165 else
4166 return c;
4168 else
4169 return c;
4172 return XPM_TK_EOF;
4175 /* Functions for color table lookup in XPM data. A Key is a string
4176 specifying the color of each pixel in XPM data. A value is either
4177 an integer that specifies a pixel color, Qt that specifies
4178 transparency, or Qnil for the unspecified color. If the length of
4179 the key string is one, a vector is used as a table. Otherwise, a
4180 hash table is used. */
4182 static Lisp_Object
4183 xpm_make_color_table_v (put_func, get_func)
4184 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
4185 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
4187 *put_func = xpm_put_color_table_v;
4188 *get_func = xpm_get_color_table_v;
4189 return Fmake_vector (make_number (256), Qnil);
4192 static void
4193 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4194 Lisp_Object color_table;
4195 unsigned char *chars_start;
4196 int chars_len;
4197 Lisp_Object color;
4199 XVECTOR (color_table)->contents[*chars_start] = color;
4202 static Lisp_Object
4203 xpm_get_color_table_v (color_table, chars_start, chars_len)
4204 Lisp_Object color_table;
4205 unsigned char *chars_start;
4206 int chars_len;
4208 return XVECTOR (color_table)->contents[*chars_start];
4211 static Lisp_Object
4212 xpm_make_color_table_h (put_func, get_func)
4213 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
4214 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
4216 *put_func = xpm_put_color_table_h;
4217 *get_func = xpm_get_color_table_h;
4218 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4219 make_float (DEFAULT_REHASH_SIZE),
4220 make_float (DEFAULT_REHASH_THRESHOLD),
4221 Qnil, Qnil, Qnil);
4224 static void
4225 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4226 Lisp_Object color_table;
4227 unsigned char *chars_start;
4228 int chars_len;
4229 Lisp_Object color;
4231 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4232 unsigned hash_code;
4233 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4235 hash_lookup (table, chars, &hash_code);
4236 hash_put (table, chars, color, hash_code);
4239 static Lisp_Object
4240 xpm_get_color_table_h (color_table, chars_start, chars_len)
4241 Lisp_Object color_table;
4242 unsigned char *chars_start;
4243 int chars_len;
4245 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4246 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4247 NULL);
4249 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4252 enum xpm_color_key {
4253 XPM_COLOR_KEY_S,
4254 XPM_COLOR_KEY_M,
4255 XPM_COLOR_KEY_G4,
4256 XPM_COLOR_KEY_G,
4257 XPM_COLOR_KEY_C
4260 static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4262 static int
4263 xpm_str_to_color_key (s)
4264 char *s;
4266 int i;
4268 for (i = 0;
4269 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4270 i++)
4271 if (strcmp (xpm_color_key_strings[i], s) == 0)
4272 return i;
4273 return -1;
4276 static int
4277 xpm_load_image (f, img, contents, end)
4278 struct frame *f;
4279 struct image *img;
4280 unsigned char *contents, *end;
4282 unsigned char *s = contents, *beg, *str;
4283 unsigned char buffer[BUFSIZ];
4284 int width, height, x, y;
4285 int num_colors, chars_per_pixel;
4286 int len, LA1;
4287 void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
4288 Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
4289 Lisp_Object frame, color_symbols, color_table;
4290 int best_key, have_mask = 0;
4291 XImagePtr ximg = NULL, mask_img = NULL;
4293 #define match() \
4294 LA1 = xpm_scan (&s, end, &beg, &len)
4296 #define expect(TOKEN) \
4297 if (LA1 != (TOKEN)) \
4298 goto failure; \
4299 else \
4300 match ()
4302 #define expect_ident(IDENT) \
4303 if (LA1 == XPM_TK_IDENT \
4304 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4305 match (); \
4306 else \
4307 goto failure
4309 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4310 goto failure;
4311 s += 9;
4312 match();
4313 expect_ident ("static");
4314 expect_ident ("char");
4315 expect ('*');
4316 expect (XPM_TK_IDENT);
4317 expect ('[');
4318 expect (']');
4319 expect ('=');
4320 expect ('{');
4321 expect (XPM_TK_STRING);
4322 if (len >= BUFSIZ)
4323 goto failure;
4324 memcpy (buffer, beg, len);
4325 buffer[len] = '\0';
4326 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4327 &num_colors, &chars_per_pixel) != 4
4328 || width <= 0 || height <= 0
4329 || num_colors <= 0 || chars_per_pixel <= 0)
4330 goto failure;
4332 if (!check_image_size (f, width, height))
4334 image_error ("Invalid image size", Qnil, Qnil);
4335 goto failure;
4338 expect (',');
4340 XSETFRAME (frame, f);
4341 if (!NILP (Fxw_display_color_p (frame)))
4342 best_key = XPM_COLOR_KEY_C;
4343 else if (!NILP (Fx_display_grayscale_p (frame)))
4344 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4345 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4346 else
4347 best_key = XPM_COLOR_KEY_M;
4349 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4350 if (chars_per_pixel == 1)
4351 color_table = xpm_make_color_table_v (&put_color_table,
4352 &get_color_table);
4353 else
4354 color_table = xpm_make_color_table_h (&put_color_table,
4355 &get_color_table);
4357 while (num_colors-- > 0)
4359 unsigned char *color, *max_color;
4360 int key, next_key, max_key = 0;
4361 Lisp_Object symbol_color = Qnil, color_val;
4362 XColor cdef;
4364 expect (XPM_TK_STRING);
4365 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4366 goto failure;
4367 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4368 buffer[len - chars_per_pixel] = '\0';
4370 str = strtok (buffer, " \t");
4371 if (str == NULL)
4372 goto failure;
4373 key = xpm_str_to_color_key (str);
4374 if (key < 0)
4375 goto failure;
4378 color = strtok (NULL, " \t");
4379 if (color == NULL)
4380 goto failure;
4382 while (str = strtok (NULL, " \t"))
4384 next_key = xpm_str_to_color_key (str);
4385 if (next_key >= 0)
4386 break;
4387 color[strlen (color)] = ' ';
4390 if (key == XPM_COLOR_KEY_S)
4392 if (NILP (symbol_color))
4393 symbol_color = build_string (color);
4395 else if (max_key < key && key <= best_key)
4397 max_key = key;
4398 max_color = color;
4400 key = next_key;
4402 while (str);
4404 color_val = Qnil;
4405 if (!NILP (color_symbols) && !NILP (symbol_color))
4407 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4409 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4410 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4411 color_val = Qt;
4412 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4413 &cdef, 0))
4414 color_val = make_number (cdef.pixel);
4416 if (NILP (color_val) && max_key > 0)
4417 if (xstricmp (max_color, "None") == 0)
4418 color_val = Qt;
4419 else if (x_defined_color (f, max_color, &cdef, 0))
4420 color_val = make_number (cdef.pixel);
4421 if (!NILP (color_val))
4422 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4424 expect (',');
4427 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4428 &ximg, &img->pixmap)
4429 || !x_create_x_image_and_pixmap (f, width, height, 1,
4430 &mask_img, &img->mask))
4432 image_error ("Out of memory (%s)", img->spec, Qnil);
4433 goto error;
4436 for (y = 0; y < height; y++)
4438 expect (XPM_TK_STRING);
4439 str = beg;
4440 if (len < width * chars_per_pixel)
4441 goto failure;
4442 for (x = 0; x < width; x++, str += chars_per_pixel)
4444 Lisp_Object color_val =
4445 (*get_color_table) (color_table, str, chars_per_pixel);
4447 XPutPixel (ximg, x, y,
4448 (INTEGERP (color_val) ? XINT (color_val)
4449 : FRAME_FOREGROUND_PIXEL (f)));
4450 XPutPixel (mask_img, x, y,
4451 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4452 : (have_mask = 1, PIX_MASK_RETAIN)));
4454 if (y + 1 < height)
4455 expect (',');
4458 img->width = width;
4459 img->height = height;
4461 x_put_x_image (f, ximg, img->pixmap, width, height);
4462 x_destroy_x_image (ximg);
4463 if (have_mask)
4465 /* Fill in the background_transparent field while we have the
4466 mask handy. */
4467 image_background_transparent (img, f, mask_img);
4469 x_put_x_image (f, mask_img, img->mask, width, height);
4470 x_destroy_x_image (mask_img);
4472 else
4474 x_destroy_x_image (mask_img);
4475 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4476 img->mask = NO_PIXMAP;
4479 return 1;
4481 failure:
4482 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4483 error:
4484 x_destroy_x_image (ximg);
4485 x_destroy_x_image (mask_img);
4486 x_clear_image (f, img);
4487 return 0;
4489 #undef match
4490 #undef expect
4491 #undef expect_ident
4494 static int
4495 xpm_load (f, img)
4496 struct frame *f;
4497 struct image *img;
4499 int success_p = 0;
4500 Lisp_Object file_name;
4502 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4503 file_name = image_spec_value (img->spec, QCfile, NULL);
4504 if (STRINGP (file_name))
4506 Lisp_Object file;
4507 unsigned char *contents;
4508 int size;
4509 struct gcpro gcpro1;
4511 file = x_find_image_file (file_name);
4512 GCPRO1 (file);
4513 if (!STRINGP (file))
4515 image_error ("Cannot find image file `%s'", file_name, Qnil);
4516 UNGCPRO;
4517 return 0;
4520 contents = slurp_file (SDATA (file), &size);
4521 if (contents == NULL)
4523 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4524 UNGCPRO;
4525 return 0;
4528 success_p = xpm_load_image (f, img, contents, contents + size);
4529 xfree (contents);
4530 UNGCPRO;
4532 else
4534 Lisp_Object data;
4536 data = image_spec_value (img->spec, QCdata, NULL);
4537 success_p = xpm_load_image (f, img, SDATA (data),
4538 SDATA (data) + SBYTES (data));
4541 return success_p;
4544 #endif /* MAC_OS */
4548 /***********************************************************************
4549 Color table
4550 ***********************************************************************/
4552 #ifdef COLOR_TABLE_SUPPORT
4554 /* An entry in the color table mapping an RGB color to a pixel color. */
4556 struct ct_color
4558 int r, g, b;
4559 unsigned long pixel;
4561 /* Next in color table collision list. */
4562 struct ct_color *next;
4565 /* The bucket vector size to use. Must be prime. */
4567 #define CT_SIZE 101
4569 /* Value is a hash of the RGB color given by R, G, and B. */
4571 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4573 /* The color hash table. */
4575 struct ct_color **ct_table;
4577 /* Number of entries in the color table. */
4579 int ct_colors_allocated;
4581 /* Initialize the color table. */
4583 static void
4584 init_color_table ()
4586 int size = CT_SIZE * sizeof (*ct_table);
4587 ct_table = (struct ct_color **) xmalloc (size);
4588 bzero (ct_table, size);
4589 ct_colors_allocated = 0;
4593 /* Free memory associated with the color table. */
4595 static void
4596 free_color_table ()
4598 int i;
4599 struct ct_color *p, *next;
4601 for (i = 0; i < CT_SIZE; ++i)
4602 for (p = ct_table[i]; p; p = next)
4604 next = p->next;
4605 xfree (p);
4608 xfree (ct_table);
4609 ct_table = NULL;
4613 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4614 entry for that color already is in the color table, return the
4615 pixel color of that entry. Otherwise, allocate a new color for R,
4616 G, B, and make an entry in the color table. */
4618 static unsigned long
4619 lookup_rgb_color (f, r, g, b)
4620 struct frame *f;
4621 int r, g, b;
4623 unsigned hash = CT_HASH_RGB (r, g, b);
4624 int i = hash % CT_SIZE;
4625 struct ct_color *p;
4626 Display_Info *dpyinfo;
4628 /* Handle TrueColor visuals specially, which improves performance by
4629 two orders of magnitude. Freeing colors on TrueColor visuals is
4630 a nop, and pixel colors specify RGB values directly. See also
4631 the Xlib spec, chapter 3.1. */
4632 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4633 if (dpyinfo->red_bits > 0)
4635 unsigned long pr, pg, pb;
4637 /* Apply gamma-correction like normal color allocation does. */
4638 if (f->gamma)
4640 XColor color;
4641 color.red = r, color.green = g, color.blue = b;
4642 gamma_correct (f, &color);
4643 r = color.red, g = color.green, b = color.blue;
4646 /* Scale down RGB values to the visual's bits per RGB, and shift
4647 them to the right position in the pixel color. Note that the
4648 original RGB values are 16-bit values, as usual in X. */
4649 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4650 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4651 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4653 /* Assemble the pixel color. */
4654 return pr | pg | pb;
4657 for (p = ct_table[i]; p; p = p->next)
4658 if (p->r == r && p->g == g && p->b == b)
4659 break;
4661 if (p == NULL)
4664 #ifdef HAVE_X_WINDOWS
4665 XColor color;
4666 Colormap cmap;
4667 int rc;
4669 color.red = r;
4670 color.green = g;
4671 color.blue = b;
4673 cmap = FRAME_X_COLORMAP (f);
4674 rc = x_alloc_nearest_color (f, cmap, &color);
4675 if (rc)
4677 ++ct_colors_allocated;
4678 p = (struct ct_color *) xmalloc (sizeof *p);
4679 p->r = r;
4680 p->g = g;
4681 p->b = b;
4682 p->pixel = color.pixel;
4683 p->next = ct_table[i];
4684 ct_table[i] = p;
4686 else
4687 return FRAME_FOREGROUND_PIXEL (f);
4689 #else
4690 COLORREF color;
4691 #ifdef HAVE_NTGUI
4692 color = PALETTERGB (r, g, b);
4693 #else
4694 color = RGB_TO_ULONG (r, g, b);
4695 #endif /* HAVE_NTGUI */
4696 ++ct_colors_allocated;
4697 p = (struct ct_color *) xmalloc (sizeof *p);
4698 p->r = r;
4699 p->g = g;
4700 p->b = b;
4701 p->pixel = color;
4702 p->next = ct_table[i];
4703 ct_table[i] = p;
4704 #endif /* HAVE_X_WINDOWS */
4708 return p->pixel;
4712 /* Look up pixel color PIXEL which is used on frame F in the color
4713 table. If not already present, allocate it. Value is PIXEL. */
4715 static unsigned long
4716 lookup_pixel_color (f, pixel)
4717 struct frame *f;
4718 unsigned long pixel;
4720 int i = pixel % CT_SIZE;
4721 struct ct_color *p;
4723 for (p = ct_table[i]; p; p = p->next)
4724 if (p->pixel == pixel)
4725 break;
4727 if (p == NULL)
4729 XColor color;
4730 Colormap cmap;
4731 int rc;
4733 #ifdef HAVE_X_WINDOWS
4734 cmap = FRAME_X_COLORMAP (f);
4735 color.pixel = pixel;
4736 x_query_color (f, &color);
4737 rc = x_alloc_nearest_color (f, cmap, &color);
4738 #else
4739 BLOCK_INPUT;
4740 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4741 color.pixel = pixel;
4742 XQueryColor (NULL, cmap, &color);
4743 rc = x_alloc_nearest_color (f, cmap, &color);
4744 UNBLOCK_INPUT;
4745 #endif /* HAVE_X_WINDOWS */
4747 if (rc)
4749 ++ct_colors_allocated;
4751 p = (struct ct_color *) xmalloc (sizeof *p);
4752 p->r = color.red;
4753 p->g = color.green;
4754 p->b = color.blue;
4755 p->pixel = pixel;
4756 p->next = ct_table[i];
4757 ct_table[i] = p;
4759 else
4760 return FRAME_FOREGROUND_PIXEL (f);
4762 return p->pixel;
4766 /* Value is a vector of all pixel colors contained in the color table,
4767 allocated via xmalloc. Set *N to the number of colors. */
4769 static unsigned long *
4770 colors_in_color_table (n)
4771 int *n;
4773 int i, j;
4774 struct ct_color *p;
4775 unsigned long *colors;
4777 if (ct_colors_allocated == 0)
4779 *n = 0;
4780 colors = NULL;
4782 else
4784 colors = (unsigned long *) xmalloc (ct_colors_allocated
4785 * sizeof *colors);
4786 *n = ct_colors_allocated;
4788 for (i = j = 0; i < CT_SIZE; ++i)
4789 for (p = ct_table[i]; p; p = p->next)
4790 colors[j++] = p->pixel;
4793 return colors;
4796 #else /* COLOR_TABLE_SUPPORT */
4798 static unsigned long
4799 lookup_rgb_color (f, r, g, b)
4800 struct frame *f;
4801 int r, g, b;
4803 unsigned long pixel;
4805 #ifdef MAC_OS
4806 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4807 gamma_correct (f, &pixel);
4808 #endif /* MAC_OS */
4810 #ifdef HAVE_NTGUI
4811 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4812 #endif /* HAVE_NTGUI */
4814 return pixel;
4817 static void
4818 init_color_table ()
4821 #endif /* COLOR_TABLE_SUPPORT */
4824 /***********************************************************************
4825 Algorithms
4826 ***********************************************************************/
4828 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
4829 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
4830 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
4832 #ifdef HAVE_NTGUI
4833 static void XPutPixel (XImagePtr , int, int, COLORREF);
4834 #endif /* HAVE_NTGUI */
4836 /* Non-zero means draw a cross on images having `:conversion
4837 disabled'. */
4839 int cross_disabled_images;
4841 /* Edge detection matrices for different edge-detection
4842 strategies. */
4844 static int emboss_matrix[9] = {
4845 /* x - 1 x x + 1 */
4846 2, -1, 0, /* y - 1 */
4847 -1, 0, 1, /* y */
4848 0, 1, -2 /* y + 1 */
4851 static int laplace_matrix[9] = {
4852 /* x - 1 x x + 1 */
4853 1, 0, 0, /* y - 1 */
4854 0, 0, 0, /* y */
4855 0, 0, -1 /* y + 1 */
4858 /* Value is the intensity of the color whose red/green/blue values
4859 are R, G, and B. */
4861 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4864 /* On frame F, return an array of XColor structures describing image
4865 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4866 non-zero means also fill the red/green/blue members of the XColor
4867 structures. Value is a pointer to the array of XColors structures,
4868 allocated with xmalloc; it must be freed by the caller. */
4870 static XColor *
4871 x_to_xcolors (f, img, rgb_p)
4872 struct frame *f;
4873 struct image *img;
4874 int rgb_p;
4876 int x, y;
4877 XColor *colors, *p;
4878 XImagePtr_or_DC ximg;
4879 #ifdef HAVE_NTGUI
4880 HDC hdc;
4881 HGDIOBJ prev;
4882 #endif /* HAVE_NTGUI */
4884 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4886 #ifndef HAVE_NTGUI
4887 /* Get the X image IMG->pixmap. */
4888 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4889 0, 0, img->width, img->height, ~0, ZPixmap);
4890 #else
4891 /* Load the image into a memory device context. */
4892 hdc = get_frame_dc (f);
4893 ximg = CreateCompatibleDC (hdc);
4894 release_frame_dc (f, hdc);
4895 prev = SelectObject (ximg, img->pixmap);
4896 #endif /* HAVE_NTGUI */
4898 /* Fill the `pixel' members of the XColor array. I wished there
4899 were an easy and portable way to circumvent XGetPixel. */
4900 p = colors;
4901 for (y = 0; y < img->height; ++y)
4903 XColor *row = p;
4905 #ifdef HAVE_X_WINDOWS
4906 for (x = 0; x < img->width; ++x, ++p)
4907 p->pixel = XGetPixel (ximg, x, y);
4908 if (rgb_p)
4909 x_query_colors (f, row, img->width);
4911 #else
4913 for (x = 0; x < img->width; ++x, ++p)
4915 /* W32_TODO: palette support needed here? */
4916 p->pixel = GET_PIXEL (ximg, x, y);
4917 if (rgb_p)
4919 #ifdef MAC_OS
4920 p->red = RED16_FROM_ULONG (p->pixel);
4921 p->green = GREEN16_FROM_ULONG (p->pixel);
4922 p->blue = BLUE16_FROM_ULONG (p->pixel);
4923 #endif /* MAC_OS */
4924 #ifdef HAVE_NTGUI
4925 p->red = 256 * GetRValue (p->pixel);
4926 p->green = 256 * GetGValue (p->pixel);
4927 p->blue = 256 * GetBValue (p->pixel);
4928 #endif /* HAVE_NTGUI */
4931 #endif /* HAVE_X_WINDOWS */
4934 Destroy_Image (ximg, prev);
4936 return colors;
4939 #ifdef HAVE_NTGUI
4941 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4942 created with CreateDIBSection, with the pointer to the bit values
4943 stored in ximg->data. */
4945 static void XPutPixel (ximg, x, y, color)
4946 XImagePtr ximg;
4947 int x, y;
4948 COLORREF color;
4950 int width = ximg->info.bmiHeader.biWidth;
4951 int height = ximg->info.bmiHeader.biHeight;
4952 unsigned char * pixel;
4954 /* True color images. */
4955 if (ximg->info.bmiHeader.biBitCount == 24)
4957 int rowbytes = width * 3;
4958 /* Ensure scanlines are aligned on 4 byte boundaries. */
4959 if (rowbytes % 4)
4960 rowbytes += 4 - (rowbytes % 4);
4962 pixel = ximg->data + y * rowbytes + x * 3;
4963 /* Windows bitmaps are in BGR order. */
4964 *pixel = GetBValue (color);
4965 *(pixel + 1) = GetGValue (color);
4966 *(pixel + 2) = GetRValue (color);
4968 /* Monochrome images. */
4969 else if (ximg->info.bmiHeader.biBitCount == 1)
4971 int rowbytes = width / 8;
4972 /* Ensure scanlines are aligned on 4 byte boundaries. */
4973 if (rowbytes % 4)
4974 rowbytes += 4 - (rowbytes % 4);
4975 pixel = ximg->data + y * rowbytes + x / 8;
4976 /* Filter out palette info. */
4977 if (color & 0x00ffffff)
4978 *pixel = *pixel | (1 << x % 8);
4979 else
4980 *pixel = *pixel & ~(1 << x % 8);
4982 else
4983 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
4986 #endif /* HAVE_NTGUI */
4988 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
4989 RGB members are set. F is the frame on which this all happens.
4990 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
4992 static void
4993 x_from_xcolors (f, img, colors)
4994 struct frame *f;
4995 struct image *img;
4996 XColor *colors;
4998 int x, y;
4999 XImagePtr oimg;
5000 Pixmap pixmap;
5001 XColor *p;
5003 init_color_table ();
5005 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5006 &oimg, &pixmap);
5007 p = colors;
5008 for (y = 0; y < img->height; ++y)
5009 for (x = 0; x < img->width; ++x, ++p)
5011 unsigned long pixel;
5012 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5013 XPutPixel (oimg, x, y, pixel);
5016 xfree (colors);
5017 x_clear_image_1 (f, img, 1, 0, 1);
5019 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5020 x_destroy_x_image (oimg);
5021 img->pixmap = pixmap;
5022 #ifdef COLOR_TABLE_SUPPORT
5023 img->colors = colors_in_color_table (&img->ncolors);
5024 free_color_table ();
5025 #endif /* COLOR_TABLE_SUPPORT */
5029 /* On frame F, perform edge-detection on image IMG.
5031 MATRIX is a nine-element array specifying the transformation
5032 matrix. See emboss_matrix for an example.
5034 COLOR_ADJUST is a color adjustment added to each pixel of the
5035 outgoing image. */
5037 static void
5038 x_detect_edges (f, img, matrix, color_adjust)
5039 struct frame *f;
5040 struct image *img;
5041 int matrix[9], color_adjust;
5043 XColor *colors = x_to_xcolors (f, img, 1);
5044 XColor *new, *p;
5045 int x, y, i, sum;
5047 for (i = sum = 0; i < 9; ++i)
5048 sum += abs (matrix[i]);
5050 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5052 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5054 for (y = 0; y < img->height; ++y)
5056 p = COLOR (new, 0, y);
5057 p->red = p->green = p->blue = 0xffff/2;
5058 p = COLOR (new, img->width - 1, y);
5059 p->red = p->green = p->blue = 0xffff/2;
5062 for (x = 1; x < img->width - 1; ++x)
5064 p = COLOR (new, x, 0);
5065 p->red = p->green = p->blue = 0xffff/2;
5066 p = COLOR (new, x, img->height - 1);
5067 p->red = p->green = p->blue = 0xffff/2;
5070 for (y = 1; y < img->height - 1; ++y)
5072 p = COLOR (new, 1, y);
5074 for (x = 1; x < img->width - 1; ++x, ++p)
5076 int r, g, b, y1, x1;
5078 r = g = b = i = 0;
5079 for (y1 = y - 1; y1 < y + 2; ++y1)
5080 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5081 if (matrix[i])
5083 XColor *t = COLOR (colors, x1, y1);
5084 r += matrix[i] * t->red;
5085 g += matrix[i] * t->green;
5086 b += matrix[i] * t->blue;
5089 r = (r / sum + color_adjust) & 0xffff;
5090 g = (g / sum + color_adjust) & 0xffff;
5091 b = (b / sum + color_adjust) & 0xffff;
5092 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5096 xfree (colors);
5097 x_from_xcolors (f, img, new);
5099 #undef COLOR
5103 /* Perform the pre-defined `emboss' edge-detection on image IMG
5104 on frame F. */
5106 static void
5107 x_emboss (f, img)
5108 struct frame *f;
5109 struct image *img;
5111 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5115 /* Transform image IMG which is used on frame F with a Laplace
5116 edge-detection algorithm. The result is an image that can be used
5117 to draw disabled buttons, for example. */
5119 static void
5120 x_laplace (f, img)
5121 struct frame *f;
5122 struct image *img;
5124 x_detect_edges (f, img, laplace_matrix, 45000);
5128 /* Perform edge-detection on image IMG on frame F, with specified
5129 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5131 MATRIX must be either
5133 - a list of at least 9 numbers in row-major form
5134 - a vector of at least 9 numbers
5136 COLOR_ADJUST nil means use a default; otherwise it must be a
5137 number. */
5139 static void
5140 x_edge_detection (f, img, matrix, color_adjust)
5141 struct frame *f;
5142 struct image *img;
5143 Lisp_Object matrix, color_adjust;
5145 int i = 0;
5146 int trans[9];
5148 if (CONSP (matrix))
5150 for (i = 0;
5151 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5152 ++i, matrix = XCDR (matrix))
5153 trans[i] = XFLOATINT (XCAR (matrix));
5155 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5157 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5158 trans[i] = XFLOATINT (AREF (matrix, i));
5161 if (NILP (color_adjust))
5162 color_adjust = make_number (0xffff / 2);
5164 if (i == 9 && NUMBERP (color_adjust))
5165 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5169 /* Transform image IMG on frame F so that it looks disabled. */
5171 static void
5172 x_disable_image (f, img)
5173 struct frame *f;
5174 struct image *img;
5176 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5177 #ifdef HAVE_NTGUI
5178 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5179 #else
5180 int n_planes = dpyinfo->n_planes;
5181 #endif /* HAVE_NTGUI */
5183 if (n_planes >= 2)
5185 /* Color (or grayscale). Convert to gray, and equalize. Just
5186 drawing such images with a stipple can look very odd, so
5187 we're using this method instead. */
5188 XColor *colors = x_to_xcolors (f, img, 1);
5189 XColor *p, *end;
5190 const int h = 15000;
5191 const int l = 30000;
5193 for (p = colors, end = colors + img->width * img->height;
5194 p < end;
5195 ++p)
5197 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5198 int i2 = (0xffff - h - l) * i / 0xffff + l;
5199 p->red = p->green = p->blue = i2;
5202 x_from_xcolors (f, img, colors);
5205 /* Draw a cross over the disabled image, if we must or if we
5206 should. */
5207 if (n_planes < 2 || cross_disabled_images)
5209 #ifndef HAVE_NTGUI
5210 Display *dpy = FRAME_X_DISPLAY (f);
5211 GC gc;
5213 #ifdef MAC_OS
5214 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
5215 #define MaskForeground(f) PIX_MASK_DRAW
5216 #else
5217 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
5218 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5219 #endif
5221 gc = XCreateGC_pixmap (dpy, img->pixmap);
5222 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5223 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5224 img->width - 1, img->height - 1);
5225 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5226 img->width - 1, 0);
5227 XFreeGC (dpy, gc);
5229 if (img->mask)
5231 gc = XCreateGC_pixmap (dpy, img->mask);
5232 XSetForeground (dpy, gc, MaskForeground (f));
5233 XDrawLine (dpy, img->mask, gc, 0, 0,
5234 img->width - 1, img->height - 1);
5235 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5236 img->width - 1, 0);
5237 XFreeGC (dpy, gc);
5239 #else
5240 HDC hdc, bmpdc;
5241 HGDIOBJ prev;
5243 hdc = get_frame_dc (f);
5244 bmpdc = CreateCompatibleDC (hdc);
5245 release_frame_dc (f, hdc);
5247 prev = SelectObject (bmpdc, img->pixmap);
5249 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5250 MoveToEx (bmpdc, 0, 0, NULL);
5251 LineTo (bmpdc, img->width - 1, img->height - 1);
5252 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5253 LineTo (bmpdc, img->width - 1, 0);
5255 if (img->mask)
5257 SelectObject (bmpdc, img->mask);
5258 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5259 MoveToEx (bmpdc, 0, 0, NULL);
5260 LineTo (bmpdc, img->width - 1, img->height - 1);
5261 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5262 LineTo (bmpdc, img->width - 1, 0);
5264 SelectObject (bmpdc, prev);
5265 DeleteDC (bmpdc);
5266 #endif /* HAVE_NTGUI */
5271 /* Build a mask for image IMG which is used on frame F. FILE is the
5272 name of an image file, for error messages. HOW determines how to
5273 determine the background color of IMG. If it is a list '(R G B)',
5274 with R, G, and B being integers >= 0, take that as the color of the
5275 background. Otherwise, determine the background color of IMG
5276 heuristically. Value is non-zero if successful. */
5278 static int
5279 x_build_heuristic_mask (f, img, how)
5280 struct frame *f;
5281 struct image *img;
5282 Lisp_Object how;
5284 XImagePtr_or_DC ximg;
5285 #ifndef HAVE_NTGUI
5286 XImagePtr mask_img;
5287 #else
5288 HDC frame_dc;
5289 HGDIOBJ prev;
5290 char *mask_img;
5291 int row_width;
5292 #endif /* HAVE_NTGUI */
5293 int x, y, rc, use_img_background;
5294 unsigned long bg = 0;
5296 if (img->mask)
5298 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5299 img->mask = NO_PIXMAP;
5300 img->background_transparent_valid = 0;
5303 #ifndef HAVE_NTGUI
5304 /* Create an image and pixmap serving as mask. */
5305 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5306 &mask_img, &img->mask);
5307 if (!rc)
5308 return 0;
5310 /* Get the X image of IMG->pixmap. */
5311 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5312 img->width, img->height,
5313 ~0, ZPixmap);
5314 #else
5315 /* Create the bit array serving as mask. */
5316 row_width = (img->width + 7) / 8;
5317 mask_img = xmalloc (row_width * img->height);
5318 bzero (mask_img, row_width * img->height);
5320 /* Create a memory device context for IMG->pixmap. */
5321 frame_dc = get_frame_dc (f);
5322 ximg = CreateCompatibleDC (frame_dc);
5323 release_frame_dc (f, frame_dc);
5324 prev = SelectObject (ximg, img->pixmap);
5325 #endif /* HAVE_NTGUI */
5327 /* Determine the background color of ximg. If HOW is `(R G B)'
5328 take that as color. Otherwise, use the image's background color. */
5329 use_img_background = 1;
5331 if (CONSP (how))
5333 int rgb[3], i;
5335 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5337 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5338 how = XCDR (how);
5341 if (i == 3 && NILP (how))
5343 char color_name[30];
5344 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5345 bg = (
5346 #ifdef HAVE_NTGUI
5347 0x00ffffff & /* Filter out palette info. */
5348 #endif /* HAVE_NTGUI */
5349 x_alloc_image_color (f, img, build_string (color_name), 0));
5350 use_img_background = 0;
5354 if (use_img_background)
5355 bg = four_corners_best (ximg, img->width, img->height);
5357 /* Set all bits in mask_img to 1 whose color in ximg is different
5358 from the background color bg. */
5359 #ifndef HAVE_NTGUI
5360 for (y = 0; y < img->height; ++y)
5361 for (x = 0; x < img->width; ++x)
5362 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5363 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5365 /* Fill in the background_transparent field while we have the mask handy. */
5366 image_background_transparent (img, f, mask_img);
5368 /* Put mask_img into img->mask. */
5369 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5370 x_destroy_x_image (mask_img);
5372 #else
5373 for (y = 0; y < img->height; ++y)
5374 for (x = 0; x < img->width; ++x)
5376 COLORREF p = GetPixel (ximg, x, y);
5377 if (p != bg)
5378 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5381 /* Create the mask image. */
5382 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5383 mask_img);
5384 /* Fill in the background_transparent field while we have the mask handy. */
5385 SelectObject (ximg, img->mask);
5386 image_background_transparent (img, f, ximg);
5388 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5389 xfree (mask_img);
5390 #endif /* HAVE_NTGUI */
5392 Destroy_Image (ximg, prev);
5394 return 1;
5398 /***********************************************************************
5399 PBM (mono, gray, color)
5400 ***********************************************************************/
5402 static int pbm_image_p P_ ((Lisp_Object object));
5403 static int pbm_load P_ ((struct frame *f, struct image *img));
5404 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5406 /* The symbol `pbm' identifying images of this type. */
5408 Lisp_Object Qpbm;
5410 /* Indices of image specification fields in gs_format, below. */
5412 enum pbm_keyword_index
5414 PBM_TYPE,
5415 PBM_FILE,
5416 PBM_DATA,
5417 PBM_ASCENT,
5418 PBM_MARGIN,
5419 PBM_RELIEF,
5420 PBM_ALGORITHM,
5421 PBM_HEURISTIC_MASK,
5422 PBM_MASK,
5423 PBM_FOREGROUND,
5424 PBM_BACKGROUND,
5425 PBM_LAST
5428 /* Vector of image_keyword structures describing the format
5429 of valid user-defined image specifications. */
5431 static struct image_keyword pbm_format[PBM_LAST] =
5433 {":type", IMAGE_SYMBOL_VALUE, 1},
5434 {":file", IMAGE_STRING_VALUE, 0},
5435 {":data", IMAGE_STRING_VALUE, 0},
5436 {":ascent", IMAGE_ASCENT_VALUE, 0},
5437 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5438 {":relief", IMAGE_INTEGER_VALUE, 0},
5439 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5440 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5441 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5442 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5443 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5446 /* Structure describing the image type `pbm'. */
5448 static struct image_type pbm_type =
5450 &Qpbm,
5451 pbm_image_p,
5452 pbm_load,
5453 x_clear_image,
5454 NULL
5458 /* Return non-zero if OBJECT is a valid PBM image specification. */
5460 static int
5461 pbm_image_p (object)
5462 Lisp_Object object;
5464 struct image_keyword fmt[PBM_LAST];
5466 bcopy (pbm_format, fmt, sizeof fmt);
5468 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5469 return 0;
5471 /* Must specify either :data or :file. */
5472 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5476 /* Scan a decimal number from *S and return it. Advance *S while
5477 reading the number. END is the end of the string. Value is -1 at
5478 end of input. */
5480 static int
5481 pbm_scan_number (s, end)
5482 unsigned char **s, *end;
5484 int c = 0, val = -1;
5486 while (*s < end)
5488 /* Skip white-space. */
5489 while (*s < end && (c = *(*s)++, isspace (c)))
5492 if (c == '#')
5494 /* Skip comment to end of line. */
5495 while (*s < end && (c = *(*s)++, c != '\n'))
5498 else if (isdigit (c))
5500 /* Read decimal number. */
5501 val = c - '0';
5502 while (*s < end && (c = *(*s)++, isdigit (c)))
5503 val = 10 * val + c - '0';
5504 break;
5506 else
5507 break;
5510 return val;
5514 #ifdef HAVE_NTGUI
5515 #if 0 /* Unused. ++kfs */
5517 /* Read FILE into memory. Value is a pointer to a buffer allocated
5518 with xmalloc holding FILE's contents. Value is null if an error
5519 occurred. *SIZE is set to the size of the file. */
5521 static char *
5522 pbm_read_file (file, size)
5523 Lisp_Object file;
5524 int *size;
5526 FILE *fp = NULL;
5527 char *buf = NULL;
5528 struct stat st;
5530 if (stat (SDATA (file), &st) == 0
5531 && (fp = fopen (SDATA (file), "rb")) != NULL
5532 && (buf = (char *) xmalloc (st.st_size),
5533 fread (buf, 1, st.st_size, fp) == st.st_size))
5535 *size = st.st_size;
5536 fclose (fp);
5538 else
5540 if (fp)
5541 fclose (fp);
5542 if (buf)
5544 xfree (buf);
5545 buf = NULL;
5549 return buf;
5551 #endif
5552 #endif /* HAVE_NTGUI */
5554 /* Load PBM image IMG for use on frame F. */
5556 static int
5557 pbm_load (f, img)
5558 struct frame *f;
5559 struct image *img;
5561 int raw_p, x, y;
5562 int width, height, max_color_idx = 0;
5563 XImagePtr ximg;
5564 Lisp_Object file, specified_file;
5565 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5566 struct gcpro gcpro1;
5567 unsigned char *contents = NULL;
5568 unsigned char *end, *p;
5569 int size;
5571 specified_file = image_spec_value (img->spec, QCfile, NULL);
5572 file = Qnil;
5573 GCPRO1 (file);
5575 if (STRINGP (specified_file))
5577 file = x_find_image_file (specified_file);
5578 if (!STRINGP (file))
5580 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5581 UNGCPRO;
5582 return 0;
5585 contents = slurp_file (SDATA (file), &size);
5586 if (contents == NULL)
5588 image_error ("Error reading `%s'", file, Qnil);
5589 UNGCPRO;
5590 return 0;
5593 p = contents;
5594 end = contents + size;
5596 else
5598 Lisp_Object data;
5599 data = image_spec_value (img->spec, QCdata, NULL);
5600 p = SDATA (data);
5601 end = p + SBYTES (data);
5604 /* Check magic number. */
5605 if (end - p < 2 || *p++ != 'P')
5607 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5608 error:
5609 xfree (contents);
5610 UNGCPRO;
5611 return 0;
5614 switch (*p++)
5616 case '1':
5617 raw_p = 0, type = PBM_MONO;
5618 break;
5620 case '2':
5621 raw_p = 0, type = PBM_GRAY;
5622 break;
5624 case '3':
5625 raw_p = 0, type = PBM_COLOR;
5626 break;
5628 case '4':
5629 raw_p = 1, type = PBM_MONO;
5630 break;
5632 case '5':
5633 raw_p = 1, type = PBM_GRAY;
5634 break;
5636 case '6':
5637 raw_p = 1, type = PBM_COLOR;
5638 break;
5640 default:
5641 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5642 goto error;
5645 /* Read width, height, maximum color-component. Characters
5646 starting with `#' up to the end of a line are ignored. */
5647 width = pbm_scan_number (&p, end);
5648 height = pbm_scan_number (&p, end);
5650 if (type != PBM_MONO)
5652 max_color_idx = pbm_scan_number (&p, end);
5653 if (raw_p && max_color_idx > 255)
5654 max_color_idx = 255;
5657 if (!check_image_size (f, width, height)
5658 || (type != PBM_MONO && max_color_idx < 0))
5659 goto error;
5661 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5662 &ximg, &img->pixmap))
5663 goto error;
5665 /* Initialize the color hash table. */
5666 init_color_table ();
5668 if (type == PBM_MONO)
5670 int c = 0, g;
5671 struct image_keyword fmt[PBM_LAST];
5672 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5673 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5675 /* Parse the image specification. */
5676 bcopy (pbm_format, fmt, sizeof fmt);
5677 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5679 /* Get foreground and background colors, maybe allocate colors. */
5680 if (fmt[PBM_FOREGROUND].count
5681 && STRINGP (fmt[PBM_FOREGROUND].value))
5682 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5683 if (fmt[PBM_BACKGROUND].count
5684 && STRINGP (fmt[PBM_BACKGROUND].value))
5686 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5687 img->background = bg;
5688 img->background_valid = 1;
5691 for (y = 0; y < height; ++y)
5692 for (x = 0; x < width; ++x)
5694 if (raw_p)
5696 if ((x & 7) == 0)
5697 c = *p++;
5698 g = c & 0x80;
5699 c <<= 1;
5701 else
5702 g = pbm_scan_number (&p, end);
5704 XPutPixel (ximg, x, y, g ? fg : bg);
5707 else
5709 for (y = 0; y < height; ++y)
5710 for (x = 0; x < width; ++x)
5712 int r, g, b;
5714 if (type == PBM_GRAY)
5715 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
5716 else if (raw_p)
5718 r = *p++;
5719 g = *p++;
5720 b = *p++;
5722 else
5724 r = pbm_scan_number (&p, end);
5725 g = pbm_scan_number (&p, end);
5726 b = pbm_scan_number (&p, end);
5729 if (r < 0 || g < 0 || b < 0)
5731 x_destroy_x_image (ximg);
5732 image_error ("Invalid pixel value in image `%s'",
5733 img->spec, Qnil);
5734 goto error;
5737 /* RGB values are now in the range 0..max_color_idx.
5738 Scale this to the range 0..0xffff supported by X. */
5739 r = (double) r * 65535 / max_color_idx;
5740 g = (double) g * 65535 / max_color_idx;
5741 b = (double) b * 65535 / max_color_idx;
5742 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5746 #ifdef COLOR_TABLE_SUPPORT
5747 /* Store in IMG->colors the colors allocated for the image, and
5748 free the color table. */
5749 img->colors = colors_in_color_table (&img->ncolors);
5750 free_color_table ();
5751 #endif /* COLOR_TABLE_SUPPORT */
5753 img->width = width;
5754 img->height = height;
5756 /* Maybe fill in the background field while we have ximg handy. */
5758 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5759 /* Casting avoids a GCC warning. */
5760 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5762 /* Put the image into a pixmap. */
5763 x_put_x_image (f, ximg, img->pixmap, width, height);
5764 x_destroy_x_image (ximg);
5766 /* X and W32 versions did it here, MAC version above. ++kfs
5767 img->width = width;
5768 img->height = height; */
5770 UNGCPRO;
5771 xfree (contents);
5772 return 1;
5776 /***********************************************************************
5778 ***********************************************************************/
5780 #if defined (HAVE_PNG) || defined (MAC_OS)
5782 /* Function prototypes. */
5784 static int png_image_p P_ ((Lisp_Object object));
5785 static int png_load P_ ((struct frame *f, struct image *img));
5787 /* The symbol `png' identifying images of this type. */
5789 Lisp_Object Qpng;
5791 /* Indices of image specification fields in png_format, below. */
5793 enum png_keyword_index
5795 PNG_TYPE,
5796 PNG_DATA,
5797 PNG_FILE,
5798 PNG_ASCENT,
5799 PNG_MARGIN,
5800 PNG_RELIEF,
5801 PNG_ALGORITHM,
5802 PNG_HEURISTIC_MASK,
5803 PNG_MASK,
5804 PNG_BACKGROUND,
5805 PNG_LAST
5808 /* Vector of image_keyword structures describing the format
5809 of valid user-defined image specifications. */
5811 static struct image_keyword png_format[PNG_LAST] =
5813 {":type", IMAGE_SYMBOL_VALUE, 1},
5814 {":data", IMAGE_STRING_VALUE, 0},
5815 {":file", IMAGE_STRING_VALUE, 0},
5816 {":ascent", IMAGE_ASCENT_VALUE, 0},
5817 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5818 {":relief", IMAGE_INTEGER_VALUE, 0},
5819 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5820 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5821 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5822 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5825 /* Structure describing the image type `png'. */
5827 static struct image_type png_type =
5829 &Qpng,
5830 png_image_p,
5831 png_load,
5832 x_clear_image,
5833 NULL
5836 /* Return non-zero if OBJECT is a valid PNG image specification. */
5838 static int
5839 png_image_p (object)
5840 Lisp_Object object;
5842 struct image_keyword fmt[PNG_LAST];
5843 bcopy (png_format, fmt, sizeof fmt);
5845 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5846 return 0;
5848 /* Must specify either the :data or :file keyword. */
5849 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5852 #endif /* HAVE_PNG || MAC_OS */
5855 #ifdef HAVE_PNG
5857 #if defined HAVE_LIBPNG_PNG_H
5858 # include <libpng/png.h>
5859 #else
5860 # include <png.h>
5861 #endif
5863 #ifdef HAVE_NTGUI
5864 /* PNG library details. */
5866 DEF_IMGLIB_FN (png_get_io_ptr);
5867 DEF_IMGLIB_FN (png_check_sig);
5868 DEF_IMGLIB_FN (png_create_read_struct);
5869 DEF_IMGLIB_FN (png_create_info_struct);
5870 DEF_IMGLIB_FN (png_destroy_read_struct);
5871 DEF_IMGLIB_FN (png_set_read_fn);
5872 DEF_IMGLIB_FN (png_set_sig_bytes);
5873 DEF_IMGLIB_FN (png_read_info);
5874 DEF_IMGLIB_FN (png_get_IHDR);
5875 DEF_IMGLIB_FN (png_get_valid);
5876 DEF_IMGLIB_FN (png_set_strip_16);
5877 DEF_IMGLIB_FN (png_set_expand);
5878 DEF_IMGLIB_FN (png_set_gray_to_rgb);
5879 DEF_IMGLIB_FN (png_set_background);
5880 DEF_IMGLIB_FN (png_get_bKGD);
5881 DEF_IMGLIB_FN (png_read_update_info);
5882 DEF_IMGLIB_FN (png_get_channels);
5883 DEF_IMGLIB_FN (png_get_rowbytes);
5884 DEF_IMGLIB_FN (png_read_image);
5885 DEF_IMGLIB_FN (png_read_end);
5886 DEF_IMGLIB_FN (png_error);
5888 static int
5889 init_png_functions (Lisp_Object libraries)
5891 HMODULE library;
5893 /* Try loading libpng under probable names. */
5894 if (!(library = w32_delayed_load (libraries, Qpng)))
5895 return 0;
5897 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5898 LOAD_IMGLIB_FN (library, png_check_sig);
5899 LOAD_IMGLIB_FN (library, png_create_read_struct);
5900 LOAD_IMGLIB_FN (library, png_create_info_struct);
5901 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5902 LOAD_IMGLIB_FN (library, png_set_read_fn);
5903 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5904 LOAD_IMGLIB_FN (library, png_read_info);
5905 LOAD_IMGLIB_FN (library, png_get_IHDR);
5906 LOAD_IMGLIB_FN (library, png_get_valid);
5907 LOAD_IMGLIB_FN (library, png_set_strip_16);
5908 LOAD_IMGLIB_FN (library, png_set_expand);
5909 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5910 LOAD_IMGLIB_FN (library, png_set_background);
5911 LOAD_IMGLIB_FN (library, png_get_bKGD);
5912 LOAD_IMGLIB_FN (library, png_read_update_info);
5913 LOAD_IMGLIB_FN (library, png_get_channels);
5914 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5915 LOAD_IMGLIB_FN (library, png_read_image);
5916 LOAD_IMGLIB_FN (library, png_read_end);
5917 LOAD_IMGLIB_FN (library, png_error);
5918 return 1;
5920 #else
5922 #define fn_png_get_io_ptr png_get_io_ptr
5923 #define fn_png_check_sig png_check_sig
5924 #define fn_png_create_read_struct png_create_read_struct
5925 #define fn_png_create_info_struct png_create_info_struct
5926 #define fn_png_destroy_read_struct png_destroy_read_struct
5927 #define fn_png_set_read_fn png_set_read_fn
5928 #define fn_png_set_sig_bytes png_set_sig_bytes
5929 #define fn_png_read_info png_read_info
5930 #define fn_png_get_IHDR png_get_IHDR
5931 #define fn_png_get_valid png_get_valid
5932 #define fn_png_set_strip_16 png_set_strip_16
5933 #define fn_png_set_expand png_set_expand
5934 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5935 #define fn_png_set_background png_set_background
5936 #define fn_png_get_bKGD png_get_bKGD
5937 #define fn_png_read_update_info png_read_update_info
5938 #define fn_png_get_channels png_get_channels
5939 #define fn_png_get_rowbytes png_get_rowbytes
5940 #define fn_png_read_image png_read_image
5941 #define fn_png_read_end png_read_end
5942 #define fn_png_error png_error
5944 #endif /* HAVE_NTGUI */
5946 /* Error and warning handlers installed when the PNG library
5947 is initialized. */
5949 static void
5950 my_png_error (png_ptr, msg)
5951 png_struct *png_ptr;
5952 char *msg;
5954 xassert (png_ptr != NULL);
5955 image_error ("PNG error: %s", build_string (msg), Qnil);
5956 longjmp (png_ptr->jmpbuf, 1);
5960 static void
5961 my_png_warning (png_ptr, msg)
5962 png_struct *png_ptr;
5963 char *msg;
5965 xassert (png_ptr != NULL);
5966 image_error ("PNG warning: %s", build_string (msg), Qnil);
5969 /* Memory source for PNG decoding. */
5971 struct png_memory_storage
5973 unsigned char *bytes; /* The data */
5974 size_t len; /* How big is it? */
5975 int index; /* Where are we? */
5979 /* Function set as reader function when reading PNG image from memory.
5980 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
5981 bytes from the input to DATA. */
5983 static void
5984 png_read_from_memory (png_ptr, data, length)
5985 png_structp png_ptr;
5986 png_bytep data;
5987 png_size_t length;
5989 struct png_memory_storage *tbr
5990 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
5992 if (length > tbr->len - tbr->index)
5993 fn_png_error (png_ptr, "Read error");
5995 bcopy (tbr->bytes + tbr->index, data, length);
5996 tbr->index = tbr->index + length;
6000 /* Function set as reader function when reading PNG image from a file.
6001 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6002 bytes from the input to DATA. */
6004 static void
6005 png_read_from_file (png_ptr, data, length)
6006 png_structp png_ptr;
6007 png_bytep data;
6008 png_size_t length;
6010 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6012 if (fread (data, 1, length, fp) < length)
6013 fn_png_error (png_ptr, "Read error");
6017 /* Load PNG image IMG for use on frame F. Value is non-zero if
6018 successful. */
6020 static int
6021 png_load (f, img)
6022 struct frame *f;
6023 struct image *img;
6025 Lisp_Object file, specified_file;
6026 Lisp_Object specified_data;
6027 int x, y, i;
6028 XImagePtr ximg, mask_img = NULL;
6029 struct gcpro gcpro1;
6030 png_struct *png_ptr = NULL;
6031 png_info *info_ptr = NULL, *end_info = NULL;
6032 FILE *volatile fp = NULL;
6033 png_byte sig[8];
6034 png_byte * volatile pixels = NULL;
6035 png_byte ** volatile rows = NULL;
6036 png_uint_32 width, height;
6037 int bit_depth, color_type, interlace_type;
6038 png_byte channels;
6039 png_uint_32 row_bytes;
6040 int transparent_p;
6041 double screen_gamma;
6042 struct png_memory_storage tbr; /* Data to be read */
6044 /* Find out what file to load. */
6045 specified_file = image_spec_value (img->spec, QCfile, NULL);
6046 specified_data = image_spec_value (img->spec, QCdata, NULL);
6047 file = Qnil;
6048 GCPRO1 (file);
6050 if (NILP (specified_data))
6052 file = x_find_image_file (specified_file);
6053 if (!STRINGP (file))
6055 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6056 UNGCPRO;
6057 return 0;
6060 /* Open the image file. */
6061 fp = fopen (SDATA (file), "rb");
6062 if (!fp)
6064 image_error ("Cannot open image file `%s'", file, Qnil);
6065 UNGCPRO;
6066 fclose (fp);
6067 return 0;
6070 /* Check PNG signature. */
6071 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6072 || !fn_png_check_sig (sig, sizeof sig))
6074 image_error ("Not a PNG file: `%s'", file, Qnil);
6075 UNGCPRO;
6076 fclose (fp);
6077 return 0;
6080 else
6082 /* Read from memory. */
6083 tbr.bytes = SDATA (specified_data);
6084 tbr.len = SBYTES (specified_data);
6085 tbr.index = 0;
6087 /* Check PNG signature. */
6088 if (tbr.len < sizeof sig
6089 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6091 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6092 UNGCPRO;
6093 return 0;
6096 /* Need to skip past the signature. */
6097 tbr.bytes += sizeof (sig);
6100 /* Initialize read and info structs for PNG lib. Casting return
6101 value avoids a GCC warning on W32. */
6102 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6103 NULL, my_png_error,
6104 my_png_warning);
6105 if (!png_ptr)
6107 if (fp) fclose (fp);
6108 UNGCPRO;
6109 return 0;
6112 /* Casting return value avoids a GCC warning on W32. */
6113 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6114 if (!info_ptr)
6116 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6117 if (fp) fclose (fp);
6118 UNGCPRO;
6119 return 0;
6122 /* Casting return value avoids a GCC warning on W32. */
6123 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6124 if (!end_info)
6126 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6127 if (fp) fclose (fp);
6128 UNGCPRO;
6129 return 0;
6132 /* Set error jump-back. We come back here when the PNG library
6133 detects an error. */
6134 if (setjmp (png_ptr->jmpbuf))
6136 error:
6137 if (png_ptr)
6138 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6139 xfree (pixels);
6140 xfree (rows);
6141 if (fp) fclose (fp);
6142 UNGCPRO;
6143 return 0;
6146 /* Read image info. */
6147 if (!NILP (specified_data))
6148 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6149 else
6150 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6152 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6153 fn_png_read_info (png_ptr, info_ptr);
6154 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6155 &interlace_type, NULL, NULL);
6157 if (!check_image_size (f, width, height))
6158 goto error;
6160 /* If image contains simply transparency data, we prefer to
6161 construct a clipping mask. */
6162 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6163 transparent_p = 1;
6164 else
6165 transparent_p = 0;
6167 /* This function is easier to write if we only have to handle
6168 one data format: RGB or RGBA with 8 bits per channel. Let's
6169 transform other formats into that format. */
6171 /* Strip more than 8 bits per channel. */
6172 if (bit_depth == 16)
6173 fn_png_set_strip_16 (png_ptr);
6175 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6176 if available. */
6177 fn_png_set_expand (png_ptr);
6179 /* Convert grayscale images to RGB. */
6180 if (color_type == PNG_COLOR_TYPE_GRAY
6181 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6182 fn_png_set_gray_to_rgb (png_ptr);
6184 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
6186 #if 0 /* Avoid double gamma correction for PNG images. */
6187 { /* Tell the PNG lib to handle gamma correction for us. */
6188 int intent;
6189 double image_gamma;
6190 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6191 if (png_get_sRGB (png_ptr, info_ptr, &intent))
6192 /* The libpng documentation says this is right in this case. */
6193 png_set_gamma (png_ptr, screen_gamma, 0.45455);
6194 else
6195 #endif
6196 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
6197 /* Image contains gamma information. */
6198 png_set_gamma (png_ptr, screen_gamma, image_gamma);
6199 else
6200 /* Use the standard default for the image gamma. */
6201 png_set_gamma (png_ptr, screen_gamma, 0.45455);
6203 #endif /* if 0 */
6205 /* Handle alpha channel by combining the image with a background
6206 color. Do this only if a real alpha channel is supplied. For
6207 simple transparency, we prefer a clipping mask. */
6208 if (!transparent_p)
6210 png_color_16 *image_bg;
6211 Lisp_Object specified_bg
6212 = image_spec_value (img->spec, QCbackground, NULL);
6214 if (STRINGP (specified_bg))
6215 /* The user specified `:background', use that. */
6217 /* W32 version incorrectly used COLORREF here!! ++kfs */
6218 XColor color;
6219 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6221 png_color_16 user_bg;
6223 bzero (&user_bg, sizeof user_bg);
6224 user_bg.red = color.red >> 8;
6225 user_bg.green = color.green >> 8;
6226 user_bg.blue = color.blue >> 8;
6228 fn_png_set_background (png_ptr, &user_bg,
6229 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6232 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
6233 /* Image contains a background color with which to
6234 combine the image. */
6235 fn_png_set_background (png_ptr, image_bg,
6236 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6237 else
6239 /* Image does not contain a background color with which
6240 to combine the image data via an alpha channel. Use
6241 the frame's background instead. */
6242 #ifdef HAVE_X_WINDOWS
6243 XColor color;
6244 png_color_16 frame_background;
6246 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6247 x_query_color (f, &color);
6249 bzero (&frame_background, sizeof frame_background);
6250 frame_background.red = color.red >> 8;
6251 frame_background.green = color.green >> 8;
6252 frame_background.blue = color.blue >> 8;
6253 #endif /* HAVE_X_WINDOWS */
6255 #ifdef HAVE_NTGUI
6256 COLORREF color;
6257 png_color_16 frame_background;
6258 color = FRAME_BACKGROUND_PIXEL (f);
6259 #if 0 /* W32 TODO : Colormap support. */
6260 x_query_color (f, &color);
6261 #endif
6262 bzero (&frame_background, sizeof frame_background);
6263 frame_background.red = GetRValue (color);
6264 frame_background.green = GetGValue (color);
6265 frame_background.blue = GetBValue (color);
6266 #endif /* HAVE_NTGUI */
6268 #ifdef MAC_OS
6269 unsigned long color;
6270 png_color_16 frame_background;
6271 color = FRAME_BACKGROUND_PIXEL (f);
6272 #if 0 /* MAC/W32 TODO : Colormap support. */
6273 x_query_color (f, &color);
6274 #endif
6275 bzero (&frame_background, sizeof frame_background);
6276 frame_background.red = RED_FROM_ULONG (color);
6277 frame_background.green = GREEN_FROM_ULONG (color);
6278 frame_background.blue = BLUE_FROM_ULONG (color);
6279 #endif /* MAC_OS */
6281 fn_png_set_background (png_ptr, &frame_background,
6282 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6286 /* Update info structure. */
6287 fn_png_read_update_info (png_ptr, info_ptr);
6289 /* Get number of channels. Valid values are 1 for grayscale images
6290 and images with a palette, 2 for grayscale images with transparency
6291 information (alpha channel), 3 for RGB images, and 4 for RGB
6292 images with alpha channel, i.e. RGBA. If conversions above were
6293 sufficient we should only have 3 or 4 channels here. */
6294 channels = fn_png_get_channels (png_ptr, info_ptr);
6295 xassert (channels == 3 || channels == 4);
6297 /* Number of bytes needed for one row of the image. */
6298 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6300 /* Allocate memory for the image. */
6301 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6302 rows = (png_byte **) xmalloc (height * sizeof *rows);
6303 for (i = 0; i < height; ++i)
6304 rows[i] = pixels + i * row_bytes;
6306 /* Read the entire image. */
6307 fn_png_read_image (png_ptr, rows);
6308 fn_png_read_end (png_ptr, info_ptr);
6309 if (fp)
6311 fclose (fp);
6312 fp = NULL;
6315 /* Create the X image and pixmap. */
6316 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6317 &img->pixmap))
6318 goto error;
6320 /* Create an image and pixmap serving as mask if the PNG image
6321 contains an alpha channel. */
6322 if (channels == 4
6323 && !transparent_p
6324 && !x_create_x_image_and_pixmap (f, width, height, 1,
6325 &mask_img, &img->mask))
6327 x_destroy_x_image (ximg);
6328 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6329 img->pixmap = NO_PIXMAP;
6330 goto error;
6333 /* Fill the X image and mask from PNG data. */
6334 init_color_table ();
6336 for (y = 0; y < height; ++y)
6338 png_byte *p = rows[y];
6340 for (x = 0; x < width; ++x)
6342 unsigned r, g, b;
6344 r = *p++ << 8;
6345 g = *p++ << 8;
6346 b = *p++ << 8;
6347 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6348 /* An alpha channel, aka mask channel, associates variable
6349 transparency with an image. Where other image formats
6350 support binary transparency---fully transparent or fully
6351 opaque---PNG allows up to 254 levels of partial transparency.
6352 The PNG library implements partial transparency by combining
6353 the image with a specified background color.
6355 I'm not sure how to handle this here nicely: because the
6356 background on which the image is displayed may change, for
6357 real alpha channel support, it would be necessary to create
6358 a new image for each possible background.
6360 What I'm doing now is that a mask is created if we have
6361 boolean transparency information. Otherwise I'm using
6362 the frame's background color to combine the image with. */
6364 if (channels == 4)
6366 if (mask_img)
6367 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6368 ++p;
6373 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6374 /* Set IMG's background color from the PNG image, unless the user
6375 overrode it. */
6377 png_color_16 *bg;
6378 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6380 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6381 img->background_valid = 1;
6385 #ifdef COLOR_TABLE_SUPPORT
6386 /* Remember colors allocated for this image. */
6387 img->colors = colors_in_color_table (&img->ncolors);
6388 free_color_table ();
6389 #endif /* COLOR_TABLE_SUPPORT */
6391 /* Clean up. */
6392 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6393 xfree (rows);
6394 xfree (pixels);
6396 img->width = width;
6397 img->height = height;
6399 /* Maybe fill in the background field while we have ximg handy.
6400 Casting avoids a GCC warning. */
6401 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6403 /* Put the image into the pixmap, then free the X image and its buffer. */
6404 x_put_x_image (f, ximg, img->pixmap, width, height);
6405 x_destroy_x_image (ximg);
6407 /* Same for the mask. */
6408 if (mask_img)
6410 /* Fill in the background_transparent field while we have the
6411 mask handy. Casting avoids a GCC warning. */
6412 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6414 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6415 x_destroy_x_image (mask_img);
6418 UNGCPRO;
6419 return 1;
6422 #else /* HAVE_PNG */
6424 #ifdef MAC_OS
6425 static int
6426 png_load (f, img)
6427 struct frame *f;
6428 struct image *img;
6430 #ifdef MAC_OSX
6431 if (MyCGImageCreateWithPNGDataProvider)
6432 return image_load_quartz2d (f, img, 1);
6433 else
6434 #endif
6435 return image_load_quicktime (f, img, kQTFileTypePNG);
6437 #endif /* MAC_OS */
6439 #endif /* !HAVE_PNG */
6443 /***********************************************************************
6444 JPEG
6445 ***********************************************************************/
6447 #if defined (HAVE_JPEG) || defined (MAC_OS)
6449 static int jpeg_image_p P_ ((Lisp_Object object));
6450 static int jpeg_load P_ ((struct frame *f, struct image *img));
6452 /* The symbol `jpeg' identifying images of this type. */
6454 Lisp_Object Qjpeg;
6456 /* Indices of image specification fields in gs_format, below. */
6458 enum jpeg_keyword_index
6460 JPEG_TYPE,
6461 JPEG_DATA,
6462 JPEG_FILE,
6463 JPEG_ASCENT,
6464 JPEG_MARGIN,
6465 JPEG_RELIEF,
6466 JPEG_ALGORITHM,
6467 JPEG_HEURISTIC_MASK,
6468 JPEG_MASK,
6469 JPEG_BACKGROUND,
6470 JPEG_LAST
6473 /* Vector of image_keyword structures describing the format
6474 of valid user-defined image specifications. */
6476 static struct image_keyword jpeg_format[JPEG_LAST] =
6478 {":type", IMAGE_SYMBOL_VALUE, 1},
6479 {":data", IMAGE_STRING_VALUE, 0},
6480 {":file", IMAGE_STRING_VALUE, 0},
6481 {":ascent", IMAGE_ASCENT_VALUE, 0},
6482 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6483 {":relief", IMAGE_INTEGER_VALUE, 0},
6484 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6485 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6486 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6487 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6490 /* Structure describing the image type `jpeg'. */
6492 static struct image_type jpeg_type =
6494 &Qjpeg,
6495 jpeg_image_p,
6496 jpeg_load,
6497 x_clear_image,
6498 NULL
6501 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6503 static int
6504 jpeg_image_p (object)
6505 Lisp_Object object;
6507 struct image_keyword fmt[JPEG_LAST];
6509 bcopy (jpeg_format, fmt, sizeof fmt);
6511 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6512 return 0;
6514 /* Must specify either the :data or :file keyword. */
6515 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6518 #endif /* HAVE_JPEG || MAC_OS */
6520 #ifdef HAVE_JPEG
6522 /* Work around a warning about HAVE_STDLIB_H being redefined in
6523 jconfig.h. */
6524 #ifdef HAVE_STDLIB_H
6525 #define HAVE_STDLIB_H_1
6526 #undef HAVE_STDLIB_H
6527 #endif /* HAVE_STLIB_H */
6529 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6530 /* In older releases of the jpeg library, jpeglib.h will define boolean
6531 differently depending on __WIN32__, so make sure it is defined. */
6532 #define __WIN32__ 1
6533 #endif
6535 #include <jpeglib.h>
6536 #include <jerror.h>
6537 #include <setjmp.h>
6539 #ifdef HAVE_STLIB_H_1
6540 #define HAVE_STDLIB_H 1
6541 #endif
6543 #ifdef HAVE_NTGUI
6545 /* JPEG library details. */
6546 DEF_IMGLIB_FN (jpeg_CreateDecompress);
6547 DEF_IMGLIB_FN (jpeg_start_decompress);
6548 DEF_IMGLIB_FN (jpeg_finish_decompress);
6549 DEF_IMGLIB_FN (jpeg_destroy_decompress);
6550 DEF_IMGLIB_FN (jpeg_read_header);
6551 DEF_IMGLIB_FN (jpeg_read_scanlines);
6552 DEF_IMGLIB_FN (jpeg_std_error);
6553 DEF_IMGLIB_FN (jpeg_resync_to_restart);
6555 static int
6556 init_jpeg_functions (Lisp_Object libraries)
6558 HMODULE library;
6560 if (!(library = w32_delayed_load (libraries, Qjpeg)))
6561 return 0;
6563 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6564 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6565 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6566 LOAD_IMGLIB_FN (library, jpeg_read_header);
6567 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6568 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6569 LOAD_IMGLIB_FN (library, jpeg_std_error);
6570 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6571 return 1;
6574 /* Wrapper since we can't directly assign the function pointer
6575 to another function pointer that was declared more completely easily. */
6576 static boolean
6577 jpeg_resync_to_restart_wrapper(cinfo, desired)
6578 j_decompress_ptr cinfo;
6579 int desired;
6581 return fn_jpeg_resync_to_restart (cinfo, desired);
6584 #else
6586 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6587 #define fn_jpeg_start_decompress jpeg_start_decompress
6588 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6589 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6590 #define fn_jpeg_read_header jpeg_read_header
6591 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6592 #define fn_jpeg_std_error jpeg_std_error
6593 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6595 #endif /* HAVE_NTGUI */
6597 struct my_jpeg_error_mgr
6599 struct jpeg_error_mgr pub;
6600 jmp_buf setjmp_buffer;
6604 static void
6605 my_error_exit (cinfo)
6606 j_common_ptr cinfo;
6608 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6609 longjmp (mgr->setjmp_buffer, 1);
6613 /* Init source method for JPEG data source manager. Called by
6614 jpeg_read_header() before any data is actually read. See
6615 libjpeg.doc from the JPEG lib distribution. */
6617 static void
6618 our_common_init_source (cinfo)
6619 j_decompress_ptr cinfo;
6624 /* Method to terminate data source. Called by
6625 jpeg_finish_decompress() after all data has been processed. */
6627 static void
6628 our_common_term_source (cinfo)
6629 j_decompress_ptr cinfo;
6634 /* Fill input buffer method for JPEG data source manager. Called
6635 whenever more data is needed. We read the whole image in one step,
6636 so this only adds a fake end of input marker at the end. */
6638 static boolean
6639 our_memory_fill_input_buffer (cinfo)
6640 j_decompress_ptr cinfo;
6642 /* Insert a fake EOI marker. */
6643 struct jpeg_source_mgr *src = cinfo->src;
6644 static JOCTET buffer[2];
6646 buffer[0] = (JOCTET) 0xFF;
6647 buffer[1] = (JOCTET) JPEG_EOI;
6649 src->next_input_byte = buffer;
6650 src->bytes_in_buffer = 2;
6651 return 1;
6655 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6656 is the JPEG data source manager. */
6658 static void
6659 our_memory_skip_input_data (cinfo, num_bytes)
6660 j_decompress_ptr cinfo;
6661 long num_bytes;
6663 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6665 if (src)
6667 if (num_bytes > src->bytes_in_buffer)
6668 ERREXIT (cinfo, JERR_INPUT_EOF);
6670 src->bytes_in_buffer -= num_bytes;
6671 src->next_input_byte += num_bytes;
6676 /* Set up the JPEG lib for reading an image from DATA which contains
6677 LEN bytes. CINFO is the decompression info structure created for
6678 reading the image. */
6680 static void
6681 jpeg_memory_src (cinfo, data, len)
6682 j_decompress_ptr cinfo;
6683 JOCTET *data;
6684 unsigned int len;
6686 struct jpeg_source_mgr *src;
6688 if (cinfo->src == NULL)
6690 /* First time for this JPEG object? */
6691 cinfo->src = (struct jpeg_source_mgr *)
6692 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6693 sizeof (struct jpeg_source_mgr));
6694 src = (struct jpeg_source_mgr *) cinfo->src;
6695 src->next_input_byte = data;
6698 src = (struct jpeg_source_mgr *) cinfo->src;
6699 src->init_source = our_common_init_source;
6700 src->fill_input_buffer = our_memory_fill_input_buffer;
6701 src->skip_input_data = our_memory_skip_input_data;
6702 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6703 src->term_source = our_common_term_source;
6704 src->bytes_in_buffer = len;
6705 src->next_input_byte = data;
6709 struct jpeg_stdio_mgr
6711 struct jpeg_source_mgr mgr;
6712 boolean finished;
6713 FILE *file;
6714 JOCTET *buffer;
6718 /* Size of buffer to read JPEG from file.
6719 Not too big, as we want to use alloc_small. */
6720 #define JPEG_STDIO_BUFFER_SIZE 8192
6723 /* Fill input buffer method for JPEG data source manager. Called
6724 whenever more data is needed. The data is read from a FILE *. */
6726 static boolean
6727 our_stdio_fill_input_buffer (cinfo)
6728 j_decompress_ptr cinfo;
6730 struct jpeg_stdio_mgr *src;
6732 src = (struct jpeg_stdio_mgr *) cinfo->src;
6733 if (!src->finished)
6735 size_t bytes;
6737 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6738 if (bytes > 0)
6739 src->mgr.bytes_in_buffer = bytes;
6740 else
6742 WARNMS (cinfo, JWRN_JPEG_EOF);
6743 src->finished = 1;
6744 src->buffer[0] = (JOCTET) 0xFF;
6745 src->buffer[1] = (JOCTET) JPEG_EOI;
6746 src->mgr.bytes_in_buffer = 2;
6748 src->mgr.next_input_byte = src->buffer;
6751 return 1;
6755 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6756 is the JPEG data source manager. */
6758 static void
6759 our_stdio_skip_input_data (cinfo, num_bytes)
6760 j_decompress_ptr cinfo;
6761 long num_bytes;
6763 struct jpeg_stdio_mgr *src;
6764 src = (struct jpeg_stdio_mgr *) cinfo->src;
6766 while (num_bytes > 0 && !src->finished)
6768 if (num_bytes <= src->mgr.bytes_in_buffer)
6770 src->mgr.bytes_in_buffer -= num_bytes;
6771 src->mgr.next_input_byte += num_bytes;
6772 break;
6774 else
6776 num_bytes -= src->mgr.bytes_in_buffer;
6777 src->mgr.bytes_in_buffer = 0;
6778 src->mgr.next_input_byte = NULL;
6780 our_stdio_fill_input_buffer (cinfo);
6786 /* Set up the JPEG lib for reading an image from a FILE *.
6787 CINFO is the decompression info structure created for
6788 reading the image. */
6790 static void
6791 jpeg_file_src (cinfo, fp)
6792 j_decompress_ptr cinfo;
6793 FILE *fp;
6795 struct jpeg_stdio_mgr *src;
6797 if (cinfo->src != NULL)
6798 src = (struct jpeg_stdio_mgr *) cinfo->src;
6799 else
6801 /* First time for this JPEG object? */
6802 cinfo->src = (struct jpeg_source_mgr *)
6803 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6804 sizeof (struct jpeg_stdio_mgr));
6805 src = (struct jpeg_stdio_mgr *) cinfo->src;
6806 src->buffer = (JOCTET *)
6807 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6808 JPEG_STDIO_BUFFER_SIZE);
6811 src->file = fp;
6812 src->finished = 0;
6813 src->mgr.init_source = our_common_init_source;
6814 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6815 src->mgr.skip_input_data = our_stdio_skip_input_data;
6816 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6817 src->mgr.term_source = our_common_term_source;
6818 src->mgr.bytes_in_buffer = 0;
6819 src->mgr.next_input_byte = NULL;
6823 /* Load image IMG for use on frame F. Patterned after example.c
6824 from the JPEG lib. */
6826 static int
6827 jpeg_load (f, img)
6828 struct frame *f;
6829 struct image *img;
6831 struct jpeg_decompress_struct cinfo;
6832 struct my_jpeg_error_mgr mgr;
6833 Lisp_Object file, specified_file;
6834 Lisp_Object specified_data;
6835 FILE * volatile fp = NULL;
6836 JSAMPARRAY buffer;
6837 int row_stride, x, y;
6838 XImagePtr ximg = NULL;
6839 int rc;
6840 unsigned long *colors;
6841 int width, height;
6842 struct gcpro gcpro1;
6844 /* Open the JPEG file. */
6845 specified_file = image_spec_value (img->spec, QCfile, NULL);
6846 specified_data = image_spec_value (img->spec, QCdata, NULL);
6847 file = Qnil;
6848 GCPRO1 (file);
6850 if (NILP (specified_data))
6852 file = x_find_image_file (specified_file);
6853 if (!STRINGP (file))
6855 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6856 UNGCPRO;
6857 return 0;
6860 fp = fopen (SDATA (file), "rb");
6861 if (fp == NULL)
6863 image_error ("Cannot open `%s'", file, Qnil);
6864 UNGCPRO;
6865 return 0;
6869 /* Customize libjpeg's error handling to call my_error_exit when an
6870 error is detected. This function will perform a longjmp.
6871 Casting return value avoids a GCC warning on W32. */
6872 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
6873 mgr.pub.error_exit = my_error_exit;
6875 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6877 if (rc == 1)
6879 /* Called from my_error_exit. Display a JPEG error. */
6880 char buffer[JMSG_LENGTH_MAX];
6881 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6882 image_error ("Error reading JPEG image `%s': %s", img->spec,
6883 build_string (buffer));
6886 /* Close the input file and destroy the JPEG object. */
6887 if (fp)
6888 fclose ((FILE *) fp);
6889 fn_jpeg_destroy_decompress (&cinfo);
6891 /* If we already have an XImage, free that. */
6892 x_destroy_x_image (ximg);
6894 /* Free pixmap and colors. */
6895 x_clear_image (f, img);
6897 UNGCPRO;
6898 return 0;
6901 /* Create the JPEG decompression object. Let it read from fp.
6902 Read the JPEG image header. */
6903 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6905 if (NILP (specified_data))
6906 jpeg_file_src (&cinfo, (FILE *) fp);
6907 else
6908 jpeg_memory_src (&cinfo, SDATA (specified_data),
6909 SBYTES (specified_data));
6911 fn_jpeg_read_header (&cinfo, 1);
6913 /* Customize decompression so that color quantization will be used.
6914 Start decompression. */
6915 cinfo.quantize_colors = 1;
6916 fn_jpeg_start_decompress (&cinfo);
6917 width = img->width = cinfo.output_width;
6918 height = img->height = cinfo.output_height;
6920 if (!check_image_size (f, width, height))
6922 image_error ("Invalid image size", Qnil, Qnil);
6923 longjmp (mgr.setjmp_buffer, 2);
6926 /* Create X image and pixmap. */
6927 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6928 longjmp (mgr.setjmp_buffer, 2);
6930 /* Allocate colors. When color quantization is used,
6931 cinfo.actual_number_of_colors has been set with the number of
6932 colors generated, and cinfo.colormap is a two-dimensional array
6933 of color indices in the range 0..cinfo.actual_number_of_colors.
6934 No more than 255 colors will be generated. */
6936 int i, ir, ig, ib;
6938 if (cinfo.out_color_components > 2)
6939 ir = 0, ig = 1, ib = 2;
6940 else if (cinfo.out_color_components > 1)
6941 ir = 0, ig = 1, ib = 0;
6942 else
6943 ir = 0, ig = 0, ib = 0;
6945 /* Use the color table mechanism because it handles colors that
6946 cannot be allocated nicely. Such colors will be replaced with
6947 a default color, and we don't have to care about which colors
6948 can be freed safely, and which can't. */
6949 init_color_table ();
6950 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6951 * sizeof *colors);
6953 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6955 /* Multiply RGB values with 255 because X expects RGB values
6956 in the range 0..0xffff. */
6957 int r = cinfo.colormap[ir][i] << 8;
6958 int g = cinfo.colormap[ig][i] << 8;
6959 int b = cinfo.colormap[ib][i] << 8;
6960 colors[i] = lookup_rgb_color (f, r, g, b);
6963 #ifdef COLOR_TABLE_SUPPORT
6964 /* Remember those colors actually allocated. */
6965 img->colors = colors_in_color_table (&img->ncolors);
6966 free_color_table ();
6967 #endif /* COLOR_TABLE_SUPPORT */
6970 /* Read pixels. */
6971 row_stride = width * cinfo.output_components;
6972 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
6973 row_stride, 1);
6974 for (y = 0; y < height; ++y)
6976 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
6977 for (x = 0; x < cinfo.output_width; ++x)
6978 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
6981 /* Clean up. */
6982 fn_jpeg_finish_decompress (&cinfo);
6983 fn_jpeg_destroy_decompress (&cinfo);
6984 if (fp)
6985 fclose ((FILE *) fp);
6987 /* Maybe fill in the background field while we have ximg handy. */
6988 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6989 /* Casting avoids a GCC warning. */
6990 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6992 /* Put the image into the pixmap. */
6993 x_put_x_image (f, ximg, img->pixmap, width, height);
6994 x_destroy_x_image (ximg);
6995 UNGCPRO;
6996 return 1;
6999 #else /* HAVE_JPEG */
7001 #ifdef MAC_OS
7002 static int
7003 jpeg_load (f, img)
7004 struct frame *f;
7005 struct image *img;
7007 #ifdef MAC_OSX
7008 return image_load_quartz2d (f, img, 0);
7009 #else
7010 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7011 #endif
7013 #endif /* MAC_OS */
7015 #endif /* !HAVE_JPEG */
7019 /***********************************************************************
7020 TIFF
7021 ***********************************************************************/
7023 #if defined (HAVE_TIFF) || defined (MAC_OS)
7025 static int tiff_image_p P_ ((Lisp_Object object));
7026 static int tiff_load P_ ((struct frame *f, struct image *img));
7028 /* The symbol `tiff' identifying images of this type. */
7030 Lisp_Object Qtiff;
7032 /* Indices of image specification fields in tiff_format, below. */
7034 enum tiff_keyword_index
7036 TIFF_TYPE,
7037 TIFF_DATA,
7038 TIFF_FILE,
7039 TIFF_ASCENT,
7040 TIFF_MARGIN,
7041 TIFF_RELIEF,
7042 TIFF_ALGORITHM,
7043 TIFF_HEURISTIC_MASK,
7044 TIFF_MASK,
7045 TIFF_BACKGROUND,
7046 TIFF_LAST
7049 /* Vector of image_keyword structures describing the format
7050 of valid user-defined image specifications. */
7052 static struct image_keyword tiff_format[TIFF_LAST] =
7054 {":type", IMAGE_SYMBOL_VALUE, 1},
7055 {":data", IMAGE_STRING_VALUE, 0},
7056 {":file", IMAGE_STRING_VALUE, 0},
7057 {":ascent", IMAGE_ASCENT_VALUE, 0},
7058 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7059 {":relief", IMAGE_INTEGER_VALUE, 0},
7060 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7061 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7062 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7063 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7066 /* Structure describing the image type `tiff'. */
7068 static struct image_type tiff_type =
7070 &Qtiff,
7071 tiff_image_p,
7072 tiff_load,
7073 x_clear_image,
7074 NULL
7077 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7079 static int
7080 tiff_image_p (object)
7081 Lisp_Object object;
7083 struct image_keyword fmt[TIFF_LAST];
7084 bcopy (tiff_format, fmt, sizeof fmt);
7086 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7087 return 0;
7089 /* Must specify either the :data or :file keyword. */
7090 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7093 #endif /* HAVE_TIFF || MAC_OS */
7095 #ifdef HAVE_TIFF
7097 #include <tiffio.h>
7099 #ifdef HAVE_NTGUI
7101 /* TIFF library details. */
7102 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7103 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7104 DEF_IMGLIB_FN (TIFFOpen);
7105 DEF_IMGLIB_FN (TIFFClientOpen);
7106 DEF_IMGLIB_FN (TIFFGetField);
7107 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7108 DEF_IMGLIB_FN (TIFFClose);
7110 static int
7111 init_tiff_functions (Lisp_Object libraries)
7113 HMODULE library;
7115 if (!(library = w32_delayed_load (libraries, Qtiff)))
7116 return 0;
7118 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7119 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7120 LOAD_IMGLIB_FN (library, TIFFOpen);
7121 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7122 LOAD_IMGLIB_FN (library, TIFFGetField);
7123 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7124 LOAD_IMGLIB_FN (library, TIFFClose);
7125 return 1;
7128 #else
7130 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7131 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7132 #define fn_TIFFOpen TIFFOpen
7133 #define fn_TIFFClientOpen TIFFClientOpen
7134 #define fn_TIFFGetField TIFFGetField
7135 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7136 #define fn_TIFFClose TIFFClose
7138 #endif /* HAVE_NTGUI */
7141 /* Reading from a memory buffer for TIFF images Based on the PNG
7142 memory source, but we have to provide a lot of extra functions.
7143 Blah.
7145 We really only need to implement read and seek, but I am not
7146 convinced that the TIFF library is smart enough not to destroy
7147 itself if we only hand it the function pointers we need to
7148 override. */
7150 typedef struct
7152 unsigned char *bytes;
7153 size_t len;
7154 int index;
7156 tiff_memory_source;
7158 static size_t
7159 tiff_read_from_memory (data, buf, size)
7160 thandle_t data;
7161 tdata_t buf;
7162 tsize_t size;
7164 tiff_memory_source *src = (tiff_memory_source *) data;
7166 if (size > src->len - src->index)
7167 return (size_t) -1;
7168 bcopy (src->bytes + src->index, buf, size);
7169 src->index += size;
7170 return size;
7173 static size_t
7174 tiff_write_from_memory (data, buf, size)
7175 thandle_t data;
7176 tdata_t buf;
7177 tsize_t size;
7179 return (size_t) -1;
7182 static toff_t
7183 tiff_seek_in_memory (data, off, whence)
7184 thandle_t data;
7185 toff_t off;
7186 int whence;
7188 tiff_memory_source *src = (tiff_memory_source *) data;
7189 int idx;
7191 switch (whence)
7193 case SEEK_SET: /* Go from beginning of source. */
7194 idx = off;
7195 break;
7197 case SEEK_END: /* Go from end of source. */
7198 idx = src->len + off;
7199 break;
7201 case SEEK_CUR: /* Go from current position. */
7202 idx = src->index + off;
7203 break;
7205 default: /* Invalid `whence'. */
7206 return -1;
7209 if (idx > src->len || idx < 0)
7210 return -1;
7212 src->index = idx;
7213 return src->index;
7216 static int
7217 tiff_close_memory (data)
7218 thandle_t data;
7220 /* NOOP */
7221 return 0;
7224 static int
7225 tiff_mmap_memory (data, pbase, psize)
7226 thandle_t data;
7227 tdata_t *pbase;
7228 toff_t *psize;
7230 /* It is already _IN_ memory. */
7231 return 0;
7234 static void
7235 tiff_unmap_memory (data, base, size)
7236 thandle_t data;
7237 tdata_t base;
7238 toff_t size;
7240 /* We don't need to do this. */
7243 static toff_t
7244 tiff_size_of_memory (data)
7245 thandle_t data;
7247 return ((tiff_memory_source *) data)->len;
7251 static void
7252 tiff_error_handler (title, format, ap)
7253 const char *title, *format;
7254 va_list ap;
7256 char buf[512];
7257 int len;
7259 len = sprintf (buf, "TIFF error: %s ", title);
7260 vsprintf (buf + len, format, ap);
7261 add_to_log (buf, Qnil, Qnil);
7265 static void
7266 tiff_warning_handler (title, format, ap)
7267 const char *title, *format;
7268 va_list ap;
7270 char buf[512];
7271 int len;
7273 len = sprintf (buf, "TIFF warning: %s ", title);
7274 vsprintf (buf + len, format, ap);
7275 add_to_log (buf, Qnil, Qnil);
7279 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7280 successful. */
7282 static int
7283 tiff_load (f, img)
7284 struct frame *f;
7285 struct image *img;
7287 Lisp_Object file, specified_file;
7288 Lisp_Object specified_data;
7289 TIFF *tiff;
7290 int width, height, x, y;
7291 uint32 *buf;
7292 int rc;
7293 XImagePtr ximg;
7294 struct gcpro gcpro1;
7295 tiff_memory_source memsrc;
7297 specified_file = image_spec_value (img->spec, QCfile, NULL);
7298 specified_data = image_spec_value (img->spec, QCdata, NULL);
7299 file = Qnil;
7300 GCPRO1 (file);
7302 fn_TIFFSetErrorHandler (tiff_error_handler);
7303 fn_TIFFSetWarningHandler (tiff_warning_handler);
7305 if (NILP (specified_data))
7307 /* Read from a file */
7308 file = x_find_image_file (specified_file);
7309 if (!STRINGP (file))
7311 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7312 UNGCPRO;
7313 return 0;
7316 /* Try to open the image file. Casting return value avoids a
7317 GCC warning on W32. */
7318 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7319 if (tiff == NULL)
7321 image_error ("Cannot open `%s'", file, Qnil);
7322 UNGCPRO;
7323 return 0;
7326 else
7328 /* Memory source! */
7329 memsrc.bytes = SDATA (specified_data);
7330 memsrc.len = SBYTES (specified_data);
7331 memsrc.index = 0;
7333 /* Casting return value avoids a GCC warning on W32. */
7334 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7335 (TIFFReadWriteProc) tiff_read_from_memory,
7336 (TIFFReadWriteProc) tiff_write_from_memory,
7337 tiff_seek_in_memory,
7338 tiff_close_memory,
7339 tiff_size_of_memory,
7340 tiff_mmap_memory,
7341 tiff_unmap_memory);
7343 if (!tiff)
7345 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7346 UNGCPRO;
7347 return 0;
7351 /* Get width and height of the image, and allocate a raster buffer
7352 of width x height 32-bit values. */
7353 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7354 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7356 if (!check_image_size (f, width, height))
7358 image_error ("Invalid image size", Qnil, Qnil);
7359 UNGCPRO;
7360 return 0;
7363 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7365 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7366 fn_TIFFClose (tiff);
7367 if (!rc)
7369 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7370 xfree (buf);
7371 UNGCPRO;
7372 return 0;
7375 /* Create the X image and pixmap. */
7376 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7378 xfree (buf);
7379 UNGCPRO;
7380 return 0;
7383 /* Initialize the color table. */
7384 init_color_table ();
7386 /* Process the pixel raster. Origin is in the lower-left corner. */
7387 for (y = 0; y < height; ++y)
7389 uint32 *row = buf + y * width;
7391 for (x = 0; x < width; ++x)
7393 uint32 abgr = row[x];
7394 int r = TIFFGetR (abgr) << 8;
7395 int g = TIFFGetG (abgr) << 8;
7396 int b = TIFFGetB (abgr) << 8;
7397 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7401 #ifdef COLOR_TABLE_SUPPORT
7402 /* Remember the colors allocated for the image. Free the color table. */
7403 img->colors = colors_in_color_table (&img->ncolors);
7404 free_color_table ();
7405 #endif /* COLOR_TABLE_SUPPORT */
7407 img->width = width;
7408 img->height = height;
7410 /* Maybe fill in the background field while we have ximg handy. */
7411 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7412 /* Casting avoids a GCC warning on W32. */
7413 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7415 /* Put the image into the pixmap, then free the X image and its buffer. */
7416 x_put_x_image (f, ximg, img->pixmap, width, height);
7417 x_destroy_x_image (ximg);
7418 xfree (buf);
7420 UNGCPRO;
7421 return 1;
7424 #else /* HAVE_TIFF */
7426 #ifdef MAC_OS
7427 static int
7428 tiff_load (f, img)
7429 struct frame *f;
7430 struct image *img;
7432 return image_load_quicktime (f, img, kQTFileTypeTIFF);
7434 #endif /* MAC_OS */
7436 #endif /* !HAVE_TIFF */
7440 /***********************************************************************
7442 ***********************************************************************/
7444 #if defined (HAVE_GIF) || defined (MAC_OS)
7446 static int gif_image_p P_ ((Lisp_Object object));
7447 static int gif_load P_ ((struct frame *f, struct image *img));
7449 /* The symbol `gif' identifying images of this type. */
7451 Lisp_Object Qgif;
7453 /* Indices of image specification fields in gif_format, below. */
7455 enum gif_keyword_index
7457 GIF_TYPE,
7458 GIF_DATA,
7459 GIF_FILE,
7460 GIF_ASCENT,
7461 GIF_MARGIN,
7462 GIF_RELIEF,
7463 GIF_ALGORITHM,
7464 GIF_HEURISTIC_MASK,
7465 GIF_MASK,
7466 GIF_IMAGE,
7467 GIF_BACKGROUND,
7468 GIF_LAST
7471 /* Vector of image_keyword structures describing the format
7472 of valid user-defined image specifications. */
7474 static struct image_keyword gif_format[GIF_LAST] =
7476 {":type", IMAGE_SYMBOL_VALUE, 1},
7477 {":data", IMAGE_STRING_VALUE, 0},
7478 {":file", IMAGE_STRING_VALUE, 0},
7479 {":ascent", IMAGE_ASCENT_VALUE, 0},
7480 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7481 {":relief", IMAGE_INTEGER_VALUE, 0},
7482 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7483 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7484 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7485 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7486 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7489 /* Structure describing the image type `gif'. */
7491 static struct image_type gif_type =
7493 &Qgif,
7494 gif_image_p,
7495 gif_load,
7496 x_clear_image,
7497 NULL
7500 /* Return non-zero if OBJECT is a valid GIF image specification. */
7502 static int
7503 gif_image_p (object)
7504 Lisp_Object object;
7506 struct image_keyword fmt[GIF_LAST];
7507 bcopy (gif_format, fmt, sizeof fmt);
7509 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7510 return 0;
7512 /* Must specify either the :data or :file keyword. */
7513 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7516 #endif /* HAVE_GIF || MAC_OS */
7518 #ifdef HAVE_GIF
7520 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7521 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7522 Undefine before redefining to avoid a preprocessor warning. */
7523 #ifdef DrawText
7524 #undef DrawText
7525 #endif
7526 /* avoid conflict with QuickdrawText.h */
7527 #define DrawText gif_DrawText
7528 #include <gif_lib.h>
7529 #undef DrawText
7531 #else /* HAVE_NTGUI || MAC_OS */
7533 #include <gif_lib.h>
7535 #endif /* HAVE_NTGUI || MAC_OS */
7538 #ifdef HAVE_NTGUI
7540 /* GIF library details. */
7541 DEF_IMGLIB_FN (DGifCloseFile);
7542 DEF_IMGLIB_FN (DGifSlurp);
7543 DEF_IMGLIB_FN (DGifOpen);
7544 DEF_IMGLIB_FN (DGifOpenFileName);
7546 static int
7547 init_gif_functions (Lisp_Object libraries)
7549 HMODULE library;
7551 if (!(library = w32_delayed_load (libraries, Qgif)))
7552 return 0;
7554 LOAD_IMGLIB_FN (library, DGifCloseFile);
7555 LOAD_IMGLIB_FN (library, DGifSlurp);
7556 LOAD_IMGLIB_FN (library, DGifOpen);
7557 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7558 return 1;
7561 #else
7563 #define fn_DGifCloseFile DGifCloseFile
7564 #define fn_DGifSlurp DGifSlurp
7565 #define fn_DGifOpen DGifOpen
7566 #define fn_DGifOpenFileName DGifOpenFileName
7568 #endif /* HAVE_NTGUI */
7570 /* Reading a GIF image from memory
7571 Based on the PNG memory stuff to a certain extent. */
7573 typedef struct
7575 unsigned char *bytes;
7576 size_t len;
7577 int index;
7579 gif_memory_source;
7581 /* Make the current memory source available to gif_read_from_memory.
7582 It's done this way because not all versions of libungif support
7583 a UserData field in the GifFileType structure. */
7584 static gif_memory_source *current_gif_memory_src;
7586 static int
7587 gif_read_from_memory (file, buf, len)
7588 GifFileType *file;
7589 GifByteType *buf;
7590 int len;
7592 gif_memory_source *src = current_gif_memory_src;
7594 if (len > src->len - src->index)
7595 return -1;
7597 bcopy (src->bytes + src->index, buf, len);
7598 src->index += len;
7599 return len;
7603 /* Load GIF image IMG for use on frame F. Value is non-zero if
7604 successful. */
7606 static int
7607 gif_load (f, img)
7608 struct frame *f;
7609 struct image *img;
7611 Lisp_Object file, specified_file;
7612 Lisp_Object specified_data;
7613 int rc, width, height, x, y, i;
7614 XImagePtr ximg;
7615 ColorMapObject *gif_color_map;
7616 unsigned long pixel_colors[256];
7617 GifFileType *gif;
7618 struct gcpro gcpro1;
7619 Lisp_Object image;
7620 int ino, image_left, image_top, image_width, image_height;
7621 gif_memory_source memsrc;
7622 unsigned char *raster;
7624 specified_file = image_spec_value (img->spec, QCfile, NULL);
7625 specified_data = image_spec_value (img->spec, QCdata, NULL);
7626 file = Qnil;
7627 GCPRO1 (file);
7629 if (NILP (specified_data))
7631 file = x_find_image_file (specified_file);
7632 if (!STRINGP (file))
7634 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7635 UNGCPRO;
7636 return 0;
7639 /* Open the GIF file. Casting return value avoids a GCC warning
7640 on W32. */
7641 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
7642 if (gif == NULL)
7644 image_error ("Cannot open `%s'", file, Qnil);
7645 UNGCPRO;
7646 return 0;
7649 else
7651 /* Read from memory! */
7652 current_gif_memory_src = &memsrc;
7653 memsrc.bytes = SDATA (specified_data);
7654 memsrc.len = SBYTES (specified_data);
7655 memsrc.index = 0;
7657 /* Casting return value avoids a GCC warning on W32. */
7658 gif = (GifFileType *)fn_DGifOpen(&memsrc, gif_read_from_memory);
7659 if (!gif)
7661 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7662 UNGCPRO;
7663 return 0;
7667 /* Before reading entire contents, check the declared image size. */
7668 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7670 image_error ("Invalid image size", Qnil, Qnil);
7671 fn_DGifCloseFile (gif);
7672 UNGCPRO;
7673 return 0;
7676 /* Read entire contents. */
7677 rc = fn_DGifSlurp (gif);
7678 if (rc == GIF_ERROR)
7680 image_error ("Error reading `%s'", img->spec, Qnil);
7681 fn_DGifCloseFile (gif);
7682 UNGCPRO;
7683 return 0;
7686 image = image_spec_value (img->spec, QCindex, NULL);
7687 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7688 if (ino >= gif->ImageCount)
7690 image_error ("Invalid image number `%s' in image `%s'",
7691 image, img->spec);
7692 fn_DGifCloseFile (gif);
7693 UNGCPRO;
7694 return 0;
7697 image_top = gif->SavedImages[ino].ImageDesc.Top;
7698 image_left = gif->SavedImages[ino].ImageDesc.Left;
7699 image_width = gif->SavedImages[ino].ImageDesc.Width;
7700 image_height = gif->SavedImages[ino].ImageDesc.Height;
7702 width = img->width = max (gif->SWidth,
7703 max (gif->Image.Left + gif->Image.Width,
7704 image_left + image_width));
7705 height = img->height = max (gif->SHeight,
7706 max (gif->Image.Top + gif->Image.Height,
7707 image_top + image_height));
7709 if (!check_image_size (f, width, height))
7711 image_error ("Invalid image size", Qnil, Qnil);
7712 fn_DGifCloseFile (gif);
7713 UNGCPRO;
7714 return 0;
7717 /* Create the X image and pixmap. */
7718 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7720 fn_DGifCloseFile (gif);
7721 UNGCPRO;
7722 return 0;
7725 /* Allocate colors. */
7726 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7727 if (!gif_color_map)
7728 gif_color_map = gif->SColorMap;
7729 init_color_table ();
7730 bzero (pixel_colors, sizeof pixel_colors);
7732 for (i = 0; i < gif_color_map->ColorCount; ++i)
7734 int r = gif_color_map->Colors[i].Red << 8;
7735 int g = gif_color_map->Colors[i].Green << 8;
7736 int b = gif_color_map->Colors[i].Blue << 8;
7737 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7740 #ifdef COLOR_TABLE_SUPPORT
7741 img->colors = colors_in_color_table (&img->ncolors);
7742 free_color_table ();
7743 #endif /* COLOR_TABLE_SUPPORT */
7745 /* Clear the part of the screen image that are not covered by
7746 the image from the GIF file. Full animated GIF support
7747 requires more than can be done here (see the gif89 spec,
7748 disposal methods). Let's simply assume that the part
7749 not covered by a sub-image is in the frame's background color. */
7750 for (y = 0; y < image_top; ++y)
7751 for (x = 0; x < width; ++x)
7752 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7754 for (y = image_top + image_height; y < height; ++y)
7755 for (x = 0; x < width; ++x)
7756 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7758 for (y = image_top; y < image_top + image_height; ++y)
7760 for (x = 0; x < image_left; ++x)
7761 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7762 for (x = image_left + image_width; x < width; ++x)
7763 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7766 /* Read the GIF image into the X image. We use a local variable
7767 `raster' here because RasterBits below is a char *, and invites
7768 problems with bytes >= 0x80. */
7769 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7771 if (gif->SavedImages[ino].ImageDesc.Interlace)
7773 static int interlace_start[] = {0, 4, 2, 1};
7774 static int interlace_increment[] = {8, 8, 4, 2};
7775 int pass;
7776 int row = interlace_start[0];
7778 pass = 0;
7780 for (y = 0; y < image_height; y++)
7782 if (row >= image_height)
7784 row = interlace_start[++pass];
7785 while (row >= image_height)
7786 row = interlace_start[++pass];
7789 for (x = 0; x < image_width; x++)
7791 int i = raster[(y * image_width) + x];
7792 XPutPixel (ximg, x + image_left, row + image_top,
7793 pixel_colors[i]);
7796 row += interlace_increment[pass];
7799 else
7801 for (y = 0; y < image_height; ++y)
7802 for (x = 0; x < image_width; ++x)
7804 int i = raster[y * image_width + x];
7805 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
7809 fn_DGifCloseFile (gif);
7811 /* Maybe fill in the background field while we have ximg handy. */
7812 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7813 /* Casting avoids a GCC warning. */
7814 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7816 /* Put the image into the pixmap, then free the X image and its buffer. */
7817 x_put_x_image (f, ximg, img->pixmap, width, height);
7818 x_destroy_x_image (ximg);
7820 UNGCPRO;
7821 return 1;
7824 #else /* !HAVE_GIF */
7826 #ifdef MAC_OS
7827 static int
7828 gif_load (f, img)
7829 struct frame *f;
7830 struct image *img;
7832 Lisp_Object specified_file, file;
7833 Lisp_Object specified_data;
7834 OSErr err;
7835 Boolean graphic_p, movie_p, prefer_graphic_p;
7836 Handle dh = NULL;
7837 Movie movie = NULL;
7838 Lisp_Object image;
7839 Track track = NULL;
7840 Media media = NULL;
7841 long nsamples;
7842 Rect rect;
7843 Lisp_Object specified_bg;
7844 XColor color;
7845 RGBColor bg_color;
7846 int width, height;
7847 XImagePtr ximg;
7848 TimeValue time;
7849 struct gcpro gcpro1;
7850 int ino;
7851 CGrafPtr old_port;
7852 GDHandle old_gdh;
7854 specified_file = image_spec_value (img->spec, QCfile, NULL);
7855 specified_data = image_spec_value (img->spec, QCdata, NULL);
7857 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7858 EnterMovies ();
7860 if (NILP (specified_data))
7862 /* Read from a file */
7863 FSSpec fss;
7864 short refnum;
7866 err = find_image_fsspec (specified_file, &file, &fss);
7867 if (err != noErr)
7869 if (err == fnfErr)
7870 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7871 else
7872 goto open_error;
7875 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
7876 &graphic_p, &movie_p, &prefer_graphic_p, 0);
7877 if (err != noErr)
7878 goto open_error;
7880 if (!graphic_p && !movie_p)
7881 goto open_error;
7882 if (prefer_graphic_p)
7883 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
7884 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
7885 if (err != noErr)
7886 goto open_error;
7887 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
7888 CloseMovieFile (refnum);
7889 if (err != noErr)
7891 image_error ("Error reading `%s'", file, Qnil);
7892 return 0;
7895 else
7897 /* Memory source! */
7898 Handle dref = NULL;
7899 long file_type_atom[3];
7901 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
7902 if (err != noErr)
7904 image_error ("Cannot allocate data handle for `%s'",
7905 img->spec, Qnil);
7906 goto error;
7909 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
7910 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
7911 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
7912 err = PtrToHand (&dh, &dref, sizeof (Handle));
7913 if (err == noErr)
7914 /* no file name */
7915 err = PtrAndHand ("\p", dref, 1);
7916 if (err == noErr)
7917 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
7918 if (err != noErr)
7920 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
7921 goto error;
7923 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
7924 &movie_p, &prefer_graphic_p, 0);
7925 if (err != noErr)
7926 goto open_error;
7928 if (!graphic_p && !movie_p)
7929 goto open_error;
7930 if (prefer_graphic_p)
7932 int success_p;
7934 DisposeHandle (dref);
7935 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
7936 DisposeHandle (dh);
7937 return success_p;
7939 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
7940 HandleDataHandlerSubType);
7941 DisposeHandle (dref);
7942 if (err != noErr)
7943 goto open_error;
7946 image = image_spec_value (img->spec, QCindex, NULL);
7947 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7948 track = GetMovieIndTrack (movie, 1);
7949 media = GetTrackMedia (track);
7950 nsamples = GetMediaSampleCount (media);
7951 if (ino >= nsamples)
7953 image_error ("Invalid image number `%s' in image `%s'",
7954 image, img->spec);
7955 goto error;
7958 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
7959 if (!STRINGP (specified_bg) ||
7960 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
7962 color.pixel = FRAME_BACKGROUND_PIXEL (f);
7963 color.red = RED16_FROM_ULONG (color.pixel);
7964 color.green = GREEN16_FROM_ULONG (color.pixel);
7965 color.blue = BLUE16_FROM_ULONG (color.pixel);
7967 GetMovieBox (movie, &rect);
7968 width = img->width = rect.right - rect.left;
7969 height = img->height = rect.bottom - rect.top;
7970 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7971 goto error;
7973 GetGWorld (&old_port, &old_gdh);
7974 SetGWorld (ximg, NULL);
7975 bg_color.red = color.red;
7976 bg_color.green = color.green;
7977 bg_color.blue = color.blue;
7978 RGBBackColor (&bg_color);
7979 SetGWorld (old_port, old_gdh);
7980 SetMovieActive (movie, 1);
7981 SetMovieGWorld (movie, ximg, NULL);
7982 SampleNumToMediaTime (media, ino + 1, &time, NULL);
7983 SetMovieTimeValue (movie, time);
7984 MoviesTask (movie, 0L);
7985 DisposeTrackMedia (media);
7986 DisposeMovieTrack (track);
7987 DisposeMovie (movie);
7988 if (dh)
7989 DisposeHandle (dh);
7990 /* Maybe fill in the background field while we have ximg handy. */
7991 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7992 IMAGE_BACKGROUND (img, f, ximg);
7994 /* Put the image into the pixmap. */
7995 x_put_x_image (f, ximg, img->pixmap, width, height);
7996 x_destroy_x_image (ximg);
7997 return 1;
7999 open_error:
8000 image_error ("Cannot open `%s'", file, Qnil);
8001 error:
8002 if (media)
8003 DisposeTrackMedia (media);
8004 if (track)
8005 DisposeMovieTrack (track);
8006 if (movie)
8007 DisposeMovie (movie);
8008 if (dh)
8009 DisposeHandle (dh);
8010 return 0;
8012 #endif /* MAC_OS */
8014 #endif /* HAVE_GIF */
8018 /***********************************************************************
8019 Ghostscript
8020 ***********************************************************************/
8022 #ifdef HAVE_X_WINDOWS
8023 #define HAVE_GHOSTSCRIPT 1
8024 #endif /* HAVE_X_WINDOWS */
8026 /* The symbol `postscript' identifying images of this type. */
8028 Lisp_Object Qpostscript;
8030 #ifdef HAVE_GHOSTSCRIPT
8032 static int gs_image_p P_ ((Lisp_Object object));
8033 static int gs_load P_ ((struct frame *f, struct image *img));
8034 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8036 /* Keyword symbols. */
8038 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8040 /* Indices of image specification fields in gs_format, below. */
8042 enum gs_keyword_index
8044 GS_TYPE,
8045 GS_PT_WIDTH,
8046 GS_PT_HEIGHT,
8047 GS_FILE,
8048 GS_LOADER,
8049 GS_BOUNDING_BOX,
8050 GS_ASCENT,
8051 GS_MARGIN,
8052 GS_RELIEF,
8053 GS_ALGORITHM,
8054 GS_HEURISTIC_MASK,
8055 GS_MASK,
8056 GS_BACKGROUND,
8057 GS_LAST
8060 /* Vector of image_keyword structures describing the format
8061 of valid user-defined image specifications. */
8063 static struct image_keyword gs_format[GS_LAST] =
8065 {":type", IMAGE_SYMBOL_VALUE, 1},
8066 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8067 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8068 {":file", IMAGE_STRING_VALUE, 1},
8069 {":loader", IMAGE_FUNCTION_VALUE, 0},
8070 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8071 {":ascent", IMAGE_ASCENT_VALUE, 0},
8072 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8073 {":relief", IMAGE_INTEGER_VALUE, 0},
8074 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8075 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8076 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8077 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8080 /* Structure describing the image type `ghostscript'. */
8082 static struct image_type gs_type =
8084 &Qpostscript,
8085 gs_image_p,
8086 gs_load,
8087 gs_clear_image,
8088 NULL
8092 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8094 static void
8095 gs_clear_image (f, img)
8096 struct frame *f;
8097 struct image *img;
8099 /* IMG->data.ptr_val may contain a recorded colormap. */
8100 xfree (img->data.ptr_val);
8101 x_clear_image (f, img);
8105 /* Return non-zero if OBJECT is a valid Ghostscript image
8106 specification. */
8108 static int
8109 gs_image_p (object)
8110 Lisp_Object object;
8112 struct image_keyword fmt[GS_LAST];
8113 Lisp_Object tem;
8114 int i;
8116 bcopy (gs_format, fmt, sizeof fmt);
8118 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8119 return 0;
8121 /* Bounding box must be a list or vector containing 4 integers. */
8122 tem = fmt[GS_BOUNDING_BOX].value;
8123 if (CONSP (tem))
8125 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8126 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8127 return 0;
8128 if (!NILP (tem))
8129 return 0;
8131 else if (VECTORP (tem))
8133 if (XVECTOR (tem)->size != 4)
8134 return 0;
8135 for (i = 0; i < 4; ++i)
8136 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8137 return 0;
8139 else
8140 return 0;
8142 return 1;
8146 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8147 if successful. */
8149 static int
8150 gs_load (f, img)
8151 struct frame *f;
8152 struct image *img;
8154 char buffer[100];
8155 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8156 struct gcpro gcpro1, gcpro2;
8157 Lisp_Object frame;
8158 double in_width, in_height;
8159 Lisp_Object pixel_colors = Qnil;
8161 /* Compute pixel size of pixmap needed from the given size in the
8162 image specification. Sizes in the specification are in pt. 1 pt
8163 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8164 info. */
8165 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8166 in_width = XFASTINT (pt_width) / 72.0;
8167 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
8168 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8169 in_height = XFASTINT (pt_height) / 72.0;
8170 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
8172 if (!check_image_size (f, img->width, img->height))
8174 image_error ("Invalid image size", Qnil, Qnil);
8175 return 0;
8178 /* Create the pixmap. */
8179 xassert (img->pixmap == NO_PIXMAP);
8181 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8182 BLOCK_INPUT;
8183 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8184 img->width, img->height,
8185 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8186 UNBLOCK_INPUT;
8188 if (!img->pixmap)
8190 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8191 return 0;
8194 /* Call the loader to fill the pixmap. It returns a process object
8195 if successful. We do not record_unwind_protect here because
8196 other places in redisplay like calling window scroll functions
8197 don't either. Let the Lisp loader use `unwind-protect' instead. */
8198 GCPRO2 (window_and_pixmap_id, pixel_colors);
8200 sprintf (buffer, "%lu %lu",
8201 (unsigned long) FRAME_X_WINDOW (f),
8202 (unsigned long) img->pixmap);
8203 window_and_pixmap_id = build_string (buffer);
8205 sprintf (buffer, "%lu %lu",
8206 FRAME_FOREGROUND_PIXEL (f),
8207 FRAME_BACKGROUND_PIXEL (f));
8208 pixel_colors = build_string (buffer);
8210 XSETFRAME (frame, f);
8211 loader = image_spec_value (img->spec, QCloader, NULL);
8212 if (NILP (loader))
8213 loader = intern ("gs-load-image");
8215 img->data.lisp_val = call6 (loader, frame, img->spec,
8216 make_number (img->width),
8217 make_number (img->height),
8218 window_and_pixmap_id,
8219 pixel_colors);
8220 UNGCPRO;
8221 return PROCESSP (img->data.lisp_val);
8225 /* Kill the Ghostscript process that was started to fill PIXMAP on
8226 frame F. Called from XTread_socket when receiving an event
8227 telling Emacs that Ghostscript has finished drawing. */
8229 void
8230 x_kill_gs_process (pixmap, f)
8231 Pixmap pixmap;
8232 struct frame *f;
8234 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8235 int class, i;
8236 struct image *img;
8238 /* Find the image containing PIXMAP. */
8239 for (i = 0; i < c->used; ++i)
8240 if (c->images[i]->pixmap == pixmap)
8241 break;
8243 /* Should someone in between have cleared the image cache, for
8244 instance, give up. */
8245 if (i == c->used)
8246 return;
8248 /* Kill the GS process. We should have found PIXMAP in the image
8249 cache and its image should contain a process object. */
8250 img = c->images[i];
8251 xassert (PROCESSP (img->data.lisp_val));
8252 Fkill_process (img->data.lisp_val, Qnil);
8253 img->data.lisp_val = Qnil;
8255 #if defined (HAVE_X_WINDOWS)
8257 /* On displays with a mutable colormap, figure out the colors
8258 allocated for the image by looking at the pixels of an XImage for
8259 img->pixmap. */
8260 class = FRAME_X_VISUAL (f)->class;
8261 if (class != StaticColor && class != StaticGray && class != TrueColor)
8263 XImagePtr ximg;
8265 BLOCK_INPUT;
8267 /* Try to get an XImage for img->pixmep. */
8268 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8269 0, 0, img->width, img->height, ~0, ZPixmap);
8270 if (ximg)
8272 int x, y;
8274 /* Initialize the color table. */
8275 init_color_table ();
8277 /* For each pixel of the image, look its color up in the
8278 color table. After having done so, the color table will
8279 contain an entry for each color used by the image. */
8280 for (y = 0; y < img->height; ++y)
8281 for (x = 0; x < img->width; ++x)
8283 unsigned long pixel = XGetPixel (ximg, x, y);
8284 lookup_pixel_color (f, pixel);
8287 /* Record colors in the image. Free color table and XImage. */
8288 #ifdef COLOR_TABLE_SUPPORT
8289 img->colors = colors_in_color_table (&img->ncolors);
8290 free_color_table ();
8291 #endif
8292 XDestroyImage (ximg);
8294 #if 0 /* This doesn't seem to be the case. If we free the colors
8295 here, we get a BadAccess later in x_clear_image when
8296 freeing the colors. */
8297 /* We have allocated colors once, but Ghostscript has also
8298 allocated colors on behalf of us. So, to get the
8299 reference counts right, free them once. */
8300 if (img->ncolors)
8301 x_free_colors (f, img->colors, img->ncolors);
8302 #endif
8304 else
8305 image_error ("Cannot get X image of `%s'; colors will not be freed",
8306 img->spec, Qnil);
8308 UNBLOCK_INPUT;
8310 #endif /* HAVE_X_WINDOWS */
8312 /* Now that we have the pixmap, compute mask and transform the
8313 image if requested. */
8314 BLOCK_INPUT;
8315 postprocess_image (f, img);
8316 UNBLOCK_INPUT;
8319 #endif /* HAVE_GHOSTSCRIPT */
8322 /***********************************************************************
8323 Tests
8324 ***********************************************************************/
8326 #if GLYPH_DEBUG
8328 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8329 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8330 (spec)
8331 Lisp_Object spec;
8333 return valid_image_p (spec) ? Qt : Qnil;
8337 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8338 (spec)
8339 Lisp_Object spec;
8341 int id = -1;
8343 if (valid_image_p (spec))
8344 id = lookup_image (SELECTED_FRAME (), spec);
8346 debug_print (spec);
8347 return make_number (id);
8350 #endif /* GLYPH_DEBUG != 0 */
8353 /***********************************************************************
8354 Initialization
8355 ***********************************************************************/
8357 #ifdef HAVE_NTGUI
8358 /* Image types that rely on external libraries are loaded dynamically
8359 if the library is available. */
8360 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8361 define_image_type (image_type, init_lib_fn (libraries))
8362 #else
8363 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8364 define_image_type (image_type, 1)
8365 #endif /* HAVE_NTGUI */
8367 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8368 doc: /* Initialize image library implementing image type TYPE.
8369 Return non-nil if TYPE is a supported image type.
8371 Image types pbm and xbm are prebuilt; other types are loaded here.
8372 Libraries to load are specified in alist LIBRARIES (usually, the value
8373 of `image-library-alist', which see). */)
8374 (type, libraries)
8375 Lisp_Object type, libraries;
8377 Lisp_Object tested;
8379 /* Don't try to reload the library. */
8380 tested = Fassq (type, Vimage_type_cache);
8381 if (CONSP (tested))
8382 return XCDR (tested);
8384 #if defined (HAVE_XPM) || defined (MAC_OS)
8385 if (EQ (type, Qxpm))
8386 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8387 #endif
8389 #if defined (HAVE_JPEG) || defined (MAC_OS)
8390 if (EQ (type, Qjpeg))
8391 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8392 #endif
8394 #if defined (HAVE_TIFF) || defined (MAC_OS)
8395 if (EQ (type, Qtiff))
8396 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8397 #endif
8399 #if defined (HAVE_GIF) || defined (MAC_OS)
8400 if (EQ (type, Qgif))
8401 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8402 #endif
8404 #if defined (HAVE_PNG) || defined (MAC_OS)
8405 if (EQ (type, Qpng))
8406 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8407 #endif
8409 #ifdef HAVE_GHOSTSCRIPT
8410 if (EQ (type, Qpostscript))
8411 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8412 #endif
8414 /* If the type is not recognized, avoid testing it ever again. */
8415 CACHE_IMAGE_TYPE (type, Qnil);
8416 return Qnil;
8419 void
8420 syms_of_image ()
8422 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8424 /* Initialize this only once, since that's what we do with Vimage_types
8425 and they are supposed to be in sync. Initializing here gives correct
8426 operation on GNU/Linux of calling dump-emacs after loading some images. */
8427 image_types = NULL;
8429 /* Must be defined now becase we're going to update it below, while
8430 defining the supported image types. */
8431 DEFVAR_LISP ("image-types", &Vimage_types,
8432 doc: /* List of potentially supported image types.
8433 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8434 To check whether it is really supported, use `image-type-available-p'. */);
8435 Vimage_types = Qnil;
8437 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8438 doc: /* Alist of image types vs external libraries needed to display them.
8440 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8441 representing a supported image type, and the rest are strings giving
8442 alternate filenames for the corresponding external libraries.
8444 Emacs tries to load the libraries in the order they appear on the
8445 list; if none is loaded, the running session of Emacs won't
8446 support the image type. Types 'pbm and 'xbm don't need to be
8447 listed; they're always supported. */);
8448 Vimage_library_alist = Qnil;
8449 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
8451 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8452 doc: /* Maximum size of images.
8453 Emacs will not load an image into memory if its pixel width or
8454 pixel height exceeds this limit.
8456 If the value is an integer, it directly specifies the maximum
8457 image height and width, measured in pixels. If it is a floating
8458 point number, it specifies the maximum image height and width
8459 as a ratio to the frame height and width. If the value is
8460 non-numeric, there is no explicit limit on the size of images. */);
8461 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8463 Vimage_type_cache = Qnil;
8464 staticpro (&Vimage_type_cache);
8466 Qpbm = intern ("pbm");
8467 staticpro (&Qpbm);
8468 ADD_IMAGE_TYPE(Qpbm);
8470 Qxbm = intern ("xbm");
8471 staticpro (&Qxbm);
8472 ADD_IMAGE_TYPE(Qxbm);
8474 define_image_type (&xbm_type, 1);
8475 define_image_type (&pbm_type, 1);
8477 QCascent = intern (":ascent");
8478 staticpro (&QCascent);
8479 QCmargin = intern (":margin");
8480 staticpro (&QCmargin);
8481 QCrelief = intern (":relief");
8482 staticpro (&QCrelief);
8483 QCconversion = intern (":conversion");
8484 staticpro (&QCconversion);
8485 QCcolor_symbols = intern (":color-symbols");
8486 staticpro (&QCcolor_symbols);
8487 QCheuristic_mask = intern (":heuristic-mask");
8488 staticpro (&QCheuristic_mask);
8489 QCindex = intern (":index");
8490 staticpro (&QCindex);
8491 QCmatrix = intern (":matrix");
8492 staticpro (&QCmatrix);
8493 QCcolor_adjustment = intern (":color-adjustment");
8494 staticpro (&QCcolor_adjustment);
8495 QCmask = intern (":mask");
8496 staticpro (&QCmask);
8498 Qlaplace = intern ("laplace");
8499 staticpro (&Qlaplace);
8500 Qemboss = intern ("emboss");
8501 staticpro (&Qemboss);
8502 Qedge_detection = intern ("edge-detection");
8503 staticpro (&Qedge_detection);
8504 Qheuristic = intern ("heuristic");
8505 staticpro (&Qheuristic);
8507 Qpostscript = intern ("postscript");
8508 staticpro (&Qpostscript);
8509 #ifdef HAVE_GHOSTSCRIPT
8510 ADD_IMAGE_TYPE(Qpostscript);
8511 QCloader = intern (":loader");
8512 staticpro (&QCloader);
8513 QCbounding_box = intern (":bounding-box");
8514 staticpro (&QCbounding_box);
8515 QCpt_width = intern (":pt-width");
8516 staticpro (&QCpt_width);
8517 QCpt_height = intern (":pt-height");
8518 staticpro (&QCpt_height);
8519 #endif /* HAVE_GHOSTSCRIPT */
8521 #if defined (HAVE_XPM) || defined (MAC_OS)
8522 Qxpm = intern ("xpm");
8523 staticpro (&Qxpm);
8524 ADD_IMAGE_TYPE(Qxpm);
8525 #endif
8527 #if defined (HAVE_JPEG) || defined (MAC_OS)
8528 Qjpeg = intern ("jpeg");
8529 staticpro (&Qjpeg);
8530 ADD_IMAGE_TYPE(Qjpeg);
8531 #endif
8533 #if defined (HAVE_TIFF) || defined (MAC_OS)
8534 Qtiff = intern ("tiff");
8535 staticpro (&Qtiff);
8536 ADD_IMAGE_TYPE(Qtiff);
8537 #endif
8539 #if defined (HAVE_GIF) || defined (MAC_OS)
8540 Qgif = intern ("gif");
8541 staticpro (&Qgif);
8542 ADD_IMAGE_TYPE(Qgif);
8543 #endif
8545 #if defined (HAVE_PNG) || defined (MAC_OS)
8546 Qpng = intern ("png");
8547 staticpro (&Qpng);
8548 ADD_IMAGE_TYPE(Qpng);
8549 #endif
8551 defsubr (&Sinit_image_library);
8552 defsubr (&Sclear_image_cache);
8553 defsubr (&Simage_size);
8554 defsubr (&Simage_mask_p);
8556 #if GLYPH_DEBUG
8557 defsubr (&Simagep);
8558 defsubr (&Slookup_image);
8559 #endif
8561 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
8562 doc: /* Non-nil means always draw a cross over disabled images.
8563 Disabled images are those having an `:conversion disabled' property.
8564 A cross is always drawn on black & white displays. */);
8565 cross_disabled_images = 0;
8567 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8568 doc: /* List of directories to search for window system bitmap files. */);
8569 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8571 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8572 doc: /* Time after which cached images are removed from the cache.
8573 When an image has not been displayed this many seconds, remove it
8574 from the image cache. Value must be an integer or nil with nil
8575 meaning don't clear the cache. */);
8576 Vimage_cache_eviction_delay = make_number (30 * 60);
8579 void
8580 init_image ()
8582 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
8583 init_image_func_pointer ();
8584 #endif
8587 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8588 (do not change this comment) */