Merged from emacs@sv.gnu.org
[emacs.git] / src / image.c
blobeae25fdb02e0a91f3aecf3fbf3a4c2b0b0e0be3d
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 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
448 #endif /* MAC_OS */
450 dpyinfo->bitmaps[id - 1].file = NULL;
451 dpyinfo->bitmaps[id - 1].height = height;
452 dpyinfo->bitmaps[id - 1].width = width;
453 dpyinfo->bitmaps[id - 1].refcount = 1;
455 #ifdef HAVE_X_WINDOWS
456 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
457 dpyinfo->bitmaps[id - 1].have_mask = 0;
458 dpyinfo->bitmaps[id - 1].depth = 1;
459 #endif /* HAVE_X_WINDOWS */
461 #ifdef HAVE_NTGUI
462 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
463 dpyinfo->bitmaps[id - 1].hinst = NULL;
464 dpyinfo->bitmaps[id - 1].depth = 1;
465 #endif /* HAVE_NTGUI */
467 return id;
470 /* Create bitmap from file FILE for frame F. */
473 x_create_bitmap_from_file (f, file)
474 struct frame *f;
475 Lisp_Object file;
477 #ifdef MAC_OS
478 return -1; /* MAC_TODO : bitmap support */
479 #endif /* MAC_OS */
481 #ifdef HAVE_NTGUI
482 return -1; /* W32_TODO : bitmap support */
483 #endif /* HAVE_NTGUI */
485 #ifdef HAVE_X_WINDOWS
486 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
487 unsigned int width, height;
488 Pixmap bitmap;
489 int xhot, yhot, result, id;
490 Lisp_Object found;
491 int fd;
492 char *filename;
494 /* Look for an existing bitmap with the same name. */
495 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
497 if (dpyinfo->bitmaps[id].refcount
498 && dpyinfo->bitmaps[id].file
499 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
501 ++dpyinfo->bitmaps[id].refcount;
502 return id + 1;
506 /* Search bitmap-file-path for the file, if appropriate. */
507 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
508 if (fd < 0)
509 return -1;
510 emacs_close (fd);
512 filename = (char *) SDATA (found);
514 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
515 filename, &width, &height, &bitmap, &xhot, &yhot);
516 if (result != BitmapSuccess)
517 return -1;
519 id = x_allocate_bitmap_record (f);
520 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
521 dpyinfo->bitmaps[id - 1].have_mask = 0;
522 dpyinfo->bitmaps[id - 1].refcount = 1;
523 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
524 dpyinfo->bitmaps[id - 1].depth = 1;
525 dpyinfo->bitmaps[id - 1].height = height;
526 dpyinfo->bitmaps[id - 1].width = width;
527 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
529 return id;
530 #endif /* HAVE_X_WINDOWS */
533 /* Free bitmap B. */
535 static void
536 Free_Bitmap_Record (dpyinfo, bm)
537 Display_Info *dpyinfo;
538 Bitmap_Record *bm;
540 #ifdef HAVE_X_WINDOWS
541 XFreePixmap (dpyinfo->display, bm->pixmap);
542 if (bm->have_mask)
543 XFreePixmap (dpyinfo->display, bm->mask);
544 #endif /* HAVE_X_WINDOWS */
546 #ifdef HAVE_NTGUI
547 DeleteObject (bm->pixmap);
548 #endif /* HAVE_NTGUI */
550 #ifdef MAC_OS
551 xfree (bm->bitmap_data); /* Added ++kfs */
552 bm->bitmap_data = NULL;
553 #endif /* MAC_OS */
555 if (bm->file)
557 xfree (bm->file);
558 bm->file = NULL;
562 /* Remove reference to bitmap with id number ID. */
564 void
565 x_destroy_bitmap (f, id)
566 FRAME_PTR f;
567 int id;
569 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
571 if (id > 0)
573 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
575 if (--bm->refcount == 0)
577 BLOCK_INPUT;
578 Free_Bitmap_Record (dpyinfo, bm);
579 UNBLOCK_INPUT;
584 /* Free all the bitmaps for the display specified by DPYINFO. */
586 void
587 x_destroy_all_bitmaps (dpyinfo)
588 Display_Info *dpyinfo;
590 int i;
591 Bitmap_Record *bm = dpyinfo->bitmaps;
593 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
594 if (bm->refcount > 0)
595 Free_Bitmap_Record (dpyinfo, bm);
597 dpyinfo->bitmaps_last = 0;
601 #ifdef HAVE_X_WINDOWS
603 /* Useful functions defined in the section
604 `Image type independent image structures' below. */
606 static unsigned long four_corners_best P_ ((XImagePtr ximg,
607 int *corners,
608 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, NULL, 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, Qcount;
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;
1146 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1147 doc: /* Return extension data for image SPEC.
1148 FRAME is the frame on which the image will be displayed. FRAME nil
1149 or omitted means use the selected frame. */)
1150 (spec, frame)
1151 Lisp_Object spec, frame;
1153 Lisp_Object ext;
1155 ext = Qnil;
1156 if (valid_image_p (spec))
1158 struct frame *f = check_x_frame (frame);
1159 int id = lookup_image (f, spec);
1160 struct image *img = IMAGE_FROM_ID (f, id);
1161 ext = img->data.lisp_val;
1164 return ext;
1168 /***********************************************************************
1169 Image type independent image structures
1170 ***********************************************************************/
1172 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1173 static void free_image P_ ((struct frame *f, struct image *img));
1174 static int check_image_size P_ ((struct frame *f, int width, int height));
1176 #define MAX_IMAGE_SIZE 6.0
1177 Lisp_Object Vmax_image_size;
1179 /* Allocate and return a new image structure for image specification
1180 SPEC. SPEC has a hash value of HASH. */
1182 static struct image *
1183 make_image (spec, hash)
1184 Lisp_Object spec;
1185 unsigned hash;
1187 struct image *img = (struct image *) xmalloc (sizeof *img);
1189 xassert (valid_image_p (spec));
1190 bzero (img, sizeof *img);
1191 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1192 xassert (img->type != NULL);
1193 img->spec = spec;
1194 img->data.lisp_val = Qnil;
1195 img->ascent = DEFAULT_IMAGE_ASCENT;
1196 img->hash = hash;
1197 img->corners[BOT_CORNER] = -1; /* Full image */
1198 return img;
1202 /* Free image IMG which was used on frame F, including its resources. */
1204 static void
1205 free_image (f, img)
1206 struct frame *f;
1207 struct image *img;
1209 if (img)
1211 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1213 /* Remove IMG from the hash table of its cache. */
1214 if (img->prev)
1215 img->prev->next = img->next;
1216 else
1217 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1219 if (img->next)
1220 img->next->prev = img->prev;
1222 c->images[img->id] = NULL;
1224 /* Free resources, then free IMG. */
1225 img->type->free (f, img);
1226 xfree (img);
1230 /* Return 1 if the given widths and heights are valid for display;
1231 otherwise, return 0. */
1234 check_image_size (f, width, height)
1235 struct frame *f;
1236 int width;
1237 int height;
1239 int w, h;
1241 if (width <= 0 || height <= 0)
1242 return 0;
1244 if (INTEGERP (Vmax_image_size))
1245 w = h = XINT (Vmax_image_size);
1246 else if (FLOATP (Vmax_image_size))
1248 if (f != NULL)
1250 w = FRAME_PIXEL_WIDTH (f);
1251 h = FRAME_PIXEL_HEIGHT (f);
1253 else
1254 w = h = 1024; /* Arbitrary size for unknown frame. */
1255 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1256 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1258 else
1259 return 1;
1261 return (width <= w && height <= h);
1264 /* Prepare image IMG for display on frame F. Must be called before
1265 drawing an image. */
1267 void
1268 prepare_image_for_display (f, img)
1269 struct frame *f;
1270 struct image *img;
1272 EMACS_TIME t;
1274 /* We're about to display IMG, so set its timestamp to `now'. */
1275 EMACS_GET_TIME (t);
1276 img->timestamp = EMACS_SECS (t);
1278 /* If IMG doesn't have a pixmap yet, load it now, using the image
1279 type dependent loader function. */
1280 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1281 img->load_failed_p = img->type->load (f, img) == 0;
1283 #if defined (MAC_OS) && USE_CG_DRAWING
1284 if (!img->load_failed_p && img->data.ptr_val == NULL)
1286 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1287 if (img->data.ptr_val == NULL)
1289 img->load_failed_p = 1;
1290 img->type->free (f, img);
1293 #endif
1297 /* Value is the number of pixels for the ascent of image IMG when
1298 drawn in face FACE. */
1301 image_ascent (img, face, slice)
1302 struct image *img;
1303 struct face *face;
1304 struct glyph_slice *slice;
1306 int height;
1307 int ascent;
1309 if (slice->height == img->height)
1310 height = img->height + img->vmargin;
1311 else if (slice->y == 0)
1312 height = slice->height + img->vmargin;
1313 else
1314 height = slice->height;
1316 if (img->ascent == CENTERED_IMAGE_ASCENT)
1318 if (face->font)
1320 #ifdef HAVE_NTGUI
1321 /* W32 specific version. Why?. ++kfs */
1322 ascent = height / 2 - (FONT_DESCENT(face->font)
1323 - FONT_BASE(face->font)) / 2;
1324 #else
1325 /* This expression is arranged so that if the image can't be
1326 exactly centered, it will be moved slightly up. This is
1327 because a typical font is `top-heavy' (due to the presence
1328 uppercase letters), so the image placement should err towards
1329 being top-heavy too. It also just generally looks better. */
1330 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1331 #endif /* HAVE_NTGUI */
1333 else
1334 ascent = height / 2;
1336 else
1337 ascent = (int) (height * img->ascent / 100.0);
1339 return ascent;
1343 /* Image background colors. */
1345 /* Find the "best" corner color of a bitmap.
1346 On W32, XIMG is assumed to a device context with the bitmap selected. */
1348 static RGB_PIXEL_COLOR
1349 four_corners_best (ximg, corners, width, height)
1350 XImagePtr_or_DC ximg;
1351 int *corners;
1352 unsigned long width, height;
1354 RGB_PIXEL_COLOR corner_pixels[4], best;
1355 int i, best_count;
1357 if (corners && corners[BOT_CORNER] >= 0)
1359 /* Get the colors at the corner_pixels of ximg. */
1360 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1361 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1362 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1363 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1365 else
1367 /* Get the colors at the corner_pixels of ximg. */
1368 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1369 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1370 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1371 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1373 /* Choose the most frequently found color as background. */
1374 for (i = best_count = 0; i < 4; ++i)
1376 int j, n;
1378 for (j = n = 0; j < 4; ++j)
1379 if (corner_pixels[i] == corner_pixels[j])
1380 ++n;
1382 if (n > best_count)
1383 best = corner_pixels[i], best_count = n;
1386 return best;
1389 /* Portability macros */
1391 #ifdef HAVE_NTGUI
1393 #define Destroy_Image(img_dc, prev) \
1394 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1396 #define Free_Pixmap(display, pixmap) \
1397 DeleteObject (pixmap)
1399 #else
1401 #define Destroy_Image(ximg, dummy) \
1402 XDestroyImage (ximg)
1404 #define Free_Pixmap(display, pixmap) \
1405 XFreePixmap (display, pixmap)
1407 #endif /* HAVE_NTGUI */
1410 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1411 it is guessed heuristically. If non-zero, XIMG is an existing
1412 XImage object (or device context with the image selected on W32) to
1413 use for the heuristic. */
1415 RGB_PIXEL_COLOR
1416 image_background (img, f, ximg)
1417 struct image *img;
1418 struct frame *f;
1419 XImagePtr_or_DC ximg;
1421 if (! img->background_valid)
1422 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1424 int free_ximg = !ximg;
1425 #ifdef HAVE_NTGUI
1426 HGDIOBJ prev;
1427 #endif /* HAVE_NTGUI */
1429 if (free_ximg)
1431 #ifndef HAVE_NTGUI
1432 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1433 0, 0, img->width, img->height, ~0, ZPixmap);
1434 #else
1435 HDC frame_dc = get_frame_dc (f);
1436 ximg = CreateCompatibleDC (frame_dc);
1437 release_frame_dc (f, frame_dc);
1438 prev = SelectObject (ximg, img->pixmap);
1439 #endif /* !HAVE_NTGUI */
1442 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1444 if (free_ximg)
1445 Destroy_Image (ximg, prev);
1447 img->background_valid = 1;
1450 return img->background;
1453 /* Return the `background_transparent' field of IMG. If IMG doesn't
1454 have one yet, it is guessed heuristically. If non-zero, MASK is an
1455 existing XImage object to use for the heuristic. */
1458 image_background_transparent (img, f, mask)
1459 struct image *img;
1460 struct frame *f;
1461 XImagePtr_or_DC mask;
1463 if (! img->background_transparent_valid)
1464 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1466 if (img->mask)
1468 int free_mask = !mask;
1469 #ifdef HAVE_NTGUI
1470 HGDIOBJ prev;
1471 #endif /* HAVE_NTGUI */
1473 if (free_mask)
1475 #ifndef HAVE_NTGUI
1476 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1477 0, 0, img->width, img->height, ~0, ZPixmap);
1478 #else
1479 HDC frame_dc = get_frame_dc (f);
1480 mask = CreateCompatibleDC (frame_dc);
1481 release_frame_dc (f, frame_dc);
1482 prev = SelectObject (mask, img->mask);
1483 #endif /* HAVE_NTGUI */
1486 img->background_transparent
1487 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1489 if (free_mask)
1490 Destroy_Image (mask, prev);
1492 else
1493 img->background_transparent = 0;
1495 img->background_transparent_valid = 1;
1498 return img->background_transparent;
1502 /***********************************************************************
1503 Helper functions for X image types
1504 ***********************************************************************/
1506 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1507 int, int));
1508 static void x_clear_image P_ ((struct frame *f, struct image *img));
1509 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1510 struct image *img,
1511 Lisp_Object color_name,
1512 unsigned long dflt));
1515 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1516 free the pixmap if any. MASK_P non-zero means clear the mask
1517 pixmap if any. COLORS_P non-zero means free colors allocated for
1518 the image, if any. */
1520 static void
1521 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1522 struct frame *f;
1523 struct image *img;
1524 int pixmap_p, mask_p, colors_p;
1526 if (pixmap_p && img->pixmap)
1528 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1529 img->pixmap = NO_PIXMAP;
1530 img->background_valid = 0;
1533 if (mask_p && img->mask)
1535 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1536 img->mask = NO_PIXMAP;
1537 img->background_transparent_valid = 0;
1540 if (colors_p && img->ncolors)
1542 /* MAC_TODO: color table support. */
1543 /* W32_TODO: color table support. */
1544 #ifdef HAVE_X_WINDOWS
1545 x_free_colors (f, img->colors, img->ncolors);
1546 #endif /* HAVE_X_WINDOWS */
1547 xfree (img->colors);
1548 img->colors = NULL;
1549 img->ncolors = 0;
1552 #if defined (MAC_OS) && USE_CG_DRAWING
1553 if (img->data.ptr_val)
1555 CGImageRelease (img->data.ptr_val);
1556 img->data.ptr_val = NULL;
1558 #endif
1561 /* Free X resources of image IMG which is used on frame F. */
1563 static void
1564 x_clear_image (f, img)
1565 struct frame *f;
1566 struct image *img;
1568 BLOCK_INPUT;
1569 x_clear_image_1 (f, img, 1, 1, 1);
1570 UNBLOCK_INPUT;
1574 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1575 cannot be allocated, use DFLT. Add a newly allocated color to
1576 IMG->colors, so that it can be freed again. Value is the pixel
1577 color. */
1579 static unsigned long
1580 x_alloc_image_color (f, img, color_name, dflt)
1581 struct frame *f;
1582 struct image *img;
1583 Lisp_Object color_name;
1584 unsigned long dflt;
1586 XColor color;
1587 unsigned long result;
1589 xassert (STRINGP (color_name));
1591 if (x_defined_color (f, SDATA (color_name), &color, 1))
1593 /* This isn't called frequently so we get away with simply
1594 reallocating the color vector to the needed size, here. */
1595 ++img->ncolors;
1596 img->colors =
1597 (unsigned long *) xrealloc (img->colors,
1598 img->ncolors * sizeof *img->colors);
1599 img->colors[img->ncolors - 1] = color.pixel;
1600 result = color.pixel;
1602 else
1603 result = dflt;
1605 return result;
1610 /***********************************************************************
1611 Image Cache
1612 ***********************************************************************/
1614 static void cache_image P_ ((struct frame *f, struct image *img));
1615 static void postprocess_image P_ ((struct frame *, struct image *));
1617 /* Return a new, initialized image cache that is allocated from the
1618 heap. Call free_image_cache to free an image cache. */
1620 struct image_cache *
1621 make_image_cache ()
1623 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1624 int size;
1626 bzero (c, sizeof *c);
1627 c->size = 50;
1628 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1629 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1630 c->buckets = (struct image **) xmalloc (size);
1631 bzero (c->buckets, size);
1632 return c;
1636 /* Free image cache of frame F. Be aware that X frames share images
1637 caches. */
1639 void
1640 free_image_cache (f)
1641 struct frame *f;
1643 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1644 if (c)
1646 int i;
1648 /* Cache should not be referenced by any frame when freed. */
1649 xassert (c->refcount == 0);
1651 for (i = 0; i < c->used; ++i)
1652 free_image (f, c->images[i]);
1653 xfree (c->images);
1654 xfree (c->buckets);
1655 xfree (c);
1656 FRAME_X_IMAGE_CACHE (f) = NULL;
1661 /* Clear image cache of frame F. FORCE_P non-zero means free all
1662 images. FORCE_P zero means clear only images that haven't been
1663 displayed for some time. Should be called from time to time to
1664 reduce the number of loaded images. If image-eviction-seconds is
1665 non-nil, this frees images in the cache which weren't displayed for
1666 at least that many seconds. */
1668 void
1669 clear_image_cache (f, force_p)
1670 struct frame *f;
1671 int force_p;
1673 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1675 if (c && INTEGERP (Vimage_cache_eviction_delay))
1677 EMACS_TIME t;
1678 unsigned long old;
1679 int i, nfreed;
1681 EMACS_GET_TIME (t);
1682 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1684 /* Block input so that we won't be interrupted by a SIGIO
1685 while being in an inconsistent state. */
1686 BLOCK_INPUT;
1688 for (i = nfreed = 0; i < c->used; ++i)
1690 struct image *img = c->images[i];
1691 if (img != NULL
1692 && (force_p || img->timestamp < old))
1694 free_image (f, img);
1695 ++nfreed;
1699 /* We may be clearing the image cache because, for example,
1700 Emacs was iconified for a longer period of time. In that
1701 case, current matrices may still contain references to
1702 images freed above. So, clear these matrices. */
1703 if (nfreed)
1705 Lisp_Object tail, frame;
1707 FOR_EACH_FRAME (tail, frame)
1709 struct frame *f = XFRAME (frame);
1710 if (FRAME_WINDOW_P (f)
1711 && FRAME_X_IMAGE_CACHE (f) == c)
1712 clear_current_matrices (f);
1715 ++windows_or_buffers_changed;
1718 UNBLOCK_INPUT;
1723 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1724 0, 1, 0,
1725 doc: /* Clear the image cache of FRAME.
1726 FRAME nil or omitted means use the selected frame.
1727 FRAME t means clear the image caches of all frames. */)
1728 (frame)
1729 Lisp_Object frame;
1731 if (EQ (frame, Qt))
1733 Lisp_Object tail;
1735 FOR_EACH_FRAME (tail, frame)
1736 if (FRAME_WINDOW_P (XFRAME (frame)))
1737 clear_image_cache (XFRAME (frame), 1);
1739 else
1740 clear_image_cache (check_x_frame (frame), 1);
1742 return Qnil;
1746 /* Compute masks and transform image IMG on frame F, as specified
1747 by the image's specification, */
1749 static void
1750 postprocess_image (f, img)
1751 struct frame *f;
1752 struct image *img;
1754 /* Manipulation of the image's mask. */
1755 if (img->pixmap)
1757 Lisp_Object conversion, spec;
1758 Lisp_Object mask;
1760 spec = img->spec;
1762 /* `:heuristic-mask t'
1763 `:mask heuristic'
1764 means build a mask heuristically.
1765 `:heuristic-mask (R G B)'
1766 `:mask (heuristic (R G B))'
1767 means build a mask from color (R G B) in the
1768 image.
1769 `:mask nil'
1770 means remove a mask, if any. */
1772 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1773 if (!NILP (mask))
1774 x_build_heuristic_mask (f, img, mask);
1775 else
1777 int found_p;
1779 mask = image_spec_value (spec, QCmask, &found_p);
1781 if (EQ (mask, Qheuristic))
1782 x_build_heuristic_mask (f, img, Qt);
1783 else if (CONSP (mask)
1784 && EQ (XCAR (mask), Qheuristic))
1786 if (CONSP (XCDR (mask)))
1787 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1788 else
1789 x_build_heuristic_mask (f, img, XCDR (mask));
1791 else if (NILP (mask) && found_p && img->mask)
1793 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1794 img->mask = NO_PIXMAP;
1799 /* Should we apply an image transformation algorithm? */
1800 conversion = image_spec_value (spec, QCconversion, NULL);
1801 if (EQ (conversion, Qdisabled))
1802 x_disable_image (f, img);
1803 else if (EQ (conversion, Qlaplace))
1804 x_laplace (f, img);
1805 else if (EQ (conversion, Qemboss))
1806 x_emboss (f, img);
1807 else if (CONSP (conversion)
1808 && EQ (XCAR (conversion), Qedge_detection))
1810 Lisp_Object tem;
1811 tem = XCDR (conversion);
1812 if (CONSP (tem))
1813 x_edge_detection (f, img,
1814 Fplist_get (tem, QCmatrix),
1815 Fplist_get (tem, QCcolor_adjustment));
1821 /* Return the id of image with Lisp specification SPEC on frame F.
1822 SPEC must be a valid Lisp image specification (see valid_image_p). */
1825 lookup_image (f, spec)
1826 struct frame *f;
1827 Lisp_Object spec;
1829 struct image_cache *c;
1830 struct image *img;
1831 int i;
1832 unsigned hash;
1833 struct gcpro gcpro1;
1834 EMACS_TIME now;
1836 /* F must be a window-system frame, and SPEC must be a valid image
1837 specification. */
1838 xassert (FRAME_WINDOW_P (f));
1839 xassert (valid_image_p (spec));
1841 c = FRAME_X_IMAGE_CACHE (f);
1843 GCPRO1 (spec);
1845 /* Look up SPEC in the hash table of the image cache. */
1846 hash = sxhash (spec, 0);
1847 i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1849 for (img = c->buckets[i]; img; img = img->next)
1850 if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
1851 break;
1853 if (img && img->load_failed_p)
1855 free_image (f, img);
1856 img = NULL;
1859 /* If not found, create a new image and cache it. */
1860 if (img == NULL)
1862 extern Lisp_Object Qpostscript;
1864 BLOCK_INPUT;
1865 img = make_image (spec, hash);
1866 cache_image (f, img);
1867 img->load_failed_p = img->type->load (f, img) == 0;
1869 /* If we can't load the image, and we don't have a width and
1870 height, use some arbitrary width and height so that we can
1871 draw a rectangle for it. */
1872 if (img->load_failed_p)
1874 Lisp_Object value;
1876 value = image_spec_value (spec, QCwidth, NULL);
1877 img->width = (INTEGERP (value)
1878 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
1879 value = image_spec_value (spec, QCheight, NULL);
1880 img->height = (INTEGERP (value)
1881 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
1883 else
1885 /* Handle image type independent image attributes
1886 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
1887 `:background COLOR'. */
1888 Lisp_Object ascent, margin, relief, bg;
1890 ascent = image_spec_value (spec, QCascent, NULL);
1891 if (INTEGERP (ascent))
1892 img->ascent = XFASTINT (ascent);
1893 else if (EQ (ascent, Qcenter))
1894 img->ascent = CENTERED_IMAGE_ASCENT;
1896 margin = image_spec_value (spec, QCmargin, NULL);
1897 if (INTEGERP (margin) && XINT (margin) >= 0)
1898 img->vmargin = img->hmargin = XFASTINT (margin);
1899 else if (CONSP (margin) && INTEGERP (XCAR (margin))
1900 && INTEGERP (XCDR (margin)))
1902 if (XINT (XCAR (margin)) > 0)
1903 img->hmargin = XFASTINT (XCAR (margin));
1904 if (XINT (XCDR (margin)) > 0)
1905 img->vmargin = XFASTINT (XCDR (margin));
1908 relief = image_spec_value (spec, QCrelief, NULL);
1909 if (INTEGERP (relief))
1911 img->relief = XINT (relief);
1912 img->hmargin += abs (img->relief);
1913 img->vmargin += abs (img->relief);
1916 if (! img->background_valid)
1918 bg = image_spec_value (img->spec, QCbackground, NULL);
1919 if (!NILP (bg))
1921 img->background
1922 = x_alloc_image_color (f, img, bg,
1923 FRAME_BACKGROUND_PIXEL (f));
1924 img->background_valid = 1;
1928 /* Do image transformations and compute masks, unless we
1929 don't have the image yet. */
1930 if (!EQ (*img->type->type, Qpostscript))
1931 postprocess_image (f, img);
1934 UNBLOCK_INPUT;
1937 /* We're using IMG, so set its timestamp to `now'. */
1938 EMACS_GET_TIME (now);
1939 img->timestamp = EMACS_SECS (now);
1941 UNGCPRO;
1943 /* Value is the image id. */
1944 return img->id;
1948 /* Cache image IMG in the image cache of frame F. */
1950 static void
1951 cache_image (f, img)
1952 struct frame *f;
1953 struct image *img;
1955 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1956 int i;
1958 /* Find a free slot in c->images. */
1959 for (i = 0; i < c->used; ++i)
1960 if (c->images[i] == NULL)
1961 break;
1963 /* If no free slot found, maybe enlarge c->images. */
1964 if (i == c->used && c->used == c->size)
1966 c->size *= 2;
1967 c->images = (struct image **) xrealloc (c->images,
1968 c->size * sizeof *c->images);
1971 /* Add IMG to c->images, and assign IMG an id. */
1972 c->images[i] = img;
1973 img->id = i;
1974 if (i == c->used)
1975 ++c->used;
1977 /* Add IMG to the cache's hash table. */
1978 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
1979 img->next = c->buckets[i];
1980 if (img->next)
1981 img->next->prev = img;
1982 img->prev = NULL;
1983 c->buckets[i] = img;
1987 /* Call FN on every image in the image cache of frame F. Used to mark
1988 Lisp Objects in the image cache. */
1990 void
1991 forall_images_in_image_cache (f, fn)
1992 struct frame *f;
1993 void (*fn) P_ ((struct image *img));
1995 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f))
1997 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1998 if (c)
2000 int i;
2001 for (i = 0; i < c->used; ++i)
2002 if (c->images[i])
2003 fn (c->images[i]);
2010 /***********************************************************************
2011 X / MAC / W32 support code
2012 ***********************************************************************/
2014 #ifdef HAVE_NTGUI
2016 /* Macro for defining functions that will be loaded from image DLLs. */
2017 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2019 /* Macro for loading those image functions from the library. */
2020 #define LOAD_IMGLIB_FN(lib,func) { \
2021 fn_##func = (void *) GetProcAddress (lib, #func); \
2022 if (!fn_##func) return 0; \
2025 /* Load a DLL implementing an image type.
2026 The `image-library-alist' variable associates a symbol,
2027 identifying an image type, to a list of possible filenames.
2028 The function returns NULL if no library could be loaded for
2029 the given image type, or if the library was previously loaded;
2030 else the handle of the DLL. */
2031 static HMODULE
2032 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2034 HMODULE library = NULL;
2036 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2038 Lisp_Object dlls = Fassq (type, libraries);
2040 if (CONSP (dlls))
2041 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2043 CHECK_STRING_CAR (dlls);
2044 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2045 break;
2049 return library;
2052 #endif /* HAVE_NTGUI */
2054 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2055 XImagePtr *, Pixmap *));
2056 static void x_destroy_x_image P_ ((XImagePtr));
2057 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2060 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2061 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2062 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2063 via xmalloc. Print error messages via image_error if an error
2064 occurs. Value is non-zero if successful.
2066 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2067 should indicate the bit depth of the image. */
2069 static int
2070 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2071 struct frame *f;
2072 int width, height, depth;
2073 XImagePtr *ximg;
2074 Pixmap *pixmap;
2076 #ifdef HAVE_X_WINDOWS
2077 Display *display = FRAME_X_DISPLAY (f);
2078 Window window = FRAME_X_WINDOW (f);
2079 Screen *screen = FRAME_X_SCREEN (f);
2081 xassert (interrupt_input_blocked);
2083 if (depth <= 0)
2084 depth = DefaultDepthOfScreen (screen);
2085 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2086 depth, ZPixmap, 0, NULL, width, height,
2087 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2088 if (*ximg == NULL)
2090 image_error ("Unable to allocate X image", Qnil, Qnil);
2091 return 0;
2094 /* Allocate image raster. */
2095 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2097 /* Allocate a pixmap of the same size. */
2098 *pixmap = XCreatePixmap (display, window, width, height, depth);
2099 if (*pixmap == NO_PIXMAP)
2101 x_destroy_x_image (*ximg);
2102 *ximg = NULL;
2103 image_error ("Unable to create X pixmap", Qnil, Qnil);
2104 return 0;
2107 return 1;
2108 #endif /* HAVE_X_WINDOWS */
2110 #ifdef HAVE_NTGUI
2112 BITMAPINFOHEADER *header;
2113 HDC hdc;
2114 int scanline_width_bits;
2115 int remainder;
2116 int palette_colors = 0;
2118 if (depth == 0)
2119 depth = 24;
2121 if (depth != 1 && depth != 4 && depth != 8
2122 && depth != 16 && depth != 24 && depth != 32)
2124 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2125 return 0;
2128 scanline_width_bits = width * depth;
2129 remainder = scanline_width_bits % 32;
2131 if (remainder)
2132 scanline_width_bits += 32 - remainder;
2134 /* Bitmaps with a depth less than 16 need a palette. */
2135 /* BITMAPINFO structure already contains the first RGBQUAD. */
2136 if (depth < 16)
2137 palette_colors = 1 << depth - 1;
2139 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2140 if (*ximg == NULL)
2142 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2143 return 0;
2146 header = &((*ximg)->info.bmiHeader);
2147 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2148 header->biSize = sizeof (*header);
2149 header->biWidth = width;
2150 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2151 header->biPlanes = 1;
2152 header->biBitCount = depth;
2153 header->biCompression = BI_RGB;
2154 header->biClrUsed = palette_colors;
2156 /* TODO: fill in palette. */
2157 if (depth == 1)
2159 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2160 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2161 (*ximg)->info.bmiColors[0].rgbRed = 0;
2162 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2163 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2164 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2165 (*ximg)->info.bmiColors[1].rgbRed = 255;
2166 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2169 hdc = get_frame_dc (f);
2171 /* Create a DIBSection and raster array for the bitmap,
2172 and store its handle in *pixmap. */
2173 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2174 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2175 /* casting avoids a GCC warning */
2176 (void **)&((*ximg)->data), NULL, 0);
2178 /* Realize display palette and garbage all frames. */
2179 release_frame_dc (f, hdc);
2181 if (*pixmap == NULL)
2183 DWORD err = GetLastError();
2184 Lisp_Object errcode;
2185 /* All system errors are < 10000, so the following is safe. */
2186 XSETINT (errcode, (int) err);
2187 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2188 x_destroy_x_image (*ximg);
2189 return 0;
2192 return 1;
2194 #endif /* HAVE_NTGUI */
2196 #ifdef MAC_OS
2197 Display *display = FRAME_X_DISPLAY (f);
2198 Window window = FRAME_X_WINDOW (f);
2200 xassert (interrupt_input_blocked);
2202 /* Allocate a pixmap of the same size. */
2203 *pixmap = XCreatePixmap (display, window, width, height, depth);
2204 if (*pixmap == NO_PIXMAP)
2206 *ximg = NULL;
2207 image_error ("Unable to create X pixmap", Qnil, Qnil);
2208 return 0;
2211 LockPixels (GetGWorldPixMap (*pixmap));
2212 *ximg = *pixmap;
2213 return 1;
2215 #endif /* MAC_OS */
2219 /* Destroy XImage XIMG. Free XIMG->data. */
2221 static void
2222 x_destroy_x_image (ximg)
2223 XImagePtr ximg;
2225 xassert (interrupt_input_blocked);
2226 if (ximg)
2228 #ifdef HAVE_X_WINDOWS
2229 xfree (ximg->data);
2230 ximg->data = NULL;
2231 XDestroyImage (ximg);
2232 #endif /* HAVE_X_WINDOWS */
2233 #ifdef HAVE_NTGUI
2234 /* Data will be freed by DestroyObject. */
2235 ximg->data = NULL;
2236 xfree (ximg);
2237 #endif /* HAVE_NTGUI */
2238 #ifdef MAC_OS
2239 XDestroyImage (ximg);
2240 #endif /* MAC_OS */
2245 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2246 are width and height of both the image and pixmap. */
2248 static void
2249 x_put_x_image (f, ximg, pixmap, width, height)
2250 struct frame *f;
2251 XImagePtr ximg;
2252 Pixmap pixmap;
2253 int width, height;
2255 #ifdef HAVE_X_WINDOWS
2256 GC gc;
2258 xassert (interrupt_input_blocked);
2259 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2260 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2261 XFreeGC (FRAME_X_DISPLAY (f), gc);
2262 #endif /* HAVE_X_WINDOWS */
2264 #ifdef HAVE_NTGUI
2265 #if 0 /* I don't think this is necessary looking at where it is used. */
2266 HDC hdc = get_frame_dc (f);
2267 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2268 release_frame_dc (f, hdc);
2269 #endif
2270 #endif /* HAVE_NTGUI */
2272 #ifdef MAC_OS
2273 xassert (ximg == pixmap);
2274 #endif /* MAC_OS */
2278 /***********************************************************************
2279 File Handling
2280 ***********************************************************************/
2282 static unsigned char *slurp_file P_ ((char *, int *));
2285 /* Find image file FILE. Look in data-directory, then
2286 x-bitmap-file-path. Value is the encoded full name of the file
2287 found, or nil if not found. */
2289 Lisp_Object
2290 x_find_image_file (file)
2291 Lisp_Object file;
2293 Lisp_Object file_found, search_path;
2294 struct gcpro gcpro1, gcpro2;
2295 int fd;
2297 file_found = Qnil;
2298 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
2299 GCPRO2 (file_found, search_path);
2301 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2302 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2304 if (fd == -1)
2305 file_found = Qnil;
2306 else
2308 file_found = ENCODE_FILE (file_found);
2309 close (fd);
2312 UNGCPRO;
2313 return file_found;
2317 /* Read FILE into memory. Value is a pointer to a buffer allocated
2318 with xmalloc holding FILE's contents. Value is null if an error
2319 occurred. *SIZE is set to the size of the file. */
2321 static unsigned char *
2322 slurp_file (file, size)
2323 char *file;
2324 int *size;
2326 FILE *fp = NULL;
2327 unsigned char *buf = NULL;
2328 struct stat st;
2330 if (stat (file, &st) == 0
2331 && (fp = fopen (file, "rb")) != NULL
2332 && (buf = (unsigned char *) xmalloc (st.st_size),
2333 fread (buf, 1, st.st_size, fp) == st.st_size))
2335 *size = st.st_size;
2336 fclose (fp);
2338 else
2340 if (fp)
2341 fclose (fp);
2342 if (buf)
2344 xfree (buf);
2345 buf = NULL;
2349 return buf;
2354 #ifdef MAC_OS
2356 /***********************************************************************
2357 MAC Image Load Functions
2358 ***********************************************************************/
2360 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2361 OSType));
2362 #ifdef MAC_OSX
2363 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2364 #endif
2366 static OSErr
2367 find_image_fsspec (specified_file, file, fss)
2368 Lisp_Object specified_file, *file;
2369 FSSpec *fss;
2371 OSErr err;
2372 AEDesc desc;
2374 *file = x_find_image_file (specified_file);
2375 if (!STRINGP (*file))
2376 return fnfErr; /* file or directory not found;
2377 incomplete pathname */
2378 /* Try to open the image file. */
2379 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2380 SBYTES (*file), typeFSS, &desc);
2381 if (err == noErr)
2383 #if TARGET_API_MAC_CARBON
2384 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2385 #else
2386 *fss = *(FSSpec *)(*(desc.dataHandle));
2387 #endif
2388 AEDisposeDesc (&desc);
2390 return err;
2393 static int
2394 image_load_qt_1 (f, img, type, fss, dh)
2395 struct frame *f;
2396 struct image *img;
2397 OSType type;
2398 FSSpec *fss;
2399 Handle dh;
2401 OSErr err;
2402 GraphicsImportComponent gi;
2403 Rect rect;
2404 int width, height;
2405 ImageDescriptionHandle desc_handle;
2406 short draw_all_pixels;
2407 Lisp_Object specified_bg;
2408 XColor color;
2409 XImagePtr ximg;
2410 RGBColor bg_color;
2412 err = OpenADefaultComponent (GraphicsImporterComponentType,
2413 type, &gi);
2414 if (err != noErr)
2416 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2417 return 0;
2419 if (dh == NULL)
2421 /* read from file system spec */
2422 err = GraphicsImportSetDataFile (gi, fss);
2423 if (err != noErr)
2425 image_error ("Cannot set fsspec to graphics importer for '%s'",
2426 img->spec, Qnil);
2427 goto error;
2430 else
2432 /* read from data handle */
2433 err = GraphicsImportSetDataHandle (gi, dh);
2434 if (err != noErr)
2436 image_error ("Cannot set data handle to graphics importer for `%s'",
2437 img->spec, Qnil);
2438 goto error;
2441 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2442 if (err != noErr || desc_handle == NULL)
2444 image_error ("Error reading `%s'", img->spec, Qnil);
2445 goto error;
2447 width = img->width = (*desc_handle)->width;
2448 height = img->height = (*desc_handle)->height;
2449 DisposeHandle ((Handle)desc_handle);
2451 if (!check_image_size (f, width, height))
2453 image_error ("Invalid image size", Qnil, Qnil);
2454 goto error;
2457 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2458 #if 0
2459 /* Don't check the error code here. It may have an undocumented
2460 value -32766. */
2461 if (err != noErr)
2463 image_error ("Error reading `%s'", img->spec, Qnil);
2464 goto error;
2466 #endif
2467 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2469 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2470 if (!STRINGP (specified_bg) ||
2471 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2473 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2474 color.red = RED16_FROM_ULONG (color.pixel);
2475 color.green = GREEN16_FROM_ULONG (color.pixel);
2476 color.blue = BLUE16_FROM_ULONG (color.pixel);
2480 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2481 goto error;
2482 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2484 CGrafPtr old_port;
2485 GDHandle old_gdh;
2487 GetGWorld (&old_port, &old_gdh);
2488 SetGWorld (ximg, NULL);
2489 bg_color.red = color.red;
2490 bg_color.green = color.green;
2491 bg_color.blue = color.blue;
2492 RGBBackColor (&bg_color);
2493 #if TARGET_API_MAC_CARBON
2494 GetPortBounds (ximg, &rect);
2495 EraseRect (&rect);
2496 #else
2497 EraseRect (&(ximg->portRect));
2498 #endif
2499 SetGWorld (old_port, old_gdh);
2501 GraphicsImportSetGWorld (gi, ximg, NULL);
2502 GraphicsImportDraw (gi);
2503 CloseComponent (gi);
2505 /* Maybe fill in the background field while we have ximg handy. */
2506 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2507 IMAGE_BACKGROUND (img, f, ximg);
2509 /* Put the image into the pixmap. */
2510 x_put_x_image (f, ximg, img->pixmap, width, height);
2511 x_destroy_x_image (ximg);
2512 return 1;
2514 error:
2515 CloseComponent (gi);
2516 return 0;
2520 /* Load an image using the QuickTime Graphics Importer.
2521 Note: The alpha channel does not work for PNG images. */
2522 static int
2523 image_load_quicktime (f, img, type)
2524 struct frame *f;
2525 struct image *img;
2526 OSType type;
2528 Lisp_Object specified_file;
2529 Lisp_Object specified_data;
2530 OSErr err;
2532 specified_file = image_spec_value (img->spec, QCfile, NULL);
2533 specified_data = image_spec_value (img->spec, QCdata, NULL);
2535 if (NILP (specified_data))
2537 /* Read from a file */
2538 Lisp_Object file;
2539 FSSpec fss;
2541 err = find_image_fsspec (specified_file, &file, &fss);
2542 if (err != noErr)
2544 if (err == fnfErr)
2545 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2546 else
2547 image_error ("Cannot open `%s'", file, Qnil);
2548 return 0;
2550 return image_load_qt_1 (f, img, type, &fss, NULL);
2552 else
2554 /* Memory source! */
2555 int success_p;
2556 Handle dh;
2558 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2559 if (err != noErr)
2561 image_error ("Cannot allocate data handle for `%s'",
2562 img->spec, Qnil);
2563 return 0;
2565 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2566 DisposeHandle (dh);
2567 return success_p;
2572 #ifdef MAC_OSX
2573 /* Load a PNG/JPEG image using Quartz 2D decoding routines.
2574 CGImageCreateWithPNGDataProvider is provided after Mac OS X 10.2.
2575 So don't use this function directly but determine at runtime
2576 whether it exists. */
2577 typedef CGImageRef (*CGImageCreateWithPNGDataProviderProcType)
2578 (CGDataProviderRef, const float [], bool, CGColorRenderingIntent);
2579 static CGImageCreateWithPNGDataProviderProcType MyCGImageCreateWithPNGDataProvider;
2582 static void
2583 init_image_func_pointer ()
2585 if (NSIsSymbolNameDefined ("_CGImageCreateWithPNGDataProvider"))
2587 MyCGImageCreateWithPNGDataProvider
2588 = (CGImageCreateWithPNGDataProviderProcType)
2589 NSAddressOfSymbol (NSLookupAndBindSymbol
2590 ("_CGImageCreateWithPNGDataProvider"));
2592 else
2593 MyCGImageCreateWithPNGDataProvider = NULL;
2597 static int
2598 image_load_quartz2d (f, img, png_p)
2599 struct frame *f;
2600 struct image *img;
2601 int png_p;
2603 Lisp_Object file, specified_file;
2604 Lisp_Object specified_data, specified_bg;
2605 struct gcpro gcpro1;
2606 CGDataProviderRef source;
2607 CGImageRef image;
2608 int width, height;
2609 XColor color;
2610 XImagePtr ximg = NULL;
2611 CGContextRef context;
2612 CGRect rectangle;
2614 /* Open the file. */
2615 specified_file = image_spec_value (img->spec, QCfile, NULL);
2616 specified_data = image_spec_value (img->spec, QCdata, NULL);
2618 file = Qnil;
2619 GCPRO1 (file);
2621 if (NILP (specified_data))
2623 CFStringRef path;
2624 CFURLRef url;
2626 file = x_find_image_file (specified_file);
2627 if (!STRINGP (file))
2629 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2630 UNGCPRO;
2631 return 0;
2633 path = cfstring_create_with_string (file);
2634 url = CFURLCreateWithFileSystemPath (NULL, path,
2635 kCFURLPOSIXPathStyle, 0);
2636 CFRelease (path);
2637 source = CGDataProviderCreateWithURL (url);
2638 CFRelease (url);
2640 else
2641 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
2642 SBYTES (specified_data), NULL);
2644 if (png_p)
2645 image = (*MyCGImageCreateWithPNGDataProvider) (source, NULL, FALSE,
2646 kCGRenderingIntentDefault);
2647 else
2648 image = CGImageCreateWithJPEGDataProvider (source, NULL, FALSE,
2649 kCGRenderingIntentDefault);
2651 CGDataProviderRelease (source);
2652 if (image == NULL)
2654 UNGCPRO;
2655 image_error ("Error reading image `%s'", img->spec, Qnil);
2656 return 0;
2658 width = img->width = CGImageGetWidth (image);
2659 height = img->height = CGImageGetHeight (image);
2661 if (!check_image_size (f, width, height))
2663 CGImageRelease (image);
2664 UNGCPRO;
2665 image_error ("Invalid image size", Qnil, Qnil);
2666 return 0;
2669 if (png_p)
2671 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2672 if (!STRINGP (specified_bg) ||
2673 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2675 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2676 color.red = RED16_FROM_ULONG (color.pixel);
2677 color.green = GREEN16_FROM_ULONG (color.pixel);
2678 color.blue = BLUE16_FROM_ULONG (color.pixel);
2682 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2684 CGImageRelease (image);
2685 UNGCPRO;
2686 return 0;
2688 rectangle = CGRectMake (0, 0, width, height);
2689 QDBeginCGContext (ximg, &context);
2690 if (png_p)
2692 CGContextSetRGBFillColor (context, color.red / 65535.0,
2693 color.green / 65535.0,
2694 color.blue / 65535.0, 1.0);
2695 CGContextFillRect (context, rectangle);
2697 CGContextDrawImage (context, rectangle, image);
2698 QDEndCGContext (ximg, &context);
2699 CGImageRelease (image);
2701 /* Maybe fill in the background field while we have ximg handy. */
2702 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2703 IMAGE_BACKGROUND (img, f, ximg);
2705 /* Put the image into the pixmap. */
2706 x_put_x_image (f, ximg, img->pixmap, width, height);
2707 x_destroy_x_image (ximg);
2708 UNGCPRO;
2709 return 1;
2711 #endif
2713 #endif /* MAC_OS */
2716 /***********************************************************************
2717 XBM images
2718 ***********************************************************************/
2720 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
2721 static int xbm_load P_ ((struct frame *f, struct image *img));
2722 static int xbm_load_image P_ ((struct frame *f, struct image *img,
2723 unsigned char *, unsigned char *));
2724 static int xbm_image_p P_ ((Lisp_Object object));
2725 static int xbm_read_bitmap_data P_ ((struct frame *f,
2726 unsigned char *, unsigned char *,
2727 int *, int *, unsigned char **));
2728 static int xbm_file_p P_ ((Lisp_Object));
2731 /* Indices of image specification fields in xbm_format, below. */
2733 enum xbm_keyword_index
2735 XBM_TYPE,
2736 XBM_FILE,
2737 XBM_WIDTH,
2738 XBM_HEIGHT,
2739 XBM_DATA,
2740 XBM_FOREGROUND,
2741 XBM_BACKGROUND,
2742 XBM_ASCENT,
2743 XBM_MARGIN,
2744 XBM_RELIEF,
2745 XBM_ALGORITHM,
2746 XBM_HEURISTIC_MASK,
2747 XBM_MASK,
2748 XBM_LAST
2751 /* Vector of image_keyword structures describing the format
2752 of valid XBM image specifications. */
2754 static struct image_keyword xbm_format[XBM_LAST] =
2756 {":type", IMAGE_SYMBOL_VALUE, 1},
2757 {":file", IMAGE_STRING_VALUE, 0},
2758 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2759 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
2760 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2761 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
2762 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
2763 {":ascent", IMAGE_ASCENT_VALUE, 0},
2764 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
2765 {":relief", IMAGE_INTEGER_VALUE, 0},
2766 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2767 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
2768 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
2771 /* Structure describing the image type XBM. */
2773 static struct image_type xbm_type =
2775 &Qxbm,
2776 xbm_image_p,
2777 xbm_load,
2778 x_clear_image,
2779 NULL
2782 /* Tokens returned from xbm_scan. */
2784 enum xbm_token
2786 XBM_TK_IDENT = 256,
2787 XBM_TK_NUMBER
2791 /* Return non-zero if OBJECT is a valid XBM-type image specification.
2792 A valid specification is a list starting with the symbol `image'
2793 The rest of the list is a property list which must contain an
2794 entry `:type xbm..
2796 If the specification specifies a file to load, it must contain
2797 an entry `:file FILENAME' where FILENAME is a string.
2799 If the specification is for a bitmap loaded from memory it must
2800 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
2801 WIDTH and HEIGHT are integers > 0. DATA may be:
2803 1. a string large enough to hold the bitmap data, i.e. it must
2804 have a size >= (WIDTH + 7) / 8 * HEIGHT
2806 2. a bool-vector of size >= WIDTH * HEIGHT
2808 3. a vector of strings or bool-vectors, one for each line of the
2809 bitmap.
2811 4. A string containing an in-memory XBM file. WIDTH and HEIGHT
2812 may not be specified in this case because they are defined in the
2813 XBM file.
2815 Both the file and data forms may contain the additional entries
2816 `:background COLOR' and `:foreground COLOR'. If not present,
2817 foreground and background of the frame on which the image is
2818 displayed is used. */
2820 static int
2821 xbm_image_p (object)
2822 Lisp_Object object;
2824 struct image_keyword kw[XBM_LAST];
2826 bcopy (xbm_format, kw, sizeof kw);
2827 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
2828 return 0;
2830 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
2832 if (kw[XBM_FILE].count)
2834 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
2835 return 0;
2837 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
2839 /* In-memory XBM file. */
2840 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
2841 return 0;
2843 else
2845 Lisp_Object data;
2846 int width, height;
2848 /* Entries for `:width', `:height' and `:data' must be present. */
2849 if (!kw[XBM_WIDTH].count
2850 || !kw[XBM_HEIGHT].count
2851 || !kw[XBM_DATA].count)
2852 return 0;
2854 data = kw[XBM_DATA].value;
2855 width = XFASTINT (kw[XBM_WIDTH].value);
2856 height = XFASTINT (kw[XBM_HEIGHT].value);
2858 /* Check type of data, and width and height against contents of
2859 data. */
2860 if (VECTORP (data))
2862 int i;
2864 /* Number of elements of the vector must be >= height. */
2865 if (XVECTOR (data)->size < height)
2866 return 0;
2868 /* Each string or bool-vector in data must be large enough
2869 for one line of the image. */
2870 for (i = 0; i < height; ++i)
2872 Lisp_Object elt = XVECTOR (data)->contents[i];
2874 if (STRINGP (elt))
2876 if (SCHARS (elt)
2877 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
2878 return 0;
2880 else if (BOOL_VECTOR_P (elt))
2882 if (XBOOL_VECTOR (elt)->size < width)
2883 return 0;
2885 else
2886 return 0;
2889 else if (STRINGP (data))
2891 if (SCHARS (data)
2892 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
2893 return 0;
2895 else if (BOOL_VECTOR_P (data))
2897 if (XBOOL_VECTOR (data)->size < width * height)
2898 return 0;
2900 else
2901 return 0;
2904 return 1;
2908 /* Scan a bitmap file. FP is the stream to read from. Value is
2909 either an enumerator from enum xbm_token, or a character for a
2910 single-character token, or 0 at end of file. If scanning an
2911 identifier, store the lexeme of the identifier in SVAL. If
2912 scanning a number, store its value in *IVAL. */
2914 static int
2915 xbm_scan (s, end, sval, ival)
2916 unsigned char **s, *end;
2917 char *sval;
2918 int *ival;
2920 unsigned int c;
2922 loop:
2924 /* Skip white space. */
2925 while (*s < end && (c = *(*s)++, isspace (c)))
2928 if (*s >= end)
2929 c = 0;
2930 else if (isdigit (c))
2932 int value = 0, digit;
2934 if (c == '0' && *s < end)
2936 c = *(*s)++;
2937 if (c == 'x' || c == 'X')
2939 while (*s < end)
2941 c = *(*s)++;
2942 if (isdigit (c))
2943 digit = c - '0';
2944 else if (c >= 'a' && c <= 'f')
2945 digit = c - 'a' + 10;
2946 else if (c >= 'A' && c <= 'F')
2947 digit = c - 'A' + 10;
2948 else
2949 break;
2950 value = 16 * value + digit;
2953 else if (isdigit (c))
2955 value = c - '0';
2956 while (*s < end
2957 && (c = *(*s)++, isdigit (c)))
2958 value = 8 * value + c - '0';
2961 else
2963 value = c - '0';
2964 while (*s < end
2965 && (c = *(*s)++, isdigit (c)))
2966 value = 10 * value + c - '0';
2969 if (*s < end)
2970 *s = *s - 1;
2971 *ival = value;
2972 c = XBM_TK_NUMBER;
2974 else if (isalpha (c) || c == '_')
2976 *sval++ = c;
2977 while (*s < end
2978 && (c = *(*s)++, (isalnum (c) || c == '_')))
2979 *sval++ = c;
2980 *sval = 0;
2981 if (*s < end)
2982 *s = *s - 1;
2983 c = XBM_TK_IDENT;
2985 else if (c == '/' && **s == '*')
2987 /* C-style comment. */
2988 ++*s;
2989 while (**s && (**s != '*' || *(*s + 1) != '/'))
2990 ++*s;
2991 if (**s)
2993 *s += 2;
2994 goto loop;
2998 return c;
3001 #ifdef HAVE_NTGUI
3003 /* Create a Windows bitmap from X bitmap data. */
3004 static HBITMAP
3005 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
3007 static unsigned char swap_nibble[16]
3008 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3009 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3010 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3011 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3012 int i, j, w1, w2;
3013 unsigned char *bits, *p;
3014 HBITMAP bmp;
3016 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
3017 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3018 bits = (unsigned char *) alloca (height * w2);
3019 bzero (bits, height * w2);
3020 for (i = 0; i < height; i++)
3022 p = bits + i*w2;
3023 for (j = 0; j < w1; j++)
3025 /* Bitswap XBM bytes to match how Windows does things. */
3026 unsigned char c = *data++;
3027 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
3028 | (swap_nibble[(c>>4) & 0xf]));
3031 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
3033 return bmp;
3036 static void convert_mono_to_color_image (f, img, foreground, background)
3037 struct frame *f;
3038 struct image *img;
3039 COLORREF foreground, background;
3041 HDC hdc, old_img_dc, new_img_dc;
3042 HGDIOBJ old_prev, new_prev;
3043 HBITMAP new_pixmap;
3045 hdc = get_frame_dc (f);
3046 old_img_dc = CreateCompatibleDC (hdc);
3047 new_img_dc = CreateCompatibleDC (hdc);
3048 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3049 release_frame_dc (f, hdc);
3050 old_prev = SelectObject (old_img_dc, img->pixmap);
3051 new_prev = SelectObject (new_img_dc, new_pixmap);
3052 SetTextColor (new_img_dc, foreground);
3053 SetBkColor (new_img_dc, background);
3055 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3056 0, 0, SRCCOPY);
3058 SelectObject (old_img_dc, old_prev);
3059 SelectObject (new_img_dc, new_prev);
3060 DeleteDC (old_img_dc);
3061 DeleteDC (new_img_dc);
3062 DeleteObject (img->pixmap);
3063 if (new_pixmap == 0)
3064 fprintf (stderr, "Failed to convert image to color.\n");
3065 else
3066 img->pixmap = new_pixmap;
3069 #define XBM_BIT_SHUFFLE(b) (~(b))
3071 #else
3073 #define XBM_BIT_SHUFFLE(b) (b)
3075 #endif /* HAVE_NTGUI */
3078 static void
3079 Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
3080 struct frame *f;
3081 struct image *img;
3082 char *data;
3083 RGB_PIXEL_COLOR fg, bg;
3084 int non_default_colors;
3086 #ifdef HAVE_NTGUI
3087 img->pixmap
3088 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3090 /* If colors were specified, transfer the bitmap to a color one. */
3091 if (non_default_colors)
3092 convert_mono_to_color_image (f, img, fg, bg);
3093 #else
3094 img->pixmap
3095 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3096 FRAME_X_WINDOW (f),
3097 data,
3098 img->width, img->height,
3099 fg, bg,
3100 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3101 #endif /* HAVE_NTGUI */
3106 /* Replacement for XReadBitmapFileData which isn't available under old
3107 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3108 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3109 the image. Return in *DATA the bitmap data allocated with xmalloc.
3110 Value is non-zero if successful. DATA null means just test if
3111 CONTENTS looks like an in-memory XBM file. */
3113 static int
3114 xbm_read_bitmap_data (f, contents, end, width, height, data)
3115 struct frame *f;
3116 unsigned char *contents, *end;
3117 int *width, *height;
3118 unsigned char **data;
3120 unsigned char *s = contents;
3121 char buffer[BUFSIZ];
3122 int padding_p = 0;
3123 int v10 = 0;
3124 int bytes_per_line, i, nbytes;
3125 unsigned char *p;
3126 int value;
3127 int LA1;
3129 #define match() \
3130 LA1 = xbm_scan (&s, end, buffer, &value)
3132 #define expect(TOKEN) \
3133 if (LA1 != (TOKEN)) \
3134 goto failure; \
3135 else \
3136 match ()
3138 #define expect_ident(IDENT) \
3139 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3140 match (); \
3141 else \
3142 goto failure
3144 *width = *height = -1;
3145 if (data)
3146 *data = NULL;
3147 LA1 = xbm_scan (&s, end, buffer, &value);
3149 /* Parse defines for width, height and hot-spots. */
3150 while (LA1 == '#')
3152 match ();
3153 expect_ident ("define");
3154 expect (XBM_TK_IDENT);
3156 if (LA1 == XBM_TK_NUMBER);
3158 char *p = strrchr (buffer, '_');
3159 p = p ? p + 1 : buffer;
3160 if (strcmp (p, "width") == 0)
3161 *width = value;
3162 else if (strcmp (p, "height") == 0)
3163 *height = value;
3165 expect (XBM_TK_NUMBER);
3168 if (!check_image_size (f, *width, *height))
3169 goto failure;
3170 else if (data == NULL)
3171 goto success;
3173 /* Parse bits. Must start with `static'. */
3174 expect_ident ("static");
3175 if (LA1 == XBM_TK_IDENT)
3177 if (strcmp (buffer, "unsigned") == 0)
3179 match ();
3180 expect_ident ("char");
3182 else if (strcmp (buffer, "short") == 0)
3184 match ();
3185 v10 = 1;
3186 if (*width % 16 && *width % 16 < 9)
3187 padding_p = 1;
3189 else if (strcmp (buffer, "char") == 0)
3190 match ();
3191 else
3192 goto failure;
3194 else
3195 goto failure;
3197 expect (XBM_TK_IDENT);
3198 expect ('[');
3199 expect (']');
3200 expect ('=');
3201 expect ('{');
3203 bytes_per_line = (*width + 7) / 8 + padding_p;
3204 nbytes = bytes_per_line * *height;
3205 p = *data = (unsigned char *) xmalloc (nbytes);
3207 if (v10)
3209 for (i = 0; i < nbytes; i += 2)
3211 int val = value;
3212 expect (XBM_TK_NUMBER);
3214 *p++ = XBM_BIT_SHUFFLE (val);
3215 if (!padding_p || ((i + 2) % bytes_per_line))
3216 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3218 if (LA1 == ',' || LA1 == '}')
3219 match ();
3220 else
3221 goto failure;
3224 else
3226 for (i = 0; i < nbytes; ++i)
3228 int val = value;
3229 expect (XBM_TK_NUMBER);
3231 *p++ = XBM_BIT_SHUFFLE (val);
3233 if (LA1 == ',' || LA1 == '}')
3234 match ();
3235 else
3236 goto failure;
3240 success:
3241 return 1;
3243 failure:
3245 if (data && *data)
3247 xfree (*data);
3248 *data = NULL;
3250 return 0;
3252 #undef match
3253 #undef expect
3254 #undef expect_ident
3258 /* Load XBM image IMG which will be displayed on frame F from buffer
3259 CONTENTS. END is the end of the buffer. Value is non-zero if
3260 successful. */
3262 static int
3263 xbm_load_image (f, img, contents, end)
3264 struct frame *f;
3265 struct image *img;
3266 unsigned char *contents, *end;
3268 int rc;
3269 unsigned char *data;
3270 int success_p = 0;
3272 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3273 if (rc)
3275 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3276 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3277 int non_default_colors = 0;
3278 Lisp_Object value;
3280 xassert (img->width > 0 && img->height > 0);
3282 /* Get foreground and background colors, maybe allocate colors. */
3283 value = image_spec_value (img->spec, QCforeground, NULL);
3284 if (!NILP (value))
3286 foreground = x_alloc_image_color (f, img, value, foreground);
3287 non_default_colors = 1;
3289 value = image_spec_value (img->spec, QCbackground, NULL);
3290 if (!NILP (value))
3292 background = x_alloc_image_color (f, img, value, background);
3293 img->background = background;
3294 img->background_valid = 1;
3295 non_default_colors = 1;
3298 Create_Pixmap_From_Bitmap_Data (f, img, data,
3299 foreground, background,
3300 non_default_colors);
3301 xfree (data);
3303 if (img->pixmap == NO_PIXMAP)
3305 x_clear_image (f, img);
3306 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3308 else
3309 success_p = 1;
3311 else
3312 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3314 return success_p;
3318 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3320 static int
3321 xbm_file_p (data)
3322 Lisp_Object data;
3324 int w, h;
3325 return (STRINGP (data)
3326 && xbm_read_bitmap_data (NULL, SDATA (data),
3327 (SDATA (data)
3328 + SBYTES (data)),
3329 &w, &h, NULL));
3333 /* Fill image IMG which is used on frame F with pixmap data. Value is
3334 non-zero if successful. */
3336 static int
3337 xbm_load (f, img)
3338 struct frame *f;
3339 struct image *img;
3341 int success_p = 0;
3342 Lisp_Object file_name;
3344 xassert (xbm_image_p (img->spec));
3346 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3347 file_name = image_spec_value (img->spec, QCfile, NULL);
3348 if (STRINGP (file_name))
3350 Lisp_Object file;
3351 unsigned char *contents;
3352 int size;
3353 struct gcpro gcpro1;
3355 file = x_find_image_file (file_name);
3356 GCPRO1 (file);
3357 if (!STRINGP (file))
3359 image_error ("Cannot find image file `%s'", file_name, Qnil);
3360 UNGCPRO;
3361 return 0;
3364 contents = slurp_file (SDATA (file), &size);
3365 if (contents == NULL)
3367 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3368 UNGCPRO;
3369 return 0;
3372 success_p = xbm_load_image (f, img, contents, contents + size);
3373 UNGCPRO;
3375 else
3377 struct image_keyword fmt[XBM_LAST];
3378 Lisp_Object data;
3379 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3380 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3381 int non_default_colors = 0;
3382 char *bits;
3383 int parsed_p;
3384 int in_memory_file_p = 0;
3386 /* See if data looks like an in-memory XBM file. */
3387 data = image_spec_value (img->spec, QCdata, NULL);
3388 in_memory_file_p = xbm_file_p (data);
3390 /* Parse the image specification. */
3391 bcopy (xbm_format, fmt, sizeof fmt);
3392 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3393 xassert (parsed_p);
3395 /* Get specified width, and height. */
3396 if (!in_memory_file_p)
3398 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3399 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3400 xassert (img->width > 0 && img->height > 0);
3403 /* Get foreground and background colors, maybe allocate colors. */
3404 if (fmt[XBM_FOREGROUND].count
3405 && STRINGP (fmt[XBM_FOREGROUND].value))
3407 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3408 foreground);
3409 non_default_colors = 1;
3412 if (fmt[XBM_BACKGROUND].count
3413 && STRINGP (fmt[XBM_BACKGROUND].value))
3415 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3416 background);
3417 non_default_colors = 1;
3420 if (in_memory_file_p)
3421 success_p = xbm_load_image (f, img, SDATA (data),
3422 (SDATA (data)
3423 + SBYTES (data)));
3424 else
3426 if (VECTORP (data))
3428 int i;
3429 char *p;
3430 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3432 p = bits = (char *) alloca (nbytes * img->height);
3433 for (i = 0; i < img->height; ++i, p += nbytes)
3435 Lisp_Object line = XVECTOR (data)->contents[i];
3436 if (STRINGP (line))
3437 bcopy (SDATA (line), p, nbytes);
3438 else
3439 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3442 else if (STRINGP (data))
3443 bits = SDATA (data);
3444 else
3445 bits = XBOOL_VECTOR (data)->data;
3447 /* Create the pixmap. */
3449 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3450 foreground, background,
3451 non_default_colors);
3452 if (img->pixmap)
3453 success_p = 1;
3454 else
3456 image_error ("Unable to create pixmap for XBM image `%s'",
3457 img->spec, Qnil);
3458 x_clear_image (f, img);
3463 return success_p;
3468 /***********************************************************************
3469 XPM images
3470 ***********************************************************************/
3472 #if defined (HAVE_XPM) || defined (MAC_OS)
3474 static int xpm_image_p P_ ((Lisp_Object object));
3475 static int xpm_load P_ ((struct frame *f, struct image *img));
3476 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3478 #endif /* HAVE_XPM || MAC_OS */
3480 #ifdef HAVE_XPM
3481 #ifdef HAVE_NTGUI
3482 /* Indicate to xpm.h that we don't have Xlib. */
3483 #define FOR_MSW
3484 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3485 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3486 #define XColor xpm_XColor
3487 #define XImage xpm_XImage
3488 #define Display xpm_Display
3489 #define PIXEL_ALREADY_TYPEDEFED
3490 #include "X11/xpm.h"
3491 #undef FOR_MSW
3492 #undef XColor
3493 #undef XImage
3494 #undef Display
3495 #undef PIXEL_ALREADY_TYPEDEFED
3496 #else
3497 #include "X11/xpm.h"
3498 #endif /* HAVE_NTGUI */
3499 #endif /* HAVE_XPM */
3501 #if defined (HAVE_XPM) || defined (MAC_OS)
3502 /* The symbol `xpm' identifying XPM-format images. */
3504 Lisp_Object Qxpm;
3506 /* Indices of image specification fields in xpm_format, below. */
3508 enum xpm_keyword_index
3510 XPM_TYPE,
3511 XPM_FILE,
3512 XPM_DATA,
3513 XPM_ASCENT,
3514 XPM_MARGIN,
3515 XPM_RELIEF,
3516 XPM_ALGORITHM,
3517 XPM_HEURISTIC_MASK,
3518 XPM_MASK,
3519 XPM_COLOR_SYMBOLS,
3520 XPM_BACKGROUND,
3521 XPM_LAST
3524 /* Vector of image_keyword structures describing the format
3525 of valid XPM image specifications. */
3527 static struct image_keyword xpm_format[XPM_LAST] =
3529 {":type", IMAGE_SYMBOL_VALUE, 1},
3530 {":file", IMAGE_STRING_VALUE, 0},
3531 {":data", IMAGE_STRING_VALUE, 0},
3532 {":ascent", IMAGE_ASCENT_VALUE, 0},
3533 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3534 {":relief", IMAGE_INTEGER_VALUE, 0},
3535 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3536 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3537 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3538 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3539 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3542 /* Structure describing the image type XPM. */
3544 static struct image_type xpm_type =
3546 &Qxpm,
3547 xpm_image_p,
3548 xpm_load,
3549 x_clear_image,
3550 NULL
3553 #ifdef HAVE_X_WINDOWS
3555 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3556 functions for allocating image colors. Our own functions handle
3557 color allocation failures more gracefully than the ones on the XPM
3558 lib. */
3560 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3561 #define ALLOC_XPM_COLORS
3562 #endif
3563 #endif /* HAVE_X_WINDOWS */
3565 #ifdef ALLOC_XPM_COLORS
3567 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3568 static void xpm_free_color_cache P_ ((void));
3569 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3570 static int xpm_color_bucket P_ ((char *));
3571 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3572 XColor *, int));
3574 /* An entry in a hash table used to cache color definitions of named
3575 colors. This cache is necessary to speed up XPM image loading in
3576 case we do color allocations ourselves. Without it, we would need
3577 a call to XParseColor per pixel in the image. */
3579 struct xpm_cached_color
3581 /* Next in collision chain. */
3582 struct xpm_cached_color *next;
3584 /* Color definition (RGB and pixel color). */
3585 XColor color;
3587 /* Color name. */
3588 char name[1];
3591 /* The hash table used for the color cache, and its bucket vector
3592 size. */
3594 #define XPM_COLOR_CACHE_BUCKETS 1001
3595 struct xpm_cached_color **xpm_color_cache;
3597 /* Initialize the color cache. */
3599 static void
3600 xpm_init_color_cache (f, attrs)
3601 struct frame *f;
3602 XpmAttributes *attrs;
3604 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3605 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3606 memset (xpm_color_cache, 0, nbytes);
3607 init_color_table ();
3609 if (attrs->valuemask & XpmColorSymbols)
3611 int i;
3612 XColor color;
3614 for (i = 0; i < attrs->numsymbols; ++i)
3615 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3616 attrs->colorsymbols[i].value, &color))
3618 color.pixel = lookup_rgb_color (f, color.red, color.green,
3619 color.blue);
3620 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
3625 /* Free the color cache. */
3627 static void
3628 xpm_free_color_cache ()
3630 struct xpm_cached_color *p, *next;
3631 int i;
3633 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
3634 for (p = xpm_color_cache[i]; p; p = next)
3636 next = p->next;
3637 xfree (p);
3640 xfree (xpm_color_cache);
3641 xpm_color_cache = NULL;
3642 free_color_table ();
3645 /* Return the bucket index for color named COLOR_NAME in the color
3646 cache. */
3648 static int
3649 xpm_color_bucket (color_name)
3650 char *color_name;
3652 unsigned h = 0;
3653 char *s;
3655 for (s = color_name; *s; ++s)
3656 h = (h << 2) ^ *s;
3657 return h %= XPM_COLOR_CACHE_BUCKETS;
3661 /* On frame F, cache values COLOR for color with name COLOR_NAME.
3662 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
3663 entry added. */
3665 static struct xpm_cached_color *
3666 xpm_cache_color (f, color_name, color, bucket)
3667 struct frame *f;
3668 char *color_name;
3669 XColor *color;
3670 int bucket;
3672 size_t nbytes;
3673 struct xpm_cached_color *p;
3675 if (bucket < 0)
3676 bucket = xpm_color_bucket (color_name);
3678 nbytes = sizeof *p + strlen (color_name);
3679 p = (struct xpm_cached_color *) xmalloc (nbytes);
3680 strcpy (p->name, color_name);
3681 p->color = *color;
3682 p->next = xpm_color_cache[bucket];
3683 xpm_color_cache[bucket] = p;
3684 return p;
3687 /* Look up color COLOR_NAME for frame F in the color cache. If found,
3688 return the cached definition in *COLOR. Otherwise, make a new
3689 entry in the cache and allocate the color. Value is zero if color
3690 allocation failed. */
3692 static int
3693 xpm_lookup_color (f, color_name, color)
3694 struct frame *f;
3695 char *color_name;
3696 XColor *color;
3698 struct xpm_cached_color *p;
3699 int h = xpm_color_bucket (color_name);
3701 for (p = xpm_color_cache[h]; p; p = p->next)
3702 if (strcmp (p->name, color_name) == 0)
3703 break;
3705 if (p != NULL)
3706 *color = p->color;
3707 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
3708 color_name, color))
3710 color->pixel = lookup_rgb_color (f, color->red, color->green,
3711 color->blue);
3712 p = xpm_cache_color (f, color_name, color, h);
3714 /* You get `opaque' at least from ImageMagick converting pbm to xpm
3715 with transparency, and it's useful. */
3716 else if (strcmp ("opaque", color_name) == 0)
3718 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
3719 color->pixel = FRAME_FOREGROUND_PIXEL (f);
3720 p = xpm_cache_color (f, color_name, color, h);
3723 return p != NULL;
3727 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
3728 CLOSURE is a pointer to the frame on which we allocate the
3729 color. Return in *COLOR the allocated color. Value is non-zero
3730 if successful. */
3732 static int
3733 xpm_alloc_color (dpy, cmap, color_name, color, closure)
3734 Display *dpy;
3735 Colormap cmap;
3736 char *color_name;
3737 XColor *color;
3738 void *closure;
3740 return xpm_lookup_color ((struct frame *) closure, color_name, color);
3744 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
3745 is a pointer to the frame on which we allocate the color. Value is
3746 non-zero if successful. */
3748 static int
3749 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
3750 Display *dpy;
3751 Colormap cmap;
3752 Pixel *pixels;
3753 int npixels;
3754 void *closure;
3756 return 1;
3759 #endif /* ALLOC_XPM_COLORS */
3762 #ifdef HAVE_NTGUI
3764 /* XPM library details. */
3766 DEF_IMGLIB_FN (XpmFreeAttributes);
3767 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
3768 DEF_IMGLIB_FN (XpmReadFileToImage);
3769 DEF_IMGLIB_FN (XImageFree);
3771 static int
3772 init_xpm_functions (Lisp_Object libraries)
3774 HMODULE library;
3776 if (!(library = w32_delayed_load (libraries, Qxpm)))
3777 return 0;
3779 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
3780 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
3781 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
3782 LOAD_IMGLIB_FN (library, XImageFree);
3783 return 1;
3786 #endif /* HAVE_NTGUI */
3789 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
3790 for XPM images. Such a list must consist of conses whose car and
3791 cdr are strings. */
3793 static int
3794 xpm_valid_color_symbols_p (color_symbols)
3795 Lisp_Object color_symbols;
3797 while (CONSP (color_symbols))
3799 Lisp_Object sym = XCAR (color_symbols);
3800 if (!CONSP (sym)
3801 || !STRINGP (XCAR (sym))
3802 || !STRINGP (XCDR (sym)))
3803 break;
3804 color_symbols = XCDR (color_symbols);
3807 return NILP (color_symbols);
3811 /* Value is non-zero if OBJECT is a valid XPM image specification. */
3813 static int
3814 xpm_image_p (object)
3815 Lisp_Object object;
3817 struct image_keyword fmt[XPM_LAST];
3818 bcopy (xpm_format, fmt, sizeof fmt);
3819 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
3820 /* Either `:file' or `:data' must be present. */
3821 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
3822 /* Either no `:color-symbols' or it's a list of conses
3823 whose car and cdr are strings. */
3824 && (fmt[XPM_COLOR_SYMBOLS].count == 0
3825 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
3828 #endif /* HAVE_XPM || MAC_OS */
3830 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
3832 x_create_bitmap_from_xpm_data (f, bits)
3833 struct frame *f;
3834 char **bits;
3836 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3837 int id, rc;
3838 XpmAttributes attrs;
3839 Pixmap bitmap, mask;
3841 bzero (&attrs, sizeof attrs);
3843 attrs.visual = FRAME_X_VISUAL (f);
3844 attrs.colormap = FRAME_X_COLORMAP (f);
3845 attrs.valuemask |= XpmVisual;
3846 attrs.valuemask |= XpmColormap;
3848 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3849 bits, &bitmap, &mask, &attrs);
3850 if (rc != XpmSuccess)
3852 XpmFreeAttributes (&attrs);
3853 return -1;
3856 id = x_allocate_bitmap_record (f);
3857 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
3858 dpyinfo->bitmaps[id - 1].have_mask = 1;
3859 dpyinfo->bitmaps[id - 1].mask = mask;
3860 dpyinfo->bitmaps[id - 1].file = NULL;
3861 dpyinfo->bitmaps[id - 1].height = attrs.height;
3862 dpyinfo->bitmaps[id - 1].width = attrs.width;
3863 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
3864 dpyinfo->bitmaps[id - 1].refcount = 1;
3866 XpmFreeAttributes (&attrs);
3867 return id;
3869 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
3871 /* Load image IMG which will be displayed on frame F. Value is
3872 non-zero if successful. */
3874 #ifdef HAVE_XPM
3876 static int
3877 xpm_load (f, img)
3878 struct frame *f;
3879 struct image *img;
3881 int rc;
3882 XpmAttributes attrs;
3883 Lisp_Object specified_file, color_symbols;
3884 #ifdef HAVE_NTGUI
3885 HDC hdc;
3886 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
3887 #endif /* HAVE_NTGUI */
3889 /* Configure the XPM lib. Use the visual of frame F. Allocate
3890 close colors. Return colors allocated. */
3891 bzero (&attrs, sizeof attrs);
3893 #ifndef HAVE_NTGUI
3894 attrs.visual = FRAME_X_VISUAL (f);
3895 attrs.colormap = FRAME_X_COLORMAP (f);
3896 attrs.valuemask |= XpmVisual;
3897 attrs.valuemask |= XpmColormap;
3898 #endif /* HAVE_NTGUI */
3900 #ifdef ALLOC_XPM_COLORS
3901 /* Allocate colors with our own functions which handle
3902 failing color allocation more gracefully. */
3903 attrs.color_closure = f;
3904 attrs.alloc_color = xpm_alloc_color;
3905 attrs.free_colors = xpm_free_colors;
3906 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
3907 #else /* not ALLOC_XPM_COLORS */
3908 /* Let the XPM lib allocate colors. */
3909 attrs.valuemask |= XpmReturnAllocPixels;
3910 #ifdef XpmAllocCloseColors
3911 attrs.alloc_close_colors = 1;
3912 attrs.valuemask |= XpmAllocCloseColors;
3913 #else /* not XpmAllocCloseColors */
3914 attrs.closeness = 600;
3915 attrs.valuemask |= XpmCloseness;
3916 #endif /* not XpmAllocCloseColors */
3917 #endif /* ALLOC_XPM_COLORS */
3918 #ifdef ALLOC_XPM_COLORS
3919 xpm_init_color_cache (f, &attrs);
3920 #endif
3922 /* If image specification contains symbolic color definitions, add
3923 these to `attrs'. */
3924 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
3925 if (CONSP (color_symbols))
3927 Lisp_Object tail;
3928 XpmColorSymbol *xpm_syms;
3929 int i, size;
3931 attrs.valuemask |= XpmColorSymbols;
3933 /* Count number of symbols. */
3934 attrs.numsymbols = 0;
3935 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
3936 ++attrs.numsymbols;
3938 /* Allocate an XpmColorSymbol array. */
3939 size = attrs.numsymbols * sizeof *xpm_syms;
3940 xpm_syms = (XpmColorSymbol *) alloca (size);
3941 bzero (xpm_syms, size);
3942 attrs.colorsymbols = xpm_syms;
3944 /* Fill the color symbol array. */
3945 for (tail = color_symbols, i = 0;
3946 CONSP (tail);
3947 ++i, tail = XCDR (tail))
3949 Lisp_Object name = XCAR (XCAR (tail));
3950 Lisp_Object color = XCDR (XCAR (tail));
3951 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
3952 strcpy (xpm_syms[i].name, SDATA (name));
3953 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
3954 strcpy (xpm_syms[i].value, SDATA (color));
3958 /* Create a pixmap for the image, either from a file, or from a
3959 string buffer containing data in the same format as an XPM file. */
3960 #ifdef ALLOC_XPM_COLORS
3961 xpm_init_color_cache (f, &attrs);
3962 #endif
3964 specified_file = image_spec_value (img->spec, QCfile, NULL);
3966 #ifdef HAVE_NTGUI
3968 HDC frame_dc = get_frame_dc (f);
3969 hdc = CreateCompatibleDC (frame_dc);
3970 release_frame_dc (f, frame_dc);
3972 #endif /* HAVE_NTGUI */
3974 if (STRINGP (specified_file))
3976 Lisp_Object file = x_find_image_file (specified_file);
3977 if (!STRINGP (file))
3979 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3980 return 0;
3983 #ifdef HAVE_NTGUI
3984 /* XpmReadFileToPixmap is not available in the Windows port of
3985 libxpm. But XpmReadFileToImage almost does what we want. */
3986 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
3987 &xpm_image, &xpm_mask,
3988 &attrs);
3989 #else
3990 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3991 SDATA (file), &img->pixmap, &img->mask,
3992 &attrs);
3993 #endif /* HAVE_NTGUI */
3995 else
3997 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
3998 #ifdef HAVE_NTGUI
3999 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4000 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4001 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
4002 &xpm_image, &xpm_mask,
4003 &attrs);
4004 #else
4005 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4006 SDATA (buffer),
4007 &img->pixmap, &img->mask,
4008 &attrs);
4009 #endif /* HAVE_NTGUI */
4012 if (rc == XpmSuccess)
4014 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4015 img->colors = colors_in_color_table (&img->ncolors);
4016 #else /* not ALLOC_XPM_COLORS */
4017 int i;
4019 #ifdef HAVE_NTGUI
4020 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4021 plus some duplicate attributes. */
4022 if (xpm_image && xpm_image->bitmap)
4024 img->pixmap = xpm_image->bitmap;
4025 /* XImageFree in libXpm frees XImage struct without destroying
4026 the bitmap, which is what we want. */
4027 fn_XImageFree (xpm_image);
4029 if (xpm_mask && xpm_mask->bitmap)
4031 /* The mask appears to be inverted compared with what we expect.
4032 TODO: invert our expectations. See other places where we
4033 have to invert bits because our idea of masks is backwards. */
4034 HGDIOBJ old_obj;
4035 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4037 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4038 SelectObject (hdc, old_obj);
4040 img->mask = xpm_mask->bitmap;
4041 fn_XImageFree (xpm_mask);
4042 DeleteDC (hdc);
4045 DeleteDC (hdc);
4046 #endif /* HAVE_NTGUI */
4048 /* Remember allocated colors. */
4049 img->ncolors = attrs.nalloc_pixels;
4050 img->colors = (unsigned long *) xmalloc (img->ncolors
4051 * sizeof *img->colors);
4052 for (i = 0; i < attrs.nalloc_pixels; ++i)
4054 img->colors[i] = attrs.alloc_pixels[i];
4055 #ifdef DEBUG_X_COLORS
4056 register_color (img->colors[i]);
4057 #endif
4059 #endif /* not ALLOC_XPM_COLORS */
4061 img->width = attrs.width;
4062 img->height = attrs.height;
4063 xassert (img->width > 0 && img->height > 0);
4065 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4066 #ifdef HAVE_NTGUI
4067 fn_XpmFreeAttributes (&attrs);
4068 #else
4069 XpmFreeAttributes (&attrs);
4070 #endif /* HAVE_NTGUI */
4072 else
4074 #ifdef HAVE_NTGUI
4075 DeleteDC (hdc);
4076 #endif /* HAVE_NTGUI */
4078 switch (rc)
4080 case XpmOpenFailed:
4081 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4082 break;
4084 case XpmFileInvalid:
4085 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4086 break;
4088 case XpmNoMemory:
4089 image_error ("Out of memory (%s)", img->spec, Qnil);
4090 break;
4092 case XpmColorFailed:
4093 image_error ("Color allocation error (%s)", img->spec, Qnil);
4094 break;
4096 default:
4097 image_error ("Unknown error (%s)", img->spec, Qnil);
4098 break;
4102 #ifdef ALLOC_XPM_COLORS
4103 xpm_free_color_cache ();
4104 #endif
4105 return rc == XpmSuccess;
4108 #endif /* HAVE_XPM */
4110 #ifdef MAC_OS
4112 /* XPM support functions for Mac OS where libxpm is not available.
4113 Only XPM version 3 (without any extensions) is supported. */
4115 static int xpm_scan P_ ((unsigned char **, unsigned char *,
4116 unsigned char **, int *));
4117 static Lisp_Object xpm_make_color_table_v
4118 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
4119 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
4120 static void xpm_put_color_table_v P_ ((Lisp_Object, unsigned char *,
4121 int, Lisp_Object));
4122 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4123 unsigned char *, int));
4124 static Lisp_Object xpm_make_color_table_h
4125 P_ ((void (**) (Lisp_Object, unsigned char *, int, Lisp_Object),
4126 Lisp_Object (**) (Lisp_Object, unsigned char *, int)));
4127 static void xpm_put_color_table_h P_ ((Lisp_Object, unsigned char *,
4128 int, Lisp_Object));
4129 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4130 unsigned char *, int));
4131 static int xpm_str_to_color_key P_ ((char *));
4132 static int xpm_load_image P_ ((struct frame *, struct image *,
4133 unsigned char *, unsigned char *));
4135 /* Tokens returned from xpm_scan. */
4137 enum xpm_token
4139 XPM_TK_IDENT = 256,
4140 XPM_TK_STRING,
4141 XPM_TK_EOF
4144 /* Scan an XPM data and return a character (< 256) or a token defined
4145 by enum xpm_token above. *S and END are the start (inclusive) and
4146 the end (exclusive) addresses of the data, respectively. Advance
4147 *S while scanning. If token is either XPM_TK_IDENT or
4148 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4149 length of the corresponding token, respectively. */
4151 static int
4152 xpm_scan (s, end, beg, len)
4153 unsigned char **s, *end, **beg;
4154 int *len;
4156 int c;
4158 while (*s < end)
4160 /* Skip white-space. */
4161 while (*s < end && (c = *(*s)++, isspace (c)))
4164 /* gnus-pointer.xpm uses '-' in its identifier.
4165 sb-dir-plus.xpm uses '+' in its identifier. */
4166 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4168 *beg = *s - 1;
4169 while (*s < end &&
4170 (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4171 ++*s;
4172 *len = *s - *beg;
4173 return XPM_TK_IDENT;
4175 else if (c == '"')
4177 *beg = *s;
4178 while (*s < end && **s != '"')
4179 ++*s;
4180 *len = *s - *beg;
4181 if (*s < end)
4182 ++*s;
4183 return XPM_TK_STRING;
4185 else if (c == '/')
4187 if (*s < end && **s == '*')
4189 /* C-style comment. */
4190 ++*s;
4193 while (*s < end && *(*s)++ != '*')
4196 while (*s < end && **s != '/');
4197 if (*s < end)
4198 ++*s;
4200 else
4201 return c;
4203 else
4204 return c;
4207 return XPM_TK_EOF;
4210 /* Functions for color table lookup in XPM data. A Key is a string
4211 specifying the color of each pixel in XPM data. A value is either
4212 an integer that specifies a pixel color, Qt that specifies
4213 transparency, or Qnil for the unspecified color. If the length of
4214 the key string is one, a vector is used as a table. Otherwise, a
4215 hash table is used. */
4217 static Lisp_Object
4218 xpm_make_color_table_v (put_func, get_func)
4219 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
4220 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
4222 *put_func = xpm_put_color_table_v;
4223 *get_func = xpm_get_color_table_v;
4224 return Fmake_vector (make_number (256), Qnil);
4227 static void
4228 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4229 Lisp_Object color_table;
4230 unsigned char *chars_start;
4231 int chars_len;
4232 Lisp_Object color;
4234 XVECTOR (color_table)->contents[*chars_start] = color;
4237 static Lisp_Object
4238 xpm_get_color_table_v (color_table, chars_start, chars_len)
4239 Lisp_Object color_table;
4240 unsigned char *chars_start;
4241 int chars_len;
4243 return XVECTOR (color_table)->contents[*chars_start];
4246 static Lisp_Object
4247 xpm_make_color_table_h (put_func, get_func)
4248 void (**put_func) (Lisp_Object, unsigned char *, int, Lisp_Object);
4249 Lisp_Object (**get_func) (Lisp_Object, unsigned char *, int);
4251 *put_func = xpm_put_color_table_h;
4252 *get_func = xpm_get_color_table_h;
4253 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4254 make_float (DEFAULT_REHASH_SIZE),
4255 make_float (DEFAULT_REHASH_THRESHOLD),
4256 Qnil, Qnil, Qnil);
4259 static void
4260 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4261 Lisp_Object color_table;
4262 unsigned char *chars_start;
4263 int chars_len;
4264 Lisp_Object color;
4266 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4267 unsigned hash_code;
4268 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4270 hash_lookup (table, chars, &hash_code);
4271 hash_put (table, chars, color, hash_code);
4274 static Lisp_Object
4275 xpm_get_color_table_h (color_table, chars_start, chars_len)
4276 Lisp_Object color_table;
4277 unsigned char *chars_start;
4278 int chars_len;
4280 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4281 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4282 NULL);
4284 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4287 enum xpm_color_key {
4288 XPM_COLOR_KEY_S,
4289 XPM_COLOR_KEY_M,
4290 XPM_COLOR_KEY_G4,
4291 XPM_COLOR_KEY_G,
4292 XPM_COLOR_KEY_C
4295 static char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4297 static int
4298 xpm_str_to_color_key (s)
4299 char *s;
4301 int i;
4303 for (i = 0;
4304 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4305 i++)
4306 if (strcmp (xpm_color_key_strings[i], s) == 0)
4307 return i;
4308 return -1;
4311 static int
4312 xpm_load_image (f, img, contents, end)
4313 struct frame *f;
4314 struct image *img;
4315 unsigned char *contents, *end;
4317 unsigned char *s = contents, *beg, *str;
4318 unsigned char buffer[BUFSIZ];
4319 int width, height, x, y;
4320 int num_colors, chars_per_pixel;
4321 int len, LA1;
4322 void (*put_color_table) (Lisp_Object, unsigned char *, int, Lisp_Object);
4323 Lisp_Object (*get_color_table) (Lisp_Object, unsigned char *, int);
4324 Lisp_Object frame, color_symbols, color_table;
4325 int best_key, have_mask = 0;
4326 XImagePtr ximg = NULL, mask_img = NULL;
4328 #define match() \
4329 LA1 = xpm_scan (&s, end, &beg, &len)
4331 #define expect(TOKEN) \
4332 if (LA1 != (TOKEN)) \
4333 goto failure; \
4334 else \
4335 match ()
4337 #define expect_ident(IDENT) \
4338 if (LA1 == XPM_TK_IDENT \
4339 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4340 match (); \
4341 else \
4342 goto failure
4344 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4345 goto failure;
4346 s += 9;
4347 match();
4348 expect_ident ("static");
4349 expect_ident ("char");
4350 expect ('*');
4351 expect (XPM_TK_IDENT);
4352 expect ('[');
4353 expect (']');
4354 expect ('=');
4355 expect ('{');
4356 expect (XPM_TK_STRING);
4357 if (len >= BUFSIZ)
4358 goto failure;
4359 memcpy (buffer, beg, len);
4360 buffer[len] = '\0';
4361 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4362 &num_colors, &chars_per_pixel) != 4
4363 || width <= 0 || height <= 0
4364 || num_colors <= 0 || chars_per_pixel <= 0)
4365 goto failure;
4367 if (!check_image_size (f, width, height))
4369 image_error ("Invalid image size", Qnil, Qnil);
4370 goto failure;
4373 expect (',');
4375 XSETFRAME (frame, f);
4376 if (!NILP (Fxw_display_color_p (frame)))
4377 best_key = XPM_COLOR_KEY_C;
4378 else if (!NILP (Fx_display_grayscale_p (frame)))
4379 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4380 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4381 else
4382 best_key = XPM_COLOR_KEY_M;
4384 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4385 if (chars_per_pixel == 1)
4386 color_table = xpm_make_color_table_v (&put_color_table,
4387 &get_color_table);
4388 else
4389 color_table = xpm_make_color_table_h (&put_color_table,
4390 &get_color_table);
4392 while (num_colors-- > 0)
4394 unsigned char *color, *max_color;
4395 int key, next_key, max_key = 0;
4396 Lisp_Object symbol_color = Qnil, color_val;
4397 XColor cdef;
4399 expect (XPM_TK_STRING);
4400 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4401 goto failure;
4402 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4403 buffer[len - chars_per_pixel] = '\0';
4405 str = strtok (buffer, " \t");
4406 if (str == NULL)
4407 goto failure;
4408 key = xpm_str_to_color_key (str);
4409 if (key < 0)
4410 goto failure;
4413 color = strtok (NULL, " \t");
4414 if (color == NULL)
4415 goto failure;
4417 while ((str = strtok (NULL, " \t")) != NULL)
4419 next_key = xpm_str_to_color_key (str);
4420 if (next_key >= 0)
4421 break;
4422 color[strlen (color)] = ' ';
4425 if (key == XPM_COLOR_KEY_S)
4427 if (NILP (symbol_color))
4428 symbol_color = build_string (color);
4430 else if (max_key < key && key <= best_key)
4432 max_key = key;
4433 max_color = color;
4435 key = next_key;
4437 while (str);
4439 color_val = Qnil;
4440 if (!NILP (color_symbols) && !NILP (symbol_color))
4442 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4444 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4446 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4447 color_val = Qt;
4448 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4449 &cdef, 0))
4450 color_val = make_number (cdef.pixel);
4453 if (NILP (color_val) && max_key > 0)
4455 if (xstricmp (max_color, "None") == 0)
4456 color_val = Qt;
4457 else if (x_defined_color (f, max_color, &cdef, 0))
4458 color_val = make_number (cdef.pixel);
4460 if (!NILP (color_val))
4461 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4463 expect (',');
4466 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4467 &ximg, &img->pixmap)
4468 || !x_create_x_image_and_pixmap (f, width, height, 1,
4469 &mask_img, &img->mask))
4471 image_error ("Out of memory (%s)", img->spec, Qnil);
4472 goto error;
4475 for (y = 0; y < height; y++)
4477 expect (XPM_TK_STRING);
4478 str = beg;
4479 if (len < width * chars_per_pixel)
4480 goto failure;
4481 for (x = 0; x < width; x++, str += chars_per_pixel)
4483 Lisp_Object color_val =
4484 (*get_color_table) (color_table, str, chars_per_pixel);
4486 XPutPixel (ximg, x, y,
4487 (INTEGERP (color_val) ? XINT (color_val)
4488 : FRAME_FOREGROUND_PIXEL (f)));
4489 XPutPixel (mask_img, x, y,
4490 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4491 : (have_mask = 1, PIX_MASK_RETAIN)));
4493 if (y + 1 < height)
4494 expect (',');
4497 img->width = width;
4498 img->height = height;
4500 /* Maybe fill in the background field while we have ximg handy. */
4501 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4502 IMAGE_BACKGROUND (img, f, ximg);
4504 x_put_x_image (f, ximg, img->pixmap, width, height);
4505 x_destroy_x_image (ximg);
4506 if (have_mask)
4508 /* Fill in the background_transparent field while we have the
4509 mask handy. */
4510 image_background_transparent (img, f, mask_img);
4512 x_put_x_image (f, mask_img, img->mask, width, height);
4513 x_destroy_x_image (mask_img);
4515 else
4517 x_destroy_x_image (mask_img);
4518 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4519 img->mask = NO_PIXMAP;
4522 return 1;
4524 failure:
4525 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4526 error:
4527 x_destroy_x_image (ximg);
4528 x_destroy_x_image (mask_img);
4529 x_clear_image (f, img);
4530 return 0;
4532 #undef match
4533 #undef expect
4534 #undef expect_ident
4537 static int
4538 xpm_load (f, img)
4539 struct frame *f;
4540 struct image *img;
4542 int success_p = 0;
4543 Lisp_Object file_name;
4545 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4546 file_name = image_spec_value (img->spec, QCfile, NULL);
4547 if (STRINGP (file_name))
4549 Lisp_Object file;
4550 unsigned char *contents;
4551 int size;
4552 struct gcpro gcpro1;
4554 file = x_find_image_file (file_name);
4555 GCPRO1 (file);
4556 if (!STRINGP (file))
4558 image_error ("Cannot find image file `%s'", file_name, Qnil);
4559 UNGCPRO;
4560 return 0;
4563 contents = slurp_file (SDATA (file), &size);
4564 if (contents == NULL)
4566 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4567 UNGCPRO;
4568 return 0;
4571 success_p = xpm_load_image (f, img, contents, contents + size);
4572 xfree (contents);
4573 UNGCPRO;
4575 else
4577 Lisp_Object data;
4579 data = image_spec_value (img->spec, QCdata, NULL);
4580 success_p = xpm_load_image (f, img, SDATA (data),
4581 SDATA (data) + SBYTES (data));
4584 return success_p;
4587 #endif /* MAC_OS */
4591 /***********************************************************************
4592 Color table
4593 ***********************************************************************/
4595 #ifdef COLOR_TABLE_SUPPORT
4597 /* An entry in the color table mapping an RGB color to a pixel color. */
4599 struct ct_color
4601 int r, g, b;
4602 unsigned long pixel;
4604 /* Next in color table collision list. */
4605 struct ct_color *next;
4608 /* The bucket vector size to use. Must be prime. */
4610 #define CT_SIZE 101
4612 /* Value is a hash of the RGB color given by R, G, and B. */
4614 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
4616 /* The color hash table. */
4618 struct ct_color **ct_table;
4620 /* Number of entries in the color table. */
4622 int ct_colors_allocated;
4624 /* Initialize the color table. */
4626 static void
4627 init_color_table ()
4629 int size = CT_SIZE * sizeof (*ct_table);
4630 ct_table = (struct ct_color **) xmalloc (size);
4631 bzero (ct_table, size);
4632 ct_colors_allocated = 0;
4636 /* Free memory associated with the color table. */
4638 static void
4639 free_color_table ()
4641 int i;
4642 struct ct_color *p, *next;
4644 for (i = 0; i < CT_SIZE; ++i)
4645 for (p = ct_table[i]; p; p = next)
4647 next = p->next;
4648 xfree (p);
4651 xfree (ct_table);
4652 ct_table = NULL;
4656 /* Value is a pixel color for RGB color R, G, B on frame F. If an
4657 entry for that color already is in the color table, return the
4658 pixel color of that entry. Otherwise, allocate a new color for R,
4659 G, B, and make an entry in the color table. */
4661 static unsigned long
4662 lookup_rgb_color (f, r, g, b)
4663 struct frame *f;
4664 int r, g, b;
4666 unsigned hash = CT_HASH_RGB (r, g, b);
4667 int i = hash % CT_SIZE;
4668 struct ct_color *p;
4669 Display_Info *dpyinfo;
4671 /* Handle TrueColor visuals specially, which improves performance by
4672 two orders of magnitude. Freeing colors on TrueColor visuals is
4673 a nop, and pixel colors specify RGB values directly. See also
4674 the Xlib spec, chapter 3.1. */
4675 dpyinfo = FRAME_X_DISPLAY_INFO (f);
4676 if (dpyinfo->red_bits > 0)
4678 unsigned long pr, pg, pb;
4680 /* Apply gamma-correction like normal color allocation does. */
4681 if (f->gamma)
4683 XColor color;
4684 color.red = r, color.green = g, color.blue = b;
4685 gamma_correct (f, &color);
4686 r = color.red, g = color.green, b = color.blue;
4689 /* Scale down RGB values to the visual's bits per RGB, and shift
4690 them to the right position in the pixel color. Note that the
4691 original RGB values are 16-bit values, as usual in X. */
4692 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
4693 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
4694 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
4696 /* Assemble the pixel color. */
4697 return pr | pg | pb;
4700 for (p = ct_table[i]; p; p = p->next)
4701 if (p->r == r && p->g == g && p->b == b)
4702 break;
4704 if (p == NULL)
4707 #ifdef HAVE_X_WINDOWS
4708 XColor color;
4709 Colormap cmap;
4710 int rc;
4712 color.red = r;
4713 color.green = g;
4714 color.blue = b;
4716 cmap = FRAME_X_COLORMAP (f);
4717 rc = x_alloc_nearest_color (f, cmap, &color);
4718 if (rc)
4720 ++ct_colors_allocated;
4721 p = (struct ct_color *) xmalloc (sizeof *p);
4722 p->r = r;
4723 p->g = g;
4724 p->b = b;
4725 p->pixel = color.pixel;
4726 p->next = ct_table[i];
4727 ct_table[i] = p;
4729 else
4730 return FRAME_FOREGROUND_PIXEL (f);
4732 #else
4733 COLORREF color;
4734 #ifdef HAVE_NTGUI
4735 color = PALETTERGB (r, g, b);
4736 #else
4737 color = RGB_TO_ULONG (r, g, b);
4738 #endif /* HAVE_NTGUI */
4739 ++ct_colors_allocated;
4740 p = (struct ct_color *) xmalloc (sizeof *p);
4741 p->r = r;
4742 p->g = g;
4743 p->b = b;
4744 p->pixel = color;
4745 p->next = ct_table[i];
4746 ct_table[i] = p;
4747 #endif /* HAVE_X_WINDOWS */
4751 return p->pixel;
4755 /* Look up pixel color PIXEL which is used on frame F in the color
4756 table. If not already present, allocate it. Value is PIXEL. */
4758 static unsigned long
4759 lookup_pixel_color (f, pixel)
4760 struct frame *f;
4761 unsigned long pixel;
4763 int i = pixel % CT_SIZE;
4764 struct ct_color *p;
4766 for (p = ct_table[i]; p; p = p->next)
4767 if (p->pixel == pixel)
4768 break;
4770 if (p == NULL)
4772 XColor color;
4773 Colormap cmap;
4774 int rc;
4776 #ifdef HAVE_X_WINDOWS
4777 cmap = FRAME_X_COLORMAP (f);
4778 color.pixel = pixel;
4779 x_query_color (f, &color);
4780 rc = x_alloc_nearest_color (f, cmap, &color);
4781 #else
4782 BLOCK_INPUT;
4783 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
4784 color.pixel = pixel;
4785 XQueryColor (NULL, cmap, &color);
4786 rc = x_alloc_nearest_color (f, cmap, &color);
4787 UNBLOCK_INPUT;
4788 #endif /* HAVE_X_WINDOWS */
4790 if (rc)
4792 ++ct_colors_allocated;
4794 p = (struct ct_color *) xmalloc (sizeof *p);
4795 p->r = color.red;
4796 p->g = color.green;
4797 p->b = color.blue;
4798 p->pixel = pixel;
4799 p->next = ct_table[i];
4800 ct_table[i] = p;
4802 else
4803 return FRAME_FOREGROUND_PIXEL (f);
4805 return p->pixel;
4809 /* Value is a vector of all pixel colors contained in the color table,
4810 allocated via xmalloc. Set *N to the number of colors. */
4812 static unsigned long *
4813 colors_in_color_table (n)
4814 int *n;
4816 int i, j;
4817 struct ct_color *p;
4818 unsigned long *colors;
4820 if (ct_colors_allocated == 0)
4822 *n = 0;
4823 colors = NULL;
4825 else
4827 colors = (unsigned long *) xmalloc (ct_colors_allocated
4828 * sizeof *colors);
4829 *n = ct_colors_allocated;
4831 for (i = j = 0; i < CT_SIZE; ++i)
4832 for (p = ct_table[i]; p; p = p->next)
4833 colors[j++] = p->pixel;
4836 return colors;
4839 #else /* COLOR_TABLE_SUPPORT */
4841 static unsigned long
4842 lookup_rgb_color (f, r, g, b)
4843 struct frame *f;
4844 int r, g, b;
4846 unsigned long pixel;
4848 #ifdef MAC_OS
4849 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
4850 gamma_correct (f, &pixel);
4851 #endif /* MAC_OS */
4853 #ifdef HAVE_NTGUI
4854 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
4855 #endif /* HAVE_NTGUI */
4857 return pixel;
4860 static void
4861 init_color_table ()
4864 #endif /* COLOR_TABLE_SUPPORT */
4867 /***********************************************************************
4868 Algorithms
4869 ***********************************************************************/
4871 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
4872 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
4873 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
4875 #ifdef HAVE_NTGUI
4876 static void XPutPixel (XImagePtr , int, int, COLORREF);
4877 #endif /* HAVE_NTGUI */
4879 /* Non-zero means draw a cross on images having `:conversion
4880 disabled'. */
4882 int cross_disabled_images;
4884 /* Edge detection matrices for different edge-detection
4885 strategies. */
4887 static int emboss_matrix[9] = {
4888 /* x - 1 x x + 1 */
4889 2, -1, 0, /* y - 1 */
4890 -1, 0, 1, /* y */
4891 0, 1, -2 /* y + 1 */
4894 static int laplace_matrix[9] = {
4895 /* x - 1 x x + 1 */
4896 1, 0, 0, /* y - 1 */
4897 0, 0, 0, /* y */
4898 0, 0, -1 /* y + 1 */
4901 /* Value is the intensity of the color whose red/green/blue values
4902 are R, G, and B. */
4904 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
4907 /* On frame F, return an array of XColor structures describing image
4908 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
4909 non-zero means also fill the red/green/blue members of the XColor
4910 structures. Value is a pointer to the array of XColors structures,
4911 allocated with xmalloc; it must be freed by the caller. */
4913 static XColor *
4914 x_to_xcolors (f, img, rgb_p)
4915 struct frame *f;
4916 struct image *img;
4917 int rgb_p;
4919 int x, y;
4920 XColor *colors, *p;
4921 XImagePtr_or_DC ximg;
4922 #ifdef HAVE_NTGUI
4923 HDC hdc;
4924 HGDIOBJ prev;
4925 #endif /* HAVE_NTGUI */
4927 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
4929 #ifndef HAVE_NTGUI
4930 /* Get the X image IMG->pixmap. */
4931 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4932 0, 0, img->width, img->height, ~0, ZPixmap);
4933 #else
4934 /* Load the image into a memory device context. */
4935 hdc = get_frame_dc (f);
4936 ximg = CreateCompatibleDC (hdc);
4937 release_frame_dc (f, hdc);
4938 prev = SelectObject (ximg, img->pixmap);
4939 #endif /* HAVE_NTGUI */
4941 /* Fill the `pixel' members of the XColor array. I wished there
4942 were an easy and portable way to circumvent XGetPixel. */
4943 p = colors;
4944 for (y = 0; y < img->height; ++y)
4946 XColor *row = p;
4948 #ifdef HAVE_X_WINDOWS
4949 for (x = 0; x < img->width; ++x, ++p)
4950 p->pixel = XGetPixel (ximg, x, y);
4951 if (rgb_p)
4952 x_query_colors (f, row, img->width);
4954 #else
4956 for (x = 0; x < img->width; ++x, ++p)
4958 /* W32_TODO: palette support needed here? */
4959 p->pixel = GET_PIXEL (ximg, x, y);
4960 if (rgb_p)
4962 #ifdef MAC_OS
4963 p->red = RED16_FROM_ULONG (p->pixel);
4964 p->green = GREEN16_FROM_ULONG (p->pixel);
4965 p->blue = BLUE16_FROM_ULONG (p->pixel);
4966 #endif /* MAC_OS */
4967 #ifdef HAVE_NTGUI
4968 p->red = 256 * GetRValue (p->pixel);
4969 p->green = 256 * GetGValue (p->pixel);
4970 p->blue = 256 * GetBValue (p->pixel);
4971 #endif /* HAVE_NTGUI */
4974 #endif /* HAVE_X_WINDOWS */
4977 Destroy_Image (ximg, prev);
4979 return colors;
4982 #ifdef HAVE_NTGUI
4984 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
4985 created with CreateDIBSection, with the pointer to the bit values
4986 stored in ximg->data. */
4988 static void XPutPixel (ximg, x, y, color)
4989 XImagePtr ximg;
4990 int x, y;
4991 COLORREF color;
4993 int width = ximg->info.bmiHeader.biWidth;
4994 int height = ximg->info.bmiHeader.biHeight;
4995 unsigned char * pixel;
4997 /* True color images. */
4998 if (ximg->info.bmiHeader.biBitCount == 24)
5000 int rowbytes = width * 3;
5001 /* Ensure scanlines are aligned on 4 byte boundaries. */
5002 if (rowbytes % 4)
5003 rowbytes += 4 - (rowbytes % 4);
5005 pixel = ximg->data + y * rowbytes + x * 3;
5006 /* Windows bitmaps are in BGR order. */
5007 *pixel = GetBValue (color);
5008 *(pixel + 1) = GetGValue (color);
5009 *(pixel + 2) = GetRValue (color);
5011 /* Monochrome images. */
5012 else if (ximg->info.bmiHeader.biBitCount == 1)
5014 int rowbytes = width / 8;
5015 /* Ensure scanlines are aligned on 4 byte boundaries. */
5016 if (rowbytes % 4)
5017 rowbytes += 4 - (rowbytes % 4);
5018 pixel = ximg->data + y * rowbytes + x / 8;
5019 /* Filter out palette info. */
5020 if (color & 0x00ffffff)
5021 *pixel = *pixel | (1 << x % 8);
5022 else
5023 *pixel = *pixel & ~(1 << x % 8);
5025 else
5026 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
5029 #endif /* HAVE_NTGUI */
5031 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5032 RGB members are set. F is the frame on which this all happens.
5033 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5035 static void
5036 x_from_xcolors (f, img, colors)
5037 struct frame *f;
5038 struct image *img;
5039 XColor *colors;
5041 int x, y;
5042 XImagePtr oimg;
5043 Pixmap pixmap;
5044 XColor *p;
5046 init_color_table ();
5048 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5049 &oimg, &pixmap);
5050 p = colors;
5051 for (y = 0; y < img->height; ++y)
5052 for (x = 0; x < img->width; ++x, ++p)
5054 unsigned long pixel;
5055 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5056 XPutPixel (oimg, x, y, pixel);
5059 xfree (colors);
5060 x_clear_image_1 (f, img, 1, 0, 1);
5062 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5063 x_destroy_x_image (oimg);
5064 img->pixmap = pixmap;
5065 #ifdef COLOR_TABLE_SUPPORT
5066 img->colors = colors_in_color_table (&img->ncolors);
5067 free_color_table ();
5068 #endif /* COLOR_TABLE_SUPPORT */
5072 /* On frame F, perform edge-detection on image IMG.
5074 MATRIX is a nine-element array specifying the transformation
5075 matrix. See emboss_matrix for an example.
5077 COLOR_ADJUST is a color adjustment added to each pixel of the
5078 outgoing image. */
5080 static void
5081 x_detect_edges (f, img, matrix, color_adjust)
5082 struct frame *f;
5083 struct image *img;
5084 int matrix[9], color_adjust;
5086 XColor *colors = x_to_xcolors (f, img, 1);
5087 XColor *new, *p;
5088 int x, y, i, sum;
5090 for (i = sum = 0; i < 9; ++i)
5091 sum += abs (matrix[i]);
5093 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5095 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5097 for (y = 0; y < img->height; ++y)
5099 p = COLOR (new, 0, y);
5100 p->red = p->green = p->blue = 0xffff/2;
5101 p = COLOR (new, img->width - 1, y);
5102 p->red = p->green = p->blue = 0xffff/2;
5105 for (x = 1; x < img->width - 1; ++x)
5107 p = COLOR (new, x, 0);
5108 p->red = p->green = p->blue = 0xffff/2;
5109 p = COLOR (new, x, img->height - 1);
5110 p->red = p->green = p->blue = 0xffff/2;
5113 for (y = 1; y < img->height - 1; ++y)
5115 p = COLOR (new, 1, y);
5117 for (x = 1; x < img->width - 1; ++x, ++p)
5119 int r, g, b, y1, x1;
5121 r = g = b = i = 0;
5122 for (y1 = y - 1; y1 < y + 2; ++y1)
5123 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5124 if (matrix[i])
5126 XColor *t = COLOR (colors, x1, y1);
5127 r += matrix[i] * t->red;
5128 g += matrix[i] * t->green;
5129 b += matrix[i] * t->blue;
5132 r = (r / sum + color_adjust) & 0xffff;
5133 g = (g / sum + color_adjust) & 0xffff;
5134 b = (b / sum + color_adjust) & 0xffff;
5135 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5139 xfree (colors);
5140 x_from_xcolors (f, img, new);
5142 #undef COLOR
5146 /* Perform the pre-defined `emboss' edge-detection on image IMG
5147 on frame F. */
5149 static void
5150 x_emboss (f, img)
5151 struct frame *f;
5152 struct image *img;
5154 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5158 /* Transform image IMG which is used on frame F with a Laplace
5159 edge-detection algorithm. The result is an image that can be used
5160 to draw disabled buttons, for example. */
5162 static void
5163 x_laplace (f, img)
5164 struct frame *f;
5165 struct image *img;
5167 x_detect_edges (f, img, laplace_matrix, 45000);
5171 /* Perform edge-detection on image IMG on frame F, with specified
5172 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5174 MATRIX must be either
5176 - a list of at least 9 numbers in row-major form
5177 - a vector of at least 9 numbers
5179 COLOR_ADJUST nil means use a default; otherwise it must be a
5180 number. */
5182 static void
5183 x_edge_detection (f, img, matrix, color_adjust)
5184 struct frame *f;
5185 struct image *img;
5186 Lisp_Object matrix, color_adjust;
5188 int i = 0;
5189 int trans[9];
5191 if (CONSP (matrix))
5193 for (i = 0;
5194 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5195 ++i, matrix = XCDR (matrix))
5196 trans[i] = XFLOATINT (XCAR (matrix));
5198 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5200 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5201 trans[i] = XFLOATINT (AREF (matrix, i));
5204 if (NILP (color_adjust))
5205 color_adjust = make_number (0xffff / 2);
5207 if (i == 9 && NUMBERP (color_adjust))
5208 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5212 /* Transform image IMG on frame F so that it looks disabled. */
5214 static void
5215 x_disable_image (f, img)
5216 struct frame *f;
5217 struct image *img;
5219 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5220 #ifdef HAVE_NTGUI
5221 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5222 #else
5223 int n_planes = dpyinfo->n_planes;
5224 #endif /* HAVE_NTGUI */
5226 if (n_planes >= 2)
5228 /* Color (or grayscale). Convert to gray, and equalize. Just
5229 drawing such images with a stipple can look very odd, so
5230 we're using this method instead. */
5231 XColor *colors = x_to_xcolors (f, img, 1);
5232 XColor *p, *end;
5233 const int h = 15000;
5234 const int l = 30000;
5236 for (p = colors, end = colors + img->width * img->height;
5237 p < end;
5238 ++p)
5240 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5241 int i2 = (0xffff - h - l) * i / 0xffff + l;
5242 p->red = p->green = p->blue = i2;
5245 x_from_xcolors (f, img, colors);
5248 /* Draw a cross over the disabled image, if we must or if we
5249 should. */
5250 if (n_planes < 2 || cross_disabled_images)
5252 #ifndef HAVE_NTGUI
5253 Display *dpy = FRAME_X_DISPLAY (f);
5254 GC gc;
5256 #ifdef MAC_OS
5257 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, NULL, 0, NULL)
5258 #define MaskForeground(f) PIX_MASK_DRAW
5259 #else
5260 #define XCreateGC_pixmap(dpy, pixmap) XCreateGC (dpy, pixmap, 0, NULL)
5261 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5262 #endif
5264 gc = XCreateGC_pixmap (dpy, img->pixmap);
5265 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5266 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5267 img->width - 1, img->height - 1);
5268 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5269 img->width - 1, 0);
5270 XFreeGC (dpy, gc);
5272 if (img->mask)
5274 gc = XCreateGC_pixmap (dpy, img->mask);
5275 XSetForeground (dpy, gc, MaskForeground (f));
5276 XDrawLine (dpy, img->mask, gc, 0, 0,
5277 img->width - 1, img->height - 1);
5278 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5279 img->width - 1, 0);
5280 XFreeGC (dpy, gc);
5282 #else
5283 HDC hdc, bmpdc;
5284 HGDIOBJ prev;
5286 hdc = get_frame_dc (f);
5287 bmpdc = CreateCompatibleDC (hdc);
5288 release_frame_dc (f, hdc);
5290 prev = SelectObject (bmpdc, img->pixmap);
5292 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5293 MoveToEx (bmpdc, 0, 0, NULL);
5294 LineTo (bmpdc, img->width - 1, img->height - 1);
5295 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5296 LineTo (bmpdc, img->width - 1, 0);
5298 if (img->mask)
5300 SelectObject (bmpdc, img->mask);
5301 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5302 MoveToEx (bmpdc, 0, 0, NULL);
5303 LineTo (bmpdc, img->width - 1, img->height - 1);
5304 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5305 LineTo (bmpdc, img->width - 1, 0);
5307 SelectObject (bmpdc, prev);
5308 DeleteDC (bmpdc);
5309 #endif /* HAVE_NTGUI */
5314 /* Build a mask for image IMG which is used on frame F. FILE is the
5315 name of an image file, for error messages. HOW determines how to
5316 determine the background color of IMG. If it is a list '(R G B)',
5317 with R, G, and B being integers >= 0, take that as the color of the
5318 background. Otherwise, determine the background color of IMG
5319 heuristically. Value is non-zero if successful. */
5321 static int
5322 x_build_heuristic_mask (f, img, how)
5323 struct frame *f;
5324 struct image *img;
5325 Lisp_Object how;
5327 XImagePtr_or_DC ximg;
5328 #ifndef HAVE_NTGUI
5329 XImagePtr mask_img;
5330 #else
5331 HDC frame_dc;
5332 HGDIOBJ prev;
5333 char *mask_img;
5334 int row_width;
5335 #endif /* HAVE_NTGUI */
5336 int x, y, rc, use_img_background;
5337 unsigned long bg = 0;
5339 if (img->mask)
5341 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5342 img->mask = NO_PIXMAP;
5343 img->background_transparent_valid = 0;
5346 #ifndef HAVE_NTGUI
5347 /* Create an image and pixmap serving as mask. */
5348 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5349 &mask_img, &img->mask);
5350 if (!rc)
5351 return 0;
5353 /* Get the X image of IMG->pixmap. */
5354 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5355 img->width, img->height,
5356 ~0, ZPixmap);
5357 #else
5358 /* Create the bit array serving as mask. */
5359 row_width = (img->width + 7) / 8;
5360 mask_img = xmalloc (row_width * img->height);
5361 bzero (mask_img, row_width * img->height);
5363 /* Create a memory device context for IMG->pixmap. */
5364 frame_dc = get_frame_dc (f);
5365 ximg = CreateCompatibleDC (frame_dc);
5366 release_frame_dc (f, frame_dc);
5367 prev = SelectObject (ximg, img->pixmap);
5368 #endif /* HAVE_NTGUI */
5370 /* Determine the background color of ximg. If HOW is `(R G B)'
5371 take that as color. Otherwise, use the image's background color. */
5372 use_img_background = 1;
5374 if (CONSP (how))
5376 int rgb[3], i;
5378 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5380 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5381 how = XCDR (how);
5384 if (i == 3 && NILP (how))
5386 char color_name[30];
5387 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5388 bg = (
5389 #ifdef HAVE_NTGUI
5390 0x00ffffff & /* Filter out palette info. */
5391 #endif /* HAVE_NTGUI */
5392 x_alloc_image_color (f, img, build_string (color_name), 0));
5393 use_img_background = 0;
5397 if (use_img_background)
5398 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5400 /* Set all bits in mask_img to 1 whose color in ximg is different
5401 from the background color bg. */
5402 #ifndef HAVE_NTGUI
5403 for (y = 0; y < img->height; ++y)
5404 for (x = 0; x < img->width; ++x)
5405 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5406 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5408 /* Fill in the background_transparent field while we have the mask handy. */
5409 image_background_transparent (img, f, mask_img);
5411 /* Put mask_img into img->mask. */
5412 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5413 x_destroy_x_image (mask_img);
5415 #else
5416 for (y = 0; y < img->height; ++y)
5417 for (x = 0; x < img->width; ++x)
5419 COLORREF p = GetPixel (ximg, x, y);
5420 if (p != bg)
5421 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5424 /* Create the mask image. */
5425 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5426 mask_img);
5427 /* Fill in the background_transparent field while we have the mask handy. */
5428 SelectObject (ximg, img->mask);
5429 image_background_transparent (img, f, ximg);
5431 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5432 xfree (mask_img);
5433 #endif /* HAVE_NTGUI */
5435 Destroy_Image (ximg, prev);
5437 return 1;
5441 /***********************************************************************
5442 PBM (mono, gray, color)
5443 ***********************************************************************/
5445 static int pbm_image_p P_ ((Lisp_Object object));
5446 static int pbm_load P_ ((struct frame *f, struct image *img));
5447 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5449 /* The symbol `pbm' identifying images of this type. */
5451 Lisp_Object Qpbm;
5453 /* Indices of image specification fields in gs_format, below. */
5455 enum pbm_keyword_index
5457 PBM_TYPE,
5458 PBM_FILE,
5459 PBM_DATA,
5460 PBM_ASCENT,
5461 PBM_MARGIN,
5462 PBM_RELIEF,
5463 PBM_ALGORITHM,
5464 PBM_HEURISTIC_MASK,
5465 PBM_MASK,
5466 PBM_FOREGROUND,
5467 PBM_BACKGROUND,
5468 PBM_LAST
5471 /* Vector of image_keyword structures describing the format
5472 of valid user-defined image specifications. */
5474 static struct image_keyword pbm_format[PBM_LAST] =
5476 {":type", IMAGE_SYMBOL_VALUE, 1},
5477 {":file", IMAGE_STRING_VALUE, 0},
5478 {":data", IMAGE_STRING_VALUE, 0},
5479 {":ascent", IMAGE_ASCENT_VALUE, 0},
5480 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5481 {":relief", IMAGE_INTEGER_VALUE, 0},
5482 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5483 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5484 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5485 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5486 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5489 /* Structure describing the image type `pbm'. */
5491 static struct image_type pbm_type =
5493 &Qpbm,
5494 pbm_image_p,
5495 pbm_load,
5496 x_clear_image,
5497 NULL
5501 /* Return non-zero if OBJECT is a valid PBM image specification. */
5503 static int
5504 pbm_image_p (object)
5505 Lisp_Object object;
5507 struct image_keyword fmt[PBM_LAST];
5509 bcopy (pbm_format, fmt, sizeof fmt);
5511 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5512 return 0;
5514 /* Must specify either :data or :file. */
5515 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5519 /* Scan a decimal number from *S and return it. Advance *S while
5520 reading the number. END is the end of the string. Value is -1 at
5521 end of input. */
5523 static int
5524 pbm_scan_number (s, end)
5525 unsigned char **s, *end;
5527 int c = 0, val = -1;
5529 while (*s < end)
5531 /* Skip white-space. */
5532 while (*s < end && (c = *(*s)++, isspace (c)))
5535 if (c == '#')
5537 /* Skip comment to end of line. */
5538 while (*s < end && (c = *(*s)++, c != '\n'))
5541 else if (isdigit (c))
5543 /* Read decimal number. */
5544 val = c - '0';
5545 while (*s < end && (c = *(*s)++, isdigit (c)))
5546 val = 10 * val + c - '0';
5547 break;
5549 else
5550 break;
5553 return val;
5557 #ifdef HAVE_NTGUI
5558 #if 0 /* Unused. ++kfs */
5560 /* Read FILE into memory. Value is a pointer to a buffer allocated
5561 with xmalloc holding FILE's contents. Value is null if an error
5562 occurred. *SIZE is set to the size of the file. */
5564 static char *
5565 pbm_read_file (file, size)
5566 Lisp_Object file;
5567 int *size;
5569 FILE *fp = NULL;
5570 char *buf = NULL;
5571 struct stat st;
5573 if (stat (SDATA (file), &st) == 0
5574 && (fp = fopen (SDATA (file), "rb")) != NULL
5575 && (buf = (char *) xmalloc (st.st_size),
5576 fread (buf, 1, st.st_size, fp) == st.st_size))
5578 *size = st.st_size;
5579 fclose (fp);
5581 else
5583 if (fp)
5584 fclose (fp);
5585 if (buf)
5587 xfree (buf);
5588 buf = NULL;
5592 return buf;
5594 #endif
5595 #endif /* HAVE_NTGUI */
5597 /* Load PBM image IMG for use on frame F. */
5599 static int
5600 pbm_load (f, img)
5601 struct frame *f;
5602 struct image *img;
5604 int raw_p, x, y;
5605 int width, height, max_color_idx = 0;
5606 XImagePtr ximg;
5607 Lisp_Object file, specified_file;
5608 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5609 struct gcpro gcpro1;
5610 unsigned char *contents = NULL;
5611 unsigned char *end, *p;
5612 int size;
5614 specified_file = image_spec_value (img->spec, QCfile, NULL);
5615 file = Qnil;
5616 GCPRO1 (file);
5618 if (STRINGP (specified_file))
5620 file = x_find_image_file (specified_file);
5621 if (!STRINGP (file))
5623 image_error ("Cannot find image file `%s'", specified_file, Qnil);
5624 UNGCPRO;
5625 return 0;
5628 contents = slurp_file (SDATA (file), &size);
5629 if (contents == NULL)
5631 image_error ("Error reading `%s'", file, Qnil);
5632 UNGCPRO;
5633 return 0;
5636 p = contents;
5637 end = contents + size;
5639 else
5641 Lisp_Object data;
5642 data = image_spec_value (img->spec, QCdata, NULL);
5643 p = SDATA (data);
5644 end = p + SBYTES (data);
5647 /* Check magic number. */
5648 if (end - p < 2 || *p++ != 'P')
5650 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5651 error:
5652 xfree (contents);
5653 UNGCPRO;
5654 return 0;
5657 switch (*p++)
5659 case '1':
5660 raw_p = 0, type = PBM_MONO;
5661 break;
5663 case '2':
5664 raw_p = 0, type = PBM_GRAY;
5665 break;
5667 case '3':
5668 raw_p = 0, type = PBM_COLOR;
5669 break;
5671 case '4':
5672 raw_p = 1, type = PBM_MONO;
5673 break;
5675 case '5':
5676 raw_p = 1, type = PBM_GRAY;
5677 break;
5679 case '6':
5680 raw_p = 1, type = PBM_COLOR;
5681 break;
5683 default:
5684 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
5685 goto error;
5688 /* Read width, height, maximum color-component. Characters
5689 starting with `#' up to the end of a line are ignored. */
5690 width = pbm_scan_number (&p, end);
5691 height = pbm_scan_number (&p, end);
5693 if (type != PBM_MONO)
5695 max_color_idx = pbm_scan_number (&p, end);
5696 if (raw_p && max_color_idx > 255)
5697 max_color_idx = 255;
5700 if (!check_image_size (f, width, height)
5701 || (type != PBM_MONO && max_color_idx < 0))
5702 goto error;
5704 if (!x_create_x_image_and_pixmap (f, width, height, 0,
5705 &ximg, &img->pixmap))
5706 goto error;
5708 /* Initialize the color hash table. */
5709 init_color_table ();
5711 if (type == PBM_MONO)
5713 int c = 0, g;
5714 struct image_keyword fmt[PBM_LAST];
5715 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
5716 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
5718 /* Parse the image specification. */
5719 bcopy (pbm_format, fmt, sizeof fmt);
5720 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
5722 /* Get foreground and background colors, maybe allocate colors. */
5723 if (fmt[PBM_FOREGROUND].count
5724 && STRINGP (fmt[PBM_FOREGROUND].value))
5725 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
5726 if (fmt[PBM_BACKGROUND].count
5727 && STRINGP (fmt[PBM_BACKGROUND].value))
5729 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
5730 img->background = bg;
5731 img->background_valid = 1;
5734 for (y = 0; y < height; ++y)
5735 for (x = 0; x < width; ++x)
5737 if (raw_p)
5739 if ((x & 7) == 0)
5740 c = *p++;
5741 g = c & 0x80;
5742 c <<= 1;
5744 else
5745 g = pbm_scan_number (&p, end);
5747 XPutPixel (ximg, x, y, g ? fg : bg);
5750 else
5752 for (y = 0; y < height; ++y)
5753 for (x = 0; x < width; ++x)
5755 int r, g, b;
5757 if (type == PBM_GRAY)
5758 r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
5759 else if (raw_p)
5761 r = *p++;
5762 g = *p++;
5763 b = *p++;
5765 else
5767 r = pbm_scan_number (&p, end);
5768 g = pbm_scan_number (&p, end);
5769 b = pbm_scan_number (&p, end);
5772 if (r < 0 || g < 0 || b < 0)
5774 x_destroy_x_image (ximg);
5775 image_error ("Invalid pixel value in image `%s'",
5776 img->spec, Qnil);
5777 goto error;
5780 /* RGB values are now in the range 0..max_color_idx.
5781 Scale this to the range 0..0xffff supported by X. */
5782 r = (double) r * 65535 / max_color_idx;
5783 g = (double) g * 65535 / max_color_idx;
5784 b = (double) b * 65535 / max_color_idx;
5785 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
5789 #ifdef COLOR_TABLE_SUPPORT
5790 /* Store in IMG->colors the colors allocated for the image, and
5791 free the color table. */
5792 img->colors = colors_in_color_table (&img->ncolors);
5793 free_color_table ();
5794 #endif /* COLOR_TABLE_SUPPORT */
5796 img->width = width;
5797 img->height = height;
5799 /* Maybe fill in the background field while we have ximg handy. */
5801 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
5802 /* Casting avoids a GCC warning. */
5803 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5805 /* Put the image into a pixmap. */
5806 x_put_x_image (f, ximg, img->pixmap, width, height);
5807 x_destroy_x_image (ximg);
5809 /* X and W32 versions did it here, MAC version above. ++kfs
5810 img->width = width;
5811 img->height = height; */
5813 UNGCPRO;
5814 xfree (contents);
5815 return 1;
5819 /***********************************************************************
5821 ***********************************************************************/
5823 #if defined (HAVE_PNG) || defined (MAC_OS)
5825 /* Function prototypes. */
5827 static int png_image_p P_ ((Lisp_Object object));
5828 static int png_load P_ ((struct frame *f, struct image *img));
5830 /* The symbol `png' identifying images of this type. */
5832 Lisp_Object Qpng;
5834 /* Indices of image specification fields in png_format, below. */
5836 enum png_keyword_index
5838 PNG_TYPE,
5839 PNG_DATA,
5840 PNG_FILE,
5841 PNG_ASCENT,
5842 PNG_MARGIN,
5843 PNG_RELIEF,
5844 PNG_ALGORITHM,
5845 PNG_HEURISTIC_MASK,
5846 PNG_MASK,
5847 PNG_BACKGROUND,
5848 PNG_LAST
5851 /* Vector of image_keyword structures describing the format
5852 of valid user-defined image specifications. */
5854 static struct image_keyword png_format[PNG_LAST] =
5856 {":type", IMAGE_SYMBOL_VALUE, 1},
5857 {":data", IMAGE_STRING_VALUE, 0},
5858 {":file", IMAGE_STRING_VALUE, 0},
5859 {":ascent", IMAGE_ASCENT_VALUE, 0},
5860 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5861 {":relief", IMAGE_INTEGER_VALUE, 0},
5862 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5863 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5864 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5865 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5868 /* Structure describing the image type `png'. */
5870 static struct image_type png_type =
5872 &Qpng,
5873 png_image_p,
5874 png_load,
5875 x_clear_image,
5876 NULL
5879 /* Return non-zero if OBJECT is a valid PNG image specification. */
5881 static int
5882 png_image_p (object)
5883 Lisp_Object object;
5885 struct image_keyword fmt[PNG_LAST];
5886 bcopy (png_format, fmt, sizeof fmt);
5888 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
5889 return 0;
5891 /* Must specify either the :data or :file keyword. */
5892 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5895 #endif /* HAVE_PNG || MAC_OS */
5898 #ifdef HAVE_PNG
5900 #if defined HAVE_LIBPNG_PNG_H
5901 # include <libpng/png.h>
5902 #else
5903 # include <png.h>
5904 #endif
5906 #ifdef HAVE_NTGUI
5907 /* PNG library details. */
5909 DEF_IMGLIB_FN (png_get_io_ptr);
5910 DEF_IMGLIB_FN (png_check_sig);
5911 DEF_IMGLIB_FN (png_create_read_struct);
5912 DEF_IMGLIB_FN (png_create_info_struct);
5913 DEF_IMGLIB_FN (png_destroy_read_struct);
5914 DEF_IMGLIB_FN (png_set_read_fn);
5915 DEF_IMGLIB_FN (png_set_sig_bytes);
5916 DEF_IMGLIB_FN (png_read_info);
5917 DEF_IMGLIB_FN (png_get_IHDR);
5918 DEF_IMGLIB_FN (png_get_valid);
5919 DEF_IMGLIB_FN (png_set_strip_16);
5920 DEF_IMGLIB_FN (png_set_expand);
5921 DEF_IMGLIB_FN (png_set_gray_to_rgb);
5922 DEF_IMGLIB_FN (png_set_background);
5923 DEF_IMGLIB_FN (png_get_bKGD);
5924 DEF_IMGLIB_FN (png_read_update_info);
5925 DEF_IMGLIB_FN (png_get_channels);
5926 DEF_IMGLIB_FN (png_get_rowbytes);
5927 DEF_IMGLIB_FN (png_read_image);
5928 DEF_IMGLIB_FN (png_read_end);
5929 DEF_IMGLIB_FN (png_error);
5931 static int
5932 init_png_functions (Lisp_Object libraries)
5934 HMODULE library;
5936 /* Try loading libpng under probable names. */
5937 if (!(library = w32_delayed_load (libraries, Qpng)))
5938 return 0;
5940 LOAD_IMGLIB_FN (library, png_get_io_ptr);
5941 LOAD_IMGLIB_FN (library, png_check_sig);
5942 LOAD_IMGLIB_FN (library, png_create_read_struct);
5943 LOAD_IMGLIB_FN (library, png_create_info_struct);
5944 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
5945 LOAD_IMGLIB_FN (library, png_set_read_fn);
5946 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
5947 LOAD_IMGLIB_FN (library, png_read_info);
5948 LOAD_IMGLIB_FN (library, png_get_IHDR);
5949 LOAD_IMGLIB_FN (library, png_get_valid);
5950 LOAD_IMGLIB_FN (library, png_set_strip_16);
5951 LOAD_IMGLIB_FN (library, png_set_expand);
5952 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
5953 LOAD_IMGLIB_FN (library, png_set_background);
5954 LOAD_IMGLIB_FN (library, png_get_bKGD);
5955 LOAD_IMGLIB_FN (library, png_read_update_info);
5956 LOAD_IMGLIB_FN (library, png_get_channels);
5957 LOAD_IMGLIB_FN (library, png_get_rowbytes);
5958 LOAD_IMGLIB_FN (library, png_read_image);
5959 LOAD_IMGLIB_FN (library, png_read_end);
5960 LOAD_IMGLIB_FN (library, png_error);
5961 return 1;
5963 #else
5965 #define fn_png_get_io_ptr png_get_io_ptr
5966 #define fn_png_check_sig png_check_sig
5967 #define fn_png_create_read_struct png_create_read_struct
5968 #define fn_png_create_info_struct png_create_info_struct
5969 #define fn_png_destroy_read_struct png_destroy_read_struct
5970 #define fn_png_set_read_fn png_set_read_fn
5971 #define fn_png_set_sig_bytes png_set_sig_bytes
5972 #define fn_png_read_info png_read_info
5973 #define fn_png_get_IHDR png_get_IHDR
5974 #define fn_png_get_valid png_get_valid
5975 #define fn_png_set_strip_16 png_set_strip_16
5976 #define fn_png_set_expand png_set_expand
5977 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
5978 #define fn_png_set_background png_set_background
5979 #define fn_png_get_bKGD png_get_bKGD
5980 #define fn_png_read_update_info png_read_update_info
5981 #define fn_png_get_channels png_get_channels
5982 #define fn_png_get_rowbytes png_get_rowbytes
5983 #define fn_png_read_image png_read_image
5984 #define fn_png_read_end png_read_end
5985 #define fn_png_error png_error
5987 #endif /* HAVE_NTGUI */
5989 /* Error and warning handlers installed when the PNG library
5990 is initialized. */
5992 static void
5993 my_png_error (png_ptr, msg)
5994 png_struct *png_ptr;
5995 char *msg;
5997 xassert (png_ptr != NULL);
5998 image_error ("PNG error: %s", build_string (msg), Qnil);
5999 longjmp (png_ptr->jmpbuf, 1);
6003 static void
6004 my_png_warning (png_ptr, msg)
6005 png_struct *png_ptr;
6006 char *msg;
6008 xassert (png_ptr != NULL);
6009 image_error ("PNG warning: %s", build_string (msg), Qnil);
6012 /* Memory source for PNG decoding. */
6014 struct png_memory_storage
6016 unsigned char *bytes; /* The data */
6017 size_t len; /* How big is it? */
6018 int index; /* Where are we? */
6022 /* Function set as reader function when reading PNG image from memory.
6023 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6024 bytes from the input to DATA. */
6026 static void
6027 png_read_from_memory (png_ptr, data, length)
6028 png_structp png_ptr;
6029 png_bytep data;
6030 png_size_t length;
6032 struct png_memory_storage *tbr
6033 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
6035 if (length > tbr->len - tbr->index)
6036 fn_png_error (png_ptr, "Read error");
6038 bcopy (tbr->bytes + tbr->index, data, length);
6039 tbr->index = tbr->index + length;
6043 /* Function set as reader function when reading PNG image from a file.
6044 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6045 bytes from the input to DATA. */
6047 static void
6048 png_read_from_file (png_ptr, data, length)
6049 png_structp png_ptr;
6050 png_bytep data;
6051 png_size_t length;
6053 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6055 if (fread (data, 1, length, fp) < length)
6056 fn_png_error (png_ptr, "Read error");
6060 /* Load PNG image IMG for use on frame F. Value is non-zero if
6061 successful. */
6063 static int
6064 png_load (f, img)
6065 struct frame *f;
6066 struct image *img;
6068 Lisp_Object file, specified_file;
6069 Lisp_Object specified_data;
6070 int x, y, i;
6071 XImagePtr ximg, mask_img = NULL;
6072 struct gcpro gcpro1;
6073 png_struct *png_ptr = NULL;
6074 png_info *info_ptr = NULL, *end_info = NULL;
6075 FILE *volatile fp = NULL;
6076 png_byte sig[8];
6077 png_byte * volatile pixels = NULL;
6078 png_byte ** volatile rows = NULL;
6079 png_uint_32 width, height;
6080 int bit_depth, color_type, interlace_type;
6081 png_byte channels;
6082 png_uint_32 row_bytes;
6083 int transparent_p;
6084 double screen_gamma;
6085 struct png_memory_storage tbr; /* Data to be read */
6087 /* Find out what file to load. */
6088 specified_file = image_spec_value (img->spec, QCfile, NULL);
6089 specified_data = image_spec_value (img->spec, QCdata, NULL);
6090 file = Qnil;
6091 GCPRO1 (file);
6093 if (NILP (specified_data))
6095 file = x_find_image_file (specified_file);
6096 if (!STRINGP (file))
6098 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6099 UNGCPRO;
6100 return 0;
6103 /* Open the image file. */
6104 fp = fopen (SDATA (file), "rb");
6105 if (!fp)
6107 image_error ("Cannot open image file `%s'", file, Qnil);
6108 UNGCPRO;
6109 fclose (fp);
6110 return 0;
6113 /* Check PNG signature. */
6114 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6115 || !fn_png_check_sig (sig, sizeof sig))
6117 image_error ("Not a PNG file: `%s'", file, Qnil);
6118 UNGCPRO;
6119 fclose (fp);
6120 return 0;
6123 else
6125 /* Read from memory. */
6126 tbr.bytes = SDATA (specified_data);
6127 tbr.len = SBYTES (specified_data);
6128 tbr.index = 0;
6130 /* Check PNG signature. */
6131 if (tbr.len < sizeof sig
6132 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6134 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6135 UNGCPRO;
6136 return 0;
6139 /* Need to skip past the signature. */
6140 tbr.bytes += sizeof (sig);
6143 /* Initialize read and info structs for PNG lib. Casting return
6144 value avoids a GCC warning on W32. */
6145 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6146 NULL, my_png_error,
6147 my_png_warning);
6148 if (!png_ptr)
6150 if (fp) fclose (fp);
6151 UNGCPRO;
6152 return 0;
6155 /* Casting return value avoids a GCC warning on W32. */
6156 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6157 if (!info_ptr)
6159 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6160 if (fp) fclose (fp);
6161 UNGCPRO;
6162 return 0;
6165 /* Casting return value avoids a GCC warning on W32. */
6166 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6167 if (!end_info)
6169 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6170 if (fp) fclose (fp);
6171 UNGCPRO;
6172 return 0;
6175 /* Set error jump-back. We come back here when the PNG library
6176 detects an error. */
6177 if (setjmp (png_ptr->jmpbuf))
6179 error:
6180 if (png_ptr)
6181 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6182 xfree (pixels);
6183 xfree (rows);
6184 if (fp) fclose (fp);
6185 UNGCPRO;
6186 return 0;
6189 /* Read image info. */
6190 if (!NILP (specified_data))
6191 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6192 else
6193 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6195 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6196 fn_png_read_info (png_ptr, info_ptr);
6197 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6198 &interlace_type, NULL, NULL);
6200 if (!check_image_size (f, width, height))
6201 goto error;
6203 /* If image contains simply transparency data, we prefer to
6204 construct a clipping mask. */
6205 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6206 transparent_p = 1;
6207 else
6208 transparent_p = 0;
6210 /* This function is easier to write if we only have to handle
6211 one data format: RGB or RGBA with 8 bits per channel. Let's
6212 transform other formats into that format. */
6214 /* Strip more than 8 bits per channel. */
6215 if (bit_depth == 16)
6216 fn_png_set_strip_16 (png_ptr);
6218 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6219 if available. */
6220 fn_png_set_expand (png_ptr);
6222 /* Convert grayscale images to RGB. */
6223 if (color_type == PNG_COLOR_TYPE_GRAY
6224 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6225 fn_png_set_gray_to_rgb (png_ptr);
6227 screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
6229 #if 0 /* Avoid double gamma correction for PNG images. */
6230 { /* Tell the PNG lib to handle gamma correction for us. */
6231 int intent;
6232 double image_gamma;
6233 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
6234 if (png_get_sRGB (png_ptr, info_ptr, &intent))
6235 /* The libpng documentation says this is right in this case. */
6236 png_set_gamma (png_ptr, screen_gamma, 0.45455);
6237 else
6238 #endif
6239 if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
6240 /* Image contains gamma information. */
6241 png_set_gamma (png_ptr, screen_gamma, image_gamma);
6242 else
6243 /* Use the standard default for the image gamma. */
6244 png_set_gamma (png_ptr, screen_gamma, 0.45455);
6246 #endif /* if 0 */
6248 /* Handle alpha channel by combining the image with a background
6249 color. Do this only if a real alpha channel is supplied. For
6250 simple transparency, we prefer a clipping mask. */
6251 if (!transparent_p)
6253 png_color_16 *image_bg;
6254 Lisp_Object specified_bg
6255 = image_spec_value (img->spec, QCbackground, NULL);
6257 if (STRINGP (specified_bg))
6258 /* The user specified `:background', use that. */
6260 /* W32 version incorrectly used COLORREF here!! ++kfs */
6261 XColor color;
6262 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6264 png_color_16 user_bg;
6266 bzero (&user_bg, sizeof user_bg);
6267 user_bg.red = color.red >> 8;
6268 user_bg.green = color.green >> 8;
6269 user_bg.blue = color.blue >> 8;
6271 fn_png_set_background (png_ptr, &user_bg,
6272 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6275 else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
6276 /* Image contains a background color with which to
6277 combine the image. */
6278 fn_png_set_background (png_ptr, image_bg,
6279 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
6280 else
6282 /* Image does not contain a background color with which
6283 to combine the image data via an alpha channel. Use
6284 the frame's background instead. */
6285 #ifdef HAVE_X_WINDOWS
6286 XColor color;
6287 png_color_16 frame_background;
6289 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6290 x_query_color (f, &color);
6292 bzero (&frame_background, sizeof frame_background);
6293 frame_background.red = color.red >> 8;
6294 frame_background.green = color.green >> 8;
6295 frame_background.blue = color.blue >> 8;
6296 #endif /* HAVE_X_WINDOWS */
6298 #ifdef HAVE_NTGUI
6299 COLORREF color;
6300 png_color_16 frame_background;
6301 color = FRAME_BACKGROUND_PIXEL (f);
6302 #if 0 /* W32 TODO : Colormap support. */
6303 x_query_color (f, &color);
6304 #endif
6305 bzero (&frame_background, sizeof frame_background);
6306 frame_background.red = GetRValue (color);
6307 frame_background.green = GetGValue (color);
6308 frame_background.blue = GetBValue (color);
6309 #endif /* HAVE_NTGUI */
6311 #ifdef MAC_OS
6312 unsigned long color;
6313 png_color_16 frame_background;
6314 color = FRAME_BACKGROUND_PIXEL (f);
6315 #if 0 /* MAC/W32 TODO : Colormap support. */
6316 x_query_color (f, &color);
6317 #endif
6318 bzero (&frame_background, sizeof frame_background);
6319 frame_background.red = RED_FROM_ULONG (color);
6320 frame_background.green = GREEN_FROM_ULONG (color);
6321 frame_background.blue = BLUE_FROM_ULONG (color);
6322 #endif /* MAC_OS */
6324 fn_png_set_background (png_ptr, &frame_background,
6325 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6329 /* Update info structure. */
6330 fn_png_read_update_info (png_ptr, info_ptr);
6332 /* Get number of channels. Valid values are 1 for grayscale images
6333 and images with a palette, 2 for grayscale images with transparency
6334 information (alpha channel), 3 for RGB images, and 4 for RGB
6335 images with alpha channel, i.e. RGBA. If conversions above were
6336 sufficient we should only have 3 or 4 channels here. */
6337 channels = fn_png_get_channels (png_ptr, info_ptr);
6338 xassert (channels == 3 || channels == 4);
6340 /* Number of bytes needed for one row of the image. */
6341 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6343 /* Allocate memory for the image. */
6344 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6345 rows = (png_byte **) xmalloc (height * sizeof *rows);
6346 for (i = 0; i < height; ++i)
6347 rows[i] = pixels + i * row_bytes;
6349 /* Read the entire image. */
6350 fn_png_read_image (png_ptr, rows);
6351 fn_png_read_end (png_ptr, info_ptr);
6352 if (fp)
6354 fclose (fp);
6355 fp = NULL;
6358 /* Create the X image and pixmap. */
6359 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6360 &img->pixmap))
6361 goto error;
6363 /* Create an image and pixmap serving as mask if the PNG image
6364 contains an alpha channel. */
6365 if (channels == 4
6366 && !transparent_p
6367 && !x_create_x_image_and_pixmap (f, width, height, 1,
6368 &mask_img, &img->mask))
6370 x_destroy_x_image (ximg);
6371 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6372 img->pixmap = NO_PIXMAP;
6373 goto error;
6376 /* Fill the X image and mask from PNG data. */
6377 init_color_table ();
6379 for (y = 0; y < height; ++y)
6381 png_byte *p = rows[y];
6383 for (x = 0; x < width; ++x)
6385 unsigned r, g, b;
6387 r = *p++ << 8;
6388 g = *p++ << 8;
6389 b = *p++ << 8;
6390 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6391 /* An alpha channel, aka mask channel, associates variable
6392 transparency with an image. Where other image formats
6393 support binary transparency---fully transparent or fully
6394 opaque---PNG allows up to 254 levels of partial transparency.
6395 The PNG library implements partial transparency by combining
6396 the image with a specified background color.
6398 I'm not sure how to handle this here nicely: because the
6399 background on which the image is displayed may change, for
6400 real alpha channel support, it would be necessary to create
6401 a new image for each possible background.
6403 What I'm doing now is that a mask is created if we have
6404 boolean transparency information. Otherwise I'm using
6405 the frame's background color to combine the image with. */
6407 if (channels == 4)
6409 if (mask_img)
6410 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6411 ++p;
6416 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6417 /* Set IMG's background color from the PNG image, unless the user
6418 overrode it. */
6420 png_color_16 *bg;
6421 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6423 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6424 img->background_valid = 1;
6428 #ifdef COLOR_TABLE_SUPPORT
6429 /* Remember colors allocated for this image. */
6430 img->colors = colors_in_color_table (&img->ncolors);
6431 free_color_table ();
6432 #endif /* COLOR_TABLE_SUPPORT */
6434 /* Clean up. */
6435 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6436 xfree (rows);
6437 xfree (pixels);
6439 img->width = width;
6440 img->height = height;
6442 /* Maybe fill in the background field while we have ximg handy.
6443 Casting avoids a GCC warning. */
6444 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6446 /* Put the image into the pixmap, then free the X image and its buffer. */
6447 x_put_x_image (f, ximg, img->pixmap, width, height);
6448 x_destroy_x_image (ximg);
6450 /* Same for the mask. */
6451 if (mask_img)
6453 /* Fill in the background_transparent field while we have the
6454 mask handy. Casting avoids a GCC warning. */
6455 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6457 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6458 x_destroy_x_image (mask_img);
6461 UNGCPRO;
6462 return 1;
6465 #else /* HAVE_PNG */
6467 #ifdef MAC_OS
6468 static int
6469 png_load (f, img)
6470 struct frame *f;
6471 struct image *img;
6473 #ifdef MAC_OSX
6474 if (MyCGImageCreateWithPNGDataProvider)
6475 return image_load_quartz2d (f, img, 1);
6476 else
6477 #endif
6478 return image_load_quicktime (f, img, kQTFileTypePNG);
6480 #endif /* MAC_OS */
6482 #endif /* !HAVE_PNG */
6486 /***********************************************************************
6487 JPEG
6488 ***********************************************************************/
6490 #if defined (HAVE_JPEG) || defined (MAC_OS)
6492 static int jpeg_image_p P_ ((Lisp_Object object));
6493 static int jpeg_load P_ ((struct frame *f, struct image *img));
6495 /* The symbol `jpeg' identifying images of this type. */
6497 Lisp_Object Qjpeg;
6499 /* Indices of image specification fields in gs_format, below. */
6501 enum jpeg_keyword_index
6503 JPEG_TYPE,
6504 JPEG_DATA,
6505 JPEG_FILE,
6506 JPEG_ASCENT,
6507 JPEG_MARGIN,
6508 JPEG_RELIEF,
6509 JPEG_ALGORITHM,
6510 JPEG_HEURISTIC_MASK,
6511 JPEG_MASK,
6512 JPEG_BACKGROUND,
6513 JPEG_LAST
6516 /* Vector of image_keyword structures describing the format
6517 of valid user-defined image specifications. */
6519 static struct image_keyword jpeg_format[JPEG_LAST] =
6521 {":type", IMAGE_SYMBOL_VALUE, 1},
6522 {":data", IMAGE_STRING_VALUE, 0},
6523 {":file", IMAGE_STRING_VALUE, 0},
6524 {":ascent", IMAGE_ASCENT_VALUE, 0},
6525 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6526 {":relief", IMAGE_INTEGER_VALUE, 0},
6527 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6528 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6529 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6530 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6533 /* Structure describing the image type `jpeg'. */
6535 static struct image_type jpeg_type =
6537 &Qjpeg,
6538 jpeg_image_p,
6539 jpeg_load,
6540 x_clear_image,
6541 NULL
6544 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6546 static int
6547 jpeg_image_p (object)
6548 Lisp_Object object;
6550 struct image_keyword fmt[JPEG_LAST];
6552 bcopy (jpeg_format, fmt, sizeof fmt);
6554 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6555 return 0;
6557 /* Must specify either the :data or :file keyword. */
6558 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6561 #endif /* HAVE_JPEG || MAC_OS */
6563 #ifdef HAVE_JPEG
6565 /* Work around a warning about HAVE_STDLIB_H being redefined in
6566 jconfig.h. */
6567 #ifdef HAVE_STDLIB_H
6568 #define HAVE_STDLIB_H_1
6569 #undef HAVE_STDLIB_H
6570 #endif /* HAVE_STLIB_H */
6572 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6573 /* In older releases of the jpeg library, jpeglib.h will define boolean
6574 differently depending on __WIN32__, so make sure it is defined. */
6575 #define __WIN32__ 1
6576 #endif
6578 #include <jpeglib.h>
6579 #include <jerror.h>
6580 #include <setjmp.h>
6582 #ifdef HAVE_STLIB_H_1
6583 #define HAVE_STDLIB_H 1
6584 #endif
6586 #ifdef HAVE_NTGUI
6588 /* JPEG library details. */
6589 DEF_IMGLIB_FN (jpeg_CreateDecompress);
6590 DEF_IMGLIB_FN (jpeg_start_decompress);
6591 DEF_IMGLIB_FN (jpeg_finish_decompress);
6592 DEF_IMGLIB_FN (jpeg_destroy_decompress);
6593 DEF_IMGLIB_FN (jpeg_read_header);
6594 DEF_IMGLIB_FN (jpeg_read_scanlines);
6595 DEF_IMGLIB_FN (jpeg_std_error);
6596 DEF_IMGLIB_FN (jpeg_resync_to_restart);
6598 static int
6599 init_jpeg_functions (Lisp_Object libraries)
6601 HMODULE library;
6603 if (!(library = w32_delayed_load (libraries, Qjpeg)))
6604 return 0;
6606 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
6607 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
6608 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
6609 LOAD_IMGLIB_FN (library, jpeg_read_header);
6610 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
6611 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
6612 LOAD_IMGLIB_FN (library, jpeg_std_error);
6613 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
6614 return 1;
6617 /* Wrapper since we can't directly assign the function pointer
6618 to another function pointer that was declared more completely easily. */
6619 static boolean
6620 jpeg_resync_to_restart_wrapper(cinfo, desired)
6621 j_decompress_ptr cinfo;
6622 int desired;
6624 return fn_jpeg_resync_to_restart (cinfo, desired);
6627 #else
6629 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
6630 #define fn_jpeg_start_decompress jpeg_start_decompress
6631 #define fn_jpeg_finish_decompress jpeg_finish_decompress
6632 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
6633 #define fn_jpeg_read_header jpeg_read_header
6634 #define fn_jpeg_read_scanlines jpeg_read_scanlines
6635 #define fn_jpeg_std_error jpeg_std_error
6636 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
6638 #endif /* HAVE_NTGUI */
6640 struct my_jpeg_error_mgr
6642 struct jpeg_error_mgr pub;
6643 jmp_buf setjmp_buffer;
6647 static void
6648 my_error_exit (cinfo)
6649 j_common_ptr cinfo;
6651 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
6652 longjmp (mgr->setjmp_buffer, 1);
6656 /* Init source method for JPEG data source manager. Called by
6657 jpeg_read_header() before any data is actually read. See
6658 libjpeg.doc from the JPEG lib distribution. */
6660 static void
6661 our_common_init_source (cinfo)
6662 j_decompress_ptr cinfo;
6667 /* Method to terminate data source. Called by
6668 jpeg_finish_decompress() after all data has been processed. */
6670 static void
6671 our_common_term_source (cinfo)
6672 j_decompress_ptr cinfo;
6677 /* Fill input buffer method for JPEG data source manager. Called
6678 whenever more data is needed. We read the whole image in one step,
6679 so this only adds a fake end of input marker at the end. */
6681 static boolean
6682 our_memory_fill_input_buffer (cinfo)
6683 j_decompress_ptr cinfo;
6685 /* Insert a fake EOI marker. */
6686 struct jpeg_source_mgr *src = cinfo->src;
6687 static JOCTET buffer[2];
6689 buffer[0] = (JOCTET) 0xFF;
6690 buffer[1] = (JOCTET) JPEG_EOI;
6692 src->next_input_byte = buffer;
6693 src->bytes_in_buffer = 2;
6694 return 1;
6698 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6699 is the JPEG data source manager. */
6701 static void
6702 our_memory_skip_input_data (cinfo, num_bytes)
6703 j_decompress_ptr cinfo;
6704 long num_bytes;
6706 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
6708 if (src)
6710 if (num_bytes > src->bytes_in_buffer)
6711 ERREXIT (cinfo, JERR_INPUT_EOF);
6713 src->bytes_in_buffer -= num_bytes;
6714 src->next_input_byte += num_bytes;
6719 /* Set up the JPEG lib for reading an image from DATA which contains
6720 LEN bytes. CINFO is the decompression info structure created for
6721 reading the image. */
6723 static void
6724 jpeg_memory_src (cinfo, data, len)
6725 j_decompress_ptr cinfo;
6726 JOCTET *data;
6727 unsigned int len;
6729 struct jpeg_source_mgr *src;
6731 if (cinfo->src == NULL)
6733 /* First time for this JPEG object? */
6734 cinfo->src = (struct jpeg_source_mgr *)
6735 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6736 sizeof (struct jpeg_source_mgr));
6737 src = (struct jpeg_source_mgr *) cinfo->src;
6738 src->next_input_byte = data;
6741 src = (struct jpeg_source_mgr *) cinfo->src;
6742 src->init_source = our_common_init_source;
6743 src->fill_input_buffer = our_memory_fill_input_buffer;
6744 src->skip_input_data = our_memory_skip_input_data;
6745 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6746 src->term_source = our_common_term_source;
6747 src->bytes_in_buffer = len;
6748 src->next_input_byte = data;
6752 struct jpeg_stdio_mgr
6754 struct jpeg_source_mgr mgr;
6755 boolean finished;
6756 FILE *file;
6757 JOCTET *buffer;
6761 /* Size of buffer to read JPEG from file.
6762 Not too big, as we want to use alloc_small. */
6763 #define JPEG_STDIO_BUFFER_SIZE 8192
6766 /* Fill input buffer method for JPEG data source manager. Called
6767 whenever more data is needed. The data is read from a FILE *. */
6769 static boolean
6770 our_stdio_fill_input_buffer (cinfo)
6771 j_decompress_ptr cinfo;
6773 struct jpeg_stdio_mgr *src;
6775 src = (struct jpeg_stdio_mgr *) cinfo->src;
6776 if (!src->finished)
6778 size_t bytes;
6780 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
6781 if (bytes > 0)
6782 src->mgr.bytes_in_buffer = bytes;
6783 else
6785 WARNMS (cinfo, JWRN_JPEG_EOF);
6786 src->finished = 1;
6787 src->buffer[0] = (JOCTET) 0xFF;
6788 src->buffer[1] = (JOCTET) JPEG_EOI;
6789 src->mgr.bytes_in_buffer = 2;
6791 src->mgr.next_input_byte = src->buffer;
6794 return 1;
6798 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
6799 is the JPEG data source manager. */
6801 static void
6802 our_stdio_skip_input_data (cinfo, num_bytes)
6803 j_decompress_ptr cinfo;
6804 long num_bytes;
6806 struct jpeg_stdio_mgr *src;
6807 src = (struct jpeg_stdio_mgr *) cinfo->src;
6809 while (num_bytes > 0 && !src->finished)
6811 if (num_bytes <= src->mgr.bytes_in_buffer)
6813 src->mgr.bytes_in_buffer -= num_bytes;
6814 src->mgr.next_input_byte += num_bytes;
6815 break;
6817 else
6819 num_bytes -= src->mgr.bytes_in_buffer;
6820 src->mgr.bytes_in_buffer = 0;
6821 src->mgr.next_input_byte = NULL;
6823 our_stdio_fill_input_buffer (cinfo);
6829 /* Set up the JPEG lib for reading an image from a FILE *.
6830 CINFO is the decompression info structure created for
6831 reading the image. */
6833 static void
6834 jpeg_file_src (cinfo, fp)
6835 j_decompress_ptr cinfo;
6836 FILE *fp;
6838 struct jpeg_stdio_mgr *src;
6840 if (cinfo->src != NULL)
6841 src = (struct jpeg_stdio_mgr *) cinfo->src;
6842 else
6844 /* First time for this JPEG object? */
6845 cinfo->src = (struct jpeg_source_mgr *)
6846 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6847 sizeof (struct jpeg_stdio_mgr));
6848 src = (struct jpeg_stdio_mgr *) cinfo->src;
6849 src->buffer = (JOCTET *)
6850 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
6851 JPEG_STDIO_BUFFER_SIZE);
6854 src->file = fp;
6855 src->finished = 0;
6856 src->mgr.init_source = our_common_init_source;
6857 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
6858 src->mgr.skip_input_data = our_stdio_skip_input_data;
6859 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
6860 src->mgr.term_source = our_common_term_source;
6861 src->mgr.bytes_in_buffer = 0;
6862 src->mgr.next_input_byte = NULL;
6866 /* Load image IMG for use on frame F. Patterned after example.c
6867 from the JPEG lib. */
6869 static int
6870 jpeg_load (f, img)
6871 struct frame *f;
6872 struct image *img;
6874 struct jpeg_decompress_struct cinfo;
6875 struct my_jpeg_error_mgr mgr;
6876 Lisp_Object file, specified_file;
6877 Lisp_Object specified_data;
6878 FILE * volatile fp = NULL;
6879 JSAMPARRAY buffer;
6880 int row_stride, x, y;
6881 XImagePtr ximg = NULL;
6882 int rc;
6883 unsigned long *colors;
6884 int width, height;
6885 struct gcpro gcpro1;
6887 /* Open the JPEG file. */
6888 specified_file = image_spec_value (img->spec, QCfile, NULL);
6889 specified_data = image_spec_value (img->spec, QCdata, NULL);
6890 file = Qnil;
6891 GCPRO1 (file);
6893 if (NILP (specified_data))
6895 file = x_find_image_file (specified_file);
6896 if (!STRINGP (file))
6898 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6899 UNGCPRO;
6900 return 0;
6903 fp = fopen (SDATA (file), "rb");
6904 if (fp == NULL)
6906 image_error ("Cannot open `%s'", file, Qnil);
6907 UNGCPRO;
6908 return 0;
6912 /* Customize libjpeg's error handling to call my_error_exit when an
6913 error is detected. This function will perform a longjmp.
6914 Casting return value avoids a GCC warning on W32. */
6915 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
6916 mgr.pub.error_exit = my_error_exit;
6918 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
6920 if (rc == 1)
6922 /* Called from my_error_exit. Display a JPEG error. */
6923 char buffer[JMSG_LENGTH_MAX];
6924 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
6925 image_error ("Error reading JPEG image `%s': %s", img->spec,
6926 build_string (buffer));
6929 /* Close the input file and destroy the JPEG object. */
6930 if (fp)
6931 fclose ((FILE *) fp);
6932 fn_jpeg_destroy_decompress (&cinfo);
6934 /* If we already have an XImage, free that. */
6935 x_destroy_x_image (ximg);
6937 /* Free pixmap and colors. */
6938 x_clear_image (f, img);
6940 UNGCPRO;
6941 return 0;
6944 /* Create the JPEG decompression object. Let it read from fp.
6945 Read the JPEG image header. */
6946 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
6948 if (NILP (specified_data))
6949 jpeg_file_src (&cinfo, (FILE *) fp);
6950 else
6951 jpeg_memory_src (&cinfo, SDATA (specified_data),
6952 SBYTES (specified_data));
6954 fn_jpeg_read_header (&cinfo, 1);
6956 /* Customize decompression so that color quantization will be used.
6957 Start decompression. */
6958 cinfo.quantize_colors = 1;
6959 fn_jpeg_start_decompress (&cinfo);
6960 width = img->width = cinfo.output_width;
6961 height = img->height = cinfo.output_height;
6963 if (!check_image_size (f, width, height))
6965 image_error ("Invalid image size", Qnil, Qnil);
6966 longjmp (mgr.setjmp_buffer, 2);
6969 /* Create X image and pixmap. */
6970 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
6971 longjmp (mgr.setjmp_buffer, 2);
6973 /* Allocate colors. When color quantization is used,
6974 cinfo.actual_number_of_colors has been set with the number of
6975 colors generated, and cinfo.colormap is a two-dimensional array
6976 of color indices in the range 0..cinfo.actual_number_of_colors.
6977 No more than 255 colors will be generated. */
6979 int i, ir, ig, ib;
6981 if (cinfo.out_color_components > 2)
6982 ir = 0, ig = 1, ib = 2;
6983 else if (cinfo.out_color_components > 1)
6984 ir = 0, ig = 1, ib = 0;
6985 else
6986 ir = 0, ig = 0, ib = 0;
6988 /* Use the color table mechanism because it handles colors that
6989 cannot be allocated nicely. Such colors will be replaced with
6990 a default color, and we don't have to care about which colors
6991 can be freed safely, and which can't. */
6992 init_color_table ();
6993 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
6994 * sizeof *colors);
6996 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
6998 /* Multiply RGB values with 255 because X expects RGB values
6999 in the range 0..0xffff. */
7000 int r = cinfo.colormap[ir][i] << 8;
7001 int g = cinfo.colormap[ig][i] << 8;
7002 int b = cinfo.colormap[ib][i] << 8;
7003 colors[i] = lookup_rgb_color (f, r, g, b);
7006 #ifdef COLOR_TABLE_SUPPORT
7007 /* Remember those colors actually allocated. */
7008 img->colors = colors_in_color_table (&img->ncolors);
7009 free_color_table ();
7010 #endif /* COLOR_TABLE_SUPPORT */
7013 /* Read pixels. */
7014 row_stride = width * cinfo.output_components;
7015 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7016 row_stride, 1);
7017 for (y = 0; y < height; ++y)
7019 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
7020 for (x = 0; x < cinfo.output_width; ++x)
7021 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7024 /* Clean up. */
7025 fn_jpeg_finish_decompress (&cinfo);
7026 fn_jpeg_destroy_decompress (&cinfo);
7027 if (fp)
7028 fclose ((FILE *) fp);
7030 /* Maybe fill in the background field while we have ximg handy. */
7031 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7032 /* Casting avoids a GCC warning. */
7033 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7035 /* Put the image into the pixmap. */
7036 x_put_x_image (f, ximg, img->pixmap, width, height);
7037 x_destroy_x_image (ximg);
7038 UNGCPRO;
7039 return 1;
7042 #else /* HAVE_JPEG */
7044 #ifdef MAC_OS
7045 static int
7046 jpeg_load (f, img)
7047 struct frame *f;
7048 struct image *img;
7050 #ifdef MAC_OSX
7051 return image_load_quartz2d (f, img, 0);
7052 #else
7053 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7054 #endif
7056 #endif /* MAC_OS */
7058 #endif /* !HAVE_JPEG */
7062 /***********************************************************************
7063 TIFF
7064 ***********************************************************************/
7066 #if defined (HAVE_TIFF) || defined (MAC_OS)
7068 static int tiff_image_p P_ ((Lisp_Object object));
7069 static int tiff_load P_ ((struct frame *f, struct image *img));
7071 /* The symbol `tiff' identifying images of this type. */
7073 Lisp_Object Qtiff;
7075 /* Indices of image specification fields in tiff_format, below. */
7077 enum tiff_keyword_index
7079 TIFF_TYPE,
7080 TIFF_DATA,
7081 TIFF_FILE,
7082 TIFF_ASCENT,
7083 TIFF_MARGIN,
7084 TIFF_RELIEF,
7085 TIFF_ALGORITHM,
7086 TIFF_HEURISTIC_MASK,
7087 TIFF_MASK,
7088 TIFF_BACKGROUND,
7089 TIFF_LAST
7092 /* Vector of image_keyword structures describing the format
7093 of valid user-defined image specifications. */
7095 static struct image_keyword tiff_format[TIFF_LAST] =
7097 {":type", IMAGE_SYMBOL_VALUE, 1},
7098 {":data", IMAGE_STRING_VALUE, 0},
7099 {":file", IMAGE_STRING_VALUE, 0},
7100 {":ascent", IMAGE_ASCENT_VALUE, 0},
7101 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7102 {":relief", IMAGE_INTEGER_VALUE, 0},
7103 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7104 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7105 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7106 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7109 /* Structure describing the image type `tiff'. */
7111 static struct image_type tiff_type =
7113 &Qtiff,
7114 tiff_image_p,
7115 tiff_load,
7116 x_clear_image,
7117 NULL
7120 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7122 static int
7123 tiff_image_p (object)
7124 Lisp_Object object;
7126 struct image_keyword fmt[TIFF_LAST];
7127 bcopy (tiff_format, fmt, sizeof fmt);
7129 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7130 return 0;
7132 /* Must specify either the :data or :file keyword. */
7133 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7136 #endif /* HAVE_TIFF || MAC_OS */
7138 #ifdef HAVE_TIFF
7140 #include <tiffio.h>
7142 #ifdef HAVE_NTGUI
7144 /* TIFF library details. */
7145 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7146 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7147 DEF_IMGLIB_FN (TIFFOpen);
7148 DEF_IMGLIB_FN (TIFFClientOpen);
7149 DEF_IMGLIB_FN (TIFFGetField);
7150 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7151 DEF_IMGLIB_FN (TIFFClose);
7153 static int
7154 init_tiff_functions (Lisp_Object libraries)
7156 HMODULE library;
7158 if (!(library = w32_delayed_load (libraries, Qtiff)))
7159 return 0;
7161 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7162 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7163 LOAD_IMGLIB_FN (library, TIFFOpen);
7164 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7165 LOAD_IMGLIB_FN (library, TIFFGetField);
7166 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7167 LOAD_IMGLIB_FN (library, TIFFClose);
7168 return 1;
7171 #else
7173 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7174 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7175 #define fn_TIFFOpen TIFFOpen
7176 #define fn_TIFFClientOpen TIFFClientOpen
7177 #define fn_TIFFGetField TIFFGetField
7178 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7179 #define fn_TIFFClose TIFFClose
7181 #endif /* HAVE_NTGUI */
7184 /* Reading from a memory buffer for TIFF images Based on the PNG
7185 memory source, but we have to provide a lot of extra functions.
7186 Blah.
7188 We really only need to implement read and seek, but I am not
7189 convinced that the TIFF library is smart enough not to destroy
7190 itself if we only hand it the function pointers we need to
7191 override. */
7193 typedef struct
7195 unsigned char *bytes;
7196 size_t len;
7197 int index;
7199 tiff_memory_source;
7201 static size_t
7202 tiff_read_from_memory (data, buf, size)
7203 thandle_t data;
7204 tdata_t buf;
7205 tsize_t size;
7207 tiff_memory_source *src = (tiff_memory_source *) data;
7209 if (size > src->len - src->index)
7210 return (size_t) -1;
7211 bcopy (src->bytes + src->index, buf, size);
7212 src->index += size;
7213 return size;
7216 static size_t
7217 tiff_write_from_memory (data, buf, size)
7218 thandle_t data;
7219 tdata_t buf;
7220 tsize_t size;
7222 return (size_t) -1;
7225 static toff_t
7226 tiff_seek_in_memory (data, off, whence)
7227 thandle_t data;
7228 toff_t off;
7229 int whence;
7231 tiff_memory_source *src = (tiff_memory_source *) data;
7232 int idx;
7234 switch (whence)
7236 case SEEK_SET: /* Go from beginning of source. */
7237 idx = off;
7238 break;
7240 case SEEK_END: /* Go from end of source. */
7241 idx = src->len + off;
7242 break;
7244 case SEEK_CUR: /* Go from current position. */
7245 idx = src->index + off;
7246 break;
7248 default: /* Invalid `whence'. */
7249 return -1;
7252 if (idx > src->len || idx < 0)
7253 return -1;
7255 src->index = idx;
7256 return src->index;
7259 static int
7260 tiff_close_memory (data)
7261 thandle_t data;
7263 /* NOOP */
7264 return 0;
7267 static int
7268 tiff_mmap_memory (data, pbase, psize)
7269 thandle_t data;
7270 tdata_t *pbase;
7271 toff_t *psize;
7273 /* It is already _IN_ memory. */
7274 return 0;
7277 static void
7278 tiff_unmap_memory (data, base, size)
7279 thandle_t data;
7280 tdata_t base;
7281 toff_t size;
7283 /* We don't need to do this. */
7286 static toff_t
7287 tiff_size_of_memory (data)
7288 thandle_t data;
7290 return ((tiff_memory_source *) data)->len;
7294 static void
7295 tiff_error_handler (title, format, ap)
7296 const char *title, *format;
7297 va_list ap;
7299 char buf[512];
7300 int len;
7302 len = sprintf (buf, "TIFF error: %s ", title);
7303 vsprintf (buf + len, format, ap);
7304 add_to_log (buf, Qnil, Qnil);
7308 static void
7309 tiff_warning_handler (title, format, ap)
7310 const char *title, *format;
7311 va_list ap;
7313 char buf[512];
7314 int len;
7316 len = sprintf (buf, "TIFF warning: %s ", title);
7317 vsprintf (buf + len, format, ap);
7318 add_to_log (buf, Qnil, Qnil);
7322 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7323 successful. */
7325 static int
7326 tiff_load (f, img)
7327 struct frame *f;
7328 struct image *img;
7330 Lisp_Object file, specified_file;
7331 Lisp_Object specified_data;
7332 TIFF *tiff;
7333 int width, height, x, y;
7334 uint32 *buf;
7335 int rc;
7336 XImagePtr ximg;
7337 struct gcpro gcpro1;
7338 tiff_memory_source memsrc;
7340 specified_file = image_spec_value (img->spec, QCfile, NULL);
7341 specified_data = image_spec_value (img->spec, QCdata, NULL);
7342 file = Qnil;
7343 GCPRO1 (file);
7345 fn_TIFFSetErrorHandler (tiff_error_handler);
7346 fn_TIFFSetWarningHandler (tiff_warning_handler);
7348 if (NILP (specified_data))
7350 /* Read from a file */
7351 file = x_find_image_file (specified_file);
7352 if (!STRINGP (file))
7354 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7355 UNGCPRO;
7356 return 0;
7359 /* Try to open the image file. Casting return value avoids a
7360 GCC warning on W32. */
7361 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7362 if (tiff == NULL)
7364 image_error ("Cannot open `%s'", file, Qnil);
7365 UNGCPRO;
7366 return 0;
7369 else
7371 /* Memory source! */
7372 memsrc.bytes = SDATA (specified_data);
7373 memsrc.len = SBYTES (specified_data);
7374 memsrc.index = 0;
7376 /* Casting return value avoids a GCC warning on W32. */
7377 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7378 (TIFFReadWriteProc) tiff_read_from_memory,
7379 (TIFFReadWriteProc) tiff_write_from_memory,
7380 tiff_seek_in_memory,
7381 tiff_close_memory,
7382 tiff_size_of_memory,
7383 tiff_mmap_memory,
7384 tiff_unmap_memory);
7386 if (!tiff)
7388 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7389 UNGCPRO;
7390 return 0;
7394 /* Get width and height of the image, and allocate a raster buffer
7395 of width x height 32-bit values. */
7396 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7397 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7399 if (!check_image_size (f, width, height))
7401 image_error ("Invalid image size", Qnil, Qnil);
7402 UNGCPRO;
7403 return 0;
7406 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7408 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7409 fn_TIFFClose (tiff);
7410 if (!rc)
7412 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7413 xfree (buf);
7414 UNGCPRO;
7415 return 0;
7418 /* Create the X image and pixmap. */
7419 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7421 xfree (buf);
7422 UNGCPRO;
7423 return 0;
7426 /* Initialize the color table. */
7427 init_color_table ();
7429 /* Process the pixel raster. Origin is in the lower-left corner. */
7430 for (y = 0; y < height; ++y)
7432 uint32 *row = buf + y * width;
7434 for (x = 0; x < width; ++x)
7436 uint32 abgr = row[x];
7437 int r = TIFFGetR (abgr) << 8;
7438 int g = TIFFGetG (abgr) << 8;
7439 int b = TIFFGetB (abgr) << 8;
7440 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7444 #ifdef COLOR_TABLE_SUPPORT
7445 /* Remember the colors allocated for the image. Free the color table. */
7446 img->colors = colors_in_color_table (&img->ncolors);
7447 free_color_table ();
7448 #endif /* COLOR_TABLE_SUPPORT */
7450 img->width = width;
7451 img->height = height;
7453 /* Maybe fill in the background field while we have ximg handy. */
7454 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7455 /* Casting avoids a GCC warning on W32. */
7456 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7458 /* Put the image into the pixmap, then free the X image and its buffer. */
7459 x_put_x_image (f, ximg, img->pixmap, width, height);
7460 x_destroy_x_image (ximg);
7461 xfree (buf);
7463 UNGCPRO;
7464 return 1;
7467 #else /* HAVE_TIFF */
7469 #ifdef MAC_OS
7470 static int
7471 tiff_load (f, img)
7472 struct frame *f;
7473 struct image *img;
7475 return image_load_quicktime (f, img, kQTFileTypeTIFF);
7477 #endif /* MAC_OS */
7479 #endif /* !HAVE_TIFF */
7483 /***********************************************************************
7485 ***********************************************************************/
7487 #if defined (HAVE_GIF) || defined (MAC_OS)
7489 static int gif_image_p P_ ((Lisp_Object object));
7490 static int gif_load P_ ((struct frame *f, struct image *img));
7491 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7493 /* The symbol `gif' identifying images of this type. */
7495 Lisp_Object Qgif;
7497 /* Indices of image specification fields in gif_format, below. */
7499 enum gif_keyword_index
7501 GIF_TYPE,
7502 GIF_DATA,
7503 GIF_FILE,
7504 GIF_ASCENT,
7505 GIF_MARGIN,
7506 GIF_RELIEF,
7507 GIF_ALGORITHM,
7508 GIF_HEURISTIC_MASK,
7509 GIF_MASK,
7510 GIF_IMAGE,
7511 GIF_BACKGROUND,
7512 GIF_LAST
7515 /* Vector of image_keyword structures describing the format
7516 of valid user-defined image specifications. */
7518 static struct image_keyword gif_format[GIF_LAST] =
7520 {":type", IMAGE_SYMBOL_VALUE, 1},
7521 {":data", IMAGE_STRING_VALUE, 0},
7522 {":file", IMAGE_STRING_VALUE, 0},
7523 {":ascent", IMAGE_ASCENT_VALUE, 0},
7524 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7525 {":relief", IMAGE_INTEGER_VALUE, 0},
7526 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7527 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7528 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7529 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7530 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7533 /* Structure describing the image type `gif'. */
7535 static struct image_type gif_type =
7537 &Qgif,
7538 gif_image_p,
7539 gif_load,
7540 gif_clear_image,
7541 NULL
7544 /* Free X resources of GIF image IMG which is used on frame F. */
7546 static void
7547 gif_clear_image (f, img)
7548 struct frame *f;
7549 struct image *img;
7551 /* IMG->data.ptr_val may contain extension data. */
7552 img->data.lisp_val = Qnil;
7553 x_clear_image (f, img);
7556 /* Return non-zero if OBJECT is a valid GIF image specification. */
7558 static int
7559 gif_image_p (object)
7560 Lisp_Object object;
7562 struct image_keyword fmt[GIF_LAST];
7563 bcopy (gif_format, fmt, sizeof fmt);
7565 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7566 return 0;
7568 /* Must specify either the :data or :file keyword. */
7569 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7572 #endif /* HAVE_GIF || MAC_OS */
7574 #ifdef HAVE_GIF
7576 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7577 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7578 Undefine before redefining to avoid a preprocessor warning. */
7579 #ifdef DrawText
7580 #undef DrawText
7581 #endif
7582 /* avoid conflict with QuickdrawText.h */
7583 #define DrawText gif_DrawText
7584 #include <gif_lib.h>
7585 #undef DrawText
7587 #else /* HAVE_NTGUI || MAC_OS */
7589 #include <gif_lib.h>
7591 #endif /* HAVE_NTGUI || MAC_OS */
7594 #ifdef HAVE_NTGUI
7596 /* GIF library details. */
7597 DEF_IMGLIB_FN (DGifCloseFile);
7598 DEF_IMGLIB_FN (DGifSlurp);
7599 DEF_IMGLIB_FN (DGifOpen);
7600 DEF_IMGLIB_FN (DGifOpenFileName);
7602 static int
7603 init_gif_functions (Lisp_Object libraries)
7605 HMODULE library;
7607 if (!(library = w32_delayed_load (libraries, Qgif)))
7608 return 0;
7610 LOAD_IMGLIB_FN (library, DGifCloseFile);
7611 LOAD_IMGLIB_FN (library, DGifSlurp);
7612 LOAD_IMGLIB_FN (library, DGifOpen);
7613 LOAD_IMGLIB_FN (library, DGifOpenFileName);
7614 return 1;
7617 #else
7619 #define fn_DGifCloseFile DGifCloseFile
7620 #define fn_DGifSlurp DGifSlurp
7621 #define fn_DGifOpen DGifOpen
7622 #define fn_DGifOpenFileName DGifOpenFileName
7624 #endif /* HAVE_NTGUI */
7626 /* Reading a GIF image from memory
7627 Based on the PNG memory stuff to a certain extent. */
7629 typedef struct
7631 unsigned char *bytes;
7632 size_t len;
7633 int index;
7635 gif_memory_source;
7637 /* Make the current memory source available to gif_read_from_memory.
7638 It's done this way because not all versions of libungif support
7639 a UserData field in the GifFileType structure. */
7640 static gif_memory_source *current_gif_memory_src;
7642 static int
7643 gif_read_from_memory (file, buf, len)
7644 GifFileType *file;
7645 GifByteType *buf;
7646 int len;
7648 gif_memory_source *src = current_gif_memory_src;
7650 if (len > src->len - src->index)
7651 return -1;
7653 bcopy (src->bytes + src->index, buf, len);
7654 src->index += len;
7655 return len;
7659 /* Load GIF image IMG for use on frame F. Value is non-zero if
7660 successful. */
7662 static int
7663 gif_load (f, img)
7664 struct frame *f;
7665 struct image *img;
7667 Lisp_Object file, specified_file;
7668 Lisp_Object specified_data;
7669 int rc, width, height, x, y, i;
7670 XImagePtr ximg;
7671 ColorMapObject *gif_color_map;
7672 unsigned long pixel_colors[256];
7673 GifFileType *gif;
7674 struct gcpro gcpro1;
7675 Lisp_Object image;
7676 int ino, image_height, image_width;
7677 gif_memory_source memsrc;
7678 unsigned char *raster;
7680 specified_file = image_spec_value (img->spec, QCfile, NULL);
7681 specified_data = image_spec_value (img->spec, QCdata, NULL);
7682 file = Qnil;
7683 GCPRO1 (file);
7685 if (NILP (specified_data))
7687 file = x_find_image_file (specified_file);
7688 if (!STRINGP (file))
7690 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7691 UNGCPRO;
7692 return 0;
7695 /* Open the GIF file. Casting return value avoids a GCC warning
7696 on W32. */
7697 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
7698 if (gif == NULL)
7700 image_error ("Cannot open `%s'", file, Qnil);
7701 UNGCPRO;
7702 return 0;
7705 else
7707 /* Read from memory! */
7708 current_gif_memory_src = &memsrc;
7709 memsrc.bytes = SDATA (specified_data);
7710 memsrc.len = SBYTES (specified_data);
7711 memsrc.index = 0;
7713 /* Casting return value avoids a GCC warning on W32. */
7714 gif = (GifFileType *)fn_DGifOpen(&memsrc, gif_read_from_memory);
7715 if (!gif)
7717 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
7718 UNGCPRO;
7719 return 0;
7723 /* Before reading entire contents, check the declared image size. */
7724 if (!check_image_size (f, gif->SWidth, gif->SHeight))
7726 image_error ("Invalid image size", Qnil, Qnil);
7727 fn_DGifCloseFile (gif);
7728 UNGCPRO;
7729 return 0;
7732 /* Read entire contents. */
7733 rc = fn_DGifSlurp (gif);
7734 if (rc == GIF_ERROR)
7736 image_error ("Error reading `%s'", img->spec, Qnil);
7737 fn_DGifCloseFile (gif);
7738 UNGCPRO;
7739 return 0;
7742 image = image_spec_value (img->spec, QCindex, NULL);
7743 ino = INTEGERP (image) ? XFASTINT (image) : 0;
7744 if (ino >= gif->ImageCount)
7746 image_error ("Invalid image number `%s' in image `%s'",
7747 image, img->spec);
7748 fn_DGifCloseFile (gif);
7749 UNGCPRO;
7750 return 0;
7753 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
7754 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
7755 image_height = gif->SavedImages[ino].ImageDesc.Height;
7756 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
7757 image_width = gif->SavedImages[ino].ImageDesc.Width;
7758 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
7760 width = img->width = max (gif->SWidth,
7761 max (gif->Image.Left + gif->Image.Width,
7762 img->corners[RIGHT_CORNER]));
7763 height = img->height = max (gif->SHeight,
7764 max (gif->Image.Top + gif->Image.Height,
7765 img->corners[BOT_CORNER]));
7767 if (!check_image_size (f, width, height))
7769 image_error ("Invalid image size", Qnil, Qnil);
7770 fn_DGifCloseFile (gif);
7771 UNGCPRO;
7772 return 0;
7775 /* Create the X image and pixmap. */
7776 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7778 fn_DGifCloseFile (gif);
7779 UNGCPRO;
7780 return 0;
7783 /* Allocate colors. */
7784 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
7785 if (!gif_color_map)
7786 gif_color_map = gif->SColorMap;
7787 init_color_table ();
7788 bzero (pixel_colors, sizeof pixel_colors);
7790 for (i = 0; i < gif_color_map->ColorCount; ++i)
7792 int r = gif_color_map->Colors[i].Red << 8;
7793 int g = gif_color_map->Colors[i].Green << 8;
7794 int b = gif_color_map->Colors[i].Blue << 8;
7795 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
7798 #ifdef COLOR_TABLE_SUPPORT
7799 img->colors = colors_in_color_table (&img->ncolors);
7800 free_color_table ();
7801 #endif /* COLOR_TABLE_SUPPORT */
7803 /* Clear the part of the screen image that are not covered by
7804 the image from the GIF file. Full animated GIF support
7805 requires more than can be done here (see the gif89 spec,
7806 disposal methods). Let's simply assume that the part
7807 not covered by a sub-image is in the frame's background color. */
7808 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
7809 for (x = 0; x < width; ++x)
7810 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7812 for (y = img->corners[BOT_CORNER]; y < height; ++y)
7813 for (x = 0; x < width; ++x)
7814 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7816 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
7818 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
7819 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7820 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
7821 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
7824 /* Read the GIF image into the X image. We use a local variable
7825 `raster' here because RasterBits below is a char *, and invites
7826 problems with bytes >= 0x80. */
7827 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
7829 if (gif->SavedImages[ino].ImageDesc.Interlace)
7831 static int interlace_start[] = {0, 4, 2, 1};
7832 static int interlace_increment[] = {8, 8, 4, 2};
7833 int pass;
7834 int row = interlace_start[0];
7836 pass = 0;
7838 for (y = 0; y < image_height; y++)
7840 if (row >= image_height)
7842 row = interlace_start[++pass];
7843 while (row >= image_height)
7844 row = interlace_start[++pass];
7847 for (x = 0; x < image_width; x++)
7849 int i = raster[(y * image_width) + x];
7850 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7851 row + img->corners[TOP_CORNER], pixel_colors[i]);
7854 row += interlace_increment[pass];
7857 else
7859 for (y = 0; y < image_height; ++y)
7860 for (x = 0; x < image_width; ++x)
7862 int i = raster[y * image_width + x];
7863 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
7864 y + img->corners[TOP_CORNER], pixel_colors[i]);
7868 /* Save GIF image extension data for `image-extension-data'.
7869 Format is (count IMAGES FUNCTION "BYTES" ...). */
7870 img->data.lisp_val = Qnil;
7871 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
7873 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
7874 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
7875 /* Append (... FUNCTION "BYTES") */
7876 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
7877 Fcons (make_number (ext->Function),
7878 img->data.lisp_val));
7879 img->data.lisp_val = Fnreverse (img->data.lisp_val);
7881 if (gif->ImageCount > 1)
7882 img->data.lisp_val = Fcons (Qcount,
7883 Fcons (make_number (gif->ImageCount),
7884 img->data.lisp_val));
7886 fn_DGifCloseFile (gif);
7888 /* Maybe fill in the background field while we have ximg handy. */
7889 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7890 /* Casting avoids a GCC warning. */
7891 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7893 /* Put the image into the pixmap, then free the X image and its buffer. */
7894 x_put_x_image (f, ximg, img->pixmap, width, height);
7895 x_destroy_x_image (ximg);
7897 UNGCPRO;
7898 return 1;
7901 #else /* !HAVE_GIF */
7903 #ifdef MAC_OS
7904 static int
7905 gif_load (f, img)
7906 struct frame *f;
7907 struct image *img;
7909 Lisp_Object specified_file, file;
7910 Lisp_Object specified_data;
7911 OSErr err;
7912 Boolean graphic_p, movie_p, prefer_graphic_p;
7913 Handle dh = NULL;
7914 Movie movie = NULL;
7915 Lisp_Object image;
7916 Track track = NULL;
7917 Media media = NULL;
7918 long nsamples;
7919 Rect rect;
7920 Lisp_Object specified_bg;
7921 XColor color;
7922 RGBColor bg_color;
7923 int width, height;
7924 XImagePtr ximg;
7925 TimeValue time;
7926 int ino;
7927 CGrafPtr old_port;
7928 GDHandle old_gdh;
7930 specified_file = image_spec_value (img->spec, QCfile, NULL);
7931 specified_data = image_spec_value (img->spec, QCdata, NULL);
7933 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
7934 EnterMovies ();
7936 if (NILP (specified_data))
7938 /* Read from a file */
7939 FSSpec fss;
7940 short refnum;
7942 err = find_image_fsspec (specified_file, &file, &fss);
7943 if (err != noErr)
7945 if (err == fnfErr)
7946 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7947 else
7948 goto open_error;
7951 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
7952 &graphic_p, &movie_p, &prefer_graphic_p, 0);
7953 if (err != noErr)
7954 goto open_error;
7956 if (!graphic_p && !movie_p)
7957 goto open_error;
7958 if (prefer_graphic_p)
7959 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
7960 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
7961 if (err != noErr)
7962 goto open_error;
7963 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
7964 CloseMovieFile (refnum);
7965 if (err != noErr)
7967 image_error ("Error reading `%s'", file, Qnil);
7968 return 0;
7971 else
7973 /* Memory source! */
7974 Handle dref = NULL;
7975 long file_type_atom[3];
7977 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
7978 if (err != noErr)
7980 image_error ("Cannot allocate data handle for `%s'",
7981 img->spec, Qnil);
7982 goto error;
7985 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
7986 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
7987 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
7988 err = PtrToHand (&dh, &dref, sizeof (Handle));
7989 if (err == noErr)
7990 /* no file name */
7991 err = PtrAndHand ("\p", dref, 1);
7992 if (err == noErr)
7993 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
7994 if (err != noErr)
7996 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
7997 goto error;
7999 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8000 &movie_p, &prefer_graphic_p, 0);
8001 if (err != noErr)
8002 goto open_error;
8004 if (!graphic_p && !movie_p)
8005 goto open_error;
8006 if (prefer_graphic_p)
8008 int success_p;
8010 DisposeHandle (dref);
8011 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8012 DisposeHandle (dh);
8013 return success_p;
8015 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8016 HandleDataHandlerSubType);
8017 DisposeHandle (dref);
8018 if (err != noErr)
8019 goto open_error;
8022 image = image_spec_value (img->spec, QCindex, NULL);
8023 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8024 track = GetMovieIndTrack (movie, 1);
8025 media = GetTrackMedia (track);
8026 nsamples = GetMediaSampleCount (media);
8027 if (ino >= nsamples)
8029 image_error ("Invalid image number `%s' in image `%s'",
8030 image, img->spec);
8031 goto error;
8034 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8035 if (!STRINGP (specified_bg) ||
8036 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8038 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8039 color.red = RED16_FROM_ULONG (color.pixel);
8040 color.green = GREEN16_FROM_ULONG (color.pixel);
8041 color.blue = BLUE16_FROM_ULONG (color.pixel);
8043 GetMovieBox (movie, &rect);
8044 width = img->width = rect.right - rect.left;
8045 height = img->height = rect.bottom - rect.top;
8046 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8047 goto error;
8049 GetGWorld (&old_port, &old_gdh);
8050 SetGWorld (ximg, NULL);
8051 bg_color.red = color.red;
8052 bg_color.green = color.green;
8053 bg_color.blue = color.blue;
8054 RGBBackColor (&bg_color);
8055 SetGWorld (old_port, old_gdh);
8056 SetMovieActive (movie, 1);
8057 SetMovieGWorld (movie, ximg, NULL);
8058 SampleNumToMediaTime (media, ino + 1, &time, NULL);
8059 SetMovieTimeValue (movie, time);
8060 MoviesTask (movie, 0L);
8061 DisposeTrackMedia (media);
8062 DisposeMovieTrack (track);
8063 DisposeMovie (movie);
8064 if (dh)
8065 DisposeHandle (dh);
8066 /* Maybe fill in the background field while we have ximg handy. */
8067 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8068 IMAGE_BACKGROUND (img, f, ximg);
8070 /* Put the image into the pixmap. */
8071 x_put_x_image (f, ximg, img->pixmap, width, height);
8072 x_destroy_x_image (ximg);
8073 return 1;
8075 open_error:
8076 image_error ("Cannot open `%s'", file, Qnil);
8077 error:
8078 if (media)
8079 DisposeTrackMedia (media);
8080 if (track)
8081 DisposeMovieTrack (track);
8082 if (movie)
8083 DisposeMovie (movie);
8084 if (dh)
8085 DisposeHandle (dh);
8086 return 0;
8088 #endif /* MAC_OS */
8090 #endif /* HAVE_GIF */
8094 /***********************************************************************
8095 Ghostscript
8096 ***********************************************************************/
8098 #ifdef HAVE_X_WINDOWS
8099 #define HAVE_GHOSTSCRIPT 1
8100 #endif /* HAVE_X_WINDOWS */
8102 /* The symbol `postscript' identifying images of this type. */
8104 Lisp_Object Qpostscript;
8106 #ifdef HAVE_GHOSTSCRIPT
8108 static int gs_image_p P_ ((Lisp_Object object));
8109 static int gs_load P_ ((struct frame *f, struct image *img));
8110 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8112 /* Keyword symbols. */
8114 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8116 /* Indices of image specification fields in gs_format, below. */
8118 enum gs_keyword_index
8120 GS_TYPE,
8121 GS_PT_WIDTH,
8122 GS_PT_HEIGHT,
8123 GS_FILE,
8124 GS_LOADER,
8125 GS_BOUNDING_BOX,
8126 GS_ASCENT,
8127 GS_MARGIN,
8128 GS_RELIEF,
8129 GS_ALGORITHM,
8130 GS_HEURISTIC_MASK,
8131 GS_MASK,
8132 GS_BACKGROUND,
8133 GS_LAST
8136 /* Vector of image_keyword structures describing the format
8137 of valid user-defined image specifications. */
8139 static struct image_keyword gs_format[GS_LAST] =
8141 {":type", IMAGE_SYMBOL_VALUE, 1},
8142 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8143 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8144 {":file", IMAGE_STRING_VALUE, 1},
8145 {":loader", IMAGE_FUNCTION_VALUE, 0},
8146 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8147 {":ascent", IMAGE_ASCENT_VALUE, 0},
8148 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8149 {":relief", IMAGE_INTEGER_VALUE, 0},
8150 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8151 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8152 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8153 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8156 /* Structure describing the image type `ghostscript'. */
8158 static struct image_type gs_type =
8160 &Qpostscript,
8161 gs_image_p,
8162 gs_load,
8163 gs_clear_image,
8164 NULL
8168 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8170 static void
8171 gs_clear_image (f, img)
8172 struct frame *f;
8173 struct image *img;
8175 /* IMG->data.ptr_val may contain a recorded colormap. */
8176 xfree (img->data.ptr_val);
8177 x_clear_image (f, img);
8181 /* Return non-zero if OBJECT is a valid Ghostscript image
8182 specification. */
8184 static int
8185 gs_image_p (object)
8186 Lisp_Object object;
8188 struct image_keyword fmt[GS_LAST];
8189 Lisp_Object tem;
8190 int i;
8192 bcopy (gs_format, fmt, sizeof fmt);
8194 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8195 return 0;
8197 /* Bounding box must be a list or vector containing 4 integers. */
8198 tem = fmt[GS_BOUNDING_BOX].value;
8199 if (CONSP (tem))
8201 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8202 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8203 return 0;
8204 if (!NILP (tem))
8205 return 0;
8207 else if (VECTORP (tem))
8209 if (XVECTOR (tem)->size != 4)
8210 return 0;
8211 for (i = 0; i < 4; ++i)
8212 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8213 return 0;
8215 else
8216 return 0;
8218 return 1;
8222 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8223 if successful. */
8225 static int
8226 gs_load (f, img)
8227 struct frame *f;
8228 struct image *img;
8230 char buffer[100];
8231 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8232 struct gcpro gcpro1, gcpro2;
8233 Lisp_Object frame;
8234 double in_width, in_height;
8235 Lisp_Object pixel_colors = Qnil;
8237 /* Compute pixel size of pixmap needed from the given size in the
8238 image specification. Sizes in the specification are in pt. 1 pt
8239 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8240 info. */
8241 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8242 in_width = XFASTINT (pt_width) / 72.0;
8243 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
8244 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8245 in_height = XFASTINT (pt_height) / 72.0;
8246 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
8248 if (!check_image_size (f, img->width, img->height))
8250 image_error ("Invalid image size", Qnil, Qnil);
8251 return 0;
8254 /* Create the pixmap. */
8255 xassert (img->pixmap == NO_PIXMAP);
8257 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8258 BLOCK_INPUT;
8259 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8260 img->width, img->height,
8261 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8262 UNBLOCK_INPUT;
8264 if (!img->pixmap)
8266 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8267 return 0;
8270 /* Call the loader to fill the pixmap. It returns a process object
8271 if successful. We do not record_unwind_protect here because
8272 other places in redisplay like calling window scroll functions
8273 don't either. Let the Lisp loader use `unwind-protect' instead. */
8274 GCPRO2 (window_and_pixmap_id, pixel_colors);
8276 sprintf (buffer, "%lu %lu",
8277 (unsigned long) FRAME_X_WINDOW (f),
8278 (unsigned long) img->pixmap);
8279 window_and_pixmap_id = build_string (buffer);
8281 sprintf (buffer, "%lu %lu",
8282 FRAME_FOREGROUND_PIXEL (f),
8283 FRAME_BACKGROUND_PIXEL (f));
8284 pixel_colors = build_string (buffer);
8286 XSETFRAME (frame, f);
8287 loader = image_spec_value (img->spec, QCloader, NULL);
8288 if (NILP (loader))
8289 loader = intern ("gs-load-image");
8291 img->data.lisp_val = call6 (loader, frame, img->spec,
8292 make_number (img->width),
8293 make_number (img->height),
8294 window_and_pixmap_id,
8295 pixel_colors);
8296 UNGCPRO;
8297 return PROCESSP (img->data.lisp_val);
8301 /* Kill the Ghostscript process that was started to fill PIXMAP on
8302 frame F. Called from XTread_socket when receiving an event
8303 telling Emacs that Ghostscript has finished drawing. */
8305 void
8306 x_kill_gs_process (pixmap, f)
8307 Pixmap pixmap;
8308 struct frame *f;
8310 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8311 int class, i;
8312 struct image *img;
8314 /* Find the image containing PIXMAP. */
8315 for (i = 0; i < c->used; ++i)
8316 if (c->images[i]->pixmap == pixmap)
8317 break;
8319 /* Should someone in between have cleared the image cache, for
8320 instance, give up. */
8321 if (i == c->used)
8322 return;
8324 /* Kill the GS process. We should have found PIXMAP in the image
8325 cache and its image should contain a process object. */
8326 img = c->images[i];
8327 xassert (PROCESSP (img->data.lisp_val));
8328 Fkill_process (img->data.lisp_val, Qnil);
8329 img->data.lisp_val = Qnil;
8331 #if defined (HAVE_X_WINDOWS)
8333 /* On displays with a mutable colormap, figure out the colors
8334 allocated for the image by looking at the pixels of an XImage for
8335 img->pixmap. */
8336 class = FRAME_X_VISUAL (f)->class;
8337 if (class != StaticColor && class != StaticGray && class != TrueColor)
8339 XImagePtr ximg;
8341 BLOCK_INPUT;
8343 /* Try to get an XImage for img->pixmep. */
8344 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8345 0, 0, img->width, img->height, ~0, ZPixmap);
8346 if (ximg)
8348 int x, y;
8350 /* Initialize the color table. */
8351 init_color_table ();
8353 /* For each pixel of the image, look its color up in the
8354 color table. After having done so, the color table will
8355 contain an entry for each color used by the image. */
8356 for (y = 0; y < img->height; ++y)
8357 for (x = 0; x < img->width; ++x)
8359 unsigned long pixel = XGetPixel (ximg, x, y);
8360 lookup_pixel_color (f, pixel);
8363 /* Record colors in the image. Free color table and XImage. */
8364 #ifdef COLOR_TABLE_SUPPORT
8365 img->colors = colors_in_color_table (&img->ncolors);
8366 free_color_table ();
8367 #endif
8368 XDestroyImage (ximg);
8370 #if 0 /* This doesn't seem to be the case. If we free the colors
8371 here, we get a BadAccess later in x_clear_image when
8372 freeing the colors. */
8373 /* We have allocated colors once, but Ghostscript has also
8374 allocated colors on behalf of us. So, to get the
8375 reference counts right, free them once. */
8376 if (img->ncolors)
8377 x_free_colors (f, img->colors, img->ncolors);
8378 #endif
8380 else
8381 image_error ("Cannot get X image of `%s'; colors will not be freed",
8382 img->spec, Qnil);
8384 UNBLOCK_INPUT;
8386 #endif /* HAVE_X_WINDOWS */
8388 /* Now that we have the pixmap, compute mask and transform the
8389 image if requested. */
8390 BLOCK_INPUT;
8391 postprocess_image (f, img);
8392 UNBLOCK_INPUT;
8395 #endif /* HAVE_GHOSTSCRIPT */
8398 /***********************************************************************
8399 Tests
8400 ***********************************************************************/
8402 #if GLYPH_DEBUG
8404 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8405 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8406 (spec)
8407 Lisp_Object spec;
8409 return valid_image_p (spec) ? Qt : Qnil;
8413 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8414 (spec)
8415 Lisp_Object spec;
8417 int id = -1;
8419 if (valid_image_p (spec))
8420 id = lookup_image (SELECTED_FRAME (), spec);
8422 debug_print (spec);
8423 return make_number (id);
8426 #endif /* GLYPH_DEBUG != 0 */
8429 /***********************************************************************
8430 Initialization
8431 ***********************************************************************/
8433 #ifdef HAVE_NTGUI
8434 /* Image types that rely on external libraries are loaded dynamically
8435 if the library is available. */
8436 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8437 define_image_type (image_type, init_lib_fn (libraries))
8438 #else
8439 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8440 define_image_type (image_type, 1)
8441 #endif /* HAVE_NTGUI */
8443 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8444 doc: /* Initialize image library implementing image type TYPE.
8445 Return non-nil if TYPE is a supported image type.
8447 Image types pbm and xbm are prebuilt; other types are loaded here.
8448 Libraries to load are specified in alist LIBRARIES (usually, the value
8449 of `image-library-alist', which see). */)
8450 (type, libraries)
8451 Lisp_Object type, libraries;
8453 Lisp_Object tested;
8455 /* Don't try to reload the library. */
8456 tested = Fassq (type, Vimage_type_cache);
8457 if (CONSP (tested))
8458 return XCDR (tested);
8460 #if defined (HAVE_XPM) || defined (MAC_OS)
8461 if (EQ (type, Qxpm))
8462 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8463 #endif
8465 #if defined (HAVE_JPEG) || defined (MAC_OS)
8466 if (EQ (type, Qjpeg))
8467 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8468 #endif
8470 #if defined (HAVE_TIFF) || defined (MAC_OS)
8471 if (EQ (type, Qtiff))
8472 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8473 #endif
8475 #if defined (HAVE_GIF) || defined (MAC_OS)
8476 if (EQ (type, Qgif))
8477 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8478 #endif
8480 #if defined (HAVE_PNG) || defined (MAC_OS)
8481 if (EQ (type, Qpng))
8482 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8483 #endif
8485 #ifdef HAVE_GHOSTSCRIPT
8486 if (EQ (type, Qpostscript))
8487 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8488 #endif
8490 /* If the type is not recognized, avoid testing it ever again. */
8491 CACHE_IMAGE_TYPE (type, Qnil);
8492 return Qnil;
8495 void
8496 syms_of_image ()
8498 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8500 /* Initialize this only once, since that's what we do with Vimage_types
8501 and they are supposed to be in sync. Initializing here gives correct
8502 operation on GNU/Linux of calling dump-emacs after loading some images. */
8503 image_types = NULL;
8505 /* Must be defined now becase we're going to update it below, while
8506 defining the supported image types. */
8507 DEFVAR_LISP ("image-types", &Vimage_types,
8508 doc: /* List of potentially supported image types.
8509 Each element of the list is a symbol for a image type, like 'jpeg or 'png.
8510 To check whether it is really supported, use `image-type-available-p'. */);
8511 Vimage_types = Qnil;
8513 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8514 doc: /* Alist of image types vs external libraries needed to display them.
8516 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8517 representing a supported image type, and the rest are strings giving
8518 alternate filenames for the corresponding external libraries.
8520 Emacs tries to load the libraries in the order they appear on the
8521 list; if none is loaded, the running session of Emacs won't
8522 support the image type. Types 'pbm and 'xbm don't need to be
8523 listed; they're always supported. */);
8524 Vimage_library_alist = Qnil;
8525 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
8527 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8528 doc: /* Maximum size of images.
8529 Emacs will not load an image into memory if its pixel width or
8530 pixel height exceeds this limit.
8532 If the value is an integer, it directly specifies the maximum
8533 image height and width, measured in pixels. If it is a floating
8534 point number, it specifies the maximum image height and width
8535 as a ratio to the frame height and width. If the value is
8536 non-numeric, there is no explicit limit on the size of images. */);
8537 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8539 Vimage_type_cache = Qnil;
8540 staticpro (&Vimage_type_cache);
8542 Qpbm = intern ("pbm");
8543 staticpro (&Qpbm);
8544 ADD_IMAGE_TYPE(Qpbm);
8546 Qxbm = intern ("xbm");
8547 staticpro (&Qxbm);
8548 ADD_IMAGE_TYPE(Qxbm);
8550 define_image_type (&xbm_type, 1);
8551 define_image_type (&pbm_type, 1);
8553 QCascent = intern (":ascent");
8554 staticpro (&QCascent);
8555 QCmargin = intern (":margin");
8556 staticpro (&QCmargin);
8557 QCrelief = intern (":relief");
8558 staticpro (&QCrelief);
8559 QCconversion = intern (":conversion");
8560 staticpro (&QCconversion);
8561 QCcolor_symbols = intern (":color-symbols");
8562 staticpro (&QCcolor_symbols);
8563 QCheuristic_mask = intern (":heuristic-mask");
8564 staticpro (&QCheuristic_mask);
8565 QCindex = intern (":index");
8566 staticpro (&QCindex);
8567 QCmatrix = intern (":matrix");
8568 staticpro (&QCmatrix);
8569 QCcolor_adjustment = intern (":color-adjustment");
8570 staticpro (&QCcolor_adjustment);
8571 QCmask = intern (":mask");
8572 staticpro (&QCmask);
8574 Qlaplace = intern ("laplace");
8575 staticpro (&Qlaplace);
8576 Qemboss = intern ("emboss");
8577 staticpro (&Qemboss);
8578 Qedge_detection = intern ("edge-detection");
8579 staticpro (&Qedge_detection);
8580 Qheuristic = intern ("heuristic");
8581 staticpro (&Qheuristic);
8583 Qpostscript = intern ("postscript");
8584 staticpro (&Qpostscript);
8585 #ifdef HAVE_GHOSTSCRIPT
8586 ADD_IMAGE_TYPE(Qpostscript);
8587 QCloader = intern (":loader");
8588 staticpro (&QCloader);
8589 QCbounding_box = intern (":bounding-box");
8590 staticpro (&QCbounding_box);
8591 QCpt_width = intern (":pt-width");
8592 staticpro (&QCpt_width);
8593 QCpt_height = intern (":pt-height");
8594 staticpro (&QCpt_height);
8595 #endif /* HAVE_GHOSTSCRIPT */
8597 #if defined (HAVE_XPM) || defined (MAC_OS)
8598 Qxpm = intern ("xpm");
8599 staticpro (&Qxpm);
8600 ADD_IMAGE_TYPE(Qxpm);
8601 #endif
8603 #if defined (HAVE_JPEG) || defined (MAC_OS)
8604 Qjpeg = intern ("jpeg");
8605 staticpro (&Qjpeg);
8606 ADD_IMAGE_TYPE(Qjpeg);
8607 #endif
8609 #if defined (HAVE_TIFF) || defined (MAC_OS)
8610 Qtiff = intern ("tiff");
8611 staticpro (&Qtiff);
8612 ADD_IMAGE_TYPE(Qtiff);
8613 #endif
8615 #if defined (HAVE_GIF) || defined (MAC_OS)
8616 Qgif = intern ("gif");
8617 staticpro (&Qgif);
8618 ADD_IMAGE_TYPE(Qgif);
8619 #endif
8621 #if defined (HAVE_PNG) || defined (MAC_OS)
8622 Qpng = intern ("png");
8623 staticpro (&Qpng);
8624 ADD_IMAGE_TYPE(Qpng);
8625 #endif
8627 defsubr (&Sinit_image_library);
8628 defsubr (&Sclear_image_cache);
8629 defsubr (&Simage_size);
8630 defsubr (&Simage_mask_p);
8631 defsubr (&Simage_extension_data);
8633 #if GLYPH_DEBUG
8634 defsubr (&Simagep);
8635 defsubr (&Slookup_image);
8636 #endif
8638 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
8639 doc: /* Non-nil means always draw a cross over disabled images.
8640 Disabled images are those having an `:conversion disabled' property.
8641 A cross is always drawn on black & white displays. */);
8642 cross_disabled_images = 0;
8644 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
8645 doc: /* List of directories to search for window system bitmap files. */);
8646 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
8648 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
8649 doc: /* Time after which cached images are removed from the cache.
8650 When an image has not been displayed this many seconds, remove it
8651 from the image cache. Value must be an integer or nil with nil
8652 meaning don't clear the cache. */);
8653 Vimage_cache_eviction_delay = make_number (30 * 60);
8656 void
8657 init_image ()
8659 #if defined (MAC_OSX) && TARGET_API_MAC_CARBON
8660 init_image_func_pointer ();
8661 #endif
8664 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
8665 (do not change this comment) */