[USE_ATSUI] (mac_draw_image_string_atsui) [MAC_OS_X]: Fix coordinate flipping.
[emacs.git] / src / image.c
blob0045770ac55055cbd2d9bd5310bb35d369c31d27
1 /* Functions for image support on window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #include <config.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <ctype.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
32 /* This makes the fields of a Display accessible, in Xlib header files. */
34 #define XLIB_ILLEGAL_ACCESS
36 #include "lisp.h"
37 #include "frame.h"
38 #include "window.h"
39 #include "dispextern.h"
40 #include "blockinput.h"
41 #include "systime.h"
42 #include <epaths.h>
43 #include "charset.h"
44 #include "coding.h"
47 #ifdef HAVE_X_WINDOWS
48 #include "xterm.h"
49 #include <sys/types.h>
50 #include <sys/stat.h>
52 #define COLOR_TABLE_SUPPORT 1
54 typedef struct x_bitmap_record Bitmap_Record;
55 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
56 #define NO_PIXMAP None
58 #define RGB_PIXEL_COLOR unsigned long
60 #define PIX_MASK_RETAIN 0
61 #define PIX_MASK_DRAW 1
62 #endif /* HAVE_X_WINDOWS */
65 #ifdef HAVE_NTGUI
66 #include "w32term.h"
68 /* W32_TODO : Color tables on W32. */
69 #undef COLOR_TABLE_SUPPORT
71 typedef struct w32_bitmap_record Bitmap_Record;
72 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
73 #define NO_PIXMAP 0
75 #define RGB_PIXEL_COLOR COLORREF
77 #define PIX_MASK_RETAIN 0
78 #define PIX_MASK_DRAW 1
80 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
81 #define x_defined_color w32_defined_color
82 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
83 #endif /* HAVE_NTGUI */
86 #ifdef MAC_OS
87 #include "macterm.h"
88 #include <sys/stat.h>
89 #ifndef MAC_OSX
90 #include <alloca.h>
91 #include <sys/param.h>
92 #endif
93 #if TARGET_API_MAC_CARBON
94 #ifdef MAC_OSX
95 #include <QuickTime/QuickTime.h>
96 #else /* not MAC_OSX */
97 #include <QuickTime.h>
98 #endif /* not MAC_OSX */
99 #else /* not TARGET_API_MAC_CARBON */
100 #include <Windows.h>
101 #include <Gestalt.h>
102 #include <TextUtils.h>
103 #include <ImageCompression.h>
104 #include <QuickTimeComponents.h>
105 #endif /* not TARGET_API_MAC_CARBON */
107 /* MAC_TODO : Color tables on Mac. */
108 #undef COLOR_TABLE_SUPPORT
110 #define ZPixmap 0 /* arbitrary */
111 typedef struct mac_bitmap_record Bitmap_Record;
113 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
114 #define NO_PIXMAP 0
116 #define RGB_PIXEL_COLOR unsigned long
118 #if USE_MAC_IMAGE_IO
119 #define PIX_MASK_DRAW 255
120 #define PIX_MASK_RETAIN 0
121 #else
122 /* A black pixel in a mask bitmap/pixmap means ``draw a source
123 pixel''. A white pixel means ``retain the current pixel''. */
124 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
125 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
126 #endif
128 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
129 #define x_defined_color mac_defined_color
130 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
132 #endif /* MAC_OS */
135 /* Search path for bitmap files. */
137 Lisp_Object Vx_bitmap_file_path;
140 static void x_disable_image P_ ((struct frame *, struct image *));
141 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
142 Lisp_Object));
144 static void init_color_table P_ ((void));
145 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
146 #ifdef COLOR_TABLE_SUPPORT
147 static void free_color_table P_ ((void));
148 static unsigned long *colors_in_color_table P_ ((int *n));
149 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
150 #endif
152 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
153 id, which is just an int that this section returns. Bitmaps are
154 reference counted so they can be shared among frames.
156 Bitmap indices are guaranteed to be > 0, so a negative number can
157 be used to indicate no bitmap.
159 If you use x_create_bitmap_from_data, then you must keep track of
160 the bitmaps yourself. That is, creating a bitmap from the same
161 data more than once will not be caught. */
163 #ifdef MAC_OS
165 static XImagePtr
166 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
167 Display *display; /* not used */
168 Pixmap pixmap;
169 int x, y; /* not used */
170 unsigned int width, height; /* not used */
171 unsigned long plane_mask; /* not used */
172 int format; /* not used */
174 #if !USE_MAC_IMAGE_IO
175 #if GLYPH_DEBUG
176 xassert (x == 0 && y == 0);
178 Rect ri, rp;
179 SetRect (&ri, 0, 0, width, height);
180 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
182 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
183 #endif
185 LockPixels (GetGWorldPixMap (pixmap));
186 #endif
188 return pixmap;
191 static void
192 XPutPixel (ximage, x, y, pixel)
193 XImagePtr ximage;
194 int x, y;
195 unsigned long pixel;
197 #if USE_MAC_IMAGE_IO
198 if (ximage->bits_per_pixel == 32)
199 ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
200 else
201 ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
202 #else
203 PixMapHandle pixmap = GetGWorldPixMap (ximage);
204 short depth = GetPixDepth (pixmap);
206 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
207 if (depth == 32)
209 char *base_addr = GetPixBaseAddr (pixmap);
210 short row_bytes = GetPixRowBytes (pixmap);
212 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
214 else
215 #endif
216 if (depth == 1)
218 char *base_addr = GetPixBaseAddr (pixmap);
219 short row_bytes = GetPixRowBytes (pixmap);
221 if (pixel == PIX_MASK_DRAW)
222 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
223 else
224 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
226 else
228 CGrafPtr old_port;
229 GDHandle old_gdh;
230 RGBColor color;
232 GetGWorld (&old_port, &old_gdh);
233 SetGWorld (ximage, NULL);
235 color.red = RED16_FROM_ULONG (pixel);
236 color.green = GREEN16_FROM_ULONG (pixel);
237 color.blue = BLUE16_FROM_ULONG (pixel);
239 SetCPixel (x, y, &color);
241 SetGWorld (old_port, old_gdh);
243 #endif
246 static unsigned long
247 XGetPixel (ximage, x, y)
248 XImagePtr ximage;
249 int x, y;
251 #if USE_MAC_IMAGE_IO
252 if (ximage->bits_per_pixel == 32)
253 return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
254 else
255 return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
256 #else
257 PixMapHandle pixmap = GetGWorldPixMap (ximage);
258 short depth = GetPixDepth (pixmap);
260 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
261 if (depth == 32)
263 char *base_addr = GetPixBaseAddr (pixmap);
264 short row_bytes = GetPixRowBytes (pixmap);
266 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
268 else
269 #endif
270 if (depth == 1)
272 char *base_addr = GetPixBaseAddr (pixmap);
273 short row_bytes = GetPixRowBytes (pixmap);
275 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
276 return PIX_MASK_DRAW;
277 else
278 return PIX_MASK_RETAIN;
280 else
282 CGrafPtr old_port;
283 GDHandle old_gdh;
284 RGBColor color;
286 GetGWorld (&old_port, &old_gdh);
287 SetGWorld (ximage, NULL);
289 GetCPixel (x, y, &color);
291 SetGWorld (old_port, old_gdh);
292 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
294 #endif
297 static void
298 XDestroyImage (ximg)
299 XImagePtr ximg;
301 #if !USE_MAC_IMAGE_IO
302 UnlockPixels (GetGWorldPixMap (ximg));
303 #endif
306 #if USE_CG_DRAWING
307 #if USE_MAC_IMAGE_IO
308 void
309 mac_data_provider_release_data (info, data, size)
310 void *info;
311 const void *data;
312 size_t size;
314 xfree ((void *)data);
316 #endif
318 static CGImageRef
319 mac_create_cg_image_from_image (f, img)
320 struct frame *f;
321 struct image *img;
323 #if USE_MAC_IMAGE_IO
324 XImagePtr ximg = img->pixmap;
325 CGDataProviderRef provider;
326 CGImageRef result;
328 if (img->mask)
330 int x, y;
331 unsigned long color, alpha;
333 for (y = 0; y < ximg->height; y++)
334 for (x = 0; x < ximg->width; x++)
336 color = XGetPixel (ximg, x, y);
337 alpha = XGetPixel (img->mask, x, y);
338 XPutPixel (ximg, x, y,
339 ARGB_TO_ULONG (alpha,
340 RED_FROM_ULONG (color)
341 * alpha / PIX_MASK_DRAW,
342 GREEN_FROM_ULONG (color)
343 * alpha / PIX_MASK_DRAW,
344 BLUE_FROM_ULONG (color)
345 * alpha / PIX_MASK_DRAW));
347 xfree (img->mask->data);
348 img->mask->data = NULL;
350 BLOCK_INPUT;
351 provider = CGDataProviderCreateWithData (NULL, ximg->data,
352 ximg->bytes_per_line * ximg->height,
353 mac_data_provider_release_data);
354 ximg->data = NULL;
355 result = CGImageCreate (ximg->width, ximg->height, 8, 32,
356 ximg->bytes_per_line, mac_cg_color_space_rgb,
357 ((img->mask ? kCGImageAlphaPremultipliedFirst
358 : kCGImageAlphaNoneSkipFirst)
359 | kCGBitmapByteOrder32Host),
360 provider, NULL, 0, kCGRenderingIntentDefault);
361 CGDataProviderRelease (provider);
362 UNBLOCK_INPUT;
364 return result;
365 #else
366 Pixmap mask;
367 CGImageRef result = NULL;
369 BLOCK_INPUT;
370 if (img->mask)
371 mask = img->mask;
372 else
374 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
375 img->width, img->height, 1);
376 if (mask)
378 CGrafPtr old_port;
379 GDHandle old_gdh;
380 Rect r;
382 GetGWorld (&old_port, &old_gdh);
383 SetGWorld (mask, NULL);
384 BackColor (blackColor); /* Don't mask. */
385 SetRect (&r, 0, 0, img->width, img->height);
386 EraseRect (&r);
387 SetGWorld (old_port, old_gdh);
390 if (mask)
392 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
393 GetGWorldPixMap (mask), &result);
394 if (mask != img->mask)
395 XFreePixmap (FRAME_X_DISPLAY (f), mask);
397 UNBLOCK_INPUT;
399 return result;
400 #endif
402 #endif /* USE_CG_DRAWING */
403 #endif /* MAC_OS */
406 /* Functions to access the contents of a bitmap, given an id. */
409 x_bitmap_height (f, id)
410 FRAME_PTR f;
411 int id;
413 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
417 x_bitmap_width (f, id)
418 FRAME_PTR f;
419 int id;
421 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
424 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
426 x_bitmap_pixmap (f, id)
427 FRAME_PTR f;
428 int id;
430 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
432 #endif
434 #ifdef HAVE_X_WINDOWS
436 x_bitmap_mask (f, id)
437 FRAME_PTR f;
438 int id;
440 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
442 #endif
444 /* Allocate a new bitmap record. Returns index of new record. */
446 static int
447 x_allocate_bitmap_record (f)
448 FRAME_PTR f;
450 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
451 int i;
453 if (dpyinfo->bitmaps == NULL)
455 dpyinfo->bitmaps_size = 10;
456 dpyinfo->bitmaps
457 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
458 dpyinfo->bitmaps_last = 1;
459 return 1;
462 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
463 return ++dpyinfo->bitmaps_last;
465 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
466 if (dpyinfo->bitmaps[i].refcount == 0)
467 return i + 1;
469 dpyinfo->bitmaps_size *= 2;
470 dpyinfo->bitmaps
471 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
472 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
473 return ++dpyinfo->bitmaps_last;
476 /* Add one reference to the reference count of the bitmap with id ID. */
478 void
479 x_reference_bitmap (f, id)
480 FRAME_PTR f;
481 int id;
483 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
486 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
489 x_create_bitmap_from_data (f, bits, width, height)
490 struct frame *f;
491 char *bits;
492 unsigned int width, height;
494 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
495 int id;
497 #ifdef HAVE_X_WINDOWS
498 Pixmap bitmap;
499 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
500 bits, width, height);
501 if (! bitmap)
502 return -1;
503 #endif /* HAVE_X_WINDOWS */
505 #ifdef HAVE_NTGUI
506 Pixmap bitmap;
507 bitmap = CreateBitmap (width, height,
508 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
509 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
510 bits);
511 if (! bitmap)
512 return -1;
513 #endif /* HAVE_NTGUI */
515 #ifdef MAC_OS
516 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
517 if (width % 16 != 0)
518 return -1;
519 #endif
521 id = x_allocate_bitmap_record (f);
522 #ifdef MAC_OS
523 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
524 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
525 #endif /* MAC_OS */
527 dpyinfo->bitmaps[id - 1].file = NULL;
528 dpyinfo->bitmaps[id - 1].height = height;
529 dpyinfo->bitmaps[id - 1].width = width;
530 dpyinfo->bitmaps[id - 1].refcount = 1;
532 #ifdef HAVE_X_WINDOWS
533 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
534 dpyinfo->bitmaps[id - 1].have_mask = 0;
535 dpyinfo->bitmaps[id - 1].depth = 1;
536 #endif /* HAVE_X_WINDOWS */
538 #ifdef HAVE_NTGUI
539 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
540 dpyinfo->bitmaps[id - 1].hinst = NULL;
541 dpyinfo->bitmaps[id - 1].depth = 1;
542 #endif /* HAVE_NTGUI */
544 return id;
547 /* Create bitmap from file FILE for frame F. */
550 x_create_bitmap_from_file (f, file)
551 struct frame *f;
552 Lisp_Object file;
554 #ifdef MAC_OS
555 return -1; /* MAC_TODO : bitmap support */
556 #endif /* MAC_OS */
558 #ifdef HAVE_NTGUI
559 return -1; /* W32_TODO : bitmap support */
560 #endif /* HAVE_NTGUI */
562 #ifdef HAVE_X_WINDOWS
563 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
564 unsigned int width, height;
565 Pixmap bitmap;
566 int xhot, yhot, result, id;
567 Lisp_Object found;
568 int fd;
569 char *filename;
571 /* Look for an existing bitmap with the same name. */
572 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
574 if (dpyinfo->bitmaps[id].refcount
575 && dpyinfo->bitmaps[id].file
576 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
578 ++dpyinfo->bitmaps[id].refcount;
579 return id + 1;
583 /* Search bitmap-file-path for the file, if appropriate. */
584 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
585 if (fd < 0)
586 return -1;
587 emacs_close (fd);
589 filename = (char *) SDATA (found);
591 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
592 filename, &width, &height, &bitmap, &xhot, &yhot);
593 if (result != BitmapSuccess)
594 return -1;
596 id = x_allocate_bitmap_record (f);
597 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
598 dpyinfo->bitmaps[id - 1].have_mask = 0;
599 dpyinfo->bitmaps[id - 1].refcount = 1;
600 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
601 dpyinfo->bitmaps[id - 1].depth = 1;
602 dpyinfo->bitmaps[id - 1].height = height;
603 dpyinfo->bitmaps[id - 1].width = width;
604 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
606 return id;
607 #endif /* HAVE_X_WINDOWS */
610 /* Free bitmap B. */
612 static void
613 Free_Bitmap_Record (dpyinfo, bm)
614 Display_Info *dpyinfo;
615 Bitmap_Record *bm;
617 #ifdef HAVE_X_WINDOWS
618 XFreePixmap (dpyinfo->display, bm->pixmap);
619 if (bm->have_mask)
620 XFreePixmap (dpyinfo->display, bm->mask);
621 #endif /* HAVE_X_WINDOWS */
623 #ifdef HAVE_NTGUI
624 DeleteObject (bm->pixmap);
625 #endif /* HAVE_NTGUI */
627 #ifdef MAC_OS
628 xfree (bm->bitmap_data); /* Added ++kfs */
629 bm->bitmap_data = NULL;
630 #endif /* MAC_OS */
632 if (bm->file)
634 xfree (bm->file);
635 bm->file = NULL;
639 /* Remove reference to bitmap with id number ID. */
641 void
642 x_destroy_bitmap (f, id)
643 FRAME_PTR f;
644 int id;
646 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
648 if (id > 0)
650 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
652 if (--bm->refcount == 0)
654 BLOCK_INPUT;
655 Free_Bitmap_Record (dpyinfo, bm);
656 UNBLOCK_INPUT;
661 /* Free all the bitmaps for the display specified by DPYINFO. */
663 void
664 x_destroy_all_bitmaps (dpyinfo)
665 Display_Info *dpyinfo;
667 int i;
668 Bitmap_Record *bm = dpyinfo->bitmaps;
670 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
671 if (bm->refcount > 0)
672 Free_Bitmap_Record (dpyinfo, bm);
674 dpyinfo->bitmaps_last = 0;
678 #ifdef HAVE_X_WINDOWS
680 /* Useful functions defined in the section
681 `Image type independent image structures' below. */
683 static unsigned long four_corners_best P_ ((XImagePtr ximg,
684 int *corners,
685 unsigned long width,
686 unsigned long height));
688 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
689 int depth, XImagePtr *ximg,
690 Pixmap *pixmap));
692 static void x_destroy_x_image P_ ((XImagePtr ximg));
695 /* Create a mask of a bitmap. Note is this not a perfect mask.
696 It's nicer with some borders in this context */
699 x_create_bitmap_mask (f, id)
700 struct frame *f;
701 int id;
703 Pixmap pixmap, mask;
704 XImagePtr ximg, mask_img;
705 unsigned long width, height;
706 int result;
707 unsigned long bg;
708 unsigned long x, y, xp, xm, yp, ym;
709 GC gc;
711 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
713 if (!(id > 0))
714 return -1;
716 pixmap = x_bitmap_pixmap (f, id);
717 width = x_bitmap_width (f, id);
718 height = x_bitmap_height (f, id);
720 BLOCK_INPUT;
721 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
722 ~0, ZPixmap);
724 if (!ximg)
726 UNBLOCK_INPUT;
727 return -1;
730 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
732 UNBLOCK_INPUT;
733 if (!result)
735 XDestroyImage (ximg);
736 return -1;
739 bg = four_corners_best (ximg, NULL, width, height);
741 for (y = 0; y < ximg->height; ++y)
743 for (x = 0; x < ximg->width; ++x)
745 xp = x != ximg->width - 1 ? x + 1 : 0;
746 xm = x != 0 ? x - 1 : ximg->width - 1;
747 yp = y != ximg->height - 1 ? y + 1 : 0;
748 ym = y != 0 ? y - 1 : ximg->height - 1;
749 if (XGetPixel (ximg, x, y) == bg
750 && XGetPixel (ximg, x, yp) == bg
751 && XGetPixel (ximg, x, ym) == bg
752 && XGetPixel (ximg, xp, y) == bg
753 && XGetPixel (ximg, xp, yp) == bg
754 && XGetPixel (ximg, xp, ym) == bg
755 && XGetPixel (ximg, xm, y) == bg
756 && XGetPixel (ximg, xm, yp) == bg
757 && XGetPixel (ximg, xm, ym) == bg)
758 XPutPixel (mask_img, x, y, 0);
759 else
760 XPutPixel (mask_img, x, y, 1);
764 xassert (interrupt_input_blocked);
765 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
766 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
767 width, height);
768 XFreeGC (FRAME_X_DISPLAY (f), gc);
770 dpyinfo->bitmaps[id - 1].have_mask = 1;
771 dpyinfo->bitmaps[id - 1].mask = mask;
773 XDestroyImage (ximg);
774 x_destroy_x_image (mask_img);
776 return 0;
779 #endif /* HAVE_X_WINDOWS */
782 /***********************************************************************
783 Image types
784 ***********************************************************************/
786 /* Value is the number of elements of vector VECTOR. */
788 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
790 /* List of supported image types. Use define_image_type to add new
791 types. Use lookup_image_type to find a type for a given symbol. */
793 static struct image_type *image_types;
795 /* A list of symbols, one for each supported image type. */
797 Lisp_Object Vimage_types;
799 /* An alist of image types and libraries that implement the type. */
801 Lisp_Object Vimage_library_alist;
803 /* Cache for delayed-loading image types. */
805 static Lisp_Object Vimage_type_cache;
807 /* The symbol `xbm' which is used as the type symbol for XBM images. */
809 Lisp_Object Qxbm;
811 /* Keywords. */
813 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
814 extern Lisp_Object QCdata, QCtype, Qcount;
815 extern Lisp_Object Qcenter;
816 Lisp_Object QCascent, QCmargin, QCrelief;
817 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
818 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
820 /* Other symbols. */
822 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
824 /* Time in seconds after which images should be removed from the cache
825 if not displayed. */
827 Lisp_Object Vimage_cache_eviction_delay;
829 /* Function prototypes. */
831 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
832 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
833 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
834 static void x_laplace P_ ((struct frame *, struct image *));
835 static void x_emboss P_ ((struct frame *, struct image *));
836 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
837 Lisp_Object));
839 #define CACHE_IMAGE_TYPE(type, status) \
840 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
842 #define ADD_IMAGE_TYPE(type) \
843 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
845 /* Define a new image type from TYPE. This adds a copy of TYPE to
846 image_types and caches the loading status of TYPE. */
848 static Lisp_Object
849 define_image_type (type, loaded)
850 struct image_type *type;
851 int loaded;
853 Lisp_Object success;
855 if (!loaded)
856 success = Qnil;
857 else
859 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
860 The initialized data segment is read-only. */
861 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
862 bcopy (type, p, sizeof *p);
863 p->next = image_types;
864 image_types = p;
865 success = Qt;
868 CACHE_IMAGE_TYPE (*type->type, success);
869 return success;
873 /* Look up image type SYMBOL, and return a pointer to its image_type
874 structure. Value is null if SYMBOL is not a known image type. */
876 static INLINE struct image_type *
877 lookup_image_type (symbol)
878 Lisp_Object symbol;
880 struct image_type *type;
882 /* We must initialize the image-type if it hasn't been already. */
883 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
884 return 0; /* unimplemented */
886 for (type = image_types; type; type = type->next)
887 if (EQ (symbol, *type->type))
888 break;
890 return type;
894 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
895 valid image specification is a list whose car is the symbol
896 `image', and whose rest is a property list. The property list must
897 contain a value for key `:type'. That value must be the name of a
898 supported image type. The rest of the property list depends on the
899 image type. */
902 valid_image_p (object)
903 Lisp_Object object;
905 int valid_p = 0;
907 if (IMAGEP (object))
909 Lisp_Object tem;
911 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
912 if (EQ (XCAR (tem), QCtype))
914 tem = XCDR (tem);
915 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
917 struct image_type *type;
918 type = lookup_image_type (XCAR (tem));
919 if (type)
920 valid_p = type->valid_p (object);
923 break;
927 return valid_p;
931 /* Log error message with format string FORMAT and argument ARG.
932 Signaling an error, e.g. when an image cannot be loaded, is not a
933 good idea because this would interrupt redisplay, and the error
934 message display would lead to another redisplay. This function
935 therefore simply displays a message. */
937 static void
938 image_error (format, arg1, arg2)
939 char *format;
940 Lisp_Object arg1, arg2;
942 add_to_log (format, arg1, arg2);
947 /***********************************************************************
948 Image specifications
949 ***********************************************************************/
951 enum image_value_type
953 IMAGE_DONT_CHECK_VALUE_TYPE,
954 IMAGE_STRING_VALUE,
955 IMAGE_STRING_OR_NIL_VALUE,
956 IMAGE_SYMBOL_VALUE,
957 IMAGE_POSITIVE_INTEGER_VALUE,
958 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
959 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
960 IMAGE_ASCENT_VALUE,
961 IMAGE_INTEGER_VALUE,
962 IMAGE_FUNCTION_VALUE,
963 IMAGE_NUMBER_VALUE,
964 IMAGE_BOOL_VALUE
967 /* Structure used when parsing image specifications. */
969 struct image_keyword
971 /* Name of keyword. */
972 char *name;
974 /* The type of value allowed. */
975 enum image_value_type type;
977 /* Non-zero means key must be present. */
978 int mandatory_p;
980 /* Used to recognize duplicate keywords in a property list. */
981 int count;
983 /* The value that was found. */
984 Lisp_Object value;
988 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
989 int, Lisp_Object));
990 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
993 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
994 has the format (image KEYWORD VALUE ...). One of the keyword/
995 value pairs must be `:type TYPE'. KEYWORDS is a vector of
996 image_keywords structures of size NKEYWORDS describing other
997 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
999 static int
1000 parse_image_spec (spec, keywords, nkeywords, type)
1001 Lisp_Object spec;
1002 struct image_keyword *keywords;
1003 int nkeywords;
1004 Lisp_Object type;
1006 int i;
1007 Lisp_Object plist;
1009 if (!IMAGEP (spec))
1010 return 0;
1012 plist = XCDR (spec);
1013 while (CONSP (plist))
1015 Lisp_Object key, value;
1017 /* First element of a pair must be a symbol. */
1018 key = XCAR (plist);
1019 plist = XCDR (plist);
1020 if (!SYMBOLP (key))
1021 return 0;
1023 /* There must follow a value. */
1024 if (!CONSP (plist))
1025 return 0;
1026 value = XCAR (plist);
1027 plist = XCDR (plist);
1029 /* Find key in KEYWORDS. Error if not found. */
1030 for (i = 0; i < nkeywords; ++i)
1031 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
1032 break;
1034 if (i == nkeywords)
1035 continue;
1037 /* Record that we recognized the keyword. If a keywords
1038 was found more than once, it's an error. */
1039 keywords[i].value = value;
1040 ++keywords[i].count;
1042 if (keywords[i].count > 1)
1043 return 0;
1045 /* Check type of value against allowed type. */
1046 switch (keywords[i].type)
1048 case IMAGE_STRING_VALUE:
1049 if (!STRINGP (value))
1050 return 0;
1051 break;
1053 case IMAGE_STRING_OR_NIL_VALUE:
1054 if (!STRINGP (value) && !NILP (value))
1055 return 0;
1056 break;
1058 case IMAGE_SYMBOL_VALUE:
1059 if (!SYMBOLP (value))
1060 return 0;
1061 break;
1063 case IMAGE_POSITIVE_INTEGER_VALUE:
1064 if (!INTEGERP (value) || XINT (value) <= 0)
1065 return 0;
1066 break;
1068 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
1069 if (INTEGERP (value) && XINT (value) >= 0)
1070 break;
1071 if (CONSP (value)
1072 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
1073 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
1074 break;
1075 return 0;
1077 case IMAGE_ASCENT_VALUE:
1078 if (SYMBOLP (value) && EQ (value, Qcenter))
1079 break;
1080 else if (INTEGERP (value)
1081 && XINT (value) >= 0
1082 && XINT (value) <= 100)
1083 break;
1084 return 0;
1086 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1087 if (!INTEGERP (value) || XINT (value) < 0)
1088 return 0;
1089 break;
1091 case IMAGE_DONT_CHECK_VALUE_TYPE:
1092 break;
1094 case IMAGE_FUNCTION_VALUE:
1095 value = indirect_function (value);
1096 if (SUBRP (value)
1097 || COMPILEDP (value)
1098 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1099 break;
1100 return 0;
1102 case IMAGE_NUMBER_VALUE:
1103 if (!INTEGERP (value) && !FLOATP (value))
1104 return 0;
1105 break;
1107 case IMAGE_INTEGER_VALUE:
1108 if (!INTEGERP (value))
1109 return 0;
1110 break;
1112 case IMAGE_BOOL_VALUE:
1113 if (!NILP (value) && !EQ (value, Qt))
1114 return 0;
1115 break;
1117 default:
1118 abort ();
1119 break;
1122 if (EQ (key, QCtype) && !EQ (type, value))
1123 return 0;
1126 /* Check that all mandatory fields are present. */
1127 for (i = 0; i < nkeywords; ++i)
1128 if (keywords[i].mandatory_p && keywords[i].count == 0)
1129 return 0;
1131 return NILP (plist);
1135 /* Return the value of KEY in image specification SPEC. Value is nil
1136 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1137 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1139 static Lisp_Object
1140 image_spec_value (spec, key, found)
1141 Lisp_Object spec, key;
1142 int *found;
1144 Lisp_Object tail;
1146 xassert (valid_image_p (spec));
1148 for (tail = XCDR (spec);
1149 CONSP (tail) && CONSP (XCDR (tail));
1150 tail = XCDR (XCDR (tail)))
1152 if (EQ (XCAR (tail), key))
1154 if (found)
1155 *found = 1;
1156 return XCAR (XCDR (tail));
1160 if (found)
1161 *found = 0;
1162 return Qnil;
1166 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1167 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1168 PIXELS non-nil means return the size in pixels, otherwise return the
1169 size in canonical character units.
1170 FRAME is the frame on which the image will be displayed. FRAME nil
1171 or omitted means use the selected frame. */)
1172 (spec, pixels, frame)
1173 Lisp_Object spec, pixels, frame;
1175 Lisp_Object size;
1177 size = Qnil;
1178 if (valid_image_p (spec))
1180 struct frame *f = check_x_frame (frame);
1181 int id = lookup_image (f, spec);
1182 struct image *img = IMAGE_FROM_ID (f, id);
1183 int width = img->width + 2 * img->hmargin;
1184 int height = img->height + 2 * img->vmargin;
1186 if (NILP (pixels))
1187 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1188 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1189 else
1190 size = Fcons (make_number (width), make_number (height));
1192 else
1193 error ("Invalid image specification");
1195 return size;
1199 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1200 doc: /* Return t if image SPEC has a mask bitmap.
1201 FRAME is the frame on which the image will be displayed. FRAME nil
1202 or omitted means use the selected frame. */)
1203 (spec, frame)
1204 Lisp_Object spec, frame;
1206 Lisp_Object mask;
1208 mask = Qnil;
1209 if (valid_image_p (spec))
1211 struct frame *f = check_x_frame (frame);
1212 int id = lookup_image (f, spec);
1213 struct image *img = IMAGE_FROM_ID (f, id);
1214 if (img->mask)
1215 mask = Qt;
1217 else
1218 error ("Invalid image specification");
1220 return mask;
1223 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1224 doc: /* Return extension data for image SPEC.
1225 FRAME is the frame on which the image will be displayed. FRAME nil
1226 or omitted means use the selected frame. */)
1227 (spec, frame)
1228 Lisp_Object spec, frame;
1230 Lisp_Object ext;
1232 ext = Qnil;
1233 if (valid_image_p (spec))
1235 struct frame *f = check_x_frame (frame);
1236 int id = lookup_image (f, spec);
1237 struct image *img = IMAGE_FROM_ID (f, id);
1238 ext = img->data.lisp_val;
1241 return ext;
1245 /***********************************************************************
1246 Image type independent image structures
1247 ***********************************************************************/
1249 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1250 static void free_image P_ ((struct frame *f, struct image *img));
1251 static int check_image_size P_ ((struct frame *f, int width, int height));
1253 #define MAX_IMAGE_SIZE 6.0
1254 Lisp_Object Vmax_image_size;
1256 /* Allocate and return a new image structure for image specification
1257 SPEC. SPEC has a hash value of HASH. */
1259 static struct image *
1260 make_image (spec, hash)
1261 Lisp_Object spec;
1262 unsigned hash;
1264 struct image *img = (struct image *) xmalloc (sizeof *img);
1266 xassert (valid_image_p (spec));
1267 bzero (img, sizeof *img);
1268 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1269 xassert (img->type != NULL);
1270 img->spec = spec;
1271 img->data.lisp_val = Qnil;
1272 img->ascent = DEFAULT_IMAGE_ASCENT;
1273 img->hash = hash;
1274 img->corners[BOT_CORNER] = -1; /* Full image */
1275 return img;
1279 /* Free image IMG which was used on frame F, including its resources. */
1281 static void
1282 free_image (f, img)
1283 struct frame *f;
1284 struct image *img;
1286 if (img)
1288 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1290 /* Remove IMG from the hash table of its cache. */
1291 if (img->prev)
1292 img->prev->next = img->next;
1293 else
1294 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1296 if (img->next)
1297 img->next->prev = img->prev;
1299 c->images[img->id] = NULL;
1301 /* Free resources, then free IMG. */
1302 img->type->free (f, img);
1303 xfree (img);
1307 /* Return 1 if the given widths and heights are valid for display;
1308 otherwise, return 0. */
1311 check_image_size (f, width, height)
1312 struct frame *f;
1313 int width;
1314 int height;
1316 int w, h;
1318 if (width <= 0 || height <= 0)
1319 return 0;
1321 if (INTEGERP (Vmax_image_size))
1322 w = h = XINT (Vmax_image_size);
1323 else if (FLOATP (Vmax_image_size))
1325 if (f != NULL)
1327 w = FRAME_PIXEL_WIDTH (f);
1328 h = FRAME_PIXEL_HEIGHT (f);
1330 else
1331 w = h = 1024; /* Arbitrary size for unknown frame. */
1332 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1333 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1335 else
1336 return 1;
1338 return (width <= w && height <= h);
1341 /* Prepare image IMG for display on frame F. Must be called before
1342 drawing an image. */
1344 void
1345 prepare_image_for_display (f, img)
1346 struct frame *f;
1347 struct image *img;
1349 EMACS_TIME t;
1351 /* We're about to display IMG, so set its timestamp to `now'. */
1352 EMACS_GET_TIME (t);
1353 img->timestamp = EMACS_SECS (t);
1355 /* If IMG doesn't have a pixmap yet, load it now, using the image
1356 type dependent loader function. */
1357 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1358 img->load_failed_p = img->type->load (f, img) == 0;
1360 #if defined (MAC_OS) && USE_CG_DRAWING
1361 if (!img->load_failed_p && img->data.ptr_val == NULL)
1363 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1364 if (img->data.ptr_val == NULL)
1366 img->load_failed_p = 1;
1367 img->type->free (f, img);
1370 #endif
1374 /* Value is the number of pixels for the ascent of image IMG when
1375 drawn in face FACE. */
1378 image_ascent (img, face, slice)
1379 struct image *img;
1380 struct face *face;
1381 struct glyph_slice *slice;
1383 int height;
1384 int ascent;
1386 if (slice->height == img->height)
1387 height = img->height + img->vmargin;
1388 else if (slice->y == 0)
1389 height = slice->height + img->vmargin;
1390 else
1391 height = slice->height;
1393 if (img->ascent == CENTERED_IMAGE_ASCENT)
1395 if (face->font)
1397 #ifdef HAVE_NTGUI
1398 /* W32 specific version. Why?. ++kfs */
1399 ascent = height / 2 - (FONT_DESCENT(face->font)
1400 - FONT_BASE(face->font)) / 2;
1401 #else
1402 /* This expression is arranged so that if the image can't be
1403 exactly centered, it will be moved slightly up. This is
1404 because a typical font is `top-heavy' (due to the presence
1405 uppercase letters), so the image placement should err towards
1406 being top-heavy too. It also just generally looks better. */
1407 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1408 #endif /* HAVE_NTGUI */
1410 else
1411 ascent = height / 2;
1413 else
1414 ascent = (int) (height * img->ascent / 100.0);
1416 return ascent;
1420 /* Image background colors. */
1422 /* Find the "best" corner color of a bitmap.
1423 On W32, XIMG is assumed to a device context with the bitmap selected. */
1425 static RGB_PIXEL_COLOR
1426 four_corners_best (ximg, corners, width, height)
1427 XImagePtr_or_DC ximg;
1428 int *corners;
1429 unsigned long width, height;
1431 RGB_PIXEL_COLOR corner_pixels[4], best;
1432 int i, best_count;
1434 if (corners && corners[BOT_CORNER] >= 0)
1436 /* Get the colors at the corner_pixels of ximg. */
1437 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1438 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1439 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1440 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1442 else
1444 /* Get the colors at the corner_pixels of ximg. */
1445 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1446 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1447 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1448 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1450 /* Choose the most frequently found color as background. */
1451 for (i = best_count = 0; i < 4; ++i)
1453 int j, n;
1455 for (j = n = 0; j < 4; ++j)
1456 if (corner_pixels[i] == corner_pixels[j])
1457 ++n;
1459 if (n > best_count)
1460 best = corner_pixels[i], best_count = n;
1463 return best;
1466 /* Portability macros */
1468 #ifdef HAVE_NTGUI
1470 #define Destroy_Image(img_dc, prev) \
1471 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1473 #define Free_Pixmap(display, pixmap) \
1474 DeleteObject (pixmap)
1476 #else
1478 #define Destroy_Image(ximg, dummy) \
1479 XDestroyImage (ximg)
1481 #define Free_Pixmap(display, pixmap) \
1482 XFreePixmap (display, pixmap)
1484 #endif /* HAVE_NTGUI */
1487 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1488 it is guessed heuristically. If non-zero, XIMG is an existing
1489 XImage object (or device context with the image selected on W32) to
1490 use for the heuristic. */
1492 RGB_PIXEL_COLOR
1493 image_background (img, f, ximg)
1494 struct image *img;
1495 struct frame *f;
1496 XImagePtr_or_DC ximg;
1498 if (! img->background_valid)
1499 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1501 int free_ximg = !ximg;
1502 #ifdef HAVE_NTGUI
1503 HGDIOBJ prev;
1504 #endif /* HAVE_NTGUI */
1506 if (free_ximg)
1508 #ifndef HAVE_NTGUI
1509 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1510 0, 0, img->width, img->height, ~0, ZPixmap);
1511 #else
1512 HDC frame_dc = get_frame_dc (f);
1513 ximg = CreateCompatibleDC (frame_dc);
1514 release_frame_dc (f, frame_dc);
1515 prev = SelectObject (ximg, img->pixmap);
1516 #endif /* !HAVE_NTGUI */
1519 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1521 if (free_ximg)
1522 Destroy_Image (ximg, prev);
1524 img->background_valid = 1;
1527 return img->background;
1530 /* Return the `background_transparent' field of IMG. If IMG doesn't
1531 have one yet, it is guessed heuristically. If non-zero, MASK is an
1532 existing XImage object to use for the heuristic. */
1535 image_background_transparent (img, f, mask)
1536 struct image *img;
1537 struct frame *f;
1538 XImagePtr_or_DC mask;
1540 if (! img->background_transparent_valid)
1541 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1543 if (img->mask)
1545 int free_mask = !mask;
1546 #ifdef HAVE_NTGUI
1547 HGDIOBJ prev;
1548 #endif /* HAVE_NTGUI */
1550 if (free_mask)
1552 #ifndef HAVE_NTGUI
1553 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1554 0, 0, img->width, img->height, ~0, ZPixmap);
1555 #else
1556 HDC frame_dc = get_frame_dc (f);
1557 mask = CreateCompatibleDC (frame_dc);
1558 release_frame_dc (f, frame_dc);
1559 prev = SelectObject (mask, img->mask);
1560 #endif /* HAVE_NTGUI */
1563 img->background_transparent
1564 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1566 if (free_mask)
1567 Destroy_Image (mask, prev);
1569 else
1570 img->background_transparent = 0;
1572 img->background_transparent_valid = 1;
1575 return img->background_transparent;
1579 /***********************************************************************
1580 Helper functions for X image types
1581 ***********************************************************************/
1583 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1584 int, int));
1585 static void x_clear_image P_ ((struct frame *f, struct image *img));
1586 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1587 struct image *img,
1588 Lisp_Object color_name,
1589 unsigned long dflt));
1592 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1593 free the pixmap if any. MASK_P non-zero means clear the mask
1594 pixmap if any. COLORS_P non-zero means free colors allocated for
1595 the image, if any. */
1597 static void
1598 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1599 struct frame *f;
1600 struct image *img;
1601 int pixmap_p, mask_p, colors_p;
1603 if (pixmap_p && img->pixmap)
1605 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1606 img->pixmap = NO_PIXMAP;
1607 img->background_valid = 0;
1610 if (mask_p && img->mask)
1612 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1613 img->mask = NO_PIXMAP;
1614 img->background_transparent_valid = 0;
1617 if (colors_p && img->ncolors)
1619 /* MAC_TODO: color table support. */
1620 /* W32_TODO: color table support. */
1621 #ifdef HAVE_X_WINDOWS
1622 x_free_colors (f, img->colors, img->ncolors);
1623 #endif /* HAVE_X_WINDOWS */
1624 xfree (img->colors);
1625 img->colors = NULL;
1626 img->ncolors = 0;
1629 #if defined (MAC_OS) && USE_CG_DRAWING
1630 if (img->data.ptr_val)
1632 CGImageRelease (img->data.ptr_val);
1633 img->data.ptr_val = NULL;
1635 #endif
1638 /* Free X resources of image IMG which is used on frame F. */
1640 static void
1641 x_clear_image (f, img)
1642 struct frame *f;
1643 struct image *img;
1645 BLOCK_INPUT;
1646 x_clear_image_1 (f, img, 1, 1, 1);
1647 UNBLOCK_INPUT;
1651 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1652 cannot be allocated, use DFLT. Add a newly allocated color to
1653 IMG->colors, so that it can be freed again. Value is the pixel
1654 color. */
1656 static unsigned long
1657 x_alloc_image_color (f, img, color_name, dflt)
1658 struct frame *f;
1659 struct image *img;
1660 Lisp_Object color_name;
1661 unsigned long dflt;
1663 XColor color;
1664 unsigned long result;
1666 xassert (STRINGP (color_name));
1668 if (x_defined_color (f, SDATA (color_name), &color, 1))
1670 /* This isn't called frequently so we get away with simply
1671 reallocating the color vector to the needed size, here. */
1672 ++img->ncolors;
1673 img->colors =
1674 (unsigned long *) xrealloc (img->colors,
1675 img->ncolors * sizeof *img->colors);
1676 img->colors[img->ncolors - 1] = color.pixel;
1677 result = color.pixel;
1679 else
1680 result = dflt;
1682 return result;
1687 /***********************************************************************
1688 Image Cache
1689 ***********************************************************************/
1691 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1692 static void cache_image P_ ((struct frame *f, struct image *img));
1693 static void postprocess_image P_ ((struct frame *, struct image *));
1695 /* Return a new, initialized image cache that is allocated from the
1696 heap. Call free_image_cache to free an image cache. */
1698 struct image_cache *
1699 make_image_cache ()
1701 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1702 int size;
1704 bzero (c, sizeof *c);
1705 c->size = 50;
1706 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1707 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1708 c->buckets = (struct image **) xmalloc (size);
1709 bzero (c->buckets, size);
1710 return c;
1714 /* Find an image matching SPEC in the cache, and return it. If no
1715 image is found, return NULL. */
1716 static struct image *
1717 search_image_cache (f, spec, hash)
1718 struct frame *f;
1719 Lisp_Object spec;
1720 unsigned hash;
1722 struct image *img;
1723 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1724 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1726 if (!c) return NULL;
1728 /* If the image spec does not specify a background color, the cached
1729 image must have the same background color as the current frame.
1730 The foreground color must also match, for the sake of monochrome
1731 images.
1733 In fact, we could ignore the foreground color matching condition
1734 for color images, or if the image spec specifies :foreground;
1735 similarly we could ignore the background color matching condition
1736 for formats that don't use transparency (such as jpeg), or if the
1737 image spec specifies :background. However, the extra memory
1738 usage is probably negligible in practice, so we don't bother. */
1740 for (img = c->buckets[i]; img; img = img->next)
1741 if (img->hash == hash
1742 && !NILP (Fequal (img->spec, spec))
1743 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1744 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1745 break;
1746 return img;
1750 /* Search frame F for an image with spec SPEC, and free it. */
1752 static void
1753 uncache_image (f, spec)
1754 struct frame *f;
1755 Lisp_Object spec;
1757 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1758 if (img)
1759 free_image (f, img);
1763 /* Free image cache of frame F. Be aware that X frames share images
1764 caches. */
1766 void
1767 free_image_cache (f)
1768 struct frame *f;
1770 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1771 if (c)
1773 int i;
1775 /* Cache should not be referenced by any frame when freed. */
1776 xassert (c->refcount == 0);
1778 for (i = 0; i < c->used; ++i)
1779 free_image (f, c->images[i]);
1780 xfree (c->images);
1781 xfree (c->buckets);
1782 xfree (c);
1783 FRAME_X_IMAGE_CACHE (f) = NULL;
1788 /* Clear image cache of frame F. FORCE_P non-zero means free all
1789 images. FORCE_P zero means clear only images that haven't been
1790 displayed for some time. Should be called from time to time to
1791 reduce the number of loaded images. If image-cache-eviction-delay
1792 is non-nil, this frees images in the cache which weren't displayed
1793 for at least that many seconds. */
1795 void
1796 clear_image_cache (f, force_p)
1797 struct frame *f;
1798 int force_p;
1800 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
1802 if (c && INTEGERP (Vimage_cache_eviction_delay))
1804 EMACS_TIME t;
1805 unsigned long old;
1806 int i, nfreed;
1808 EMACS_GET_TIME (t);
1809 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1811 /* Block input so that we won't be interrupted by a SIGIO
1812 while being in an inconsistent state. */
1813 BLOCK_INPUT;
1815 for (i = nfreed = 0; i < c->used; ++i)
1817 struct image *img = c->images[i];
1818 if (img != NULL
1819 && (force_p || img->timestamp < old))
1821 free_image (f, img);
1822 ++nfreed;
1826 /* We may be clearing the image cache because, for example,
1827 Emacs was iconified for a longer period of time. In that
1828 case, current matrices may still contain references to
1829 images freed above. So, clear these matrices. */
1830 if (nfreed)
1832 Lisp_Object tail, frame;
1834 FOR_EACH_FRAME (tail, frame)
1836 struct frame *f = XFRAME (frame);
1837 if (FRAME_WINDOW_P (f)
1838 && FRAME_X_IMAGE_CACHE (f) == c)
1839 clear_current_matrices (f);
1842 ++windows_or_buffers_changed;
1845 UNBLOCK_INPUT;
1850 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1851 0, 1, 0,
1852 doc: /* Clear the image cache of FRAME.
1853 FRAME nil or omitted means use the selected frame.
1854 FRAME t means clear the image caches of all frames. */)
1855 (frame)
1856 Lisp_Object frame;
1858 if (EQ (frame, Qt))
1860 Lisp_Object tail;
1862 FOR_EACH_FRAME (tail, frame)
1863 if (FRAME_WINDOW_P (XFRAME (frame)))
1864 clear_image_cache (XFRAME (frame), 1);
1866 else
1867 clear_image_cache (check_x_frame (frame), 1);
1869 return Qnil;
1873 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1874 1, 2, 0,
1875 doc: /* Refresh the image with specification SPEC on frame FRAME.
1876 If SPEC specifies an image file, the displayed image is updated with
1877 the current contents of that file.
1878 FRAME nil or omitted means use the selected frame.
1879 FRAME t means refresh the image on all frames. */)
1880 (spec, frame)
1881 Lisp_Object spec, frame;
1883 if (!valid_image_p (spec))
1884 error ("Invalid image specification");
1886 if (EQ (frame, Qt))
1888 Lisp_Object tail;
1889 FOR_EACH_FRAME (tail, frame)
1891 struct frame *f = XFRAME (frame);
1892 if (FRAME_WINDOW_P (f))
1893 uncache_image (f, spec);
1896 else
1897 uncache_image (check_x_frame (frame), spec);
1899 return Qnil;
1903 /* Compute masks and transform image IMG on frame F, as specified
1904 by the image's specification, */
1906 static void
1907 postprocess_image (f, img)
1908 struct frame *f;
1909 struct image *img;
1911 /* Manipulation of the image's mask. */
1912 if (img->pixmap)
1914 Lisp_Object conversion, spec;
1915 Lisp_Object mask;
1917 spec = img->spec;
1919 /* `:heuristic-mask t'
1920 `:mask heuristic'
1921 means build a mask heuristically.
1922 `:heuristic-mask (R G B)'
1923 `:mask (heuristic (R G B))'
1924 means build a mask from color (R G B) in the
1925 image.
1926 `:mask nil'
1927 means remove a mask, if any. */
1929 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1930 if (!NILP (mask))
1931 x_build_heuristic_mask (f, img, mask);
1932 else
1934 int found_p;
1936 mask = image_spec_value (spec, QCmask, &found_p);
1938 if (EQ (mask, Qheuristic))
1939 x_build_heuristic_mask (f, img, Qt);
1940 else if (CONSP (mask)
1941 && EQ (XCAR (mask), Qheuristic))
1943 if (CONSP (XCDR (mask)))
1944 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1945 else
1946 x_build_heuristic_mask (f, img, XCDR (mask));
1948 else if (NILP (mask) && found_p && img->mask)
1950 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1951 img->mask = NO_PIXMAP;
1956 /* Should we apply an image transformation algorithm? */
1957 conversion = image_spec_value (spec, QCconversion, NULL);
1958 if (EQ (conversion, Qdisabled))
1959 x_disable_image (f, img);
1960 else if (EQ (conversion, Qlaplace))
1961 x_laplace (f, img);
1962 else if (EQ (conversion, Qemboss))
1963 x_emboss (f, img);
1964 else if (CONSP (conversion)
1965 && EQ (XCAR (conversion), Qedge_detection))
1967 Lisp_Object tem;
1968 tem = XCDR (conversion);
1969 if (CONSP (tem))
1970 x_edge_detection (f, img,
1971 Fplist_get (tem, QCmatrix),
1972 Fplist_get (tem, QCcolor_adjustment));
1978 /* Return the id of image with Lisp specification SPEC on frame F.
1979 SPEC must be a valid Lisp image specification (see valid_image_p). */
1982 lookup_image (f, spec)
1983 struct frame *f;
1984 Lisp_Object spec;
1986 struct image *img;
1987 unsigned hash;
1988 struct gcpro gcpro1;
1989 EMACS_TIME now;
1991 /* F must be a window-system frame, and SPEC must be a valid image
1992 specification. */
1993 xassert (FRAME_WINDOW_P (f));
1994 xassert (valid_image_p (spec));
1996 GCPRO1 (spec);
1998 /* Look up SPEC in the hash table of the image cache. */
1999 hash = sxhash (spec, 0);
2000 img = search_image_cache (f, spec, hash);
2001 if (img && img->load_failed_p)
2003 free_image (f, img);
2004 img = NULL;
2007 /* If not found, create a new image and cache it. */
2008 if (img == NULL)
2010 extern Lisp_Object Qpostscript;
2012 BLOCK_INPUT;
2013 img = make_image (spec, hash);
2014 cache_image (f, img);
2015 img->load_failed_p = img->type->load (f, img) == 0;
2016 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
2017 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
2019 /* If we can't load the image, and we don't have a width and
2020 height, use some arbitrary width and height so that we can
2021 draw a rectangle for it. */
2022 if (img->load_failed_p)
2024 Lisp_Object value;
2026 value = image_spec_value (spec, QCwidth, NULL);
2027 img->width = (INTEGERP (value)
2028 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
2029 value = image_spec_value (spec, QCheight, NULL);
2030 img->height = (INTEGERP (value)
2031 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
2033 else
2035 /* Handle image type independent image attributes
2036 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2037 `:background COLOR'. */
2038 Lisp_Object ascent, margin, relief, bg;
2040 ascent = image_spec_value (spec, QCascent, NULL);
2041 if (INTEGERP (ascent))
2042 img->ascent = XFASTINT (ascent);
2043 else if (EQ (ascent, Qcenter))
2044 img->ascent = CENTERED_IMAGE_ASCENT;
2046 margin = image_spec_value (spec, QCmargin, NULL);
2047 if (INTEGERP (margin) && XINT (margin) >= 0)
2048 img->vmargin = img->hmargin = XFASTINT (margin);
2049 else if (CONSP (margin) && INTEGERP (XCAR (margin))
2050 && INTEGERP (XCDR (margin)))
2052 if (XINT (XCAR (margin)) > 0)
2053 img->hmargin = XFASTINT (XCAR (margin));
2054 if (XINT (XCDR (margin)) > 0)
2055 img->vmargin = XFASTINT (XCDR (margin));
2058 relief = image_spec_value (spec, QCrelief, NULL);
2059 if (INTEGERP (relief))
2061 img->relief = XINT (relief);
2062 img->hmargin += abs (img->relief);
2063 img->vmargin += abs (img->relief);
2066 if (! img->background_valid)
2068 bg = image_spec_value (img->spec, QCbackground, NULL);
2069 if (!NILP (bg))
2071 img->background
2072 = x_alloc_image_color (f, img, bg,
2073 FRAME_BACKGROUND_PIXEL (f));
2074 img->background_valid = 1;
2078 /* Do image transformations and compute masks, unless we
2079 don't have the image yet. */
2080 if (!EQ (*img->type->type, Qpostscript))
2081 postprocess_image (f, img);
2084 UNBLOCK_INPUT;
2087 /* We're using IMG, so set its timestamp to `now'. */
2088 EMACS_GET_TIME (now);
2089 img->timestamp = EMACS_SECS (now);
2091 UNGCPRO;
2093 /* Value is the image id. */
2094 return img->id;
2098 /* Cache image IMG in the image cache of frame F. */
2100 static void
2101 cache_image (f, img)
2102 struct frame *f;
2103 struct image *img;
2105 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
2106 int i;
2108 /* Find a free slot in c->images. */
2109 for (i = 0; i < c->used; ++i)
2110 if (c->images[i] == NULL)
2111 break;
2113 /* If no free slot found, maybe enlarge c->images. */
2114 if (i == c->used && c->used == c->size)
2116 c->size *= 2;
2117 c->images = (struct image **) xrealloc (c->images,
2118 c->size * sizeof *c->images);
2121 /* Add IMG to c->images, and assign IMG an id. */
2122 c->images[i] = img;
2123 img->id = i;
2124 if (i == c->used)
2125 ++c->used;
2127 /* Add IMG to the cache's hash table. */
2128 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
2129 img->next = c->buckets[i];
2130 if (img->next)
2131 img->next->prev = img;
2132 img->prev = NULL;
2133 c->buckets[i] = img;
2137 /* Call FN on every image in the image cache of frame F. Used to mark
2138 Lisp Objects in the image cache. */
2140 void
2141 forall_images_in_image_cache (f, fn)
2142 struct frame *f;
2143 void (*fn) P_ ((struct image *img));
2145 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f))
2147 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
2148 if (c)
2150 int i;
2151 for (i = 0; i < c->used; ++i)
2152 if (c->images[i])
2153 fn (c->images[i]);
2160 /***********************************************************************
2161 X / MAC / W32 support code
2162 ***********************************************************************/
2164 #ifdef HAVE_NTGUI
2166 /* Macro for defining functions that will be loaded from image DLLs. */
2167 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2169 /* Macro for loading those image functions from the library. */
2170 #define LOAD_IMGLIB_FN(lib,func) { \
2171 fn_##func = (void *) GetProcAddress (lib, #func); \
2172 if (!fn_##func) return 0; \
2175 /* Load a DLL implementing an image type.
2176 The `image-library-alist' variable associates a symbol,
2177 identifying an image type, to a list of possible filenames.
2178 The function returns NULL if no library could be loaded for
2179 the given image type, or if the library was previously loaded;
2180 else the handle of the DLL. */
2181 static HMODULE
2182 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2184 HMODULE library = NULL;
2186 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2188 Lisp_Object dlls = Fassq (type, libraries);
2190 if (CONSP (dlls))
2191 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2193 CHECK_STRING_CAR (dlls);
2194 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2195 break;
2199 return library;
2202 #endif /* HAVE_NTGUI */
2204 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2205 XImagePtr *, Pixmap *));
2206 static void x_destroy_x_image P_ ((XImagePtr));
2207 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2210 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2211 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2212 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2213 via xmalloc. Print error messages via image_error if an error
2214 occurs. Value is non-zero if successful.
2216 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2217 should indicate the bit depth of the image. */
2219 static int
2220 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2221 struct frame *f;
2222 int width, height, depth;
2223 XImagePtr *ximg;
2224 Pixmap *pixmap;
2226 #ifdef HAVE_X_WINDOWS
2227 Display *display = FRAME_X_DISPLAY (f);
2228 Window window = FRAME_X_WINDOW (f);
2229 Screen *screen = FRAME_X_SCREEN (f);
2231 xassert (interrupt_input_blocked);
2233 if (depth <= 0)
2234 depth = DefaultDepthOfScreen (screen);
2235 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2236 depth, ZPixmap, 0, NULL, width, height,
2237 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2238 if (*ximg == NULL)
2240 image_error ("Unable to allocate X image", Qnil, Qnil);
2241 return 0;
2244 /* Allocate image raster. */
2245 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2247 /* Allocate a pixmap of the same size. */
2248 *pixmap = XCreatePixmap (display, window, width, height, depth);
2249 if (*pixmap == NO_PIXMAP)
2251 x_destroy_x_image (*ximg);
2252 *ximg = NULL;
2253 image_error ("Unable to create X pixmap", Qnil, Qnil);
2254 return 0;
2257 return 1;
2258 #endif /* HAVE_X_WINDOWS */
2260 #ifdef HAVE_NTGUI
2262 BITMAPINFOHEADER *header;
2263 HDC hdc;
2264 int scanline_width_bits;
2265 int remainder;
2266 int palette_colors = 0;
2268 if (depth == 0)
2269 depth = 24;
2271 if (depth != 1 && depth != 4 && depth != 8
2272 && depth != 16 && depth != 24 && depth != 32)
2274 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2275 return 0;
2278 scanline_width_bits = width * depth;
2279 remainder = scanline_width_bits % 32;
2281 if (remainder)
2282 scanline_width_bits += 32 - remainder;
2284 /* Bitmaps with a depth less than 16 need a palette. */
2285 /* BITMAPINFO structure already contains the first RGBQUAD. */
2286 if (depth < 16)
2287 palette_colors = 1 << depth - 1;
2289 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2290 if (*ximg == NULL)
2292 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2293 return 0;
2296 header = &((*ximg)->info.bmiHeader);
2297 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2298 header->biSize = sizeof (*header);
2299 header->biWidth = width;
2300 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2301 header->biPlanes = 1;
2302 header->biBitCount = depth;
2303 header->biCompression = BI_RGB;
2304 header->biClrUsed = palette_colors;
2306 /* TODO: fill in palette. */
2307 if (depth == 1)
2309 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2310 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2311 (*ximg)->info.bmiColors[0].rgbRed = 0;
2312 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2313 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2314 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2315 (*ximg)->info.bmiColors[1].rgbRed = 255;
2316 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2319 hdc = get_frame_dc (f);
2321 /* Create a DIBSection and raster array for the bitmap,
2322 and store its handle in *pixmap. */
2323 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2324 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2325 /* casting avoids a GCC warning */
2326 (void **)&((*ximg)->data), NULL, 0);
2328 /* Realize display palette and garbage all frames. */
2329 release_frame_dc (f, hdc);
2331 if (*pixmap == NULL)
2333 DWORD err = GetLastError();
2334 Lisp_Object errcode;
2335 /* All system errors are < 10000, so the following is safe. */
2336 XSETINT (errcode, (int) err);
2337 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2338 x_destroy_x_image (*ximg);
2339 return 0;
2342 return 1;
2344 #endif /* HAVE_NTGUI */
2346 #ifdef MAC_OS
2347 Display *display = FRAME_X_DISPLAY (f);
2348 Window window = FRAME_X_WINDOW (f);
2350 xassert (interrupt_input_blocked);
2352 /* Allocate a pixmap of the same size. */
2353 *pixmap = XCreatePixmap (display, window, width, height, depth);
2354 if (*pixmap == NO_PIXMAP)
2356 *ximg = NULL;
2357 image_error ("Unable to create X pixmap", Qnil, Qnil);
2358 return 0;
2361 #if !USE_MAC_IMAGE_IO
2362 LockPixels (GetGWorldPixMap (*pixmap));
2363 #endif
2364 *ximg = *pixmap;
2365 return 1;
2367 #endif /* MAC_OS */
2371 /* Destroy XImage XIMG. Free XIMG->data. */
2373 static void
2374 x_destroy_x_image (ximg)
2375 XImagePtr ximg;
2377 xassert (interrupt_input_blocked);
2378 if (ximg)
2380 #ifdef HAVE_X_WINDOWS
2381 xfree (ximg->data);
2382 ximg->data = NULL;
2383 XDestroyImage (ximg);
2384 #endif /* HAVE_X_WINDOWS */
2385 #ifdef HAVE_NTGUI
2386 /* Data will be freed by DestroyObject. */
2387 ximg->data = NULL;
2388 xfree (ximg);
2389 #endif /* HAVE_NTGUI */
2390 #ifdef MAC_OS
2391 XDestroyImage (ximg);
2392 #endif /* MAC_OS */
2397 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2398 are width and height of both the image and pixmap. */
2400 static void
2401 x_put_x_image (f, ximg, pixmap, width, height)
2402 struct frame *f;
2403 XImagePtr ximg;
2404 Pixmap pixmap;
2405 int width, height;
2407 #ifdef HAVE_X_WINDOWS
2408 GC gc;
2410 xassert (interrupt_input_blocked);
2411 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2412 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2413 XFreeGC (FRAME_X_DISPLAY (f), gc);
2414 #endif /* HAVE_X_WINDOWS */
2416 #ifdef HAVE_NTGUI
2417 #if 0 /* I don't think this is necessary looking at where it is used. */
2418 HDC hdc = get_frame_dc (f);
2419 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2420 release_frame_dc (f, hdc);
2421 #endif
2422 #endif /* HAVE_NTGUI */
2424 #ifdef MAC_OS
2425 xassert (ximg == pixmap);
2426 #endif /* MAC_OS */
2430 /***********************************************************************
2431 File Handling
2432 ***********************************************************************/
2434 static unsigned char *slurp_file P_ ((char *, int *));
2437 /* Find image file FILE. Look in data-directory, then
2438 x-bitmap-file-path. Value is the encoded full name of the file
2439 found, or nil if not found. */
2441 Lisp_Object
2442 x_find_image_file (file)
2443 Lisp_Object file;
2445 Lisp_Object file_found, search_path;
2446 struct gcpro gcpro1, gcpro2;
2447 int fd;
2449 file_found = Qnil;
2450 search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
2451 GCPRO2 (file_found, search_path);
2453 /* Try to find FILE in data-directory, then x-bitmap-file-path. */
2454 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2456 if (fd == -1)
2457 file_found = Qnil;
2458 else
2460 file_found = ENCODE_FILE (file_found);
2461 close (fd);
2464 UNGCPRO;
2465 return file_found;
2469 /* Read FILE into memory. Value is a pointer to a buffer allocated
2470 with xmalloc holding FILE's contents. Value is null if an error
2471 occurred. *SIZE is set to the size of the file. */
2473 static unsigned char *
2474 slurp_file (file, size)
2475 char *file;
2476 int *size;
2478 FILE *fp = NULL;
2479 unsigned char *buf = NULL;
2480 struct stat st;
2482 if (stat (file, &st) == 0
2483 && (fp = fopen (file, "rb")) != NULL
2484 && (buf = (unsigned char *) xmalloc (st.st_size),
2485 fread (buf, 1, st.st_size, fp) == st.st_size))
2487 *size = st.st_size;
2488 fclose (fp);
2490 else
2492 if (fp)
2493 fclose (fp);
2494 if (buf)
2496 xfree (buf);
2497 buf = NULL;
2501 return buf;
2506 #ifdef MAC_OS
2508 /***********************************************************************
2509 MAC Image Load Functions
2510 ***********************************************************************/
2512 #if USE_MAC_IMAGE_IO
2513 static int
2514 image_load_image_io (f, img, type)
2515 struct frame *f;
2516 struct image *img;
2517 CFStringRef type;
2519 CFDictionaryRef options, src_props = NULL, props = NULL;
2520 CFStringRef keys[2];
2521 CFTypeRef values[2];
2522 Lisp_Object specified_file, specified_data;
2523 CGImageSourceRef source = NULL;
2524 size_t count;
2525 CGImageRef image = NULL;
2526 int loop_count = -1;
2527 double delay_time = -1.0;
2528 int width, height;
2529 XImagePtr ximg = NULL;
2530 CGContextRef context;
2531 CGRect rectangle;
2532 int has_alpha_p, gif_p;
2534 gif_p = UTTypeEqual (type, kUTTypeGIF);
2536 keys[0] = kCGImageSourceTypeIdentifierHint;
2537 values[0] = (CFTypeRef) type;
2538 keys[1] = kCGImageSourceShouldCache;
2539 values[1] = (CFTypeRef) kCFBooleanFalse;
2540 options = CFDictionaryCreate (NULL, (const void **) keys,
2541 (const void **) values,
2542 sizeof (keys) / sizeof (keys[0]),
2543 &kCFTypeDictionaryKeyCallBacks,
2544 &kCFTypeDictionaryValueCallBacks);
2545 if (options == NULL)
2547 image_error ("Error creating options for image `%s'", img->spec, Qnil);
2548 return 0;
2551 /* Open the file. */
2552 specified_file = image_spec_value (img->spec, QCfile, NULL);
2553 specified_data = image_spec_value (img->spec, QCdata, NULL);
2555 if (NILP (specified_data))
2557 Lisp_Object file;
2558 CFStringRef path;
2559 CFURLRef url;
2561 file = x_find_image_file (specified_file);
2562 if (!STRINGP (file))
2564 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2565 return 0;
2567 path = cfstring_create_with_utf8_cstring (SDATA (file));
2568 if (path)
2570 url = CFURLCreateWithFileSystemPath (NULL, path,
2571 kCFURLPOSIXPathStyle, 0);
2572 CFRelease (path);
2573 if (url)
2575 source = CGImageSourceCreateWithURL (url, NULL);
2576 CFRelease (url);
2580 else
2582 CFDataRef data = CFDataCreate (NULL, SDATA (specified_data),
2583 SBYTES (specified_data));
2585 if (data)
2587 source = CGImageSourceCreateWithData (data, options);
2588 CFRelease (data);
2591 CFRelease (options);
2593 if (source)
2595 CFStringRef real_type = CGImageSourceGetType (source);
2597 if (real_type && UTTypeEqual (type, real_type))
2598 src_props = CGImageSourceCopyProperties (source, NULL);
2599 if (src_props)
2601 EMACS_INT ino = 0;
2603 count = CGImageSourceGetCount (source);
2604 if (gif_p)
2606 Lisp_Object image = image_spec_value (img->spec, QCindex, NULL);
2608 if (INTEGERP (image))
2609 ino = XFASTINT (image);
2611 if (ino >= 0 && ino < count)
2613 props = CGImageSourceCopyPropertiesAtIndex (source, ino, NULL);
2614 if (props)
2615 image = CGImageSourceCreateImageAtIndex (source, ino, NULL);
2618 CFRelease (source);
2621 if (image == NULL)
2623 if (src_props)
2624 CFRelease (src_props);
2625 if (props)
2626 CFRelease (props);
2627 image_error ("Error reading image `%s'", img->spec, Qnil);
2628 return 0;
2630 else
2632 CFBooleanRef boolean;
2634 if (CFDictionaryGetValueIfPresent (props, kCGImagePropertyHasAlpha,
2635 (const void **) &boolean))
2636 has_alpha_p = CFBooleanGetValue (boolean);
2637 if (gif_p)
2639 CFDictionaryRef dict;
2640 CFNumberRef number;
2642 dict = CFDictionaryGetValue (src_props,
2643 kCGImagePropertyGIFDictionary);
2644 if (dict
2645 && CFDictionaryGetValueIfPresent (dict,
2646 kCGImagePropertyGIFLoopCount,
2647 (const void **) &number))
2648 CFNumberGetValue (number, kCFNumberIntType, &loop_count);
2650 dict = CFDictionaryGetValue (props, kCGImagePropertyGIFDictionary);
2651 if (dict
2652 && CFDictionaryGetValueIfPresent (dict,
2653 kCGImagePropertyGIFDelayTime,
2654 (const void **) &number))
2655 CFNumberGetValue (number, kCFNumberDoubleType, &delay_time);
2657 CFRelease (src_props);
2658 CFRelease (props);
2661 width = img->width = CGImageGetWidth (image);
2662 height = img->height = CGImageGetHeight (image);
2664 if (!check_image_size (f, width, height))
2666 CGImageRelease (image);
2667 image_error ("Invalid image size", Qnil, Qnil);
2668 return 0;
2671 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2673 CGImageRelease (image);
2674 image_error ("Out of memory (%s)", img->spec, Qnil);
2675 return 0;
2677 rectangle = CGRectMake (0, 0, width, height);
2679 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
2680 ximg->bytes_per_line,
2681 mac_cg_color_space_rgb,
2682 kCGImageAlphaNoneSkipFirst
2683 | kCGBitmapByteOrder32Host);
2684 if (has_alpha_p)
2686 Lisp_Object specified_bg;
2687 XColor color;
2689 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2690 if (!STRINGP (specified_bg)
2691 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2693 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2694 color.red = RED16_FROM_ULONG (color.pixel);
2695 color.green = GREEN16_FROM_ULONG (color.pixel);
2696 color.blue = BLUE16_FROM_ULONG (color.pixel);
2698 CGContextSetRGBFillColor (context, color.red / 65535.0,
2699 color.green / 65535.0,
2700 color.blue / 65535.0, 1.0);
2701 CGContextFillRect (context, rectangle);
2703 CGContextDrawImage (context, rectangle, image);
2704 CGContextRelease (context);
2705 CGImageRelease (image);
2707 /* Save GIF image extension data for `image-extension-data'.
2708 Format is (count IMAGES
2709 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2710 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2711 if (gif_p)
2713 img->data.lisp_val = Qnil;
2714 if (delay_time >= 0)
2716 Lisp_Object gce = make_uninit_string (4);
2717 int centisec = delay_time * 100.0 + 0.5;
2719 /* Fill the delay time field. */
2720 SSET (gce, 1, centisec & 0xff);
2721 SSET (gce, 2, (centisec >> 8) & 0xff);
2722 /* We don't know about other fields. */
2723 SSET (gce, 0, 0);
2724 SSET (gce, 3, 0);
2725 img->data.lisp_val = Fcons (make_number (0xf9),
2726 Fcons (gce,
2727 img->data.lisp_val));
2729 if (loop_count >= 0)
2731 Lisp_Object data_sub_block = make_uninit_string (3);
2733 SSET (data_sub_block, 0, 0x01);
2734 SSET (data_sub_block, 1, loop_count & 0xff);
2735 SSET (data_sub_block, 2, (loop_count >> 8) & 0xff);
2736 img->data.lisp_val = Fcons (make_number (0),
2737 Fcons (data_sub_block,
2738 img->data.lisp_val));
2739 img->data.lisp_val = Fcons (make_number (0xff),
2740 Fcons (build_string ("NETSCAPE2.0"),
2741 img->data.lisp_val));
2743 if (count > 1)
2744 img->data.lisp_val = Fcons (Qcount,
2745 Fcons (make_number (count),
2746 img->data.lisp_val));
2749 /* Maybe fill in the background field while we have ximg handy. */
2750 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2751 IMAGE_BACKGROUND (img, f, ximg);
2753 /* Put the image into the pixmap. */
2754 x_put_x_image (f, ximg, img->pixmap, width, height);
2755 x_destroy_x_image (ximg);
2756 return 1;
2758 #else /* !USE_MAC_IMAGE_IO */
2759 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2760 OSType));
2761 #ifdef MAC_OSX
2762 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2763 #endif
2765 static OSErr
2766 find_image_fsspec (specified_file, file, fss)
2767 Lisp_Object specified_file, *file;
2768 FSSpec *fss;
2770 OSErr err;
2771 AEDesc desc;
2773 *file = x_find_image_file (specified_file);
2774 if (!STRINGP (*file))
2775 return fnfErr; /* file or directory not found;
2776 incomplete pathname */
2777 /* Try to open the image file. */
2778 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2779 SBYTES (*file), typeFSS, &desc);
2780 if (err == noErr)
2782 #if TARGET_API_MAC_CARBON
2783 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2784 #else
2785 *fss = *(FSSpec *)(*(desc.dataHandle));
2786 #endif
2787 AEDisposeDesc (&desc);
2789 return err;
2792 static int
2793 image_load_qt_1 (f, img, type, fss, dh)
2794 struct frame *f;
2795 struct image *img;
2796 OSType type;
2797 const FSSpec *fss;
2798 Handle dh;
2800 ComponentResult err;
2801 GraphicsImportComponent gi;
2802 Rect rect;
2803 int width, height;
2804 ImageDescriptionHandle desc_handle;
2805 short draw_all_pixels;
2806 Lisp_Object specified_bg;
2807 XColor color;
2808 XImagePtr ximg;
2809 RGBColor bg_color;
2811 err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
2812 if (err != noErr)
2814 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2815 return 0;
2817 if (dh == NULL)
2819 /* read from file system spec */
2820 err = GraphicsImportSetDataFile (gi, fss);
2821 if (err != noErr)
2823 image_error ("Cannot set fsspec to graphics importer for '%s'",
2824 img->spec, Qnil);
2825 goto error;
2828 else
2830 /* read from data handle */
2831 err = GraphicsImportSetDataHandle (gi, dh);
2832 if (err != noErr)
2834 image_error ("Cannot set data handle to graphics importer for `%s'",
2835 img->spec, Qnil);
2836 goto error;
2839 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2840 if (err != noErr || desc_handle == NULL)
2842 image_error ("Error reading `%s'", img->spec, Qnil);
2843 goto error;
2845 width = img->width = (*desc_handle)->width;
2846 height = img->height = (*desc_handle)->height;
2847 DisposeHandle ((Handle)desc_handle);
2849 if (!check_image_size (f, width, height))
2851 image_error ("Invalid image size", Qnil, Qnil);
2852 goto error;
2855 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2856 #if 0
2857 /* Don't check the error code here. It may have an undocumented
2858 value -32766. */
2859 if (err != noErr)
2861 image_error ("Error reading `%s'", img->spec, Qnil);
2862 goto error;
2864 #endif
2865 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2867 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2868 if (!STRINGP (specified_bg) ||
2869 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2871 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2872 color.red = RED16_FROM_ULONG (color.pixel);
2873 color.green = GREEN16_FROM_ULONG (color.pixel);
2874 color.blue = BLUE16_FROM_ULONG (color.pixel);
2878 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2879 goto error;
2880 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2882 CGrafPtr old_port;
2883 GDHandle old_gdh;
2885 GetGWorld (&old_port, &old_gdh);
2886 SetGWorld (ximg, NULL);
2887 bg_color.red = color.red;
2888 bg_color.green = color.green;
2889 bg_color.blue = color.blue;
2890 RGBBackColor (&bg_color);
2891 #if TARGET_API_MAC_CARBON
2892 GetPortBounds (ximg, &rect);
2893 EraseRect (&rect);
2894 #else
2895 EraseRect (&(ximg->portRect));
2896 #endif
2897 SetGWorld (old_port, old_gdh);
2899 GraphicsImportSetGWorld (gi, ximg, NULL);
2900 GraphicsImportDraw (gi);
2901 CloseComponent (gi);
2903 /* Maybe fill in the background field while we have ximg handy. */
2904 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2905 IMAGE_BACKGROUND (img, f, ximg);
2907 /* Put the image into the pixmap. */
2908 x_put_x_image (f, ximg, img->pixmap, width, height);
2909 x_destroy_x_image (ximg);
2910 return 1;
2912 error:
2913 CloseComponent (gi);
2914 return 0;
2918 /* Load an image using the QuickTime Graphics Importer.
2919 Note: The alpha channel does not work for PNG images. */
2920 static int
2921 image_load_quicktime (f, img, type)
2922 struct frame *f;
2923 struct image *img;
2924 OSType type;
2926 Lisp_Object specified_file;
2927 Lisp_Object specified_data;
2928 OSErr err;
2930 specified_file = image_spec_value (img->spec, QCfile, NULL);
2931 specified_data = image_spec_value (img->spec, QCdata, NULL);
2933 if (NILP (specified_data))
2935 /* Read from a file */
2936 Lisp_Object file;
2937 FSSpec fss;
2939 err = find_image_fsspec (specified_file, &file, &fss);
2940 if (err != noErr)
2942 if (err == fnfErr)
2943 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2944 else
2945 image_error ("Cannot open `%s'", file, Qnil);
2946 return 0;
2948 return image_load_qt_1 (f, img, type, &fss, NULL);
2950 else
2952 /* Memory source! */
2953 int success_p;
2954 Handle dh;
2956 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2957 if (err != noErr)
2959 image_error ("Cannot allocate data handle for `%s'",
2960 img->spec, Qnil);
2961 return 0;
2963 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2964 DisposeHandle (dh);
2965 return success_p;
2970 #ifdef MAC_OSX
2971 static int
2972 image_load_quartz2d (f, img, png_p)
2973 struct frame *f;
2974 struct image *img;
2975 int png_p;
2977 Lisp_Object file, specified_file;
2978 Lisp_Object specified_data, specified_bg;
2979 struct gcpro gcpro1;
2980 CGDataProviderRef source;
2981 CGImageRef image;
2982 int width, height;
2983 XColor color;
2984 XImagePtr ximg = NULL;
2985 CGContextRef context;
2986 CGRect rectangle;
2988 /* Open the file. */
2989 specified_file = image_spec_value (img->spec, QCfile, NULL);
2990 specified_data = image_spec_value (img->spec, QCdata, NULL);
2992 file = Qnil;
2993 GCPRO1 (file);
2995 if (NILP (specified_data))
2997 CFStringRef path;
2998 CFURLRef url;
3000 file = x_find_image_file (specified_file);
3001 if (!STRINGP (file))
3003 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3004 UNGCPRO;
3005 return 0;
3007 path = cfstring_create_with_utf8_cstring (SDATA (file));
3008 url = CFURLCreateWithFileSystemPath (NULL, path,
3009 kCFURLPOSIXPathStyle, 0);
3010 CFRelease (path);
3011 source = CGDataProviderCreateWithURL (url);
3012 CFRelease (url);
3014 else
3015 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
3016 SBYTES (specified_data), NULL);
3018 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3019 if (png_p)
3020 image = CGImageCreateWithPNGDataProvider (source, NULL, false,
3021 kCGRenderingIntentDefault);
3022 else
3023 #endif
3024 image = CGImageCreateWithJPEGDataProvider (source, NULL, false,
3025 kCGRenderingIntentDefault);
3027 CGDataProviderRelease (source);
3028 if (image == NULL)
3030 UNGCPRO;
3031 image_error ("Error reading image `%s'", img->spec, Qnil);
3032 return 0;
3034 width = img->width = CGImageGetWidth (image);
3035 height = img->height = CGImageGetHeight (image);
3037 if (!check_image_size (f, width, height))
3039 CGImageRelease (image);
3040 UNGCPRO;
3041 image_error ("Invalid image size", Qnil, Qnil);
3042 return 0;
3045 if (png_p)
3047 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
3048 if (!STRINGP (specified_bg) ||
3049 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
3051 color.pixel = FRAME_BACKGROUND_PIXEL (f);
3052 color.red = RED16_FROM_ULONG (color.pixel);
3053 color.green = GREEN16_FROM_ULONG (color.pixel);
3054 color.blue = BLUE16_FROM_ULONG (color.pixel);
3058 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
3060 CGImageRelease (image);
3061 UNGCPRO;
3062 return 0;
3064 rectangle = CGRectMake (0, 0, width, height);
3065 QDBeginCGContext (ximg, &context);
3066 if (png_p)
3068 CGContextSetRGBFillColor (context, color.red / 65535.0,
3069 color.green / 65535.0,
3070 color.blue / 65535.0, 1.0);
3071 CGContextFillRect (context, rectangle);
3073 CGContextDrawImage (context, rectangle, image);
3074 QDEndCGContext (ximg, &context);
3075 CGImageRelease (image);
3077 /* Maybe fill in the background field while we have ximg handy. */
3078 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3079 IMAGE_BACKGROUND (img, f, ximg);
3081 /* Put the image into the pixmap. */
3082 x_put_x_image (f, ximg, img->pixmap, width, height);
3083 x_destroy_x_image (ximg);
3084 UNGCPRO;
3085 return 1;
3087 #endif
3088 #endif /* !USE_MAC_IMAGE_IO */
3090 #endif /* MAC_OS */
3093 /***********************************************************************
3094 XBM images
3095 ***********************************************************************/
3097 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
3098 static int xbm_load P_ ((struct frame *f, struct image *img));
3099 static int xbm_load_image P_ ((struct frame *f, struct image *img,
3100 unsigned char *, unsigned char *));
3101 static int xbm_image_p P_ ((Lisp_Object object));
3102 static int xbm_read_bitmap_data P_ ((struct frame *f,
3103 unsigned char *, unsigned char *,
3104 int *, int *, unsigned char **));
3105 static int xbm_file_p P_ ((Lisp_Object));
3108 /* Indices of image specification fields in xbm_format, below. */
3110 enum xbm_keyword_index
3112 XBM_TYPE,
3113 XBM_FILE,
3114 XBM_WIDTH,
3115 XBM_HEIGHT,
3116 XBM_DATA,
3117 XBM_FOREGROUND,
3118 XBM_BACKGROUND,
3119 XBM_ASCENT,
3120 XBM_MARGIN,
3121 XBM_RELIEF,
3122 XBM_ALGORITHM,
3123 XBM_HEURISTIC_MASK,
3124 XBM_MASK,
3125 XBM_LAST
3128 /* Vector of image_keyword structures describing the format
3129 of valid XBM image specifications. */
3131 static struct image_keyword xbm_format[XBM_LAST] =
3133 {":type", IMAGE_SYMBOL_VALUE, 1},
3134 {":file", IMAGE_STRING_VALUE, 0},
3135 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3136 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3137 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3138 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
3139 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
3140 {":ascent", IMAGE_ASCENT_VALUE, 0},
3141 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3142 {":relief", IMAGE_INTEGER_VALUE, 0},
3143 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3144 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3145 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
3148 /* Structure describing the image type XBM. */
3150 static struct image_type xbm_type =
3152 &Qxbm,
3153 xbm_image_p,
3154 xbm_load,
3155 x_clear_image,
3156 NULL
3159 /* Tokens returned from xbm_scan. */
3161 enum xbm_token
3163 XBM_TK_IDENT = 256,
3164 XBM_TK_NUMBER
3168 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3169 A valid specification is a list starting with the symbol `image'
3170 The rest of the list is a property list which must contain an
3171 entry `:type xbm..
3173 If the specification specifies a file to load, it must contain
3174 an entry `:file FILENAME' where FILENAME is a string.
3176 If the specification is for a bitmap loaded from memory it must
3177 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3178 WIDTH and HEIGHT are integers > 0. DATA may be:
3180 1. a string large enough to hold the bitmap data, i.e. it must
3181 have a size >= (WIDTH + 7) / 8 * HEIGHT
3183 2. a bool-vector of size >= WIDTH * HEIGHT
3185 3. a vector of strings or bool-vectors, one for each line of the
3186 bitmap.
3188 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3189 may not be specified in this case because they are defined in the
3190 XBM file.
3192 Both the file and data forms may contain the additional entries
3193 `:background COLOR' and `:foreground COLOR'. If not present,
3194 foreground and background of the frame on which the image is
3195 displayed is used. */
3197 static int
3198 xbm_image_p (object)
3199 Lisp_Object object;
3201 struct image_keyword kw[XBM_LAST];
3203 bcopy (xbm_format, kw, sizeof kw);
3204 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
3205 return 0;
3207 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
3209 if (kw[XBM_FILE].count)
3211 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
3212 return 0;
3214 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
3216 /* In-memory XBM file. */
3217 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
3218 return 0;
3220 else
3222 Lisp_Object data;
3223 int width, height;
3225 /* Entries for `:width', `:height' and `:data' must be present. */
3226 if (!kw[XBM_WIDTH].count
3227 || !kw[XBM_HEIGHT].count
3228 || !kw[XBM_DATA].count)
3229 return 0;
3231 data = kw[XBM_DATA].value;
3232 width = XFASTINT (kw[XBM_WIDTH].value);
3233 height = XFASTINT (kw[XBM_HEIGHT].value);
3235 /* Check type of data, and width and height against contents of
3236 data. */
3237 if (VECTORP (data))
3239 int i;
3241 /* Number of elements of the vector must be >= height. */
3242 if (XVECTOR (data)->size < height)
3243 return 0;
3245 /* Each string or bool-vector in data must be large enough
3246 for one line of the image. */
3247 for (i = 0; i < height; ++i)
3249 Lisp_Object elt = XVECTOR (data)->contents[i];
3251 if (STRINGP (elt))
3253 if (SCHARS (elt)
3254 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
3255 return 0;
3257 else if (BOOL_VECTOR_P (elt))
3259 if (XBOOL_VECTOR (elt)->size < width)
3260 return 0;
3262 else
3263 return 0;
3266 else if (STRINGP (data))
3268 if (SCHARS (data)
3269 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
3270 return 0;
3272 else if (BOOL_VECTOR_P (data))
3274 if (XBOOL_VECTOR (data)->size < width * height)
3275 return 0;
3277 else
3278 return 0;
3281 return 1;
3285 /* Scan a bitmap file. FP is the stream to read from. Value is
3286 either an enumerator from enum xbm_token, or a character for a
3287 single-character token, or 0 at end of file. If scanning an
3288 identifier, store the lexeme of the identifier in SVAL. If
3289 scanning a number, store its value in *IVAL. */
3291 static int
3292 xbm_scan (s, end, sval, ival)
3293 unsigned char **s, *end;
3294 char *sval;
3295 int *ival;
3297 unsigned int c;
3299 loop:
3301 /* Skip white space. */
3302 while (*s < end && (c = *(*s)++, isspace (c)))
3305 if (*s >= end)
3306 c = 0;
3307 else if (isdigit (c))
3309 int value = 0, digit;
3311 if (c == '0' && *s < end)
3313 c = *(*s)++;
3314 if (c == 'x' || c == 'X')
3316 while (*s < end)
3318 c = *(*s)++;
3319 if (isdigit (c))
3320 digit = c - '0';
3321 else if (c >= 'a' && c <= 'f')
3322 digit = c - 'a' + 10;
3323 else if (c >= 'A' && c <= 'F')
3324 digit = c - 'A' + 10;
3325 else
3326 break;
3327 value = 16 * value + digit;
3330 else if (isdigit (c))
3332 value = c - '0';
3333 while (*s < end
3334 && (c = *(*s)++, isdigit (c)))
3335 value = 8 * value + c - '0';
3338 else
3340 value = c - '0';
3341 while (*s < end
3342 && (c = *(*s)++, isdigit (c)))
3343 value = 10 * value + c - '0';
3346 if (*s < end)
3347 *s = *s - 1;
3348 *ival = value;
3349 c = XBM_TK_NUMBER;
3351 else if (isalpha (c) || c == '_')
3353 *sval++ = c;
3354 while (*s < end
3355 && (c = *(*s)++, (isalnum (c) || c == '_')))
3356 *sval++ = c;
3357 *sval = 0;
3358 if (*s < end)
3359 *s = *s - 1;
3360 c = XBM_TK_IDENT;
3362 else if (c == '/' && **s == '*')
3364 /* C-style comment. */
3365 ++*s;
3366 while (**s && (**s != '*' || *(*s + 1) != '/'))
3367 ++*s;
3368 if (**s)
3370 *s += 2;
3371 goto loop;
3375 return c;
3378 #ifdef HAVE_NTGUI
3380 /* Create a Windows bitmap from X bitmap data. */
3381 static HBITMAP
3382 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
3384 static unsigned char swap_nibble[16]
3385 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3386 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3387 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3388 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3389 int i, j, w1, w2;
3390 unsigned char *bits, *p;
3391 HBITMAP bmp;
3393 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
3394 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3395 bits = (unsigned char *) alloca (height * w2);
3396 bzero (bits, height * w2);
3397 for (i = 0; i < height; i++)
3399 p = bits + i*w2;
3400 for (j = 0; j < w1; j++)
3402 /* Bitswap XBM bytes to match how Windows does things. */
3403 unsigned char c = *data++;
3404 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
3405 | (swap_nibble[(c>>4) & 0xf]));
3408 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
3410 return bmp;
3413 static void
3414 convert_mono_to_color_image (f, img, foreground, background)
3415 struct frame *f;
3416 struct image *img;
3417 COLORREF foreground, background;
3419 HDC hdc, old_img_dc, new_img_dc;
3420 HGDIOBJ old_prev, new_prev;
3421 HBITMAP new_pixmap;
3423 hdc = get_frame_dc (f);
3424 old_img_dc = CreateCompatibleDC (hdc);
3425 new_img_dc = CreateCompatibleDC (hdc);
3426 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3427 release_frame_dc (f, hdc);
3428 old_prev = SelectObject (old_img_dc, img->pixmap);
3429 new_prev = SelectObject (new_img_dc, new_pixmap);
3430 /* Windows convention for mono bitmaps is black = background,
3431 white = foreground. */
3432 SetTextColor (new_img_dc, background);
3433 SetBkColor (new_img_dc, foreground);
3435 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3436 0, 0, SRCCOPY);
3438 SelectObject (old_img_dc, old_prev);
3439 SelectObject (new_img_dc, new_prev);
3440 DeleteDC (old_img_dc);
3441 DeleteDC (new_img_dc);
3442 DeleteObject (img->pixmap);
3443 if (new_pixmap == 0)
3444 fprintf (stderr, "Failed to convert image to color.\n");
3445 else
3446 img->pixmap = new_pixmap;
3449 #define XBM_BIT_SHUFFLE(b) (~(b))
3451 #else
3453 #define XBM_BIT_SHUFFLE(b) (b)
3455 #endif /* HAVE_NTGUI */
3458 static void
3459 Create_Pixmap_From_Bitmap_Data(f, img, data, fg, bg, non_default_colors)
3460 struct frame *f;
3461 struct image *img;
3462 char *data;
3463 RGB_PIXEL_COLOR fg, bg;
3464 int non_default_colors;
3466 #ifdef HAVE_NTGUI
3467 img->pixmap
3468 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3470 /* If colors were specified, transfer the bitmap to a color one. */
3471 if (non_default_colors)
3472 convert_mono_to_color_image (f, img, fg, bg);
3473 #else
3474 img->pixmap
3475 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3476 FRAME_X_WINDOW (f),
3477 data,
3478 img->width, img->height,
3479 fg, bg,
3480 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3481 #endif /* HAVE_NTGUI */
3486 /* Replacement for XReadBitmapFileData which isn't available under old
3487 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3488 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3489 the image. Return in *DATA the bitmap data allocated with xmalloc.
3490 Value is non-zero if successful. DATA null means just test if
3491 CONTENTS looks like an in-memory XBM file. */
3493 static int
3494 xbm_read_bitmap_data (f, contents, end, width, height, data)
3495 struct frame *f;
3496 unsigned char *contents, *end;
3497 int *width, *height;
3498 unsigned char **data;
3500 unsigned char *s = contents;
3501 char buffer[BUFSIZ];
3502 int padding_p = 0;
3503 int v10 = 0;
3504 int bytes_per_line, i, nbytes;
3505 unsigned char *p;
3506 int value;
3507 int LA1;
3509 #define match() \
3510 LA1 = xbm_scan (&s, end, buffer, &value)
3512 #define expect(TOKEN) \
3513 if (LA1 != (TOKEN)) \
3514 goto failure; \
3515 else \
3516 match ()
3518 #define expect_ident(IDENT) \
3519 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3520 match (); \
3521 else \
3522 goto failure
3524 *width = *height = -1;
3525 if (data)
3526 *data = NULL;
3527 LA1 = xbm_scan (&s, end, buffer, &value);
3529 /* Parse defines for width, height and hot-spots. */
3530 while (LA1 == '#')
3532 match ();
3533 expect_ident ("define");
3534 expect (XBM_TK_IDENT);
3536 if (LA1 == XBM_TK_NUMBER)
3538 char *p = strrchr (buffer, '_');
3539 p = p ? p + 1 : buffer;
3540 if (strcmp (p, "width") == 0)
3541 *width = value;
3542 else if (strcmp (p, "height") == 0)
3543 *height = value;
3545 expect (XBM_TK_NUMBER);
3548 if (!check_image_size (f, *width, *height))
3549 goto failure;
3550 else if (data == NULL)
3551 goto success;
3553 /* Parse bits. Must start with `static'. */
3554 expect_ident ("static");
3555 if (LA1 == XBM_TK_IDENT)
3557 if (strcmp (buffer, "unsigned") == 0)
3559 match ();
3560 expect_ident ("char");
3562 else if (strcmp (buffer, "short") == 0)
3564 match ();
3565 v10 = 1;
3566 if (*width % 16 && *width % 16 < 9)
3567 padding_p = 1;
3569 else if (strcmp (buffer, "char") == 0)
3570 match ();
3571 else
3572 goto failure;
3574 else
3575 goto failure;
3577 expect (XBM_TK_IDENT);
3578 expect ('[');
3579 expect (']');
3580 expect ('=');
3581 expect ('{');
3583 bytes_per_line = (*width + 7) / 8 + padding_p;
3584 nbytes = bytes_per_line * *height;
3585 p = *data = (unsigned char *) xmalloc (nbytes);
3587 if (v10)
3589 for (i = 0; i < nbytes; i += 2)
3591 int val = value;
3592 expect (XBM_TK_NUMBER);
3594 *p++ = XBM_BIT_SHUFFLE (val);
3595 if (!padding_p || ((i + 2) % bytes_per_line))
3596 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3598 if (LA1 == ',' || LA1 == '}')
3599 match ();
3600 else
3601 goto failure;
3604 else
3606 for (i = 0; i < nbytes; ++i)
3608 int val = value;
3609 expect (XBM_TK_NUMBER);
3611 *p++ = XBM_BIT_SHUFFLE (val);
3613 if (LA1 == ',' || LA1 == '}')
3614 match ();
3615 else
3616 goto failure;
3620 success:
3621 return 1;
3623 failure:
3625 if (data && *data)
3627 xfree (*data);
3628 *data = NULL;
3630 return 0;
3632 #undef match
3633 #undef expect
3634 #undef expect_ident
3638 /* Load XBM image IMG which will be displayed on frame F from buffer
3639 CONTENTS. END is the end of the buffer. Value is non-zero if
3640 successful. */
3642 static int
3643 xbm_load_image (f, img, contents, end)
3644 struct frame *f;
3645 struct image *img;
3646 unsigned char *contents, *end;
3648 int rc;
3649 unsigned char *data;
3650 int success_p = 0;
3652 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3653 if (rc)
3655 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3656 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3657 int non_default_colors = 0;
3658 Lisp_Object value;
3660 xassert (img->width > 0 && img->height > 0);
3662 /* Get foreground and background colors, maybe allocate colors. */
3663 value = image_spec_value (img->spec, QCforeground, NULL);
3664 if (!NILP (value))
3666 foreground = x_alloc_image_color (f, img, value, foreground);
3667 non_default_colors = 1;
3669 value = image_spec_value (img->spec, QCbackground, NULL);
3670 if (!NILP (value))
3672 background = x_alloc_image_color (f, img, value, background);
3673 img->background = background;
3674 img->background_valid = 1;
3675 non_default_colors = 1;
3678 Create_Pixmap_From_Bitmap_Data (f, img, data,
3679 foreground, background,
3680 non_default_colors);
3681 xfree (data);
3683 if (img->pixmap == NO_PIXMAP)
3685 x_clear_image (f, img);
3686 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3688 else
3689 success_p = 1;
3691 else
3692 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3694 return success_p;
3698 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3700 static int
3701 xbm_file_p (data)
3702 Lisp_Object data;
3704 int w, h;
3705 return (STRINGP (data)
3706 && xbm_read_bitmap_data (NULL, SDATA (data),
3707 (SDATA (data)
3708 + SBYTES (data)),
3709 &w, &h, NULL));
3713 /* Fill image IMG which is used on frame F with pixmap data. Value is
3714 non-zero if successful. */
3716 static int
3717 xbm_load (f, img)
3718 struct frame *f;
3719 struct image *img;
3721 int success_p = 0;
3722 Lisp_Object file_name;
3724 xassert (xbm_image_p (img->spec));
3726 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3727 file_name = image_spec_value (img->spec, QCfile, NULL);
3728 if (STRINGP (file_name))
3730 Lisp_Object file;
3731 unsigned char *contents;
3732 int size;
3733 struct gcpro gcpro1;
3735 file = x_find_image_file (file_name);
3736 GCPRO1 (file);
3737 if (!STRINGP (file))
3739 image_error ("Cannot find image file `%s'", file_name, Qnil);
3740 UNGCPRO;
3741 return 0;
3744 contents = slurp_file (SDATA (file), &size);
3745 if (contents == NULL)
3747 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3748 UNGCPRO;
3749 return 0;
3752 success_p = xbm_load_image (f, img, contents, contents + size);
3753 UNGCPRO;
3755 else
3757 struct image_keyword fmt[XBM_LAST];
3758 Lisp_Object data;
3759 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3760 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3761 int non_default_colors = 0;
3762 char *bits;
3763 int parsed_p;
3764 int in_memory_file_p = 0;
3766 /* See if data looks like an in-memory XBM file. */
3767 data = image_spec_value (img->spec, QCdata, NULL);
3768 in_memory_file_p = xbm_file_p (data);
3770 /* Parse the image specification. */
3771 bcopy (xbm_format, fmt, sizeof fmt);
3772 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3773 xassert (parsed_p);
3775 /* Get specified width, and height. */
3776 if (!in_memory_file_p)
3778 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3779 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3780 xassert (img->width > 0 && img->height > 0);
3783 /* Get foreground and background colors, maybe allocate colors. */
3784 if (fmt[XBM_FOREGROUND].count
3785 && STRINGP (fmt[XBM_FOREGROUND].value))
3787 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3788 foreground);
3789 non_default_colors = 1;
3792 if (fmt[XBM_BACKGROUND].count
3793 && STRINGP (fmt[XBM_BACKGROUND].value))
3795 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3796 background);
3797 non_default_colors = 1;
3800 if (in_memory_file_p)
3801 success_p = xbm_load_image (f, img, SDATA (data),
3802 (SDATA (data)
3803 + SBYTES (data)));
3804 else
3806 if (VECTORP (data))
3808 int i;
3809 char *p;
3810 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3812 p = bits = (char *) alloca (nbytes * img->height);
3813 for (i = 0; i < img->height; ++i, p += nbytes)
3815 Lisp_Object line = XVECTOR (data)->contents[i];
3816 if (STRINGP (line))
3817 bcopy (SDATA (line), p, nbytes);
3818 else
3819 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3822 else if (STRINGP (data))
3823 bits = SDATA (data);
3824 else
3825 bits = XBOOL_VECTOR (data)->data;
3827 #ifdef WINDOWSNT
3829 char *invertedBits;
3830 int nbytes, i;
3831 /* Windows mono bitmaps are reversed compared with X. */
3832 invertedBits = bits;
3833 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3834 * img->height;
3835 bits = (char *) alloca(nbytes);
3836 for (i = 0; i < nbytes; i++)
3837 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3839 #endif
3840 /* Create the pixmap. */
3842 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3843 foreground, background,
3844 non_default_colors);
3845 if (img->pixmap)
3846 success_p = 1;
3847 else
3849 image_error ("Unable to create pixmap for XBM image `%s'",
3850 img->spec, Qnil);
3851 x_clear_image (f, img);
3856 return success_p;
3861 /***********************************************************************
3862 XPM images
3863 ***********************************************************************/
3865 #if defined (HAVE_XPM) || defined (MAC_OS)
3867 static int xpm_image_p P_ ((Lisp_Object object));
3868 static int xpm_load P_ ((struct frame *f, struct image *img));
3869 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3871 #endif /* HAVE_XPM || MAC_OS */
3873 #ifdef HAVE_XPM
3874 #ifdef HAVE_NTGUI
3875 /* Indicate to xpm.h that we don't have Xlib. */
3876 #define FOR_MSW
3877 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3878 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3879 #define XColor xpm_XColor
3880 #define XImage xpm_XImage
3881 #define Display xpm_Display
3882 #define PIXEL_ALREADY_TYPEDEFED
3883 #include "X11/xpm.h"
3884 #undef FOR_MSW
3885 #undef XColor
3886 #undef XImage
3887 #undef Display
3888 #undef PIXEL_ALREADY_TYPEDEFED
3889 #else
3890 #include "X11/xpm.h"
3891 #endif /* HAVE_NTGUI */
3892 #endif /* HAVE_XPM */
3894 #if defined (HAVE_XPM) || defined (MAC_OS)
3895 /* The symbol `xpm' identifying XPM-format images. */
3897 Lisp_Object Qxpm;
3899 /* Indices of image specification fields in xpm_format, below. */
3901 enum xpm_keyword_index
3903 XPM_TYPE,
3904 XPM_FILE,
3905 XPM_DATA,
3906 XPM_ASCENT,
3907 XPM_MARGIN,
3908 XPM_RELIEF,
3909 XPM_ALGORITHM,
3910 XPM_HEURISTIC_MASK,
3911 XPM_MASK,
3912 XPM_COLOR_SYMBOLS,
3913 XPM_BACKGROUND,
3914 XPM_LAST
3917 /* Vector of image_keyword structures describing the format
3918 of valid XPM image specifications. */
3920 static struct image_keyword xpm_format[XPM_LAST] =
3922 {":type", IMAGE_SYMBOL_VALUE, 1},
3923 {":file", IMAGE_STRING_VALUE, 0},
3924 {":data", IMAGE_STRING_VALUE, 0},
3925 {":ascent", IMAGE_ASCENT_VALUE, 0},
3926 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3927 {":relief", IMAGE_INTEGER_VALUE, 0},
3928 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3929 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3930 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3931 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3932 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3935 /* Structure describing the image type XPM. */
3937 static struct image_type xpm_type =
3939 &Qxpm,
3940 xpm_image_p,
3941 xpm_load,
3942 x_clear_image,
3943 NULL
3946 #ifdef HAVE_X_WINDOWS
3948 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3949 functions for allocating image colors. Our own functions handle
3950 color allocation failures more gracefully than the ones on the XPM
3951 lib. */
3953 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3954 #define ALLOC_XPM_COLORS
3955 #endif
3956 #endif /* HAVE_X_WINDOWS */
3958 #ifdef ALLOC_XPM_COLORS
3960 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3961 static void xpm_free_color_cache P_ ((void));
3962 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3963 static int xpm_color_bucket P_ ((char *));
3964 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3965 XColor *, int));
3967 /* An entry in a hash table used to cache color definitions of named
3968 colors. This cache is necessary to speed up XPM image loading in
3969 case we do color allocations ourselves. Without it, we would need
3970 a call to XParseColor per pixel in the image. */
3972 struct xpm_cached_color
3974 /* Next in collision chain. */
3975 struct xpm_cached_color *next;
3977 /* Color definition (RGB and pixel color). */
3978 XColor color;
3980 /* Color name. */
3981 char name[1];
3984 /* The hash table used for the color cache, and its bucket vector
3985 size. */
3987 #define XPM_COLOR_CACHE_BUCKETS 1001
3988 struct xpm_cached_color **xpm_color_cache;
3990 /* Initialize the color cache. */
3992 static void
3993 xpm_init_color_cache (f, attrs)
3994 struct frame *f;
3995 XpmAttributes *attrs;
3997 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
3998 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
3999 memset (xpm_color_cache, 0, nbytes);
4000 init_color_table ();
4002 if (attrs->valuemask & XpmColorSymbols)
4004 int i;
4005 XColor color;
4007 for (i = 0; i < attrs->numsymbols; ++i)
4008 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4009 attrs->colorsymbols[i].value, &color))
4011 color.pixel = lookup_rgb_color (f, color.red, color.green,
4012 color.blue);
4013 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
4018 /* Free the color cache. */
4020 static void
4021 xpm_free_color_cache ()
4023 struct xpm_cached_color *p, *next;
4024 int i;
4026 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
4027 for (p = xpm_color_cache[i]; p; p = next)
4029 next = p->next;
4030 xfree (p);
4033 xfree (xpm_color_cache);
4034 xpm_color_cache = NULL;
4035 free_color_table ();
4038 /* Return the bucket index for color named COLOR_NAME in the color
4039 cache. */
4041 static int
4042 xpm_color_bucket (color_name)
4043 char *color_name;
4045 unsigned h = 0;
4046 char *s;
4048 for (s = color_name; *s; ++s)
4049 h = (h << 2) ^ *s;
4050 return h %= XPM_COLOR_CACHE_BUCKETS;
4054 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4055 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4056 entry added. */
4058 static struct xpm_cached_color *
4059 xpm_cache_color (f, color_name, color, bucket)
4060 struct frame *f;
4061 char *color_name;
4062 XColor *color;
4063 int bucket;
4065 size_t nbytes;
4066 struct xpm_cached_color *p;
4068 if (bucket < 0)
4069 bucket = xpm_color_bucket (color_name);
4071 nbytes = sizeof *p + strlen (color_name);
4072 p = (struct xpm_cached_color *) xmalloc (nbytes);
4073 strcpy (p->name, color_name);
4074 p->color = *color;
4075 p->next = xpm_color_cache[bucket];
4076 xpm_color_cache[bucket] = p;
4077 return p;
4080 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4081 return the cached definition in *COLOR. Otherwise, make a new
4082 entry in the cache and allocate the color. Value is zero if color
4083 allocation failed. */
4085 static int
4086 xpm_lookup_color (f, color_name, color)
4087 struct frame *f;
4088 char *color_name;
4089 XColor *color;
4091 struct xpm_cached_color *p;
4092 int h = xpm_color_bucket (color_name);
4094 for (p = xpm_color_cache[h]; p; p = p->next)
4095 if (strcmp (p->name, color_name) == 0)
4096 break;
4098 if (p != NULL)
4099 *color = p->color;
4100 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4101 color_name, color))
4103 color->pixel = lookup_rgb_color (f, color->red, color->green,
4104 color->blue);
4105 p = xpm_cache_color (f, color_name, color, h);
4107 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4108 with transparency, and it's useful. */
4109 else if (strcmp ("opaque", color_name) == 0)
4111 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
4112 color->pixel = FRAME_FOREGROUND_PIXEL (f);
4113 p = xpm_cache_color (f, color_name, color, h);
4116 return p != NULL;
4120 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4121 CLOSURE is a pointer to the frame on which we allocate the
4122 color. Return in *COLOR the allocated color. Value is non-zero
4123 if successful. */
4125 static int
4126 xpm_alloc_color (dpy, cmap, color_name, color, closure)
4127 Display *dpy;
4128 Colormap cmap;
4129 char *color_name;
4130 XColor *color;
4131 void *closure;
4133 return xpm_lookup_color ((struct frame *) closure, color_name, color);
4137 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4138 is a pointer to the frame on which we allocate the color. Value is
4139 non-zero if successful. */
4141 static int
4142 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
4143 Display *dpy;
4144 Colormap cmap;
4145 Pixel *pixels;
4146 int npixels;
4147 void *closure;
4149 return 1;
4152 #endif /* ALLOC_XPM_COLORS */
4155 #ifdef HAVE_NTGUI
4157 /* XPM library details. */
4159 DEF_IMGLIB_FN (XpmFreeAttributes);
4160 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
4161 DEF_IMGLIB_FN (XpmReadFileToImage);
4162 DEF_IMGLIB_FN (XImageFree);
4164 static int
4165 init_xpm_functions (Lisp_Object libraries)
4167 HMODULE library;
4169 if (!(library = w32_delayed_load (libraries, Qxpm)))
4170 return 0;
4172 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
4173 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
4174 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
4175 LOAD_IMGLIB_FN (library, XImageFree);
4176 return 1;
4179 #endif /* HAVE_NTGUI */
4182 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4183 for XPM images. Such a list must consist of conses whose car and
4184 cdr are strings. */
4186 static int
4187 xpm_valid_color_symbols_p (color_symbols)
4188 Lisp_Object color_symbols;
4190 while (CONSP (color_symbols))
4192 Lisp_Object sym = XCAR (color_symbols);
4193 if (!CONSP (sym)
4194 || !STRINGP (XCAR (sym))
4195 || !STRINGP (XCDR (sym)))
4196 break;
4197 color_symbols = XCDR (color_symbols);
4200 return NILP (color_symbols);
4204 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4206 static int
4207 xpm_image_p (object)
4208 Lisp_Object object;
4210 struct image_keyword fmt[XPM_LAST];
4211 bcopy (xpm_format, fmt, sizeof fmt);
4212 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
4213 /* Either `:file' or `:data' must be present. */
4214 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
4215 /* Either no `:color-symbols' or it's a list of conses
4216 whose car and cdr are strings. */
4217 && (fmt[XPM_COLOR_SYMBOLS].count == 0
4218 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
4221 #endif /* HAVE_XPM || MAC_OS */
4223 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4225 x_create_bitmap_from_xpm_data (f, bits)
4226 struct frame *f;
4227 char **bits;
4229 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4230 int id, rc;
4231 XpmAttributes attrs;
4232 Pixmap bitmap, mask;
4234 bzero (&attrs, sizeof attrs);
4236 attrs.visual = FRAME_X_VISUAL (f);
4237 attrs.colormap = FRAME_X_COLORMAP (f);
4238 attrs.valuemask |= XpmVisual;
4239 attrs.valuemask |= XpmColormap;
4241 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4242 bits, &bitmap, &mask, &attrs);
4243 if (rc != XpmSuccess)
4245 XpmFreeAttributes (&attrs);
4246 return -1;
4249 id = x_allocate_bitmap_record (f);
4250 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
4251 dpyinfo->bitmaps[id - 1].have_mask = 1;
4252 dpyinfo->bitmaps[id - 1].mask = mask;
4253 dpyinfo->bitmaps[id - 1].file = NULL;
4254 dpyinfo->bitmaps[id - 1].height = attrs.height;
4255 dpyinfo->bitmaps[id - 1].width = attrs.width;
4256 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
4257 dpyinfo->bitmaps[id - 1].refcount = 1;
4259 XpmFreeAttributes (&attrs);
4260 return id;
4262 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4264 /* Load image IMG which will be displayed on frame F. Value is
4265 non-zero if successful. */
4267 #ifdef HAVE_XPM
4269 static int
4270 xpm_load (f, img)
4271 struct frame *f;
4272 struct image *img;
4274 int rc;
4275 XpmAttributes attrs;
4276 Lisp_Object specified_file, color_symbols;
4277 #ifdef HAVE_NTGUI
4278 HDC hdc;
4279 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
4280 #endif /* HAVE_NTGUI */
4282 /* Configure the XPM lib. Use the visual of frame F. Allocate
4283 close colors. Return colors allocated. */
4284 bzero (&attrs, sizeof attrs);
4286 #ifndef HAVE_NTGUI
4287 attrs.visual = FRAME_X_VISUAL (f);
4288 attrs.colormap = FRAME_X_COLORMAP (f);
4289 attrs.valuemask |= XpmVisual;
4290 attrs.valuemask |= XpmColormap;
4291 #endif /* HAVE_NTGUI */
4293 #ifdef ALLOC_XPM_COLORS
4294 /* Allocate colors with our own functions which handle
4295 failing color allocation more gracefully. */
4296 attrs.color_closure = f;
4297 attrs.alloc_color = xpm_alloc_color;
4298 attrs.free_colors = xpm_free_colors;
4299 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
4300 #else /* not ALLOC_XPM_COLORS */
4301 /* Let the XPM lib allocate colors. */
4302 attrs.valuemask |= XpmReturnAllocPixels;
4303 #ifdef XpmAllocCloseColors
4304 attrs.alloc_close_colors = 1;
4305 attrs.valuemask |= XpmAllocCloseColors;
4306 #else /* not XpmAllocCloseColors */
4307 attrs.closeness = 600;
4308 attrs.valuemask |= XpmCloseness;
4309 #endif /* not XpmAllocCloseColors */
4310 #endif /* ALLOC_XPM_COLORS */
4312 /* If image specification contains symbolic color definitions, add
4313 these to `attrs'. */
4314 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4315 if (CONSP (color_symbols))
4317 Lisp_Object tail;
4318 XpmColorSymbol *xpm_syms;
4319 int i, size;
4321 attrs.valuemask |= XpmColorSymbols;
4323 /* Count number of symbols. */
4324 attrs.numsymbols = 0;
4325 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
4326 ++attrs.numsymbols;
4328 /* Allocate an XpmColorSymbol array. */
4329 size = attrs.numsymbols * sizeof *xpm_syms;
4330 xpm_syms = (XpmColorSymbol *) alloca (size);
4331 bzero (xpm_syms, size);
4332 attrs.colorsymbols = xpm_syms;
4334 /* Fill the color symbol array. */
4335 for (tail = color_symbols, i = 0;
4336 CONSP (tail);
4337 ++i, tail = XCDR (tail))
4339 Lisp_Object name = XCAR (XCAR (tail));
4340 Lisp_Object color = XCDR (XCAR (tail));
4341 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
4342 strcpy (xpm_syms[i].name, SDATA (name));
4343 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
4344 strcpy (xpm_syms[i].value, SDATA (color));
4348 /* Create a pixmap for the image, either from a file, or from a
4349 string buffer containing data in the same format as an XPM file. */
4350 #ifdef ALLOC_XPM_COLORS
4351 xpm_init_color_cache (f, &attrs);
4352 #endif
4354 specified_file = image_spec_value (img->spec, QCfile, NULL);
4356 #ifdef HAVE_NTGUI
4358 HDC frame_dc = get_frame_dc (f);
4359 hdc = CreateCompatibleDC (frame_dc);
4360 release_frame_dc (f, frame_dc);
4362 #endif /* HAVE_NTGUI */
4364 if (STRINGP (specified_file))
4366 Lisp_Object file = x_find_image_file (specified_file);
4367 if (!STRINGP (file))
4369 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4370 return 0;
4373 #ifdef HAVE_NTGUI
4374 /* XpmReadFileToPixmap is not available in the Windows port of
4375 libxpm. But XpmReadFileToImage almost does what we want. */
4376 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
4377 &xpm_image, &xpm_mask,
4378 &attrs);
4379 #else
4380 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4381 SDATA (file), &img->pixmap, &img->mask,
4382 &attrs);
4383 #endif /* HAVE_NTGUI */
4385 else
4387 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
4388 #ifdef HAVE_NTGUI
4389 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4390 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4391 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
4392 &xpm_image, &xpm_mask,
4393 &attrs);
4394 #else
4395 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4396 SDATA (buffer),
4397 &img->pixmap, &img->mask,
4398 &attrs);
4399 #endif /* HAVE_NTGUI */
4402 if (rc == XpmSuccess)
4404 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4405 img->colors = colors_in_color_table (&img->ncolors);
4406 #else /* not ALLOC_XPM_COLORS */
4407 int i;
4409 #ifdef HAVE_NTGUI
4410 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4411 plus some duplicate attributes. */
4412 if (xpm_image && xpm_image->bitmap)
4414 img->pixmap = xpm_image->bitmap;
4415 /* XImageFree in libXpm frees XImage struct without destroying
4416 the bitmap, which is what we want. */
4417 fn_XImageFree (xpm_image);
4419 if (xpm_mask && xpm_mask->bitmap)
4421 /* The mask appears to be inverted compared with what we expect.
4422 TODO: invert our expectations. See other places where we
4423 have to invert bits because our idea of masks is backwards. */
4424 HGDIOBJ old_obj;
4425 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4427 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4428 SelectObject (hdc, old_obj);
4430 img->mask = xpm_mask->bitmap;
4431 fn_XImageFree (xpm_mask);
4432 DeleteDC (hdc);
4435 DeleteDC (hdc);
4436 #endif /* HAVE_NTGUI */
4438 /* Remember allocated colors. */
4439 img->ncolors = attrs.nalloc_pixels;
4440 img->colors = (unsigned long *) xmalloc (img->ncolors
4441 * sizeof *img->colors);
4442 for (i = 0; i < attrs.nalloc_pixels; ++i)
4444 img->colors[i] = attrs.alloc_pixels[i];
4445 #ifdef DEBUG_X_COLORS
4446 register_color (img->colors[i]);
4447 #endif
4449 #endif /* not ALLOC_XPM_COLORS */
4451 img->width = attrs.width;
4452 img->height = attrs.height;
4453 xassert (img->width > 0 && img->height > 0);
4455 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4456 #ifdef HAVE_NTGUI
4457 fn_XpmFreeAttributes (&attrs);
4458 #else
4459 XpmFreeAttributes (&attrs);
4460 #endif /* HAVE_NTGUI */
4462 else
4464 #ifdef HAVE_NTGUI
4465 DeleteDC (hdc);
4466 #endif /* HAVE_NTGUI */
4468 switch (rc)
4470 case XpmOpenFailed:
4471 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4472 break;
4474 case XpmFileInvalid:
4475 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4476 break;
4478 case XpmNoMemory:
4479 image_error ("Out of memory (%s)", img->spec, Qnil);
4480 break;
4482 case XpmColorFailed:
4483 image_error ("Color allocation error (%s)", img->spec, Qnil);
4484 break;
4486 default:
4487 image_error ("Unknown error (%s)", img->spec, Qnil);
4488 break;
4492 #ifdef ALLOC_XPM_COLORS
4493 xpm_free_color_cache ();
4494 #endif
4495 return rc == XpmSuccess;
4498 #endif /* HAVE_XPM */
4500 #ifdef MAC_OS
4502 /* XPM support functions for Mac OS where libxpm is not available.
4503 Only XPM version 3 (without any extensions) is supported. */
4505 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
4506 const unsigned char **, int *));
4507 static Lisp_Object xpm_make_color_table_v
4508 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4509 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4510 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
4511 int, Lisp_Object));
4512 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4513 const unsigned char *, int));
4514 static Lisp_Object xpm_make_color_table_h
4515 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4516 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4517 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
4518 int, Lisp_Object));
4519 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4520 const unsigned char *, int));
4521 static int xpm_str_to_color_key P_ ((const char *));
4522 static int xpm_load_image P_ ((struct frame *, struct image *,
4523 const unsigned char *, const unsigned char *));
4525 /* Tokens returned from xpm_scan. */
4527 enum xpm_token
4529 XPM_TK_IDENT = 256,
4530 XPM_TK_STRING,
4531 XPM_TK_EOF
4534 /* Scan an XPM data and return a character (< 256) or a token defined
4535 by enum xpm_token above. *S and END are the start (inclusive) and
4536 the end (exclusive) addresses of the data, respectively. Advance
4537 *S while scanning. If token is either XPM_TK_IDENT or
4538 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4539 length of the corresponding token, respectively. */
4541 static int
4542 xpm_scan (s, end, beg, len)
4543 const unsigned char **s, *end, **beg;
4544 int *len;
4546 int c;
4548 while (*s < end)
4550 /* Skip white-space. */
4551 while (*s < end && (c = *(*s)++, isspace (c)))
4554 /* gnus-pointer.xpm uses '-' in its identifier.
4555 sb-dir-plus.xpm uses '+' in its identifier. */
4556 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4558 *beg = *s - 1;
4559 while (*s < end
4560 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4561 ++*s;
4562 *len = *s - *beg;
4563 return XPM_TK_IDENT;
4565 else if (c == '"')
4567 *beg = *s;
4568 while (*s < end && **s != '"')
4569 ++*s;
4570 *len = *s - *beg;
4571 if (*s < end)
4572 ++*s;
4573 return XPM_TK_STRING;
4575 else if (c == '/')
4577 if (*s < end && **s == '*')
4579 /* C-style comment. */
4580 ++*s;
4583 while (*s < end && *(*s)++ != '*')
4586 while (*s < end && **s != '/');
4587 if (*s < end)
4588 ++*s;
4590 else
4591 return c;
4593 else
4594 return c;
4597 return XPM_TK_EOF;
4600 /* Functions for color table lookup in XPM data. A key is a string
4601 specifying the color of each pixel in XPM data. A value is either
4602 an integer that specifies a pixel color, Qt that specifies
4603 transparency, or Qnil for the unspecified color. If the length of
4604 the key string is one, a vector is used as a table. Otherwise, a
4605 hash table is used. */
4607 static Lisp_Object
4608 xpm_make_color_table_v (put_func, get_func)
4609 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4610 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4612 *put_func = xpm_put_color_table_v;
4613 *get_func = xpm_get_color_table_v;
4614 return Fmake_vector (make_number (256), Qnil);
4617 static void
4618 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4619 Lisp_Object color_table;
4620 const unsigned char *chars_start;
4621 int chars_len;
4622 Lisp_Object color;
4624 XVECTOR (color_table)->contents[*chars_start] = color;
4627 static Lisp_Object
4628 xpm_get_color_table_v (color_table, chars_start, chars_len)
4629 Lisp_Object color_table;
4630 const unsigned char *chars_start;
4631 int chars_len;
4633 return XVECTOR (color_table)->contents[*chars_start];
4636 static Lisp_Object
4637 xpm_make_color_table_h (put_func, get_func)
4638 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4639 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4641 *put_func = xpm_put_color_table_h;
4642 *get_func = xpm_get_color_table_h;
4643 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4644 make_float (DEFAULT_REHASH_SIZE),
4645 make_float (DEFAULT_REHASH_THRESHOLD),
4646 Qnil, Qnil, Qnil);
4649 static void
4650 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4651 Lisp_Object color_table;
4652 const unsigned char *chars_start;
4653 int chars_len;
4654 Lisp_Object color;
4656 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4657 unsigned hash_code;
4658 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4660 hash_lookup (table, chars, &hash_code);
4661 hash_put (table, chars, color, hash_code);
4664 static Lisp_Object
4665 xpm_get_color_table_h (color_table, chars_start, chars_len)
4666 Lisp_Object color_table;
4667 const unsigned char *chars_start;
4668 int chars_len;
4670 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4671 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4672 NULL);
4674 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4677 enum xpm_color_key {
4678 XPM_COLOR_KEY_S,
4679 XPM_COLOR_KEY_M,
4680 XPM_COLOR_KEY_G4,
4681 XPM_COLOR_KEY_G,
4682 XPM_COLOR_KEY_C
4685 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4687 static int
4688 xpm_str_to_color_key (s)
4689 const char *s;
4691 int i;
4693 for (i = 0;
4694 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4695 i++)
4696 if (strcmp (xpm_color_key_strings[i], s) == 0)
4697 return i;
4698 return -1;
4701 static int
4702 xpm_load_image (f, img, contents, end)
4703 struct frame *f;
4704 struct image *img;
4705 const unsigned char *contents, *end;
4707 const unsigned char *s = contents, *beg, *str;
4708 unsigned char buffer[BUFSIZ];
4709 int width, height, x, y;
4710 int num_colors, chars_per_pixel;
4711 int len, LA1;
4712 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4713 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
4714 Lisp_Object frame, color_symbols, color_table;
4715 int best_key, have_mask = 0;
4716 XImagePtr ximg = NULL, mask_img = NULL;
4718 #define match() \
4719 LA1 = xpm_scan (&s, end, &beg, &len)
4721 #define expect(TOKEN) \
4722 if (LA1 != (TOKEN)) \
4723 goto failure; \
4724 else \
4725 match ()
4727 #define expect_ident(IDENT) \
4728 if (LA1 == XPM_TK_IDENT \
4729 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4730 match (); \
4731 else \
4732 goto failure
4734 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4735 goto failure;
4736 s += 9;
4737 match();
4738 expect_ident ("static");
4739 expect_ident ("char");
4740 expect ('*');
4741 expect (XPM_TK_IDENT);
4742 expect ('[');
4743 expect (']');
4744 expect ('=');
4745 expect ('{');
4746 expect (XPM_TK_STRING);
4747 if (len >= BUFSIZ)
4748 goto failure;
4749 memcpy (buffer, beg, len);
4750 buffer[len] = '\0';
4751 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4752 &num_colors, &chars_per_pixel) != 4
4753 || width <= 0 || height <= 0
4754 || num_colors <= 0 || chars_per_pixel <= 0)
4755 goto failure;
4757 if (!check_image_size (f, width, height))
4759 image_error ("Invalid image size", Qnil, Qnil);
4760 goto failure;
4763 expect (',');
4765 XSETFRAME (frame, f);
4766 if (!NILP (Fxw_display_color_p (frame)))
4767 best_key = XPM_COLOR_KEY_C;
4768 else if (!NILP (Fx_display_grayscale_p (frame)))
4769 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4770 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4771 else
4772 best_key = XPM_COLOR_KEY_M;
4774 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4775 if (chars_per_pixel == 1)
4776 color_table = xpm_make_color_table_v (&put_color_table,
4777 &get_color_table);
4778 else
4779 color_table = xpm_make_color_table_h (&put_color_table,
4780 &get_color_table);
4782 while (num_colors-- > 0)
4784 unsigned char *color, *max_color;
4785 int key, next_key, max_key = 0;
4786 Lisp_Object symbol_color = Qnil, color_val;
4787 XColor cdef;
4789 expect (XPM_TK_STRING);
4790 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4791 goto failure;
4792 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4793 buffer[len - chars_per_pixel] = '\0';
4795 str = strtok (buffer, " \t");
4796 if (str == NULL)
4797 goto failure;
4798 key = xpm_str_to_color_key (str);
4799 if (key < 0)
4800 goto failure;
4803 color = strtok (NULL, " \t");
4804 if (color == NULL)
4805 goto failure;
4807 while ((str = strtok (NULL, " \t")) != NULL)
4809 next_key = xpm_str_to_color_key (str);
4810 if (next_key >= 0)
4811 break;
4812 color[strlen (color)] = ' ';
4815 if (key == XPM_COLOR_KEY_S)
4817 if (NILP (symbol_color))
4818 symbol_color = build_string (color);
4820 else if (max_key < key && key <= best_key)
4822 max_key = key;
4823 max_color = color;
4825 key = next_key;
4827 while (str);
4829 color_val = Qnil;
4830 if (!NILP (color_symbols) && !NILP (symbol_color))
4832 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4834 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4836 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4837 color_val = Qt;
4838 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4839 &cdef, 0))
4840 color_val = make_number (cdef.pixel);
4843 if (NILP (color_val) && max_key > 0)
4845 if (xstricmp (max_color, "None") == 0)
4846 color_val = Qt;
4847 else if (x_defined_color (f, max_color, &cdef, 0))
4848 color_val = make_number (cdef.pixel);
4850 if (!NILP (color_val))
4851 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4853 expect (',');
4856 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4857 &ximg, &img->pixmap)
4858 || !x_create_x_image_and_pixmap (f, width, height, 1,
4859 &mask_img, &img->mask))
4861 image_error ("Out of memory (%s)", img->spec, Qnil);
4862 goto error;
4865 for (y = 0; y < height; y++)
4867 expect (XPM_TK_STRING);
4868 str = beg;
4869 if (len < width * chars_per_pixel)
4870 goto failure;
4871 for (x = 0; x < width; x++, str += chars_per_pixel)
4873 Lisp_Object color_val =
4874 (*get_color_table) (color_table, str, chars_per_pixel);
4876 XPutPixel (ximg, x, y,
4877 (INTEGERP (color_val) ? XINT (color_val)
4878 : FRAME_FOREGROUND_PIXEL (f)));
4879 XPutPixel (mask_img, x, y,
4880 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4881 : (have_mask = 1, PIX_MASK_RETAIN)));
4883 if (y + 1 < height)
4884 expect (',');
4887 img->width = width;
4888 img->height = height;
4890 /* Maybe fill in the background field while we have ximg handy. */
4891 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4892 IMAGE_BACKGROUND (img, f, ximg);
4894 x_put_x_image (f, ximg, img->pixmap, width, height);
4895 x_destroy_x_image (ximg);
4896 if (have_mask)
4898 /* Fill in the background_transparent field while we have the
4899 mask handy. */
4900 image_background_transparent (img, f, mask_img);
4902 x_put_x_image (f, mask_img, img->mask, width, height);
4903 x_destroy_x_image (mask_img);
4905 else
4907 x_destroy_x_image (mask_img);
4908 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4909 img->mask = NO_PIXMAP;
4912 return 1;
4914 failure:
4915 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4916 error:
4917 x_destroy_x_image (ximg);
4918 x_destroy_x_image (mask_img);
4919 x_clear_image (f, img);
4920 return 0;
4922 #undef match
4923 #undef expect
4924 #undef expect_ident
4927 static int
4928 xpm_load (f, img)
4929 struct frame *f;
4930 struct image *img;
4932 int success_p = 0;
4933 Lisp_Object file_name;
4935 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4936 file_name = image_spec_value (img->spec, QCfile, NULL);
4937 if (STRINGP (file_name))
4939 Lisp_Object file;
4940 unsigned char *contents;
4941 int size;
4942 struct gcpro gcpro1;
4944 file = x_find_image_file (file_name);
4945 GCPRO1 (file);
4946 if (!STRINGP (file))
4948 image_error ("Cannot find image file `%s'", file_name, Qnil);
4949 UNGCPRO;
4950 return 0;
4953 contents = slurp_file (SDATA (file), &size);
4954 if (contents == NULL)
4956 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4957 UNGCPRO;
4958 return 0;
4961 success_p = xpm_load_image (f, img, contents, contents + size);
4962 xfree (contents);
4963 UNGCPRO;
4965 else
4967 Lisp_Object data;
4969 data = image_spec_value (img->spec, QCdata, NULL);
4970 success_p = xpm_load_image (f, img, SDATA (data),
4971 SDATA (data) + SBYTES (data));
4974 return success_p;
4977 #endif /* MAC_OS */
4981 /***********************************************************************
4982 Color table
4983 ***********************************************************************/
4985 #ifdef COLOR_TABLE_SUPPORT
4987 /* An entry in the color table mapping an RGB color to a pixel color. */
4989 struct ct_color
4991 int r, g, b;
4992 unsigned long pixel;
4994 /* Next in color table collision list. */
4995 struct ct_color *next;
4998 /* The bucket vector size to use. Must be prime. */
5000 #define CT_SIZE 101
5002 /* Value is a hash of the RGB color given by R, G, and B. */
5004 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5006 /* The color hash table. */
5008 struct ct_color **ct_table;
5010 /* Number of entries in the color table. */
5012 int ct_colors_allocated;
5014 /* Initialize the color table. */
5016 static void
5017 init_color_table ()
5019 int size = CT_SIZE * sizeof (*ct_table);
5020 ct_table = (struct ct_color **) xmalloc (size);
5021 bzero (ct_table, size);
5022 ct_colors_allocated = 0;
5026 /* Free memory associated with the color table. */
5028 static void
5029 free_color_table ()
5031 int i;
5032 struct ct_color *p, *next;
5034 for (i = 0; i < CT_SIZE; ++i)
5035 for (p = ct_table[i]; p; p = next)
5037 next = p->next;
5038 xfree (p);
5041 xfree (ct_table);
5042 ct_table = NULL;
5046 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5047 entry for that color already is in the color table, return the
5048 pixel color of that entry. Otherwise, allocate a new color for R,
5049 G, B, and make an entry in the color table. */
5051 static unsigned long
5052 lookup_rgb_color (f, r, g, b)
5053 struct frame *f;
5054 int r, g, b;
5056 unsigned hash = CT_HASH_RGB (r, g, b);
5057 int i = hash % CT_SIZE;
5058 struct ct_color *p;
5059 Display_Info *dpyinfo;
5061 /* Handle TrueColor visuals specially, which improves performance by
5062 two orders of magnitude. Freeing colors on TrueColor visuals is
5063 a nop, and pixel colors specify RGB values directly. See also
5064 the Xlib spec, chapter 3.1. */
5065 dpyinfo = FRAME_X_DISPLAY_INFO (f);
5066 if (dpyinfo->red_bits > 0)
5068 unsigned long pr, pg, pb;
5070 /* Apply gamma-correction like normal color allocation does. */
5071 if (f->gamma)
5073 XColor color;
5074 color.red = r, color.green = g, color.blue = b;
5075 gamma_correct (f, &color);
5076 r = color.red, g = color.green, b = color.blue;
5079 /* Scale down RGB values to the visual's bits per RGB, and shift
5080 them to the right position in the pixel color. Note that the
5081 original RGB values are 16-bit values, as usual in X. */
5082 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
5083 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
5084 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
5086 /* Assemble the pixel color. */
5087 return pr | pg | pb;
5090 for (p = ct_table[i]; p; p = p->next)
5091 if (p->r == r && p->g == g && p->b == b)
5092 break;
5094 if (p == NULL)
5097 #ifdef HAVE_X_WINDOWS
5098 XColor color;
5099 Colormap cmap;
5100 int rc;
5102 color.red = r;
5103 color.green = g;
5104 color.blue = b;
5106 cmap = FRAME_X_COLORMAP (f);
5107 rc = x_alloc_nearest_color (f, cmap, &color);
5108 if (rc)
5110 ++ct_colors_allocated;
5111 p = (struct ct_color *) xmalloc (sizeof *p);
5112 p->r = r;
5113 p->g = g;
5114 p->b = b;
5115 p->pixel = color.pixel;
5116 p->next = ct_table[i];
5117 ct_table[i] = p;
5119 else
5120 return FRAME_FOREGROUND_PIXEL (f);
5122 #else
5123 COLORREF color;
5124 #ifdef HAVE_NTGUI
5125 color = PALETTERGB (r, g, b);
5126 #else
5127 color = RGB_TO_ULONG (r, g, b);
5128 #endif /* HAVE_NTGUI */
5129 ++ct_colors_allocated;
5130 p = (struct ct_color *) xmalloc (sizeof *p);
5131 p->r = r;
5132 p->g = g;
5133 p->b = b;
5134 p->pixel = color;
5135 p->next = ct_table[i];
5136 ct_table[i] = p;
5137 #endif /* HAVE_X_WINDOWS */
5141 return p->pixel;
5145 /* Look up pixel color PIXEL which is used on frame F in the color
5146 table. If not already present, allocate it. Value is PIXEL. */
5148 static unsigned long
5149 lookup_pixel_color (f, pixel)
5150 struct frame *f;
5151 unsigned long pixel;
5153 int i = pixel % CT_SIZE;
5154 struct ct_color *p;
5156 for (p = ct_table[i]; p; p = p->next)
5157 if (p->pixel == pixel)
5158 break;
5160 if (p == NULL)
5162 XColor color;
5163 Colormap cmap;
5164 int rc;
5166 #ifdef HAVE_X_WINDOWS
5167 cmap = FRAME_X_COLORMAP (f);
5168 color.pixel = pixel;
5169 x_query_color (f, &color);
5170 rc = x_alloc_nearest_color (f, cmap, &color);
5171 #else
5172 BLOCK_INPUT;
5173 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5174 color.pixel = pixel;
5175 XQueryColor (NULL, cmap, &color);
5176 rc = x_alloc_nearest_color (f, cmap, &color);
5177 UNBLOCK_INPUT;
5178 #endif /* HAVE_X_WINDOWS */
5180 if (rc)
5182 ++ct_colors_allocated;
5184 p = (struct ct_color *) xmalloc (sizeof *p);
5185 p->r = color.red;
5186 p->g = color.green;
5187 p->b = color.blue;
5188 p->pixel = pixel;
5189 p->next = ct_table[i];
5190 ct_table[i] = p;
5192 else
5193 return FRAME_FOREGROUND_PIXEL (f);
5195 return p->pixel;
5199 /* Value is a vector of all pixel colors contained in the color table,
5200 allocated via xmalloc. Set *N to the number of colors. */
5202 static unsigned long *
5203 colors_in_color_table (n)
5204 int *n;
5206 int i, j;
5207 struct ct_color *p;
5208 unsigned long *colors;
5210 if (ct_colors_allocated == 0)
5212 *n = 0;
5213 colors = NULL;
5215 else
5217 colors = (unsigned long *) xmalloc (ct_colors_allocated
5218 * sizeof *colors);
5219 *n = ct_colors_allocated;
5221 for (i = j = 0; i < CT_SIZE; ++i)
5222 for (p = ct_table[i]; p; p = p->next)
5223 colors[j++] = p->pixel;
5226 return colors;
5229 #else /* COLOR_TABLE_SUPPORT */
5231 static unsigned long
5232 lookup_rgb_color (f, r, g, b)
5233 struct frame *f;
5234 int r, g, b;
5236 unsigned long pixel;
5238 #ifdef MAC_OS
5239 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5240 gamma_correct (f, &pixel);
5241 #endif /* MAC_OS */
5243 #ifdef HAVE_NTGUI
5244 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
5245 #endif /* HAVE_NTGUI */
5247 return pixel;
5250 static void
5251 init_color_table ()
5254 #endif /* COLOR_TABLE_SUPPORT */
5257 /***********************************************************************
5258 Algorithms
5259 ***********************************************************************/
5261 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
5262 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
5263 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
5265 #ifdef HAVE_NTGUI
5266 static void XPutPixel (XImagePtr , int, int, COLORREF);
5267 #endif /* HAVE_NTGUI */
5269 /* Non-zero means draw a cross on images having `:conversion
5270 disabled'. */
5272 int cross_disabled_images;
5274 /* Edge detection matrices for different edge-detection
5275 strategies. */
5277 static int emboss_matrix[9] = {
5278 /* x - 1 x x + 1 */
5279 2, -1, 0, /* y - 1 */
5280 -1, 0, 1, /* y */
5281 0, 1, -2 /* y + 1 */
5284 static int laplace_matrix[9] = {
5285 /* x - 1 x x + 1 */
5286 1, 0, 0, /* y - 1 */
5287 0, 0, 0, /* y */
5288 0, 0, -1 /* y + 1 */
5291 /* Value is the intensity of the color whose red/green/blue values
5292 are R, G, and B. */
5294 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5297 /* On frame F, return an array of XColor structures describing image
5298 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5299 non-zero means also fill the red/green/blue members of the XColor
5300 structures. Value is a pointer to the array of XColors structures,
5301 allocated with xmalloc; it must be freed by the caller. */
5303 static XColor *
5304 x_to_xcolors (f, img, rgb_p)
5305 struct frame *f;
5306 struct image *img;
5307 int rgb_p;
5309 int x, y;
5310 XColor *colors, *p;
5311 XImagePtr_or_DC ximg;
5312 #ifdef HAVE_NTGUI
5313 HDC hdc;
5314 HGDIOBJ prev;
5315 #endif /* HAVE_NTGUI */
5317 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
5319 #ifndef HAVE_NTGUI
5320 /* Get the X image IMG->pixmap. */
5321 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5322 0, 0, img->width, img->height, ~0, ZPixmap);
5323 #else
5324 /* Load the image into a memory device context. */
5325 hdc = get_frame_dc (f);
5326 ximg = CreateCompatibleDC (hdc);
5327 release_frame_dc (f, hdc);
5328 prev = SelectObject (ximg, img->pixmap);
5329 #endif /* HAVE_NTGUI */
5331 /* Fill the `pixel' members of the XColor array. I wished there
5332 were an easy and portable way to circumvent XGetPixel. */
5333 p = colors;
5334 for (y = 0; y < img->height; ++y)
5336 XColor *row = p;
5338 #ifdef HAVE_X_WINDOWS
5339 for (x = 0; x < img->width; ++x, ++p)
5340 p->pixel = XGetPixel (ximg, x, y);
5341 if (rgb_p)
5342 x_query_colors (f, row, img->width);
5344 #else
5346 for (x = 0; x < img->width; ++x, ++p)
5348 /* W32_TODO: palette support needed here? */
5349 p->pixel = GET_PIXEL (ximg, x, y);
5350 if (rgb_p)
5352 #ifdef MAC_OS
5353 p->red = RED16_FROM_ULONG (p->pixel);
5354 p->green = GREEN16_FROM_ULONG (p->pixel);
5355 p->blue = BLUE16_FROM_ULONG (p->pixel);
5356 #endif /* MAC_OS */
5357 #ifdef HAVE_NTGUI
5358 p->red = 256 * GetRValue (p->pixel);
5359 p->green = 256 * GetGValue (p->pixel);
5360 p->blue = 256 * GetBValue (p->pixel);
5361 #endif /* HAVE_NTGUI */
5364 #endif /* HAVE_X_WINDOWS */
5367 Destroy_Image (ximg, prev);
5369 return colors;
5372 #ifdef HAVE_NTGUI
5374 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5375 created with CreateDIBSection, with the pointer to the bit values
5376 stored in ximg->data. */
5378 static void
5379 XPutPixel (ximg, x, y, color)
5380 XImagePtr ximg;
5381 int x, y;
5382 COLORREF color;
5384 int width = ximg->info.bmiHeader.biWidth;
5385 int height = ximg->info.bmiHeader.biHeight;
5386 unsigned char * pixel;
5388 /* True color images. */
5389 if (ximg->info.bmiHeader.biBitCount == 24)
5391 int rowbytes = width * 3;
5392 /* Ensure scanlines are aligned on 4 byte boundaries. */
5393 if (rowbytes % 4)
5394 rowbytes += 4 - (rowbytes % 4);
5396 pixel = ximg->data + y * rowbytes + x * 3;
5397 /* Windows bitmaps are in BGR order. */
5398 *pixel = GetBValue (color);
5399 *(pixel + 1) = GetGValue (color);
5400 *(pixel + 2) = GetRValue (color);
5402 /* Monochrome images. */
5403 else if (ximg->info.bmiHeader.biBitCount == 1)
5405 int rowbytes = width / 8;
5406 /* Ensure scanlines are aligned on 4 byte boundaries. */
5407 if (rowbytes % 4)
5408 rowbytes += 4 - (rowbytes % 4);
5409 pixel = ximg->data + y * rowbytes + x / 8;
5410 /* Filter out palette info. */
5411 if (color & 0x00ffffff)
5412 *pixel = *pixel | (1 << x % 8);
5413 else
5414 *pixel = *pixel & ~(1 << x % 8);
5416 else
5417 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
5420 #endif /* HAVE_NTGUI */
5422 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5423 RGB members are set. F is the frame on which this all happens.
5424 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5426 static void
5427 x_from_xcolors (f, img, colors)
5428 struct frame *f;
5429 struct image *img;
5430 XColor *colors;
5432 int x, y;
5433 XImagePtr oimg;
5434 Pixmap pixmap;
5435 XColor *p;
5437 init_color_table ();
5439 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5440 &oimg, &pixmap);
5441 p = colors;
5442 for (y = 0; y < img->height; ++y)
5443 for (x = 0; x < img->width; ++x, ++p)
5445 unsigned long pixel;
5446 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5447 XPutPixel (oimg, x, y, pixel);
5450 xfree (colors);
5451 x_clear_image_1 (f, img, 1, 0, 1);
5453 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5454 x_destroy_x_image (oimg);
5455 img->pixmap = pixmap;
5456 #ifdef COLOR_TABLE_SUPPORT
5457 img->colors = colors_in_color_table (&img->ncolors);
5458 free_color_table ();
5459 #endif /* COLOR_TABLE_SUPPORT */
5463 /* On frame F, perform edge-detection on image IMG.
5465 MATRIX is a nine-element array specifying the transformation
5466 matrix. See emboss_matrix for an example.
5468 COLOR_ADJUST is a color adjustment added to each pixel of the
5469 outgoing image. */
5471 static void
5472 x_detect_edges (f, img, matrix, color_adjust)
5473 struct frame *f;
5474 struct image *img;
5475 int matrix[9], color_adjust;
5477 XColor *colors = x_to_xcolors (f, img, 1);
5478 XColor *new, *p;
5479 int x, y, i, sum;
5481 for (i = sum = 0; i < 9; ++i)
5482 sum += abs (matrix[i]);
5484 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5486 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5488 for (y = 0; y < img->height; ++y)
5490 p = COLOR (new, 0, y);
5491 p->red = p->green = p->blue = 0xffff/2;
5492 p = COLOR (new, img->width - 1, y);
5493 p->red = p->green = p->blue = 0xffff/2;
5496 for (x = 1; x < img->width - 1; ++x)
5498 p = COLOR (new, x, 0);
5499 p->red = p->green = p->blue = 0xffff/2;
5500 p = COLOR (new, x, img->height - 1);
5501 p->red = p->green = p->blue = 0xffff/2;
5504 for (y = 1; y < img->height - 1; ++y)
5506 p = COLOR (new, 1, y);
5508 for (x = 1; x < img->width - 1; ++x, ++p)
5510 int r, g, b, y1, x1;
5512 r = g = b = i = 0;
5513 for (y1 = y - 1; y1 < y + 2; ++y1)
5514 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5515 if (matrix[i])
5517 XColor *t = COLOR (colors, x1, y1);
5518 r += matrix[i] * t->red;
5519 g += matrix[i] * t->green;
5520 b += matrix[i] * t->blue;
5523 r = (r / sum + color_adjust) & 0xffff;
5524 g = (g / sum + color_adjust) & 0xffff;
5525 b = (b / sum + color_adjust) & 0xffff;
5526 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5530 xfree (colors);
5531 x_from_xcolors (f, img, new);
5533 #undef COLOR
5537 /* Perform the pre-defined `emboss' edge-detection on image IMG
5538 on frame F. */
5540 static void
5541 x_emboss (f, img)
5542 struct frame *f;
5543 struct image *img;
5545 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5549 /* Transform image IMG which is used on frame F with a Laplace
5550 edge-detection algorithm. The result is an image that can be used
5551 to draw disabled buttons, for example. */
5553 static void
5554 x_laplace (f, img)
5555 struct frame *f;
5556 struct image *img;
5558 x_detect_edges (f, img, laplace_matrix, 45000);
5562 /* Perform edge-detection on image IMG on frame F, with specified
5563 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5565 MATRIX must be either
5567 - a list of at least 9 numbers in row-major form
5568 - a vector of at least 9 numbers
5570 COLOR_ADJUST nil means use a default; otherwise it must be a
5571 number. */
5573 static void
5574 x_edge_detection (f, img, matrix, color_adjust)
5575 struct frame *f;
5576 struct image *img;
5577 Lisp_Object matrix, color_adjust;
5579 int i = 0;
5580 int trans[9];
5582 if (CONSP (matrix))
5584 for (i = 0;
5585 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5586 ++i, matrix = XCDR (matrix))
5587 trans[i] = XFLOATINT (XCAR (matrix));
5589 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5591 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5592 trans[i] = XFLOATINT (AREF (matrix, i));
5595 if (NILP (color_adjust))
5596 color_adjust = make_number (0xffff / 2);
5598 if (i == 9 && NUMBERP (color_adjust))
5599 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5603 /* Transform image IMG on frame F so that it looks disabled. */
5605 static void
5606 x_disable_image (f, img)
5607 struct frame *f;
5608 struct image *img;
5610 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5611 #ifdef HAVE_NTGUI
5612 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5613 #else
5614 int n_planes = dpyinfo->n_planes;
5615 #endif /* HAVE_NTGUI */
5617 if (n_planes >= 2)
5619 /* Color (or grayscale). Convert to gray, and equalize. Just
5620 drawing such images with a stipple can look very odd, so
5621 we're using this method instead. */
5622 XColor *colors = x_to_xcolors (f, img, 1);
5623 XColor *p, *end;
5624 const int h = 15000;
5625 const int l = 30000;
5627 for (p = colors, end = colors + img->width * img->height;
5628 p < end;
5629 ++p)
5631 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5632 int i2 = (0xffff - h - l) * i / 0xffff + l;
5633 p->red = p->green = p->blue = i2;
5636 x_from_xcolors (f, img, colors);
5639 /* Draw a cross over the disabled image, if we must or if we
5640 should. */
5641 if (n_planes < 2 || cross_disabled_images)
5643 #ifndef HAVE_NTGUI
5644 Display *dpy = FRAME_X_DISPLAY (f);
5645 GC gc;
5647 #ifdef MAC_OS
5648 #define MaskForeground(f) PIX_MASK_DRAW
5649 #else
5650 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5651 #endif
5653 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
5654 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5655 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5656 img->width - 1, img->height - 1);
5657 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5658 img->width - 1, 0);
5659 XFreeGC (dpy, gc);
5661 if (img->mask)
5663 gc = XCreateGC (dpy, img->mask, 0, NULL);
5664 XSetForeground (dpy, gc, MaskForeground (f));
5665 XDrawLine (dpy, img->mask, gc, 0, 0,
5666 img->width - 1, img->height - 1);
5667 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5668 img->width - 1, 0);
5669 XFreeGC (dpy, gc);
5671 #else
5672 HDC hdc, bmpdc;
5673 HGDIOBJ prev;
5675 hdc = get_frame_dc (f);
5676 bmpdc = CreateCompatibleDC (hdc);
5677 release_frame_dc (f, hdc);
5679 prev = SelectObject (bmpdc, img->pixmap);
5681 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5682 MoveToEx (bmpdc, 0, 0, NULL);
5683 LineTo (bmpdc, img->width - 1, img->height - 1);
5684 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5685 LineTo (bmpdc, img->width - 1, 0);
5687 if (img->mask)
5689 SelectObject (bmpdc, img->mask);
5690 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5691 MoveToEx (bmpdc, 0, 0, NULL);
5692 LineTo (bmpdc, img->width - 1, img->height - 1);
5693 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5694 LineTo (bmpdc, img->width - 1, 0);
5696 SelectObject (bmpdc, prev);
5697 DeleteDC (bmpdc);
5698 #endif /* HAVE_NTGUI */
5703 /* Build a mask for image IMG which is used on frame F. FILE is the
5704 name of an image file, for error messages. HOW determines how to
5705 determine the background color of IMG. If it is a list '(R G B)',
5706 with R, G, and B being integers >= 0, take that as the color of the
5707 background. Otherwise, determine the background color of IMG
5708 heuristically. Value is non-zero if successful. */
5710 static int
5711 x_build_heuristic_mask (f, img, how)
5712 struct frame *f;
5713 struct image *img;
5714 Lisp_Object how;
5716 XImagePtr_or_DC ximg;
5717 #ifndef HAVE_NTGUI
5718 XImagePtr mask_img;
5719 #else
5720 HDC frame_dc;
5721 HGDIOBJ prev;
5722 char *mask_img;
5723 int row_width;
5724 #endif /* HAVE_NTGUI */
5725 int x, y, rc, use_img_background;
5726 unsigned long bg = 0;
5728 if (img->mask)
5730 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5731 img->mask = NO_PIXMAP;
5732 img->background_transparent_valid = 0;
5735 #ifndef HAVE_NTGUI
5736 /* Create an image and pixmap serving as mask. */
5737 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5738 &mask_img, &img->mask);
5739 if (!rc)
5740 return 0;
5742 /* Get the X image of IMG->pixmap. */
5743 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5744 img->width, img->height,
5745 ~0, ZPixmap);
5746 #else
5747 /* Create the bit array serving as mask. */
5748 row_width = (img->width + 7) / 8;
5749 mask_img = xmalloc (row_width * img->height);
5750 bzero (mask_img, row_width * img->height);
5752 /* Create a memory device context for IMG->pixmap. */
5753 frame_dc = get_frame_dc (f);
5754 ximg = CreateCompatibleDC (frame_dc);
5755 release_frame_dc (f, frame_dc);
5756 prev = SelectObject (ximg, img->pixmap);
5757 #endif /* HAVE_NTGUI */
5759 /* Determine the background color of ximg. If HOW is `(R G B)'
5760 take that as color. Otherwise, use the image's background color. */
5761 use_img_background = 1;
5763 if (CONSP (how))
5765 int rgb[3], i;
5767 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5769 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5770 how = XCDR (how);
5773 if (i == 3 && NILP (how))
5775 char color_name[30];
5776 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5777 bg = (
5778 #ifdef HAVE_NTGUI
5779 0x00ffffff & /* Filter out palette info. */
5780 #endif /* HAVE_NTGUI */
5781 x_alloc_image_color (f, img, build_string (color_name), 0));
5782 use_img_background = 0;
5786 if (use_img_background)
5787 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5789 /* Set all bits in mask_img to 1 whose color in ximg is different
5790 from the background color bg. */
5791 #ifndef HAVE_NTGUI
5792 for (y = 0; y < img->height; ++y)
5793 for (x = 0; x < img->width; ++x)
5794 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5795 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5797 /* Fill in the background_transparent field while we have the mask handy. */
5798 image_background_transparent (img, f, mask_img);
5800 /* Put mask_img into img->mask. */
5801 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5802 x_destroy_x_image (mask_img);
5804 #else
5805 for (y = 0; y < img->height; ++y)
5806 for (x = 0; x < img->width; ++x)
5808 COLORREF p = GetPixel (ximg, x, y);
5809 if (p != bg)
5810 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5813 /* Create the mask image. */
5814 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5815 mask_img);
5816 /* Fill in the background_transparent field while we have the mask handy. */
5817 SelectObject (ximg, img->mask);
5818 image_background_transparent (img, f, ximg);
5820 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5821 xfree (mask_img);
5822 #endif /* HAVE_NTGUI */
5824 Destroy_Image (ximg, prev);
5826 return 1;
5830 /***********************************************************************
5831 PBM (mono, gray, color)
5832 ***********************************************************************/
5834 static int pbm_image_p P_ ((Lisp_Object object));
5835 static int pbm_load P_ ((struct frame *f, struct image *img));
5836 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5838 /* The symbol `pbm' identifying images of this type. */
5840 Lisp_Object Qpbm;
5842 /* Indices of image specification fields in gs_format, below. */
5844 enum pbm_keyword_index
5846 PBM_TYPE,
5847 PBM_FILE,
5848 PBM_DATA,
5849 PBM_ASCENT,
5850 PBM_MARGIN,
5851 PBM_RELIEF,
5852 PBM_ALGORITHM,
5853 PBM_HEURISTIC_MASK,
5854 PBM_MASK,
5855 PBM_FOREGROUND,
5856 PBM_BACKGROUND,
5857 PBM_LAST
5860 /* Vector of image_keyword structures describing the format
5861 of valid user-defined image specifications. */
5863 static struct image_keyword pbm_format[PBM_LAST] =
5865 {":type", IMAGE_SYMBOL_VALUE, 1},
5866 {":file", IMAGE_STRING_VALUE, 0},
5867 {":data", IMAGE_STRING_VALUE, 0},
5868 {":ascent", IMAGE_ASCENT_VALUE, 0},
5869 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5870 {":relief", IMAGE_INTEGER_VALUE, 0},
5871 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5872 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5873 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5874 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5875 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5878 /* Structure describing the image type `pbm'. */
5880 static struct image_type pbm_type =
5882 &Qpbm,
5883 pbm_image_p,
5884 pbm_load,
5885 x_clear_image,
5886 NULL
5890 /* Return non-zero if OBJECT is a valid PBM image specification. */
5892 static int
5893 pbm_image_p (object)
5894 Lisp_Object object;
5896 struct image_keyword fmt[PBM_LAST];
5898 bcopy (pbm_format, fmt, sizeof fmt);
5900 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5901 return 0;
5903 /* Must specify either :data or :file. */
5904 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5908 /* Scan a decimal number from *S and return it. Advance *S while
5909 reading the number. END is the end of the string. Value is -1 at
5910 end of input. */
5912 static int
5913 pbm_scan_number (s, end)
5914 unsigned char **s, *end;
5916 int c = 0, val = -1;
5918 while (*s < end)
5920 /* Skip white-space. */
5921 while (*s < end && (c = *(*s)++, isspace (c)))
5924 if (c == '#')
5926 /* Skip comment to end of line. */
5927 while (*s < end && (c = *(*s)++, c != '\n'))
5930 else if (isdigit (c))
5932 /* Read decimal number. */
5933 val = c - '0';
5934 while (*s < end && (c = *(*s)++, isdigit (c)))
5935 val = 10 * val + c - '0';
5936 break;
5938 else
5939 break;
5942 return val;
5946 #ifdef HAVE_NTGUI
5947 #if 0 /* Unused. ++kfs */
5949 /* Read FILE into memory. Value is a pointer to a buffer allocated
5950 with xmalloc holding FILE's contents. Value is null if an error
5951 occurred. *SIZE is set to the size of the file. */
5953 static char *
5954 pbm_read_file (file, size)
5955 Lisp_Object file;
5956 int *size;
5958 FILE *fp = NULL;
5959 char *buf = NULL;
5960 struct stat st;
5962 if (stat (SDATA (file), &st) == 0
5963 && (fp = fopen (SDATA (file), "rb")) != NULL
5964 && (buf = (char *) xmalloc (st.st_size),
5965 fread (buf, 1, st.st_size, fp) == st.st_size))
5967 *size = st.st_size;
5968 fclose (fp);
5970 else
5972 if (fp)
5973 fclose (fp);
5974 if (buf)
5976 xfree (buf);
5977 buf = NULL;
5981 return buf;
5983 #endif
5984 #endif /* HAVE_NTGUI */
5986 /* Load PBM image IMG for use on frame F. */
5988 static int
5989 pbm_load (f, img)
5990 struct frame *f;
5991 struct image *img;
5993 int raw_p, x, y;
5994 int width, height, max_color_idx = 0;
5995 XImagePtr ximg;
5996 Lisp_Object file, specified_file;
5997 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
5998 struct gcpro gcpro1;
5999 unsigned char *contents = NULL;
6000 unsigned char *end, *p;
6001 int size;
6003 specified_file = image_spec_value (img->spec, QCfile, NULL);
6004 file = Qnil;
6005 GCPRO1 (file);
6007 if (STRINGP (specified_file))
6009 file = x_find_image_file (specified_file);
6010 if (!STRINGP (file))
6012 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6013 UNGCPRO;
6014 return 0;
6017 contents = slurp_file (SDATA (file), &size);
6018 if (contents == NULL)
6020 image_error ("Error reading `%s'", file, Qnil);
6021 UNGCPRO;
6022 return 0;
6025 p = contents;
6026 end = contents + size;
6028 else
6030 Lisp_Object data;
6031 data = image_spec_value (img->spec, QCdata, NULL);
6032 p = SDATA (data);
6033 end = p + SBYTES (data);
6036 /* Check magic number. */
6037 if (end - p < 2 || *p++ != 'P')
6039 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6040 error:
6041 xfree (contents);
6042 UNGCPRO;
6043 return 0;
6046 switch (*p++)
6048 case '1':
6049 raw_p = 0, type = PBM_MONO;
6050 break;
6052 case '2':
6053 raw_p = 0, type = PBM_GRAY;
6054 break;
6056 case '3':
6057 raw_p = 0, type = PBM_COLOR;
6058 break;
6060 case '4':
6061 raw_p = 1, type = PBM_MONO;
6062 break;
6064 case '5':
6065 raw_p = 1, type = PBM_GRAY;
6066 break;
6068 case '6':
6069 raw_p = 1, type = PBM_COLOR;
6070 break;
6072 default:
6073 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6074 goto error;
6077 /* Read width, height, maximum color-component. Characters
6078 starting with `#' up to the end of a line are ignored. */
6079 width = pbm_scan_number (&p, end);
6080 height = pbm_scan_number (&p, end);
6082 if (type != PBM_MONO)
6084 max_color_idx = pbm_scan_number (&p, end);
6085 if (max_color_idx > 65535 || max_color_idx < 0)
6087 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
6088 goto error;
6092 if (!check_image_size (f, width, height))
6094 image_error ("Invalid image size", Qnil, Qnil);
6095 goto error;
6098 if (!x_create_x_image_and_pixmap (f, width, height, 0,
6099 &ximg, &img->pixmap))
6100 goto error;
6102 /* Initialize the color hash table. */
6103 init_color_table ();
6105 if (type == PBM_MONO)
6107 int c = 0, g;
6108 struct image_keyword fmt[PBM_LAST];
6109 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6110 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6112 /* Parse the image specification. */
6113 bcopy (pbm_format, fmt, sizeof fmt);
6114 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6116 /* Get foreground and background colors, maybe allocate colors. */
6117 if (fmt[PBM_FOREGROUND].count
6118 && STRINGP (fmt[PBM_FOREGROUND].value))
6119 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6120 if (fmt[PBM_BACKGROUND].count
6121 && STRINGP (fmt[PBM_BACKGROUND].value))
6123 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6124 img->background = bg;
6125 img->background_valid = 1;
6128 for (y = 0; y < height; ++y)
6129 for (x = 0; x < width; ++x)
6131 if (raw_p)
6133 if ((x & 7) == 0)
6135 if (p >= end)
6137 x_destroy_x_image (ximg);
6138 x_clear_image (f, img);
6139 image_error ("Invalid image size in image `%s'",
6140 img->spec, Qnil);
6141 goto error;
6143 c = *p++;
6145 g = c & 0x80;
6146 c <<= 1;
6148 else
6149 g = pbm_scan_number (&p, end);
6151 XPutPixel (ximg, x, y, g ? fg : bg);
6154 else
6156 int expected_size = height * width;
6157 if (max_color_idx > 255)
6158 expected_size *= 2;
6159 if (type == PBM_COLOR)
6160 expected_size *= 3;
6162 if (raw_p && p + expected_size > end)
6164 x_destroy_x_image (ximg);
6165 x_clear_image (f, img);
6166 image_error ("Invalid image size in image `%s'",
6167 img->spec, Qnil);
6168 goto error;
6171 for (y = 0; y < height; ++y)
6172 for (x = 0; x < width; ++x)
6174 int r, g, b;
6176 if (type == PBM_GRAY && raw_p)
6178 r = g = b = *p++;
6179 if (max_color_idx > 255)
6180 r = g = b = r * 256 + *p++;
6182 else if (type == PBM_GRAY)
6183 r = g = b = pbm_scan_number (&p, end);
6184 else if (raw_p)
6186 r = *p++;
6187 if (max_color_idx > 255)
6188 r = r * 256 + *p++;
6189 g = *p++;
6190 if (max_color_idx > 255)
6191 g = g * 256 + *p++;
6192 b = *p++;
6193 if (max_color_idx > 255)
6194 b = b * 256 + *p++;
6196 else
6198 r = pbm_scan_number (&p, end);
6199 g = pbm_scan_number (&p, end);
6200 b = pbm_scan_number (&p, end);
6203 if (r < 0 || g < 0 || b < 0)
6205 x_destroy_x_image (ximg);
6206 image_error ("Invalid pixel value in image `%s'",
6207 img->spec, Qnil);
6208 goto error;
6211 /* RGB values are now in the range 0..max_color_idx.
6212 Scale this to the range 0..0xffff supported by X. */
6213 r = (double) r * 65535 / max_color_idx;
6214 g = (double) g * 65535 / max_color_idx;
6215 b = (double) b * 65535 / max_color_idx;
6216 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6220 #ifdef COLOR_TABLE_SUPPORT
6221 /* Store in IMG->colors the colors allocated for the image, and
6222 free the color table. */
6223 img->colors = colors_in_color_table (&img->ncolors);
6224 free_color_table ();
6225 #endif /* COLOR_TABLE_SUPPORT */
6227 img->width = width;
6228 img->height = height;
6230 /* Maybe fill in the background field while we have ximg handy. */
6232 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6233 /* Casting avoids a GCC warning. */
6234 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6236 /* Put the image into a pixmap. */
6237 x_put_x_image (f, ximg, img->pixmap, width, height);
6238 x_destroy_x_image (ximg);
6240 /* X and W32 versions did it here, MAC version above. ++kfs
6241 img->width = width;
6242 img->height = height; */
6244 UNGCPRO;
6245 xfree (contents);
6246 return 1;
6250 /***********************************************************************
6252 ***********************************************************************/
6254 #if defined (HAVE_PNG) || defined (MAC_OS)
6256 /* Function prototypes. */
6258 static int png_image_p P_ ((Lisp_Object object));
6259 static int png_load P_ ((struct frame *f, struct image *img));
6261 /* The symbol `png' identifying images of this type. */
6263 Lisp_Object Qpng;
6265 /* Indices of image specification fields in png_format, below. */
6267 enum png_keyword_index
6269 PNG_TYPE,
6270 PNG_DATA,
6271 PNG_FILE,
6272 PNG_ASCENT,
6273 PNG_MARGIN,
6274 PNG_RELIEF,
6275 PNG_ALGORITHM,
6276 PNG_HEURISTIC_MASK,
6277 PNG_MASK,
6278 PNG_BACKGROUND,
6279 PNG_LAST
6282 /* Vector of image_keyword structures describing the format
6283 of valid user-defined image specifications. */
6285 static struct image_keyword png_format[PNG_LAST] =
6287 {":type", IMAGE_SYMBOL_VALUE, 1},
6288 {":data", IMAGE_STRING_VALUE, 0},
6289 {":file", IMAGE_STRING_VALUE, 0},
6290 {":ascent", IMAGE_ASCENT_VALUE, 0},
6291 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6292 {":relief", IMAGE_INTEGER_VALUE, 0},
6293 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6294 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6295 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6296 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6299 /* Structure describing the image type `png'. */
6301 static struct image_type png_type =
6303 &Qpng,
6304 png_image_p,
6305 png_load,
6306 x_clear_image,
6307 NULL
6310 /* Return non-zero if OBJECT is a valid PNG image specification. */
6312 static int
6313 png_image_p (object)
6314 Lisp_Object object;
6316 struct image_keyword fmt[PNG_LAST];
6317 bcopy (png_format, fmt, sizeof fmt);
6319 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
6320 return 0;
6322 /* Must specify either the :data or :file keyword. */
6323 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6326 #endif /* HAVE_PNG || MAC_OS */
6329 #ifdef HAVE_PNG
6331 #if defined HAVE_LIBPNG_PNG_H
6332 # include <libpng/png.h>
6333 #else
6334 # include <png.h>
6335 #endif
6337 #ifdef HAVE_NTGUI
6338 /* PNG library details. */
6340 DEF_IMGLIB_FN (png_get_io_ptr);
6341 DEF_IMGLIB_FN (png_check_sig);
6342 DEF_IMGLIB_FN (png_create_read_struct);
6343 DEF_IMGLIB_FN (png_create_info_struct);
6344 DEF_IMGLIB_FN (png_destroy_read_struct);
6345 DEF_IMGLIB_FN (png_set_read_fn);
6346 DEF_IMGLIB_FN (png_set_sig_bytes);
6347 DEF_IMGLIB_FN (png_read_info);
6348 DEF_IMGLIB_FN (png_get_IHDR);
6349 DEF_IMGLIB_FN (png_get_valid);
6350 DEF_IMGLIB_FN (png_set_strip_16);
6351 DEF_IMGLIB_FN (png_set_expand);
6352 DEF_IMGLIB_FN (png_set_gray_to_rgb);
6353 DEF_IMGLIB_FN (png_set_background);
6354 DEF_IMGLIB_FN (png_get_bKGD);
6355 DEF_IMGLIB_FN (png_read_update_info);
6356 DEF_IMGLIB_FN (png_get_channels);
6357 DEF_IMGLIB_FN (png_get_rowbytes);
6358 DEF_IMGLIB_FN (png_read_image);
6359 DEF_IMGLIB_FN (png_read_end);
6360 DEF_IMGLIB_FN (png_error);
6362 static int
6363 init_png_functions (Lisp_Object libraries)
6365 HMODULE library;
6367 /* Try loading libpng under probable names. */
6368 if (!(library = w32_delayed_load (libraries, Qpng)))
6369 return 0;
6371 LOAD_IMGLIB_FN (library, png_get_io_ptr);
6372 LOAD_IMGLIB_FN (library, png_check_sig);
6373 LOAD_IMGLIB_FN (library, png_create_read_struct);
6374 LOAD_IMGLIB_FN (library, png_create_info_struct);
6375 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
6376 LOAD_IMGLIB_FN (library, png_set_read_fn);
6377 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
6378 LOAD_IMGLIB_FN (library, png_read_info);
6379 LOAD_IMGLIB_FN (library, png_get_IHDR);
6380 LOAD_IMGLIB_FN (library, png_get_valid);
6381 LOAD_IMGLIB_FN (library, png_set_strip_16);
6382 LOAD_IMGLIB_FN (library, png_set_expand);
6383 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
6384 LOAD_IMGLIB_FN (library, png_set_background);
6385 LOAD_IMGLIB_FN (library, png_get_bKGD);
6386 LOAD_IMGLIB_FN (library, png_read_update_info);
6387 LOAD_IMGLIB_FN (library, png_get_channels);
6388 LOAD_IMGLIB_FN (library, png_get_rowbytes);
6389 LOAD_IMGLIB_FN (library, png_read_image);
6390 LOAD_IMGLIB_FN (library, png_read_end);
6391 LOAD_IMGLIB_FN (library, png_error);
6392 return 1;
6394 #else
6396 #define fn_png_get_io_ptr png_get_io_ptr
6397 #define fn_png_check_sig png_check_sig
6398 #define fn_png_create_read_struct png_create_read_struct
6399 #define fn_png_create_info_struct png_create_info_struct
6400 #define fn_png_destroy_read_struct png_destroy_read_struct
6401 #define fn_png_set_read_fn png_set_read_fn
6402 #define fn_png_set_sig_bytes png_set_sig_bytes
6403 #define fn_png_read_info png_read_info
6404 #define fn_png_get_IHDR png_get_IHDR
6405 #define fn_png_get_valid png_get_valid
6406 #define fn_png_set_strip_16 png_set_strip_16
6407 #define fn_png_set_expand png_set_expand
6408 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6409 #define fn_png_set_background png_set_background
6410 #define fn_png_get_bKGD png_get_bKGD
6411 #define fn_png_read_update_info png_read_update_info
6412 #define fn_png_get_channels png_get_channels
6413 #define fn_png_get_rowbytes png_get_rowbytes
6414 #define fn_png_read_image png_read_image
6415 #define fn_png_read_end png_read_end
6416 #define fn_png_error png_error
6418 #endif /* HAVE_NTGUI */
6420 /* Error and warning handlers installed when the PNG library
6421 is initialized. */
6423 static void
6424 my_png_error (png_ptr, msg)
6425 png_struct *png_ptr;
6426 char *msg;
6428 xassert (png_ptr != NULL);
6429 image_error ("PNG error: %s", build_string (msg), Qnil);
6430 longjmp (png_ptr->jmpbuf, 1);
6434 static void
6435 my_png_warning (png_ptr, msg)
6436 png_struct *png_ptr;
6437 char *msg;
6439 xassert (png_ptr != NULL);
6440 image_error ("PNG warning: %s", build_string (msg), Qnil);
6443 /* Memory source for PNG decoding. */
6445 struct png_memory_storage
6447 unsigned char *bytes; /* The data */
6448 size_t len; /* How big is it? */
6449 int index; /* Where are we? */
6453 /* Function set as reader function when reading PNG image from memory.
6454 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6455 bytes from the input to DATA. */
6457 static void
6458 png_read_from_memory (png_ptr, data, length)
6459 png_structp png_ptr;
6460 png_bytep data;
6461 png_size_t length;
6463 struct png_memory_storage *tbr
6464 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
6466 if (length > tbr->len - tbr->index)
6467 fn_png_error (png_ptr, "Read error");
6469 bcopy (tbr->bytes + tbr->index, data, length);
6470 tbr->index = tbr->index + length;
6474 /* Function set as reader function when reading PNG image from a file.
6475 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6476 bytes from the input to DATA. */
6478 static void
6479 png_read_from_file (png_ptr, data, length)
6480 png_structp png_ptr;
6481 png_bytep data;
6482 png_size_t length;
6484 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6486 if (fread (data, 1, length, fp) < length)
6487 fn_png_error (png_ptr, "Read error");
6491 /* Load PNG image IMG for use on frame F. Value is non-zero if
6492 successful. */
6494 static int
6495 png_load (f, img)
6496 struct frame *f;
6497 struct image *img;
6499 Lisp_Object file, specified_file;
6500 Lisp_Object specified_data;
6501 int x, y, i;
6502 XImagePtr ximg, mask_img = NULL;
6503 struct gcpro gcpro1;
6504 png_struct *png_ptr = NULL;
6505 png_info *info_ptr = NULL, *end_info = NULL;
6506 FILE *volatile fp = NULL;
6507 png_byte sig[8];
6508 png_byte * volatile pixels = NULL;
6509 png_byte ** volatile rows = NULL;
6510 png_uint_32 width, height;
6511 int bit_depth, color_type, interlace_type;
6512 png_byte channels;
6513 png_uint_32 row_bytes;
6514 int transparent_p;
6515 struct png_memory_storage tbr; /* Data to be read */
6517 /* Find out what file to load. */
6518 specified_file = image_spec_value (img->spec, QCfile, NULL);
6519 specified_data = image_spec_value (img->spec, QCdata, NULL);
6520 file = Qnil;
6521 GCPRO1 (file);
6523 if (NILP (specified_data))
6525 file = x_find_image_file (specified_file);
6526 if (!STRINGP (file))
6528 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6529 UNGCPRO;
6530 return 0;
6533 /* Open the image file. */
6534 fp = fopen (SDATA (file), "rb");
6535 if (!fp)
6537 image_error ("Cannot open image file `%s'", file, Qnil);
6538 UNGCPRO;
6539 return 0;
6542 /* Check PNG signature. */
6543 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6544 || !fn_png_check_sig (sig, sizeof sig))
6546 image_error ("Not a PNG file: `%s'", file, Qnil);
6547 UNGCPRO;
6548 fclose (fp);
6549 return 0;
6552 else
6554 /* Read from memory. */
6555 tbr.bytes = SDATA (specified_data);
6556 tbr.len = SBYTES (specified_data);
6557 tbr.index = 0;
6559 /* Check PNG signature. */
6560 if (tbr.len < sizeof sig
6561 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6563 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6564 UNGCPRO;
6565 return 0;
6568 /* Need to skip past the signature. */
6569 tbr.bytes += sizeof (sig);
6572 /* Initialize read and info structs for PNG lib. Casting return
6573 value avoids a GCC warning on W32. */
6574 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6575 NULL, my_png_error,
6576 my_png_warning);
6577 if (!png_ptr)
6579 if (fp) fclose (fp);
6580 UNGCPRO;
6581 return 0;
6584 /* Casting return value avoids a GCC warning on W32. */
6585 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6586 if (!info_ptr)
6588 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6589 if (fp) fclose (fp);
6590 UNGCPRO;
6591 return 0;
6594 /* Casting return value avoids a GCC warning on W32. */
6595 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6596 if (!end_info)
6598 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6599 if (fp) fclose (fp);
6600 UNGCPRO;
6601 return 0;
6604 /* Set error jump-back. We come back here when the PNG library
6605 detects an error. */
6606 if (setjmp (png_ptr->jmpbuf))
6608 error:
6609 if (png_ptr)
6610 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6611 xfree (pixels);
6612 xfree (rows);
6613 if (fp) fclose (fp);
6614 UNGCPRO;
6615 return 0;
6618 /* Read image info. */
6619 if (!NILP (specified_data))
6620 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6621 else
6622 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6624 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6625 fn_png_read_info (png_ptr, info_ptr);
6626 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6627 &interlace_type, NULL, NULL);
6629 if (!check_image_size (f, width, height))
6630 goto error;
6632 /* If image contains simply transparency data, we prefer to
6633 construct a clipping mask. */
6634 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6635 transparent_p = 1;
6636 else
6637 transparent_p = 0;
6639 /* This function is easier to write if we only have to handle
6640 one data format: RGB or RGBA with 8 bits per channel. Let's
6641 transform other formats into that format. */
6643 /* Strip more than 8 bits per channel. */
6644 if (bit_depth == 16)
6645 fn_png_set_strip_16 (png_ptr);
6647 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6648 if available. */
6649 fn_png_set_expand (png_ptr);
6651 /* Convert grayscale images to RGB. */
6652 if (color_type == PNG_COLOR_TYPE_GRAY
6653 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6654 fn_png_set_gray_to_rgb (png_ptr);
6656 /* Handle alpha channel by combining the image with a background
6657 color. Do this only if a real alpha channel is supplied. For
6658 simple transparency, we prefer a clipping mask. */
6659 if (!transparent_p)
6661 png_color_16 *image_bg;
6662 Lisp_Object specified_bg
6663 = image_spec_value (img->spec, QCbackground, NULL);
6664 int shift = (bit_depth == 16) ? 0 : 8;
6666 if (STRINGP (specified_bg))
6667 /* The user specified `:background', use that. */
6669 /* W32 version incorrectly used COLORREF here!! ++kfs */
6670 XColor color;
6671 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6673 png_color_16 user_bg;
6675 bzero (&user_bg, sizeof user_bg);
6676 user_bg.red = color.red >> shift;
6677 user_bg.green = color.green >> shift;
6678 user_bg.blue = color.blue >> shift;
6680 fn_png_set_background (png_ptr, &user_bg,
6681 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6684 else
6686 /* We use the current frame background, ignoring any default
6687 background color set by the image. */
6688 #ifdef HAVE_X_WINDOWS
6689 XColor color;
6690 png_color_16 frame_background;
6692 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6693 x_query_color (f, &color);
6695 bzero (&frame_background, sizeof frame_background);
6696 frame_background.red = color.red >> shift;
6697 frame_background.green = color.green >> shift;
6698 frame_background.blue = color.blue >> shift;
6699 #endif /* HAVE_X_WINDOWS */
6701 #ifdef HAVE_NTGUI
6702 COLORREF color;
6703 png_color_16 frame_background;
6704 color = FRAME_BACKGROUND_PIXEL (f);
6705 #if 0 /* W32 TODO : Colormap support. */
6706 x_query_color (f, &color);
6707 #endif
6708 bzero (&frame_background, sizeof frame_background);
6709 frame_background.red = GetRValue (color);
6710 frame_background.green = GetGValue (color);
6711 frame_background.blue = GetBValue (color);
6712 #endif /* HAVE_NTGUI */
6714 #ifdef MAC_OS
6715 unsigned long color;
6716 png_color_16 frame_background;
6717 color = FRAME_BACKGROUND_PIXEL (f);
6718 #if 0 /* MAC/W32 TODO : Colormap support. */
6719 x_query_color (f, &color);
6720 #endif
6721 bzero (&frame_background, sizeof frame_background);
6722 frame_background.red = RED_FROM_ULONG (color);
6723 frame_background.green = GREEN_FROM_ULONG (color);
6724 frame_background.blue = BLUE_FROM_ULONG (color);
6725 #endif /* MAC_OS */
6727 fn_png_set_background (png_ptr, &frame_background,
6728 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6732 /* Update info structure. */
6733 fn_png_read_update_info (png_ptr, info_ptr);
6735 /* Get number of channels. Valid values are 1 for grayscale images
6736 and images with a palette, 2 for grayscale images with transparency
6737 information (alpha channel), 3 for RGB images, and 4 for RGB
6738 images with alpha channel, i.e. RGBA. If conversions above were
6739 sufficient we should only have 3 or 4 channels here. */
6740 channels = fn_png_get_channels (png_ptr, info_ptr);
6741 xassert (channels == 3 || channels == 4);
6743 /* Number of bytes needed for one row of the image. */
6744 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6746 /* Allocate memory for the image. */
6747 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6748 rows = (png_byte **) xmalloc (height * sizeof *rows);
6749 for (i = 0; i < height; ++i)
6750 rows[i] = pixels + i * row_bytes;
6752 /* Read the entire image. */
6753 fn_png_read_image (png_ptr, rows);
6754 fn_png_read_end (png_ptr, info_ptr);
6755 if (fp)
6757 fclose (fp);
6758 fp = NULL;
6761 /* Create the X image and pixmap. */
6762 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6763 &img->pixmap))
6764 goto error;
6766 /* Create an image and pixmap serving as mask if the PNG image
6767 contains an alpha channel. */
6768 if (channels == 4
6769 && !transparent_p
6770 && !x_create_x_image_and_pixmap (f, width, height, 1,
6771 &mask_img, &img->mask))
6773 x_destroy_x_image (ximg);
6774 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6775 img->pixmap = NO_PIXMAP;
6776 goto error;
6779 /* Fill the X image and mask from PNG data. */
6780 init_color_table ();
6782 for (y = 0; y < height; ++y)
6784 png_byte *p = rows[y];
6786 for (x = 0; x < width; ++x)
6788 unsigned r, g, b;
6790 r = *p++ << 8;
6791 g = *p++ << 8;
6792 b = *p++ << 8;
6793 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6794 /* An alpha channel, aka mask channel, associates variable
6795 transparency with an image. Where other image formats
6796 support binary transparency---fully transparent or fully
6797 opaque---PNG allows up to 254 levels of partial transparency.
6798 The PNG library implements partial transparency by combining
6799 the image with a specified background color.
6801 I'm not sure how to handle this here nicely: because the
6802 background on which the image is displayed may change, for
6803 real alpha channel support, it would be necessary to create
6804 a new image for each possible background.
6806 What I'm doing now is that a mask is created if we have
6807 boolean transparency information. Otherwise I'm using
6808 the frame's background color to combine the image with. */
6810 if (channels == 4)
6812 if (mask_img)
6813 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6814 ++p;
6819 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6820 /* Set IMG's background color from the PNG image, unless the user
6821 overrode it. */
6823 png_color_16 *bg;
6824 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6826 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6827 img->background_valid = 1;
6831 #ifdef COLOR_TABLE_SUPPORT
6832 /* Remember colors allocated for this image. */
6833 img->colors = colors_in_color_table (&img->ncolors);
6834 free_color_table ();
6835 #endif /* COLOR_TABLE_SUPPORT */
6837 /* Clean up. */
6838 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6839 xfree (rows);
6840 xfree (pixels);
6842 img->width = width;
6843 img->height = height;
6845 /* Maybe fill in the background field while we have ximg handy.
6846 Casting avoids a GCC warning. */
6847 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6849 /* Put the image into the pixmap, then free the X image and its buffer. */
6850 x_put_x_image (f, ximg, img->pixmap, width, height);
6851 x_destroy_x_image (ximg);
6853 /* Same for the mask. */
6854 if (mask_img)
6856 /* Fill in the background_transparent field while we have the
6857 mask handy. Casting avoids a GCC warning. */
6858 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6860 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6861 x_destroy_x_image (mask_img);
6864 UNGCPRO;
6865 return 1;
6868 #else /* HAVE_PNG */
6870 #ifdef MAC_OS
6871 static int
6872 png_load (f, img)
6873 struct frame *f;
6874 struct image *img;
6876 #if USE_MAC_IMAGE_IO
6877 return image_load_image_io (f, img, kUTTypePNG);
6878 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6879 return image_load_quartz2d (f, img, 1);
6880 #else
6881 return image_load_quicktime (f, img, kQTFileTypePNG);
6882 #endif
6884 #endif /* MAC_OS */
6886 #endif /* !HAVE_PNG */
6890 /***********************************************************************
6891 JPEG
6892 ***********************************************************************/
6894 #if defined (HAVE_JPEG) || defined (MAC_OS)
6896 static int jpeg_image_p P_ ((Lisp_Object object));
6897 static int jpeg_load P_ ((struct frame *f, struct image *img));
6899 /* The symbol `jpeg' identifying images of this type. */
6901 Lisp_Object Qjpeg;
6903 /* Indices of image specification fields in gs_format, below. */
6905 enum jpeg_keyword_index
6907 JPEG_TYPE,
6908 JPEG_DATA,
6909 JPEG_FILE,
6910 JPEG_ASCENT,
6911 JPEG_MARGIN,
6912 JPEG_RELIEF,
6913 JPEG_ALGORITHM,
6914 JPEG_HEURISTIC_MASK,
6915 JPEG_MASK,
6916 JPEG_BACKGROUND,
6917 JPEG_LAST
6920 /* Vector of image_keyword structures describing the format
6921 of valid user-defined image specifications. */
6923 static struct image_keyword jpeg_format[JPEG_LAST] =
6925 {":type", IMAGE_SYMBOL_VALUE, 1},
6926 {":data", IMAGE_STRING_VALUE, 0},
6927 {":file", IMAGE_STRING_VALUE, 0},
6928 {":ascent", IMAGE_ASCENT_VALUE, 0},
6929 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6930 {":relief", IMAGE_INTEGER_VALUE, 0},
6931 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6932 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6933 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6934 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6937 /* Structure describing the image type `jpeg'. */
6939 static struct image_type jpeg_type =
6941 &Qjpeg,
6942 jpeg_image_p,
6943 jpeg_load,
6944 x_clear_image,
6945 NULL
6948 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6950 static int
6951 jpeg_image_p (object)
6952 Lisp_Object object;
6954 struct image_keyword fmt[JPEG_LAST];
6956 bcopy (jpeg_format, fmt, sizeof fmt);
6958 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6959 return 0;
6961 /* Must specify either the :data or :file keyword. */
6962 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6965 #endif /* HAVE_JPEG || MAC_OS */
6967 #ifdef HAVE_JPEG
6969 /* Work around a warning about HAVE_STDLIB_H being redefined in
6970 jconfig.h. */
6971 #ifdef HAVE_STDLIB_H
6972 #define HAVE_STDLIB_H_1
6973 #undef HAVE_STDLIB_H
6974 #endif /* HAVE_STLIB_H */
6976 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
6977 /* In older releases of the jpeg library, jpeglib.h will define boolean
6978 differently depending on __WIN32__, so make sure it is defined. */
6979 #define __WIN32__ 1
6980 #endif
6982 #include <jpeglib.h>
6983 #include <jerror.h>
6984 #include <setjmp.h>
6986 #ifdef HAVE_STLIB_H_1
6987 #define HAVE_STDLIB_H 1
6988 #endif
6990 #ifdef HAVE_NTGUI
6992 /* JPEG library details. */
6993 DEF_IMGLIB_FN (jpeg_CreateDecompress);
6994 DEF_IMGLIB_FN (jpeg_start_decompress);
6995 DEF_IMGLIB_FN (jpeg_finish_decompress);
6996 DEF_IMGLIB_FN (jpeg_destroy_decompress);
6997 DEF_IMGLIB_FN (jpeg_read_header);
6998 DEF_IMGLIB_FN (jpeg_read_scanlines);
6999 DEF_IMGLIB_FN (jpeg_std_error);
7000 DEF_IMGLIB_FN (jpeg_resync_to_restart);
7002 static int
7003 init_jpeg_functions (Lisp_Object libraries)
7005 HMODULE library;
7007 if (!(library = w32_delayed_load (libraries, Qjpeg)))
7008 return 0;
7010 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
7011 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
7012 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
7013 LOAD_IMGLIB_FN (library, jpeg_read_header);
7014 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
7015 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
7016 LOAD_IMGLIB_FN (library, jpeg_std_error);
7017 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
7018 return 1;
7021 /* Wrapper since we can't directly assign the function pointer
7022 to another function pointer that was declared more completely easily. */
7023 static boolean
7024 jpeg_resync_to_restart_wrapper(cinfo, desired)
7025 j_decompress_ptr cinfo;
7026 int desired;
7028 return fn_jpeg_resync_to_restart (cinfo, desired);
7031 #else
7033 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7034 #define fn_jpeg_start_decompress jpeg_start_decompress
7035 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7036 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7037 #define fn_jpeg_read_header jpeg_read_header
7038 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7039 #define fn_jpeg_std_error jpeg_std_error
7040 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7042 #endif /* HAVE_NTGUI */
7044 struct my_jpeg_error_mgr
7046 struct jpeg_error_mgr pub;
7047 jmp_buf setjmp_buffer;
7051 static void
7052 my_error_exit (cinfo)
7053 j_common_ptr cinfo;
7055 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7056 longjmp (mgr->setjmp_buffer, 1);
7060 /* Init source method for JPEG data source manager. Called by
7061 jpeg_read_header() before any data is actually read. See
7062 libjpeg.doc from the JPEG lib distribution. */
7064 static void
7065 our_common_init_source (cinfo)
7066 j_decompress_ptr cinfo;
7071 /* Method to terminate data source. Called by
7072 jpeg_finish_decompress() after all data has been processed. */
7074 static void
7075 our_common_term_source (cinfo)
7076 j_decompress_ptr cinfo;
7081 /* Fill input buffer method for JPEG data source manager. Called
7082 whenever more data is needed. We read the whole image in one step,
7083 so this only adds a fake end of input marker at the end. */
7085 static JOCTET our_memory_buffer[2];
7087 static boolean
7088 our_memory_fill_input_buffer (cinfo)
7089 j_decompress_ptr cinfo;
7091 /* Insert a fake EOI marker. */
7092 struct jpeg_source_mgr *src = cinfo->src;
7094 our_memory_buffer[0] = (JOCTET) 0xFF;
7095 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
7097 src->next_input_byte = our_memory_buffer;
7098 src->bytes_in_buffer = 2;
7099 return 1;
7103 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7104 is the JPEG data source manager. */
7106 static void
7107 our_memory_skip_input_data (cinfo, num_bytes)
7108 j_decompress_ptr cinfo;
7109 long num_bytes;
7111 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7113 if (src)
7115 if (num_bytes > src->bytes_in_buffer)
7116 ERREXIT (cinfo, JERR_INPUT_EOF);
7118 src->bytes_in_buffer -= num_bytes;
7119 src->next_input_byte += num_bytes;
7124 /* Set up the JPEG lib for reading an image from DATA which contains
7125 LEN bytes. CINFO is the decompression info structure created for
7126 reading the image. */
7128 static void
7129 jpeg_memory_src (cinfo, data, len)
7130 j_decompress_ptr cinfo;
7131 JOCTET *data;
7132 unsigned int len;
7134 struct jpeg_source_mgr *src;
7136 if (cinfo->src == NULL)
7138 /* First time for this JPEG object? */
7139 cinfo->src = (struct jpeg_source_mgr *)
7140 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7141 sizeof (struct jpeg_source_mgr));
7142 src = (struct jpeg_source_mgr *) cinfo->src;
7143 src->next_input_byte = data;
7146 src = (struct jpeg_source_mgr *) cinfo->src;
7147 src->init_source = our_common_init_source;
7148 src->fill_input_buffer = our_memory_fill_input_buffer;
7149 src->skip_input_data = our_memory_skip_input_data;
7150 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7151 src->term_source = our_common_term_source;
7152 src->bytes_in_buffer = len;
7153 src->next_input_byte = data;
7157 struct jpeg_stdio_mgr
7159 struct jpeg_source_mgr mgr;
7160 boolean finished;
7161 FILE *file;
7162 JOCTET *buffer;
7166 /* Size of buffer to read JPEG from file.
7167 Not too big, as we want to use alloc_small. */
7168 #define JPEG_STDIO_BUFFER_SIZE 8192
7171 /* Fill input buffer method for JPEG data source manager. Called
7172 whenever more data is needed. The data is read from a FILE *. */
7174 static boolean
7175 our_stdio_fill_input_buffer (cinfo)
7176 j_decompress_ptr cinfo;
7178 struct jpeg_stdio_mgr *src;
7180 src = (struct jpeg_stdio_mgr *) cinfo->src;
7181 if (!src->finished)
7183 size_t bytes;
7185 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
7186 if (bytes > 0)
7187 src->mgr.bytes_in_buffer = bytes;
7188 else
7190 WARNMS (cinfo, JWRN_JPEG_EOF);
7191 src->finished = 1;
7192 src->buffer[0] = (JOCTET) 0xFF;
7193 src->buffer[1] = (JOCTET) JPEG_EOI;
7194 src->mgr.bytes_in_buffer = 2;
7196 src->mgr.next_input_byte = src->buffer;
7199 return 1;
7203 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7204 is the JPEG data source manager. */
7206 static void
7207 our_stdio_skip_input_data (cinfo, num_bytes)
7208 j_decompress_ptr cinfo;
7209 long num_bytes;
7211 struct jpeg_stdio_mgr *src;
7212 src = (struct jpeg_stdio_mgr *) cinfo->src;
7214 while (num_bytes > 0 && !src->finished)
7216 if (num_bytes <= src->mgr.bytes_in_buffer)
7218 src->mgr.bytes_in_buffer -= num_bytes;
7219 src->mgr.next_input_byte += num_bytes;
7220 break;
7222 else
7224 num_bytes -= src->mgr.bytes_in_buffer;
7225 src->mgr.bytes_in_buffer = 0;
7226 src->mgr.next_input_byte = NULL;
7228 our_stdio_fill_input_buffer (cinfo);
7234 /* Set up the JPEG lib for reading an image from a FILE *.
7235 CINFO is the decompression info structure created for
7236 reading the image. */
7238 static void
7239 jpeg_file_src (cinfo, fp)
7240 j_decompress_ptr cinfo;
7241 FILE *fp;
7243 struct jpeg_stdio_mgr *src;
7245 if (cinfo->src != NULL)
7246 src = (struct jpeg_stdio_mgr *) cinfo->src;
7247 else
7249 /* First time for this JPEG object? */
7250 cinfo->src = (struct jpeg_source_mgr *)
7251 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7252 sizeof (struct jpeg_stdio_mgr));
7253 src = (struct jpeg_stdio_mgr *) cinfo->src;
7254 src->buffer = (JOCTET *)
7255 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7256 JPEG_STDIO_BUFFER_SIZE);
7259 src->file = fp;
7260 src->finished = 0;
7261 src->mgr.init_source = our_common_init_source;
7262 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
7263 src->mgr.skip_input_data = our_stdio_skip_input_data;
7264 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7265 src->mgr.term_source = our_common_term_source;
7266 src->mgr.bytes_in_buffer = 0;
7267 src->mgr.next_input_byte = NULL;
7271 /* Load image IMG for use on frame F. Patterned after example.c
7272 from the JPEG lib. */
7274 static int
7275 jpeg_load (f, img)
7276 struct frame *f;
7277 struct image *img;
7279 struct jpeg_decompress_struct cinfo;
7280 struct my_jpeg_error_mgr mgr;
7281 Lisp_Object file, specified_file;
7282 Lisp_Object specified_data;
7283 FILE * volatile fp = NULL;
7284 JSAMPARRAY buffer;
7285 int row_stride, x, y;
7286 XImagePtr ximg = NULL;
7287 int rc;
7288 unsigned long *colors;
7289 int width, height;
7290 struct gcpro gcpro1;
7292 /* Open the JPEG file. */
7293 specified_file = image_spec_value (img->spec, QCfile, NULL);
7294 specified_data = image_spec_value (img->spec, QCdata, NULL);
7295 file = Qnil;
7296 GCPRO1 (file);
7298 if (NILP (specified_data))
7300 file = x_find_image_file (specified_file);
7301 if (!STRINGP (file))
7303 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7304 UNGCPRO;
7305 return 0;
7308 fp = fopen (SDATA (file), "rb");
7309 if (fp == NULL)
7311 image_error ("Cannot open `%s'", file, Qnil);
7312 UNGCPRO;
7313 return 0;
7317 /* Customize libjpeg's error handling to call my_error_exit when an
7318 error is detected. This function will perform a longjmp.
7319 Casting return value avoids a GCC warning on W32. */
7320 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
7321 mgr.pub.error_exit = my_error_exit;
7323 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7325 if (rc == 1)
7327 /* Called from my_error_exit. Display a JPEG error. */
7328 char buffer[JMSG_LENGTH_MAX];
7329 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7330 image_error ("Error reading JPEG image `%s': %s", img->spec,
7331 build_string (buffer));
7334 /* Close the input file and destroy the JPEG object. */
7335 if (fp)
7336 fclose ((FILE *) fp);
7337 fn_jpeg_destroy_decompress (&cinfo);
7339 /* If we already have an XImage, free that. */
7340 x_destroy_x_image (ximg);
7342 /* Free pixmap and colors. */
7343 x_clear_image (f, img);
7345 UNGCPRO;
7346 return 0;
7349 /* Create the JPEG decompression object. Let it read from fp.
7350 Read the JPEG image header. */
7351 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
7353 if (NILP (specified_data))
7354 jpeg_file_src (&cinfo, (FILE *) fp);
7355 else
7356 jpeg_memory_src (&cinfo, SDATA (specified_data),
7357 SBYTES (specified_data));
7359 fn_jpeg_read_header (&cinfo, 1);
7361 /* Customize decompression so that color quantization will be used.
7362 Start decompression. */
7363 cinfo.quantize_colors = 1;
7364 fn_jpeg_start_decompress (&cinfo);
7365 width = img->width = cinfo.output_width;
7366 height = img->height = cinfo.output_height;
7368 if (!check_image_size (f, width, height))
7370 image_error ("Invalid image size", Qnil, Qnil);
7371 longjmp (mgr.setjmp_buffer, 2);
7374 /* Create X image and pixmap. */
7375 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7376 longjmp (mgr.setjmp_buffer, 2);
7378 /* Allocate colors. When color quantization is used,
7379 cinfo.actual_number_of_colors has been set with the number of
7380 colors generated, and cinfo.colormap is a two-dimensional array
7381 of color indices in the range 0..cinfo.actual_number_of_colors.
7382 No more than 255 colors will be generated. */
7384 int i, ir, ig, ib;
7386 if (cinfo.out_color_components > 2)
7387 ir = 0, ig = 1, ib = 2;
7388 else if (cinfo.out_color_components > 1)
7389 ir = 0, ig = 1, ib = 0;
7390 else
7391 ir = 0, ig = 0, ib = 0;
7393 /* Use the color table mechanism because it handles colors that
7394 cannot be allocated nicely. Such colors will be replaced with
7395 a default color, and we don't have to care about which colors
7396 can be freed safely, and which can't. */
7397 init_color_table ();
7398 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7399 * sizeof *colors);
7401 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7403 /* Multiply RGB values with 255 because X expects RGB values
7404 in the range 0..0xffff. */
7405 int r = cinfo.colormap[ir][i] << 8;
7406 int g = cinfo.colormap[ig][i] << 8;
7407 int b = cinfo.colormap[ib][i] << 8;
7408 colors[i] = lookup_rgb_color (f, r, g, b);
7411 #ifdef COLOR_TABLE_SUPPORT
7412 /* Remember those colors actually allocated. */
7413 img->colors = colors_in_color_table (&img->ncolors);
7414 free_color_table ();
7415 #endif /* COLOR_TABLE_SUPPORT */
7418 /* Read pixels. */
7419 row_stride = width * cinfo.output_components;
7420 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7421 row_stride, 1);
7422 for (y = 0; y < height; ++y)
7424 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
7425 for (x = 0; x < cinfo.output_width; ++x)
7426 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7429 /* Clean up. */
7430 fn_jpeg_finish_decompress (&cinfo);
7431 fn_jpeg_destroy_decompress (&cinfo);
7432 if (fp)
7433 fclose ((FILE *) fp);
7435 /* Maybe fill in the background field while we have ximg handy. */
7436 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7437 /* Casting avoids a GCC warning. */
7438 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7440 /* Put the image into the pixmap. */
7441 x_put_x_image (f, ximg, img->pixmap, width, height);
7442 x_destroy_x_image (ximg);
7443 UNGCPRO;
7444 return 1;
7447 #else /* HAVE_JPEG */
7449 #ifdef MAC_OS
7450 static int
7451 jpeg_load (f, img)
7452 struct frame *f;
7453 struct image *img;
7455 #if USE_MAC_IMAGE_IO
7456 return image_load_image_io (f, img, kUTTypeJPEG);
7457 #elif defined (MAC_OSX)
7458 return image_load_quartz2d (f, img, 0);
7459 #else
7460 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7461 #endif
7463 #endif /* MAC_OS */
7465 #endif /* !HAVE_JPEG */
7469 /***********************************************************************
7470 TIFF
7471 ***********************************************************************/
7473 #if defined (HAVE_TIFF) || defined (MAC_OS)
7475 static int tiff_image_p P_ ((Lisp_Object object));
7476 static int tiff_load P_ ((struct frame *f, struct image *img));
7478 /* The symbol `tiff' identifying images of this type. */
7480 Lisp_Object Qtiff;
7482 /* Indices of image specification fields in tiff_format, below. */
7484 enum tiff_keyword_index
7486 TIFF_TYPE,
7487 TIFF_DATA,
7488 TIFF_FILE,
7489 TIFF_ASCENT,
7490 TIFF_MARGIN,
7491 TIFF_RELIEF,
7492 TIFF_ALGORITHM,
7493 TIFF_HEURISTIC_MASK,
7494 TIFF_MASK,
7495 TIFF_BACKGROUND,
7496 TIFF_LAST
7499 /* Vector of image_keyword structures describing the format
7500 of valid user-defined image specifications. */
7502 static struct image_keyword tiff_format[TIFF_LAST] =
7504 {":type", IMAGE_SYMBOL_VALUE, 1},
7505 {":data", IMAGE_STRING_VALUE, 0},
7506 {":file", IMAGE_STRING_VALUE, 0},
7507 {":ascent", IMAGE_ASCENT_VALUE, 0},
7508 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7509 {":relief", IMAGE_INTEGER_VALUE, 0},
7510 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7511 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7512 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7513 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7516 /* Structure describing the image type `tiff'. */
7518 static struct image_type tiff_type =
7520 &Qtiff,
7521 tiff_image_p,
7522 tiff_load,
7523 x_clear_image,
7524 NULL
7527 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7529 static int
7530 tiff_image_p (object)
7531 Lisp_Object object;
7533 struct image_keyword fmt[TIFF_LAST];
7534 bcopy (tiff_format, fmt, sizeof fmt);
7536 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7537 return 0;
7539 /* Must specify either the :data or :file keyword. */
7540 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7543 #endif /* HAVE_TIFF || MAC_OS */
7545 #ifdef HAVE_TIFF
7547 #include <tiffio.h>
7549 #ifdef HAVE_NTGUI
7551 /* TIFF library details. */
7552 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7553 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7554 DEF_IMGLIB_FN (TIFFOpen);
7555 DEF_IMGLIB_FN (TIFFClientOpen);
7556 DEF_IMGLIB_FN (TIFFGetField);
7557 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7558 DEF_IMGLIB_FN (TIFFClose);
7560 static int
7561 init_tiff_functions (Lisp_Object libraries)
7563 HMODULE library;
7565 if (!(library = w32_delayed_load (libraries, Qtiff)))
7566 return 0;
7568 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7569 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7570 LOAD_IMGLIB_FN (library, TIFFOpen);
7571 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7572 LOAD_IMGLIB_FN (library, TIFFGetField);
7573 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7574 LOAD_IMGLIB_FN (library, TIFFClose);
7575 return 1;
7578 #else
7580 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7581 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7582 #define fn_TIFFOpen TIFFOpen
7583 #define fn_TIFFClientOpen TIFFClientOpen
7584 #define fn_TIFFGetField TIFFGetField
7585 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7586 #define fn_TIFFClose TIFFClose
7588 #endif /* HAVE_NTGUI */
7591 /* Reading from a memory buffer for TIFF images Based on the PNG
7592 memory source, but we have to provide a lot of extra functions.
7593 Blah.
7595 We really only need to implement read and seek, but I am not
7596 convinced that the TIFF library is smart enough not to destroy
7597 itself if we only hand it the function pointers we need to
7598 override. */
7600 typedef struct
7602 unsigned char *bytes;
7603 size_t len;
7604 int index;
7606 tiff_memory_source;
7608 static size_t
7609 tiff_read_from_memory (data, buf, size)
7610 thandle_t data;
7611 tdata_t buf;
7612 tsize_t size;
7614 tiff_memory_source *src = (tiff_memory_source *) data;
7616 if (size > src->len - src->index)
7617 return (size_t) -1;
7618 bcopy (src->bytes + src->index, buf, size);
7619 src->index += size;
7620 return size;
7623 static size_t
7624 tiff_write_from_memory (data, buf, size)
7625 thandle_t data;
7626 tdata_t buf;
7627 tsize_t size;
7629 return (size_t) -1;
7632 static toff_t
7633 tiff_seek_in_memory (data, off, whence)
7634 thandle_t data;
7635 toff_t off;
7636 int whence;
7638 tiff_memory_source *src = (tiff_memory_source *) data;
7639 int idx;
7641 switch (whence)
7643 case SEEK_SET: /* Go from beginning of source. */
7644 idx = off;
7645 break;
7647 case SEEK_END: /* Go from end of source. */
7648 idx = src->len + off;
7649 break;
7651 case SEEK_CUR: /* Go from current position. */
7652 idx = src->index + off;
7653 break;
7655 default: /* Invalid `whence'. */
7656 return -1;
7659 if (idx > src->len || idx < 0)
7660 return -1;
7662 src->index = idx;
7663 return src->index;
7666 static int
7667 tiff_close_memory (data)
7668 thandle_t data;
7670 /* NOOP */
7671 return 0;
7674 static int
7675 tiff_mmap_memory (data, pbase, psize)
7676 thandle_t data;
7677 tdata_t *pbase;
7678 toff_t *psize;
7680 /* It is already _IN_ memory. */
7681 return 0;
7684 static void
7685 tiff_unmap_memory (data, base, size)
7686 thandle_t data;
7687 tdata_t base;
7688 toff_t size;
7690 /* We don't need to do this. */
7693 static toff_t
7694 tiff_size_of_memory (data)
7695 thandle_t data;
7697 return ((tiff_memory_source *) data)->len;
7701 static void
7702 tiff_error_handler (title, format, ap)
7703 const char *title, *format;
7704 va_list ap;
7706 char buf[512];
7707 int len;
7709 len = sprintf (buf, "TIFF error: %s ", title);
7710 vsprintf (buf + len, format, ap);
7711 add_to_log (buf, Qnil, Qnil);
7715 static void
7716 tiff_warning_handler (title, format, ap)
7717 const char *title, *format;
7718 va_list ap;
7720 char buf[512];
7721 int len;
7723 len = sprintf (buf, "TIFF warning: %s ", title);
7724 vsprintf (buf + len, format, ap);
7725 add_to_log (buf, Qnil, Qnil);
7729 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7730 successful. */
7732 static int
7733 tiff_load (f, img)
7734 struct frame *f;
7735 struct image *img;
7737 Lisp_Object file, specified_file;
7738 Lisp_Object specified_data;
7739 TIFF *tiff;
7740 int width, height, x, y;
7741 uint32 *buf;
7742 int rc;
7743 XImagePtr ximg;
7744 struct gcpro gcpro1;
7745 tiff_memory_source memsrc;
7747 specified_file = image_spec_value (img->spec, QCfile, NULL);
7748 specified_data = image_spec_value (img->spec, QCdata, NULL);
7749 file = Qnil;
7750 GCPRO1 (file);
7752 fn_TIFFSetErrorHandler (tiff_error_handler);
7753 fn_TIFFSetWarningHandler (tiff_warning_handler);
7755 if (NILP (specified_data))
7757 /* Read from a file */
7758 file = x_find_image_file (specified_file);
7759 if (!STRINGP (file))
7761 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7762 UNGCPRO;
7763 return 0;
7766 /* Try to open the image file. Casting return value avoids a
7767 GCC warning on W32. */
7768 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7769 if (tiff == NULL)
7771 image_error ("Cannot open `%s'", file, Qnil);
7772 UNGCPRO;
7773 return 0;
7776 else
7778 /* Memory source! */
7779 memsrc.bytes = SDATA (specified_data);
7780 memsrc.len = SBYTES (specified_data);
7781 memsrc.index = 0;
7783 /* Casting return value avoids a GCC warning on W32. */
7784 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7785 (TIFFReadWriteProc) tiff_read_from_memory,
7786 (TIFFReadWriteProc) tiff_write_from_memory,
7787 tiff_seek_in_memory,
7788 tiff_close_memory,
7789 tiff_size_of_memory,
7790 tiff_mmap_memory,
7791 tiff_unmap_memory);
7793 if (!tiff)
7795 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7796 UNGCPRO;
7797 return 0;
7801 /* Get width and height of the image, and allocate a raster buffer
7802 of width x height 32-bit values. */
7803 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7804 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7806 if (!check_image_size (f, width, height))
7808 image_error ("Invalid image size", Qnil, Qnil);
7809 UNGCPRO;
7810 return 0;
7813 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7815 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7816 fn_TIFFClose (tiff);
7817 if (!rc)
7819 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7820 xfree (buf);
7821 UNGCPRO;
7822 return 0;
7825 /* Create the X image and pixmap. */
7826 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7828 xfree (buf);
7829 UNGCPRO;
7830 return 0;
7833 /* Initialize the color table. */
7834 init_color_table ();
7836 /* Process the pixel raster. Origin is in the lower-left corner. */
7837 for (y = 0; y < height; ++y)
7839 uint32 *row = buf + y * width;
7841 for (x = 0; x < width; ++x)
7843 uint32 abgr = row[x];
7844 int r = TIFFGetR (abgr) << 8;
7845 int g = TIFFGetG (abgr) << 8;
7846 int b = TIFFGetB (abgr) << 8;
7847 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7851 #ifdef COLOR_TABLE_SUPPORT
7852 /* Remember the colors allocated for the image. Free the color table. */
7853 img->colors = colors_in_color_table (&img->ncolors);
7854 free_color_table ();
7855 #endif /* COLOR_TABLE_SUPPORT */
7857 img->width = width;
7858 img->height = height;
7860 /* Maybe fill in the background field while we have ximg handy. */
7861 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7862 /* Casting avoids a GCC warning on W32. */
7863 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7865 /* Put the image into the pixmap, then free the X image and its buffer. */
7866 x_put_x_image (f, ximg, img->pixmap, width, height);
7867 x_destroy_x_image (ximg);
7868 xfree (buf);
7870 UNGCPRO;
7871 return 1;
7874 #else /* HAVE_TIFF */
7876 #ifdef MAC_OS
7877 static int
7878 tiff_load (f, img)
7879 struct frame *f;
7880 struct image *img;
7882 #if USE_MAC_IMAGE_IO
7883 return image_load_image_io (f, img, kUTTypeTIFF);
7884 #else
7885 return image_load_quicktime (f, img, kQTFileTypeTIFF);
7886 #endif
7888 #endif /* MAC_OS */
7890 #endif /* !HAVE_TIFF */
7894 /***********************************************************************
7896 ***********************************************************************/
7898 #if defined (HAVE_GIF) || defined (MAC_OS)
7900 static int gif_image_p P_ ((Lisp_Object object));
7901 static int gif_load P_ ((struct frame *f, struct image *img));
7902 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7904 /* The symbol `gif' identifying images of this type. */
7906 Lisp_Object Qgif;
7908 /* Indices of image specification fields in gif_format, below. */
7910 enum gif_keyword_index
7912 GIF_TYPE,
7913 GIF_DATA,
7914 GIF_FILE,
7915 GIF_ASCENT,
7916 GIF_MARGIN,
7917 GIF_RELIEF,
7918 GIF_ALGORITHM,
7919 GIF_HEURISTIC_MASK,
7920 GIF_MASK,
7921 GIF_IMAGE,
7922 GIF_BACKGROUND,
7923 GIF_LAST
7926 /* Vector of image_keyword structures describing the format
7927 of valid user-defined image specifications. */
7929 static struct image_keyword gif_format[GIF_LAST] =
7931 {":type", IMAGE_SYMBOL_VALUE, 1},
7932 {":data", IMAGE_STRING_VALUE, 0},
7933 {":file", IMAGE_STRING_VALUE, 0},
7934 {":ascent", IMAGE_ASCENT_VALUE, 0},
7935 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7936 {":relief", IMAGE_INTEGER_VALUE, 0},
7937 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7938 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7939 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7940 {":index", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7941 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7944 /* Structure describing the image type `gif'. */
7946 static struct image_type gif_type =
7948 &Qgif,
7949 gif_image_p,
7950 gif_load,
7951 gif_clear_image,
7952 NULL
7955 /* Free X resources of GIF image IMG which is used on frame F. */
7957 static void
7958 gif_clear_image (f, img)
7959 struct frame *f;
7960 struct image *img;
7962 /* IMG->data.ptr_val may contain extension data. */
7963 img->data.lisp_val = Qnil;
7964 x_clear_image (f, img);
7967 /* Return non-zero if OBJECT is a valid GIF image specification. */
7969 static int
7970 gif_image_p (object)
7971 Lisp_Object object;
7973 struct image_keyword fmt[GIF_LAST];
7974 bcopy (gif_format, fmt, sizeof fmt);
7976 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
7977 return 0;
7979 /* Must specify either the :data or :file keyword. */
7980 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
7983 #endif /* HAVE_GIF || MAC_OS */
7985 #ifdef HAVE_GIF
7987 #if defined (HAVE_NTGUI) || defined (MAC_OS)
7988 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
7989 Undefine before redefining to avoid a preprocessor warning. */
7990 #ifdef DrawText
7991 #undef DrawText
7992 #endif
7993 /* avoid conflict with QuickdrawText.h */
7994 #define DrawText gif_DrawText
7995 #include <gif_lib.h>
7996 #undef DrawText
7998 #else /* HAVE_NTGUI || MAC_OS */
8000 #include <gif_lib.h>
8002 #endif /* HAVE_NTGUI || MAC_OS */
8005 #ifdef HAVE_NTGUI
8007 /* GIF library details. */
8008 DEF_IMGLIB_FN (DGifCloseFile);
8009 DEF_IMGLIB_FN (DGifSlurp);
8010 DEF_IMGLIB_FN (DGifOpen);
8011 DEF_IMGLIB_FN (DGifOpenFileName);
8013 static int
8014 init_gif_functions (Lisp_Object libraries)
8016 HMODULE library;
8018 if (!(library = w32_delayed_load (libraries, Qgif)))
8019 return 0;
8021 LOAD_IMGLIB_FN (library, DGifCloseFile);
8022 LOAD_IMGLIB_FN (library, DGifSlurp);
8023 LOAD_IMGLIB_FN (library, DGifOpen);
8024 LOAD_IMGLIB_FN (library, DGifOpenFileName);
8025 return 1;
8028 #else
8030 #define fn_DGifCloseFile DGifCloseFile
8031 #define fn_DGifSlurp DGifSlurp
8032 #define fn_DGifOpen DGifOpen
8033 #define fn_DGifOpenFileName DGifOpenFileName
8035 #endif /* HAVE_NTGUI */
8037 /* Reading a GIF image from memory
8038 Based on the PNG memory stuff to a certain extent. */
8040 typedef struct
8042 unsigned char *bytes;
8043 size_t len;
8044 int index;
8046 gif_memory_source;
8048 /* Make the current memory source available to gif_read_from_memory.
8049 It's done this way because not all versions of libungif support
8050 a UserData field in the GifFileType structure. */
8051 static gif_memory_source *current_gif_memory_src;
8053 static int
8054 gif_read_from_memory (file, buf, len)
8055 GifFileType *file;
8056 GifByteType *buf;
8057 int len;
8059 gif_memory_source *src = current_gif_memory_src;
8061 if (len > src->len - src->index)
8062 return -1;
8064 bcopy (src->bytes + src->index, buf, len);
8065 src->index += len;
8066 return len;
8070 /* Load GIF image IMG for use on frame F. Value is non-zero if
8071 successful. */
8073 static int interlace_start[] = {0, 4, 2, 1};
8074 static int interlace_increment[] = {8, 8, 4, 2};
8076 static int
8077 gif_load (f, img)
8078 struct frame *f;
8079 struct image *img;
8081 Lisp_Object file, specified_file;
8082 Lisp_Object specified_data;
8083 int rc, width, height, x, y, i;
8084 XImagePtr ximg;
8085 ColorMapObject *gif_color_map;
8086 unsigned long pixel_colors[256];
8087 GifFileType *gif;
8088 struct gcpro gcpro1;
8089 Lisp_Object image;
8090 int ino, image_height, image_width;
8091 gif_memory_source memsrc;
8092 unsigned char *raster;
8094 specified_file = image_spec_value (img->spec, QCfile, NULL);
8095 specified_data = image_spec_value (img->spec, QCdata, NULL);
8096 file = Qnil;
8097 GCPRO1 (file);
8099 if (NILP (specified_data))
8101 file = x_find_image_file (specified_file);
8102 if (!STRINGP (file))
8104 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8105 UNGCPRO;
8106 return 0;
8109 /* Open the GIF file. Casting return value avoids a GCC warning
8110 on W32. */
8111 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
8112 if (gif == NULL)
8114 image_error ("Cannot open `%s'", file, Qnil);
8115 UNGCPRO;
8116 return 0;
8119 else
8121 /* Read from memory! */
8122 current_gif_memory_src = &memsrc;
8123 memsrc.bytes = SDATA (specified_data);
8124 memsrc.len = SBYTES (specified_data);
8125 memsrc.index = 0;
8127 /* Casting return value avoids a GCC warning on W32. */
8128 gif = (GifFileType *)fn_DGifOpen(&memsrc, gif_read_from_memory);
8129 if (!gif)
8131 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8132 UNGCPRO;
8133 return 0;
8137 /* Before reading entire contents, check the declared image size. */
8138 if (!check_image_size (f, gif->SWidth, gif->SHeight))
8140 image_error ("Invalid image size", Qnil, Qnil);
8141 fn_DGifCloseFile (gif);
8142 UNGCPRO;
8143 return 0;
8146 /* Read entire contents. */
8147 rc = fn_DGifSlurp (gif);
8148 if (rc == GIF_ERROR)
8150 image_error ("Error reading `%s'", img->spec, Qnil);
8151 fn_DGifCloseFile (gif);
8152 UNGCPRO;
8153 return 0;
8156 image = image_spec_value (img->spec, QCindex, NULL);
8157 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8158 if (ino >= gif->ImageCount)
8160 image_error ("Invalid image number `%s' in image `%s'",
8161 image, img->spec);
8162 fn_DGifCloseFile (gif);
8163 UNGCPRO;
8164 return 0;
8167 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
8168 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
8169 image_height = gif->SavedImages[ino].ImageDesc.Height;
8170 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
8171 image_width = gif->SavedImages[ino].ImageDesc.Width;
8172 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
8174 width = img->width = max (gif->SWidth,
8175 max (gif->Image.Left + gif->Image.Width,
8176 img->corners[RIGHT_CORNER]));
8177 height = img->height = max (gif->SHeight,
8178 max (gif->Image.Top + gif->Image.Height,
8179 img->corners[BOT_CORNER]));
8181 if (!check_image_size (f, width, height))
8183 image_error ("Invalid image size", Qnil, Qnil);
8184 fn_DGifCloseFile (gif);
8185 UNGCPRO;
8186 return 0;
8189 /* Create the X image and pixmap. */
8190 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8192 fn_DGifCloseFile (gif);
8193 UNGCPRO;
8194 return 0;
8197 /* Allocate colors. */
8198 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8199 if (!gif_color_map)
8200 gif_color_map = gif->SColorMap;
8201 init_color_table ();
8202 bzero (pixel_colors, sizeof pixel_colors);
8204 if (gif_color_map)
8205 for (i = 0; i < gif_color_map->ColorCount; ++i)
8207 int r = gif_color_map->Colors[i].Red << 8;
8208 int g = gif_color_map->Colors[i].Green << 8;
8209 int b = gif_color_map->Colors[i].Blue << 8;
8210 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8213 #ifdef COLOR_TABLE_SUPPORT
8214 img->colors = colors_in_color_table (&img->ncolors);
8215 free_color_table ();
8216 #endif /* COLOR_TABLE_SUPPORT */
8218 /* Clear the part of the screen image that are not covered by
8219 the image from the GIF file. Full animated GIF support
8220 requires more than can be done here (see the gif89 spec,
8221 disposal methods). Let's simply assume that the part
8222 not covered by a sub-image is in the frame's background color. */
8223 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
8224 for (x = 0; x < width; ++x)
8225 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8227 for (y = img->corners[BOT_CORNER]; y < height; ++y)
8228 for (x = 0; x < width; ++x)
8229 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8231 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
8233 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
8234 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8235 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
8236 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8239 /* Read the GIF image into the X image. We use a local variable
8240 `raster' here because RasterBits below is a char *, and invites
8241 problems with bytes >= 0x80. */
8242 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8244 if (gif->SavedImages[ino].ImageDesc.Interlace)
8246 int pass;
8247 int row = interlace_start[0];
8249 pass = 0;
8251 for (y = 0; y < image_height; y++)
8253 if (row >= image_height)
8255 row = interlace_start[++pass];
8256 while (row >= image_height)
8257 row = interlace_start[++pass];
8260 for (x = 0; x < image_width; x++)
8262 int i = raster[(y * image_width) + x];
8263 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8264 row + img->corners[TOP_CORNER], pixel_colors[i]);
8267 row += interlace_increment[pass];
8270 else
8272 for (y = 0; y < image_height; ++y)
8273 for (x = 0; x < image_width; ++x)
8275 int i = raster[y * image_width + x];
8276 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8277 y + img->corners[TOP_CORNER], pixel_colors[i]);
8281 /* Save GIF image extension data for `image-extension-data'.
8282 Format is (count IMAGES FUNCTION "BYTES" ...). */
8283 img->data.lisp_val = Qnil;
8284 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
8286 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
8287 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
8288 /* Append (... FUNCTION "BYTES") */
8289 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
8290 Fcons (make_number (ext->Function),
8291 img->data.lisp_val));
8292 img->data.lisp_val = Fnreverse (img->data.lisp_val);
8294 if (gif->ImageCount > 1)
8295 img->data.lisp_val = Fcons (Qcount,
8296 Fcons (make_number (gif->ImageCount),
8297 img->data.lisp_val));
8299 fn_DGifCloseFile (gif);
8301 /* Maybe fill in the background field while we have ximg handy. */
8302 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8303 /* Casting avoids a GCC warning. */
8304 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8306 /* Put the image into the pixmap, then free the X image and its buffer. */
8307 x_put_x_image (f, ximg, img->pixmap, width, height);
8308 x_destroy_x_image (ximg);
8310 UNGCPRO;
8311 return 1;
8314 #else /* !HAVE_GIF */
8316 #ifdef MAC_OS
8317 static int
8318 gif_load (f, img)
8319 struct frame *f;
8320 struct image *img;
8322 #if USE_MAC_IMAGE_IO
8323 return image_load_image_io (f, img, kUTTypeGIF);
8324 #else /* !USE_MAC_IMAGE_IO */
8325 Lisp_Object specified_file, file;
8326 Lisp_Object specified_data;
8327 OSErr err;
8328 Boolean graphic_p, movie_p, prefer_graphic_p;
8329 Handle dh = NULL;
8330 Movie movie = NULL;
8331 Lisp_Object image;
8332 Track track = NULL;
8333 Media media = NULL;
8334 long nsamples;
8335 Rect rect;
8336 Lisp_Object specified_bg;
8337 XColor color;
8338 RGBColor bg_color;
8339 int width, height;
8340 XImagePtr ximg;
8341 TimeScale time_scale;
8342 TimeValue time, duration;
8343 int ino;
8344 CGrafPtr old_port;
8345 GDHandle old_gdh;
8347 specified_file = image_spec_value (img->spec, QCfile, NULL);
8348 specified_data = image_spec_value (img->spec, QCdata, NULL);
8350 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8351 EnterMovies ();
8353 if (NILP (specified_data))
8355 /* Read from a file */
8356 FSSpec fss;
8357 short refnum;
8359 err = find_image_fsspec (specified_file, &file, &fss);
8360 if (err != noErr)
8362 if (err == fnfErr)
8363 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8364 else
8365 goto open_error;
8368 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8369 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8370 if (err != noErr)
8371 goto open_error;
8373 if (!graphic_p && !movie_p)
8374 goto open_error;
8375 if (prefer_graphic_p)
8376 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8377 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8378 if (err != noErr)
8379 goto open_error;
8380 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8381 CloseMovieFile (refnum);
8382 if (err != noErr)
8384 image_error ("Error reading `%s'", file, Qnil);
8385 return 0;
8388 else
8390 /* Memory source! */
8391 Handle dref = NULL;
8392 long file_type_atom[3];
8394 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8395 if (err != noErr)
8397 image_error ("Cannot allocate data handle for `%s'",
8398 img->spec, Qnil);
8399 goto error;
8402 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8403 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8404 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8405 err = PtrToHand (&dh, &dref, sizeof (Handle));
8406 if (err == noErr)
8407 /* no file name */
8408 err = PtrAndHand ("\p", dref, 1);
8409 if (err == noErr)
8410 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8411 if (err != noErr)
8413 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8414 goto error;
8416 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8417 &movie_p, &prefer_graphic_p, 0);
8418 if (err != noErr)
8419 goto open_error;
8421 if (!graphic_p && !movie_p)
8422 goto open_error;
8423 if (prefer_graphic_p)
8425 int success_p;
8427 DisposeHandle (dref);
8428 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8429 DisposeHandle (dh);
8430 return success_p;
8432 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8433 HandleDataHandlerSubType);
8434 DisposeHandle (dref);
8435 if (err != noErr)
8436 goto open_error;
8439 image = image_spec_value (img->spec, QCindex, NULL);
8440 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8441 track = GetMovieIndTrack (movie, 1);
8442 media = GetTrackMedia (track);
8443 nsamples = GetMediaSampleCount (media);
8444 if (ino >= nsamples)
8446 image_error ("Invalid image number `%s' in image `%s'",
8447 image, img->spec);
8448 goto error;
8450 time_scale = GetMediaTimeScale (media);
8452 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8453 if (!STRINGP (specified_bg)
8454 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8456 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8457 color.red = RED16_FROM_ULONG (color.pixel);
8458 color.green = GREEN16_FROM_ULONG (color.pixel);
8459 color.blue = BLUE16_FROM_ULONG (color.pixel);
8461 GetMovieBox (movie, &rect);
8462 width = img->width = rect.right - rect.left;
8463 height = img->height = rect.bottom - rect.top;
8464 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8465 goto error;
8467 GetGWorld (&old_port, &old_gdh);
8468 SetGWorld (ximg, NULL);
8469 bg_color.red = color.red;
8470 bg_color.green = color.green;
8471 bg_color.blue = color.blue;
8472 RGBBackColor (&bg_color);
8473 SetGWorld (old_port, old_gdh);
8474 SetMovieActive (movie, 1);
8475 SetMovieGWorld (movie, ximg, NULL);
8476 SampleNumToMediaTime (media, ino + 1, &time, &duration);
8477 SetMovieTimeValue (movie, time);
8478 MoviesTask (movie, 0L);
8479 DisposeTrackMedia (media);
8480 DisposeMovieTrack (track);
8481 DisposeMovie (movie);
8482 if (dh)
8483 DisposeHandle (dh);
8485 /* Save GIF image extension data for `image-extension-data'.
8486 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8488 Lisp_Object gce = make_uninit_string (4);
8489 int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
8491 /* Fill the delay time field. */
8492 SSET (gce, 1, centisec & 0xff);
8493 SSET (gce, 2, (centisec >> 8) & 0xff);
8494 /* We don't know about other fields. */
8495 SSET (gce, 0, 0);
8496 SSET (gce, 3, 0);
8498 img->data.lisp_val = list4 (Qcount, make_number (nsamples),
8499 make_number (0xf9), gce);
8502 /* Maybe fill in the background field while we have ximg handy. */
8503 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8504 IMAGE_BACKGROUND (img, f, ximg);
8506 /* Put the image into the pixmap. */
8507 x_put_x_image (f, ximg, img->pixmap, width, height);
8508 x_destroy_x_image (ximg);
8509 return 1;
8511 open_error:
8512 image_error ("Cannot open `%s'", file, Qnil);
8513 error:
8514 if (media)
8515 DisposeTrackMedia (media);
8516 if (track)
8517 DisposeMovieTrack (track);
8518 if (movie)
8519 DisposeMovie (movie);
8520 if (dh)
8521 DisposeHandle (dh);
8522 return 0;
8523 #endif /* !USE_MAC_IMAGE_IO */
8525 #endif /* MAC_OS */
8527 #endif /* HAVE_GIF */
8531 /***********************************************************************
8532 Ghostscript
8533 ***********************************************************************/
8535 #ifdef HAVE_X_WINDOWS
8536 #define HAVE_GHOSTSCRIPT 1
8537 #endif /* HAVE_X_WINDOWS */
8539 /* The symbol `postscript' identifying images of this type. */
8541 Lisp_Object Qpostscript;
8543 #ifdef HAVE_GHOSTSCRIPT
8545 static int gs_image_p P_ ((Lisp_Object object));
8546 static int gs_load P_ ((struct frame *f, struct image *img));
8547 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8549 /* Keyword symbols. */
8551 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8553 /* Indices of image specification fields in gs_format, below. */
8555 enum gs_keyword_index
8557 GS_TYPE,
8558 GS_PT_WIDTH,
8559 GS_PT_HEIGHT,
8560 GS_FILE,
8561 GS_LOADER,
8562 GS_BOUNDING_BOX,
8563 GS_ASCENT,
8564 GS_MARGIN,
8565 GS_RELIEF,
8566 GS_ALGORITHM,
8567 GS_HEURISTIC_MASK,
8568 GS_MASK,
8569 GS_BACKGROUND,
8570 GS_LAST
8573 /* Vector of image_keyword structures describing the format
8574 of valid user-defined image specifications. */
8576 static struct image_keyword gs_format[GS_LAST] =
8578 {":type", IMAGE_SYMBOL_VALUE, 1},
8579 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8580 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
8581 {":file", IMAGE_STRING_VALUE, 1},
8582 {":loader", IMAGE_FUNCTION_VALUE, 0},
8583 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
8584 {":ascent", IMAGE_ASCENT_VALUE, 0},
8585 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8586 {":relief", IMAGE_INTEGER_VALUE, 0},
8587 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8588 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8589 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8590 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8593 /* Structure describing the image type `ghostscript'. */
8595 static struct image_type gs_type =
8597 &Qpostscript,
8598 gs_image_p,
8599 gs_load,
8600 gs_clear_image,
8601 NULL
8605 /* Free X resources of Ghostscript image IMG which is used on frame F. */
8607 static void
8608 gs_clear_image (f, img)
8609 struct frame *f;
8610 struct image *img;
8612 /* IMG->data.ptr_val may contain a recorded colormap. */
8613 xfree (img->data.ptr_val);
8614 x_clear_image (f, img);
8618 /* Return non-zero if OBJECT is a valid Ghostscript image
8619 specification. */
8621 static int
8622 gs_image_p (object)
8623 Lisp_Object object;
8625 struct image_keyword fmt[GS_LAST];
8626 Lisp_Object tem;
8627 int i;
8629 bcopy (gs_format, fmt, sizeof fmt);
8631 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
8632 return 0;
8634 /* Bounding box must be a list or vector containing 4 integers. */
8635 tem = fmt[GS_BOUNDING_BOX].value;
8636 if (CONSP (tem))
8638 for (i = 0; i < 4; ++i, tem = XCDR (tem))
8639 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
8640 return 0;
8641 if (!NILP (tem))
8642 return 0;
8644 else if (VECTORP (tem))
8646 if (XVECTOR (tem)->size != 4)
8647 return 0;
8648 for (i = 0; i < 4; ++i)
8649 if (!INTEGERP (XVECTOR (tem)->contents[i]))
8650 return 0;
8652 else
8653 return 0;
8655 return 1;
8659 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
8660 if successful. */
8662 static int
8663 gs_load (f, img)
8664 struct frame *f;
8665 struct image *img;
8667 char buffer[100];
8668 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
8669 struct gcpro gcpro1, gcpro2;
8670 Lisp_Object frame;
8671 double in_width, in_height;
8672 Lisp_Object pixel_colors = Qnil;
8674 /* Compute pixel size of pixmap needed from the given size in the
8675 image specification. Sizes in the specification are in pt. 1 pt
8676 = 1/72 in, xdpi and ydpi are stored in the frame's X display
8677 info. */
8678 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
8679 in_width = XFASTINT (pt_width) / 72.0;
8680 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
8681 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
8682 in_height = XFASTINT (pt_height) / 72.0;
8683 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
8685 if (!check_image_size (f, img->width, img->height))
8687 image_error ("Invalid image size", Qnil, Qnil);
8688 return 0;
8691 /* Create the pixmap. */
8692 xassert (img->pixmap == NO_PIXMAP);
8694 /* Only W32 version did BLOCK_INPUT here. ++kfs */
8695 BLOCK_INPUT;
8696 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8697 img->width, img->height,
8698 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
8699 UNBLOCK_INPUT;
8701 if (!img->pixmap)
8703 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
8704 return 0;
8707 /* Call the loader to fill the pixmap. It returns a process object
8708 if successful. We do not record_unwind_protect here because
8709 other places in redisplay like calling window scroll functions
8710 don't either. Let the Lisp loader use `unwind-protect' instead. */
8711 GCPRO2 (window_and_pixmap_id, pixel_colors);
8713 sprintf (buffer, "%lu %lu",
8714 (unsigned long) FRAME_X_WINDOW (f),
8715 (unsigned long) img->pixmap);
8716 window_and_pixmap_id = build_string (buffer);
8718 sprintf (buffer, "%lu %lu",
8719 FRAME_FOREGROUND_PIXEL (f),
8720 FRAME_BACKGROUND_PIXEL (f));
8721 pixel_colors = build_string (buffer);
8723 XSETFRAME (frame, f);
8724 loader = image_spec_value (img->spec, QCloader, NULL);
8725 if (NILP (loader))
8726 loader = intern ("gs-load-image");
8728 img->data.lisp_val = call6 (loader, frame, img->spec,
8729 make_number (img->width),
8730 make_number (img->height),
8731 window_and_pixmap_id,
8732 pixel_colors);
8733 UNGCPRO;
8734 return PROCESSP (img->data.lisp_val);
8738 /* Kill the Ghostscript process that was started to fill PIXMAP on
8739 frame F. Called from XTread_socket when receiving an event
8740 telling Emacs that Ghostscript has finished drawing. */
8742 void
8743 x_kill_gs_process (pixmap, f)
8744 Pixmap pixmap;
8745 struct frame *f;
8747 struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
8748 int class, i;
8749 struct image *img;
8751 /* Find the image containing PIXMAP. */
8752 for (i = 0; i < c->used; ++i)
8753 if (c->images[i]->pixmap == pixmap)
8754 break;
8756 /* Should someone in between have cleared the image cache, for
8757 instance, give up. */
8758 if (i == c->used)
8759 return;
8761 /* Kill the GS process. We should have found PIXMAP in the image
8762 cache and its image should contain a process object. */
8763 img = c->images[i];
8764 xassert (PROCESSP (img->data.lisp_val));
8765 Fkill_process (img->data.lisp_val, Qnil);
8766 img->data.lisp_val = Qnil;
8768 #if defined (HAVE_X_WINDOWS)
8770 /* On displays with a mutable colormap, figure out the colors
8771 allocated for the image by looking at the pixels of an XImage for
8772 img->pixmap. */
8773 class = FRAME_X_VISUAL (f)->class;
8774 if (class != StaticColor && class != StaticGray && class != TrueColor)
8776 XImagePtr ximg;
8778 BLOCK_INPUT;
8780 /* Try to get an XImage for img->pixmep. */
8781 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
8782 0, 0, img->width, img->height, ~0, ZPixmap);
8783 if (ximg)
8785 int x, y;
8787 /* Initialize the color table. */
8788 init_color_table ();
8790 /* For each pixel of the image, look its color up in the
8791 color table. After having done so, the color table will
8792 contain an entry for each color used by the image. */
8793 for (y = 0; y < img->height; ++y)
8794 for (x = 0; x < img->width; ++x)
8796 unsigned long pixel = XGetPixel (ximg, x, y);
8797 lookup_pixel_color (f, pixel);
8800 /* Record colors in the image. Free color table and XImage. */
8801 #ifdef COLOR_TABLE_SUPPORT
8802 img->colors = colors_in_color_table (&img->ncolors);
8803 free_color_table ();
8804 #endif
8805 XDestroyImage (ximg);
8807 #if 0 /* This doesn't seem to be the case. If we free the colors
8808 here, we get a BadAccess later in x_clear_image when
8809 freeing the colors. */
8810 /* We have allocated colors once, but Ghostscript has also
8811 allocated colors on behalf of us. So, to get the
8812 reference counts right, free them once. */
8813 if (img->ncolors)
8814 x_free_colors (f, img->colors, img->ncolors);
8815 #endif
8817 else
8818 image_error ("Cannot get X image of `%s'; colors will not be freed",
8819 img->spec, Qnil);
8821 UNBLOCK_INPUT;
8823 #endif /* HAVE_X_WINDOWS */
8825 /* Now that we have the pixmap, compute mask and transform the
8826 image if requested. */
8827 BLOCK_INPUT;
8828 postprocess_image (f, img);
8829 UNBLOCK_INPUT;
8832 #endif /* HAVE_GHOSTSCRIPT */
8835 /***********************************************************************
8836 Tests
8837 ***********************************************************************/
8839 #if GLYPH_DEBUG
8841 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
8842 doc: /* Value is non-nil if SPEC is a valid image specification. */)
8843 (spec)
8844 Lisp_Object spec;
8846 return valid_image_p (spec) ? Qt : Qnil;
8850 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
8851 (spec)
8852 Lisp_Object spec;
8854 int id = -1;
8856 if (valid_image_p (spec))
8857 id = lookup_image (SELECTED_FRAME (), spec);
8859 debug_print (spec);
8860 return make_number (id);
8863 #endif /* GLYPH_DEBUG != 0 */
8866 /***********************************************************************
8867 Initialization
8868 ***********************************************************************/
8870 #ifdef HAVE_NTGUI
8871 /* Image types that rely on external libraries are loaded dynamically
8872 if the library is available. */
8873 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8874 define_image_type (image_type, init_lib_fn (libraries))
8875 #else
8876 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
8877 define_image_type (image_type, 1)
8878 #endif /* HAVE_NTGUI */
8880 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
8881 doc: /* Initialize image library implementing image type TYPE.
8882 Return non-nil if TYPE is a supported image type.
8884 Image types pbm and xbm are prebuilt; other types are loaded here.
8885 Libraries to load are specified in alist LIBRARIES (usually, the value
8886 of `image-library-alist', which see). */)
8887 (type, libraries)
8888 Lisp_Object type, libraries;
8890 Lisp_Object tested;
8892 /* Don't try to reload the library. */
8893 tested = Fassq (type, Vimage_type_cache);
8894 if (CONSP (tested))
8895 return XCDR (tested);
8897 #if defined (HAVE_XPM) || defined (MAC_OS)
8898 if (EQ (type, Qxpm))
8899 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
8900 #endif
8902 #if defined (HAVE_JPEG) || defined (MAC_OS)
8903 if (EQ (type, Qjpeg))
8904 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
8905 #endif
8907 #if defined (HAVE_TIFF) || defined (MAC_OS)
8908 if (EQ (type, Qtiff))
8909 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
8910 #endif
8912 #if defined (HAVE_GIF) || defined (MAC_OS)
8913 if (EQ (type, Qgif))
8914 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
8915 #endif
8917 #if defined (HAVE_PNG) || defined (MAC_OS)
8918 if (EQ (type, Qpng))
8919 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
8920 #endif
8922 #ifdef HAVE_GHOSTSCRIPT
8923 if (EQ (type, Qpostscript))
8924 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
8925 #endif
8927 /* If the type is not recognized, avoid testing it ever again. */
8928 CACHE_IMAGE_TYPE (type, Qnil);
8929 return Qnil;
8932 void
8933 syms_of_image ()
8935 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
8937 /* Initialize this only once, since that's what we do with Vimage_types
8938 and they are supposed to be in sync. Initializing here gives correct
8939 operation on GNU/Linux of calling dump-emacs after loading some images. */
8940 image_types = NULL;
8942 /* Must be defined now becase we're going to update it below, while
8943 defining the supported image types. */
8944 DEFVAR_LISP ("image-types", &Vimage_types,
8945 doc: /* List of potentially supported image types.
8946 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
8947 To check whether it is really supported, use `image-type-available-p'. */);
8948 Vimage_types = Qnil;
8950 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
8951 doc: /* Alist of image types vs external libraries needed to display them.
8953 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
8954 representing a supported image type, and the rest are strings giving
8955 alternate filenames for the corresponding external libraries.
8957 Emacs tries to load the libraries in the order they appear on the
8958 list; if none is loaded, the running session of Emacs won't
8959 support the image type. Types 'pbm and 'xbm don't need to be
8960 listed; they are always supported. */);
8961 Vimage_library_alist = Qnil;
8962 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
8964 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
8965 doc: /* Maximum size of images.
8966 Emacs will not load an image into memory if its pixel width or
8967 pixel height exceeds this limit.
8969 If the value is an integer, it directly specifies the maximum
8970 image height and width, measured in pixels. If it is a floating
8971 point number, it specifies the maximum image height and width
8972 as a ratio to the frame height and width. If the value is
8973 non-numeric, there is no explicit limit on the size of images. */);
8974 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
8976 Vimage_type_cache = Qnil;
8977 staticpro (&Vimage_type_cache);
8979 Qpbm = intern ("pbm");
8980 staticpro (&Qpbm);
8981 ADD_IMAGE_TYPE(Qpbm);
8983 Qxbm = intern ("xbm");
8984 staticpro (&Qxbm);
8985 ADD_IMAGE_TYPE(Qxbm);
8987 define_image_type (&xbm_type, 1);
8988 define_image_type (&pbm_type, 1);
8990 QCascent = intern (":ascent");
8991 staticpro (&QCascent);
8992 QCmargin = intern (":margin");
8993 staticpro (&QCmargin);
8994 QCrelief = intern (":relief");
8995 staticpro (&QCrelief);
8996 QCconversion = intern (":conversion");
8997 staticpro (&QCconversion);
8998 QCcolor_symbols = intern (":color-symbols");
8999 staticpro (&QCcolor_symbols);
9000 QCheuristic_mask = intern (":heuristic-mask");
9001 staticpro (&QCheuristic_mask);
9002 QCindex = intern (":index");
9003 staticpro (&QCindex);
9004 QCmatrix = intern (":matrix");
9005 staticpro (&QCmatrix);
9006 QCcolor_adjustment = intern (":color-adjustment");
9007 staticpro (&QCcolor_adjustment);
9008 QCmask = intern (":mask");
9009 staticpro (&QCmask);
9011 Qlaplace = intern ("laplace");
9012 staticpro (&Qlaplace);
9013 Qemboss = intern ("emboss");
9014 staticpro (&Qemboss);
9015 Qedge_detection = intern ("edge-detection");
9016 staticpro (&Qedge_detection);
9017 Qheuristic = intern ("heuristic");
9018 staticpro (&Qheuristic);
9020 Qpostscript = intern ("postscript");
9021 staticpro (&Qpostscript);
9022 #ifdef HAVE_GHOSTSCRIPT
9023 ADD_IMAGE_TYPE(Qpostscript);
9024 QCloader = intern (":loader");
9025 staticpro (&QCloader);
9026 QCbounding_box = intern (":bounding-box");
9027 staticpro (&QCbounding_box);
9028 QCpt_width = intern (":pt-width");
9029 staticpro (&QCpt_width);
9030 QCpt_height = intern (":pt-height");
9031 staticpro (&QCpt_height);
9032 #endif /* HAVE_GHOSTSCRIPT */
9034 #if defined (HAVE_XPM) || defined (MAC_OS)
9035 Qxpm = intern ("xpm");
9036 staticpro (&Qxpm);
9037 ADD_IMAGE_TYPE(Qxpm);
9038 #endif
9040 #if defined (HAVE_JPEG) || defined (MAC_OS)
9041 Qjpeg = intern ("jpeg");
9042 staticpro (&Qjpeg);
9043 ADD_IMAGE_TYPE(Qjpeg);
9044 #endif
9046 #if defined (HAVE_TIFF) || defined (MAC_OS)
9047 Qtiff = intern ("tiff");
9048 staticpro (&Qtiff);
9049 ADD_IMAGE_TYPE(Qtiff);
9050 #endif
9052 #if defined (HAVE_GIF) || defined (MAC_OS)
9053 Qgif = intern ("gif");
9054 staticpro (&Qgif);
9055 ADD_IMAGE_TYPE(Qgif);
9056 #endif
9058 #if defined (HAVE_PNG) || defined (MAC_OS)
9059 Qpng = intern ("png");
9060 staticpro (&Qpng);
9061 ADD_IMAGE_TYPE(Qpng);
9062 #endif
9064 defsubr (&Sinit_image_library);
9065 defsubr (&Sclear_image_cache);
9066 defsubr (&Simage_refresh);
9067 defsubr (&Simage_size);
9068 defsubr (&Simage_mask_p);
9069 defsubr (&Simage_extension_data);
9071 #if GLYPH_DEBUG
9072 defsubr (&Simagep);
9073 defsubr (&Slookup_image);
9074 #endif
9076 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
9077 doc: /* Non-nil means always draw a cross over disabled images.
9078 Disabled images are those having a `:conversion disabled' property.
9079 A cross is always drawn on black & white displays. */);
9080 cross_disabled_images = 0;
9082 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
9083 doc: /* List of directories to search for window system bitmap files. */);
9084 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
9086 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
9087 doc: /* Time after which cached images are removed from the cache.
9088 When an image has not been displayed this many seconds, remove it
9089 from the image cache. Value must be an integer or nil with nil
9090 meaning don't clear the cache. */);
9091 Vimage_cache_eviction_delay = make_number (30 * 60);
9094 void
9095 init_image ()
9099 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9100 (do not change this comment) */