(ibuffer-aif, ibuffer-awhen, ibuffer-save-marks)
[emacs.git] / src / image.c
blob3628a7f05dd5a279de9b0e86ae5f6c037301bedf
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 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <ctype.h>
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 /* This makes the fields of a Display accessible, in Xlib header files. */
32 #define XLIB_ILLEGAL_ACCESS
34 #include "lisp.h"
35 #include "frame.h"
36 #include "window.h"
37 #include "dispextern.h"
38 #include "blockinput.h"
39 #include "systime.h"
40 #include <epaths.h>
41 #include "character.h"
42 #include "coding.h"
43 #include "termhooks.h"
44 #include "font.h"
46 #ifdef HAVE_X_WINDOWS
47 #include "xterm.h"
48 #include <sys/types.h>
49 #include <sys/stat.h>
51 #define COLOR_TABLE_SUPPORT 1
53 typedef struct x_bitmap_record Bitmap_Record;
54 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
55 #define NO_PIXMAP None
57 #define RGB_PIXEL_COLOR unsigned long
59 #define PIX_MASK_RETAIN 0
60 #define PIX_MASK_DRAW 1
61 #endif /* HAVE_X_WINDOWS */
64 #ifdef HAVE_NTGUI
65 #include "w32term.h"
67 /* W32_TODO : Color tables on W32. */
68 #undef COLOR_TABLE_SUPPORT
70 typedef struct w32_bitmap_record Bitmap_Record;
71 #define GET_PIXEL(ximg, x, y) GetPixel(ximg, x, y)
72 #define NO_PIXMAP 0
74 #define RGB_PIXEL_COLOR COLORREF
76 #define PIX_MASK_RETAIN 0
77 #define PIX_MASK_DRAW 1
79 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
80 #define x_defined_color w32_defined_color
81 #define DefaultDepthOfScreen(screen) (one_w32_display_info.n_cbits)
82 #endif /* HAVE_NTGUI */
85 #ifdef MAC_OS
86 #include "macterm.h"
87 #include <sys/stat.h>
88 #ifndef MAC_OSX
89 #include <alloca.h>
90 #include <sys/param.h>
91 #endif
92 #if TARGET_API_MAC_CARBON
93 #ifdef MAC_OSX
94 #include <QuickTime/QuickTime.h>
95 #else /* not MAC_OSX */
96 #include <QuickTime.h>
97 #endif /* not MAC_OSX */
98 #else /* not TARGET_API_MAC_CARBON */
99 #include <Windows.h>
100 #include <Gestalt.h>
101 #include <TextUtils.h>
102 #include <ImageCompression.h>
103 #include <QuickTimeComponents.h>
104 #endif /* not TARGET_API_MAC_CARBON */
106 /* MAC_TODO : Color tables on Mac. */
107 #undef COLOR_TABLE_SUPPORT
109 #define ZPixmap 0 /* arbitrary */
110 typedef struct mac_bitmap_record Bitmap_Record;
112 #define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
113 #define NO_PIXMAP 0
115 #define RGB_PIXEL_COLOR unsigned long
117 #if USE_MAC_IMAGE_IO
118 #define PIX_MASK_DRAW 255
119 #define PIX_MASK_RETAIN 0
120 #else
121 /* A black pixel in a mask bitmap/pixmap means ``draw a source
122 pixel''. A white pixel means ``retain the current pixel''. */
123 #define PIX_MASK_DRAW RGB_TO_ULONG(0,0,0)
124 #define PIX_MASK_RETAIN RGB_TO_ULONG(255,255,255)
125 #endif
127 #define FRAME_X_VISUAL(f) FRAME_X_DISPLAY_INFO (f)->visual
128 #define x_defined_color mac_defined_color
129 #define DefaultDepthOfScreen(screen) (one_mac_display_info.n_planes)
131 #endif /* MAC_OS */
134 /* Search path for bitmap files. */
136 Lisp_Object Vx_bitmap_file_path;
139 static void x_disable_image P_ ((struct frame *, struct image *));
140 static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
141 Lisp_Object));
143 static void init_color_table P_ ((void));
144 static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
145 #ifdef COLOR_TABLE_SUPPORT
146 static void free_color_table P_ ((void));
147 static unsigned long *colors_in_color_table P_ ((int *n));
148 static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
149 #endif
151 /* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
152 id, which is just an int that this section returns. Bitmaps are
153 reference counted so they can be shared among frames.
155 Bitmap indices are guaranteed to be > 0, so a negative number can
156 be used to indicate no bitmap.
158 If you use x_create_bitmap_from_data, then you must keep track of
159 the bitmaps yourself. That is, creating a bitmap from the same
160 data more than once will not be caught. */
162 #ifdef MAC_OS
164 static XImagePtr
165 XGetImage (display, pixmap, x, y, width, height, plane_mask, format)
166 Display *display; /* not used */
167 Pixmap pixmap;
168 int x, y; /* not used */
169 unsigned int width, height; /* not used */
170 unsigned long plane_mask; /* not used */
171 int format; /* not used */
173 #if !USE_MAC_IMAGE_IO
174 #if GLYPH_DEBUG
175 xassert (x == 0 && y == 0);
177 Rect ri, rp;
178 SetRect (&ri, 0, 0, width, height);
179 xassert (EqualRect (&ri, GetPixBounds (GetGWorldPixMap (pixmap), &rp)));
181 xassert (! (pixelsLocked & GetPixelsState (GetGWorldPixMap (pixmap))));
182 #endif
184 LockPixels (GetGWorldPixMap (pixmap));
185 #endif
187 return pixmap;
190 static void
191 XPutPixel (ximage, x, y, pixel)
192 XImagePtr ximage;
193 int x, y;
194 unsigned long pixel;
196 #if USE_MAC_IMAGE_IO
197 if (ximage->bits_per_pixel == 32)
198 ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
199 else
200 ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x] = pixel;
201 #else
202 PixMapHandle pixmap = GetGWorldPixMap (ximage);
203 short depth = GetPixDepth (pixmap);
205 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
206 if (depth == 32)
208 char *base_addr = GetPixBaseAddr (pixmap);
209 short row_bytes = GetPixRowBytes (pixmap);
211 ((unsigned long *) (base_addr + y * row_bytes))[x] = 0xff000000 | pixel;
213 else
214 #endif
215 if (depth == 1)
217 char *base_addr = GetPixBaseAddr (pixmap);
218 short row_bytes = GetPixRowBytes (pixmap);
220 if (pixel == PIX_MASK_DRAW)
221 base_addr[y * row_bytes + x / 8] |= (1 << 7) >> (x & 7);
222 else
223 base_addr[y * row_bytes + x / 8] &= ~((1 << 7) >> (x & 7));
225 else
227 CGrafPtr old_port;
228 GDHandle old_gdh;
229 RGBColor color;
231 GetGWorld (&old_port, &old_gdh);
232 SetGWorld (ximage, NULL);
234 color.red = RED16_FROM_ULONG (pixel);
235 color.green = GREEN16_FROM_ULONG (pixel);
236 color.blue = BLUE16_FROM_ULONG (pixel);
238 SetCPixel (x, y, &color);
240 SetGWorld (old_port, old_gdh);
242 #endif
245 static unsigned long
246 XGetPixel (ximage, x, y)
247 XImagePtr ximage;
248 int x, y;
250 #if USE_MAC_IMAGE_IO
251 if (ximage->bits_per_pixel == 32)
252 return ((unsigned int *)(ximage->data + y * ximage->bytes_per_line))[x];
253 else
254 return ((unsigned char *)(ximage->data + y * ximage->bytes_per_line))[x];
255 #else
256 PixMapHandle pixmap = GetGWorldPixMap (ximage);
257 short depth = GetPixDepth (pixmap);
259 #if defined (WORDS_BIG_ENDIAN) || !USE_CG_DRAWING
260 if (depth == 32)
262 char *base_addr = GetPixBaseAddr (pixmap);
263 short row_bytes = GetPixRowBytes (pixmap);
265 return ((unsigned long *) (base_addr + y * row_bytes))[x] & 0x00ffffff;
267 else
268 #endif
269 if (depth == 1)
271 char *base_addr = GetPixBaseAddr (pixmap);
272 short row_bytes = GetPixRowBytes (pixmap);
274 if (base_addr[y * row_bytes + x / 8] & (1 << (~x & 7)))
275 return PIX_MASK_DRAW;
276 else
277 return PIX_MASK_RETAIN;
279 else
281 CGrafPtr old_port;
282 GDHandle old_gdh;
283 RGBColor color;
285 GetGWorld (&old_port, &old_gdh);
286 SetGWorld (ximage, NULL);
288 GetCPixel (x, y, &color);
290 SetGWorld (old_port, old_gdh);
291 return RGB_TO_ULONG (color.red >> 8, color.green >> 8, color.blue >> 8);
293 #endif
296 static void
297 XDestroyImage (ximg)
298 XImagePtr ximg;
300 #if !USE_MAC_IMAGE_IO
301 UnlockPixels (GetGWorldPixMap (ximg));
302 #endif
305 #if USE_CG_DRAWING
306 #if USE_MAC_IMAGE_IO
307 void
308 mac_data_provider_release_data (info, data, size)
309 void *info;
310 const void *data;
311 size_t size;
313 xfree ((void *)data);
315 #endif
317 static CGImageRef
318 mac_create_cg_image_from_image (f, img)
319 struct frame *f;
320 struct image *img;
322 #if USE_MAC_IMAGE_IO
323 XImagePtr ximg = img->pixmap;
324 CGDataProviderRef provider;
325 CGImageRef result;
327 if (img->mask)
329 int x, y;
330 unsigned long color, alpha;
332 for (y = 0; y < ximg->height; y++)
333 for (x = 0; x < ximg->width; x++)
335 color = XGetPixel (ximg, x, y);
336 alpha = XGetPixel (img->mask, x, y);
337 XPutPixel (ximg, x, y,
338 ARGB_TO_ULONG (alpha,
339 RED_FROM_ULONG (color)
340 * alpha / PIX_MASK_DRAW,
341 GREEN_FROM_ULONG (color)
342 * alpha / PIX_MASK_DRAW,
343 BLUE_FROM_ULONG (color)
344 * alpha / PIX_MASK_DRAW));
346 xfree (img->mask->data);
347 img->mask->data = NULL;
349 BLOCK_INPUT;
350 provider = CGDataProviderCreateWithData (NULL, ximg->data,
351 ximg->bytes_per_line * ximg->height,
352 mac_data_provider_release_data);
353 ximg->data = NULL;
354 result = CGImageCreate (ximg->width, ximg->height, 8, 32,
355 ximg->bytes_per_line, mac_cg_color_space_rgb,
356 (img->mask ? kCGImageAlphaPremultipliedFirst
357 : kCGImageAlphaNoneSkipFirst)
358 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
359 | kCGBitmapByteOrder32Host
360 #endif
361 , provider, NULL, 0, kCGRenderingIntentDefault);
362 CGDataProviderRelease (provider);
363 UNBLOCK_INPUT;
365 return result;
366 #else
367 Pixmap mask;
368 CGImageRef result = NULL;
370 BLOCK_INPUT;
371 if (img->mask)
372 mask = img->mask;
373 else
375 mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
376 img->width, img->height, 1);
377 if (mask)
379 CGrafPtr old_port;
380 GDHandle old_gdh;
381 Rect r;
383 GetGWorld (&old_port, &old_gdh);
384 SetGWorld (mask, NULL);
385 BackColor (blackColor); /* Don't mask. */
386 SetRect (&r, 0, 0, img->width, img->height);
387 EraseRect (&r);
388 SetGWorld (old_port, old_gdh);
391 if (mask)
393 CreateCGImageFromPixMaps (GetGWorldPixMap (img->pixmap),
394 GetGWorldPixMap (mask), &result);
395 if (mask != img->mask)
396 XFreePixmap (FRAME_X_DISPLAY (f), mask);
398 UNBLOCK_INPUT;
400 return result;
401 #endif
403 #endif /* USE_CG_DRAWING */
404 #endif /* MAC_OS */
407 /* Functions to access the contents of a bitmap, given an id. */
410 x_bitmap_height (f, id)
411 FRAME_PTR f;
412 int id;
414 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].height;
418 x_bitmap_width (f, id)
419 FRAME_PTR f;
420 int id;
422 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].width;
425 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
427 x_bitmap_pixmap (f, id)
428 FRAME_PTR f;
429 int id;
431 return (int) FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
433 #endif
435 #ifdef HAVE_X_WINDOWS
437 x_bitmap_mask (f, id)
438 FRAME_PTR f;
439 int id;
441 return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask;
443 #endif
445 /* Allocate a new bitmap record. Returns index of new record. */
447 static int
448 x_allocate_bitmap_record (f)
449 FRAME_PTR f;
451 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
452 int i;
454 if (dpyinfo->bitmaps == NULL)
456 dpyinfo->bitmaps_size = 10;
457 dpyinfo->bitmaps
458 = (Bitmap_Record *) xmalloc (dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
459 dpyinfo->bitmaps_last = 1;
460 return 1;
463 if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
464 return ++dpyinfo->bitmaps_last;
466 for (i = 0; i < dpyinfo->bitmaps_size; ++i)
467 if (dpyinfo->bitmaps[i].refcount == 0)
468 return i + 1;
470 dpyinfo->bitmaps_size *= 2;
471 dpyinfo->bitmaps
472 = (Bitmap_Record *) xrealloc (dpyinfo->bitmaps,
473 dpyinfo->bitmaps_size * sizeof (Bitmap_Record));
474 return ++dpyinfo->bitmaps_last;
477 /* Add one reference to the reference count of the bitmap with id ID. */
479 void
480 x_reference_bitmap (f, id)
481 FRAME_PTR f;
482 int id;
484 ++FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
487 /* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at BITS. */
490 x_create_bitmap_from_data (f, bits, width, height)
491 struct frame *f;
492 char *bits;
493 unsigned int width, height;
495 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
496 int id;
498 #ifdef HAVE_X_WINDOWS
499 Pixmap bitmap;
500 bitmap = XCreateBitmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
501 bits, width, height);
502 if (! bitmap)
503 return -1;
504 #endif /* HAVE_X_WINDOWS */
506 #ifdef HAVE_NTGUI
507 Pixmap bitmap;
508 bitmap = CreateBitmap (width, height,
509 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_planes,
510 FRAME_X_DISPLAY_INFO (XFRAME (frame))->n_cbits,
511 bits);
512 if (! bitmap)
513 return -1;
514 #endif /* HAVE_NTGUI */
516 #ifdef MAC_OS
517 /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
518 if (width % 16 != 0)
519 return -1;
520 #endif
522 id = x_allocate_bitmap_record (f);
523 #ifdef MAC_OS
524 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
525 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
526 #endif /* MAC_OS */
528 dpyinfo->bitmaps[id - 1].file = NULL;
529 dpyinfo->bitmaps[id - 1].height = height;
530 dpyinfo->bitmaps[id - 1].width = width;
531 dpyinfo->bitmaps[id - 1].refcount = 1;
533 #ifdef HAVE_X_WINDOWS
534 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
535 dpyinfo->bitmaps[id - 1].have_mask = 0;
536 dpyinfo->bitmaps[id - 1].depth = 1;
537 #endif /* HAVE_X_WINDOWS */
539 #ifdef HAVE_NTGUI
540 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
541 dpyinfo->bitmaps[id - 1].hinst = NULL;
542 dpyinfo->bitmaps[id - 1].depth = 1;
543 #endif /* HAVE_NTGUI */
545 return id;
548 /* Create bitmap from file FILE for frame F. */
551 x_create_bitmap_from_file (f, file)
552 struct frame *f;
553 Lisp_Object file;
555 #ifdef MAC_OS
556 return -1; /* MAC_TODO : bitmap support */
557 #endif /* MAC_OS */
559 #ifdef HAVE_NTGUI
560 return -1; /* W32_TODO : bitmap support */
561 #endif /* HAVE_NTGUI */
563 #ifdef HAVE_X_WINDOWS
564 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
565 unsigned int width, height;
566 Pixmap bitmap;
567 int xhot, yhot, result, id;
568 Lisp_Object found;
569 int fd;
570 char *filename;
572 /* Look for an existing bitmap with the same name. */
573 for (id = 0; id < dpyinfo->bitmaps_last; ++id)
575 if (dpyinfo->bitmaps[id].refcount
576 && dpyinfo->bitmaps[id].file
577 && !strcmp (dpyinfo->bitmaps[id].file, (char *) SDATA (file)))
579 ++dpyinfo->bitmaps[id].refcount;
580 return id + 1;
584 /* Search bitmap-file-path for the file, if appropriate. */
585 fd = openp (Vx_bitmap_file_path, file, Qnil, &found, Qnil);
586 if (fd < 0)
587 return -1;
588 emacs_close (fd);
590 filename = (char *) SDATA (found);
592 result = XReadBitmapFile (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
593 filename, &width, &height, &bitmap, &xhot, &yhot);
594 if (result != BitmapSuccess)
595 return -1;
597 id = x_allocate_bitmap_record (f);
598 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
599 dpyinfo->bitmaps[id - 1].have_mask = 0;
600 dpyinfo->bitmaps[id - 1].refcount = 1;
601 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
602 dpyinfo->bitmaps[id - 1].depth = 1;
603 dpyinfo->bitmaps[id - 1].height = height;
604 dpyinfo->bitmaps[id - 1].width = width;
605 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
607 return id;
608 #endif /* HAVE_X_WINDOWS */
611 /* Free bitmap B. */
613 static void
614 free_bitmap_record (dpyinfo, bm)
615 Display_Info *dpyinfo;
616 Bitmap_Record *bm;
618 #ifdef HAVE_X_WINDOWS
619 XFreePixmap (dpyinfo->display, bm->pixmap);
620 if (bm->have_mask)
621 XFreePixmap (dpyinfo->display, bm->mask);
622 #endif /* HAVE_X_WINDOWS */
624 #ifdef HAVE_NTGUI
625 DeleteObject (bm->pixmap);
626 #endif /* HAVE_NTGUI */
628 #ifdef MAC_OS
629 xfree (bm->bitmap_data); /* Added ++kfs */
630 bm->bitmap_data = NULL;
631 #endif /* MAC_OS */
633 if (bm->file)
635 xfree (bm->file);
636 bm->file = NULL;
640 /* Remove reference to bitmap with id number ID. */
642 void
643 x_destroy_bitmap (f, id)
644 FRAME_PTR f;
645 int id;
647 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
649 if (id > 0)
651 Bitmap_Record *bm = &dpyinfo->bitmaps[id - 1];
653 if (--bm->refcount == 0)
655 BLOCK_INPUT;
656 free_bitmap_record (dpyinfo, bm);
657 UNBLOCK_INPUT;
662 /* Free all the bitmaps for the display specified by DPYINFO. */
664 void
665 x_destroy_all_bitmaps (dpyinfo)
666 Display_Info *dpyinfo;
668 int i;
669 Bitmap_Record *bm = dpyinfo->bitmaps;
671 for (i = 0; i < dpyinfo->bitmaps_last; i++, bm++)
672 if (bm->refcount > 0)
673 free_bitmap_record (dpyinfo, bm);
675 dpyinfo->bitmaps_last = 0;
679 #ifdef HAVE_X_WINDOWS
681 /* Useful functions defined in the section
682 `Image type independent image structures' below. */
684 static unsigned long four_corners_best P_ ((XImagePtr ximg,
685 int *corners,
686 unsigned long width,
687 unsigned long height));
689 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height,
690 int depth, XImagePtr *ximg,
691 Pixmap *pixmap));
693 static void x_destroy_x_image P_ ((XImagePtr ximg));
696 /* Create a mask of a bitmap. Note is this not a perfect mask.
697 It's nicer with some borders in this context */
700 x_create_bitmap_mask (f, id)
701 struct frame *f;
702 int id;
704 Pixmap pixmap, mask;
705 XImagePtr ximg, mask_img;
706 unsigned long width, height;
707 int result;
708 unsigned long bg;
709 unsigned long x, y, xp, xm, yp, ym;
710 GC gc;
712 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
714 if (!(id > 0))
715 return -1;
717 pixmap = x_bitmap_pixmap (f, id);
718 width = x_bitmap_width (f, id);
719 height = x_bitmap_height (f, id);
721 BLOCK_INPUT;
722 ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height,
723 ~0, ZPixmap);
725 if (!ximg)
727 UNBLOCK_INPUT;
728 return -1;
731 result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
733 UNBLOCK_INPUT;
734 if (!result)
736 XDestroyImage (ximg);
737 return -1;
740 bg = four_corners_best (ximg, NULL, width, height);
742 for (y = 0; y < ximg->height; ++y)
744 for (x = 0; x < ximg->width; ++x)
746 xp = x != ximg->width - 1 ? x + 1 : 0;
747 xm = x != 0 ? x - 1 : ximg->width - 1;
748 yp = y != ximg->height - 1 ? y + 1 : 0;
749 ym = y != 0 ? y - 1 : ximg->height - 1;
750 if (XGetPixel (ximg, x, y) == bg
751 && XGetPixel (ximg, x, yp) == bg
752 && XGetPixel (ximg, x, ym) == bg
753 && XGetPixel (ximg, xp, y) == bg
754 && XGetPixel (ximg, xp, yp) == bg
755 && XGetPixel (ximg, xp, ym) == bg
756 && XGetPixel (ximg, xm, y) == bg
757 && XGetPixel (ximg, xm, yp) == bg
758 && XGetPixel (ximg, xm, ym) == bg)
759 XPutPixel (mask_img, x, y, 0);
760 else
761 XPutPixel (mask_img, x, y, 1);
765 xassert (interrupt_input_blocked);
766 gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL);
767 XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0,
768 width, height);
769 XFreeGC (FRAME_X_DISPLAY (f), gc);
771 dpyinfo->bitmaps[id - 1].have_mask = 1;
772 dpyinfo->bitmaps[id - 1].mask = mask;
774 XDestroyImage (ximg);
775 x_destroy_x_image (mask_img);
777 return 0;
780 #endif /* HAVE_X_WINDOWS */
783 /***********************************************************************
784 Image types
785 ***********************************************************************/
787 /* Value is the number of elements of vector VECTOR. */
789 #define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
791 /* List of supported image types. Use define_image_type to add new
792 types. Use lookup_image_type to find a type for a given symbol. */
794 static struct image_type *image_types;
796 /* A list of symbols, one for each supported image type. */
798 Lisp_Object Vimage_types;
800 /* An alist of image types and libraries that implement the type. */
802 Lisp_Object Vimage_library_alist;
804 /* Cache for delayed-loading image types. */
806 static Lisp_Object Vimage_type_cache;
808 /* The symbol `xbm' which is used as the type symbol for XBM images. */
810 Lisp_Object Qxbm;
812 /* Keywords. */
814 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
815 extern Lisp_Object QCdata, QCtype;
816 extern Lisp_Object Qcenter;
817 Lisp_Object QCascent, QCmargin, QCrelief, Qcount;
818 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
819 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
821 /* Other symbols. */
823 Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
825 /* Time in seconds after which images should be removed from the cache
826 if not displayed. */
828 Lisp_Object Vimage_cache_eviction_delay;
830 /* Function prototypes. */
832 static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded));
833 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
834 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
835 static void x_laplace P_ ((struct frame *, struct image *));
836 static void x_emboss P_ ((struct frame *, struct image *));
837 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
838 Lisp_Object));
840 #define CACHE_IMAGE_TYPE(type, status) \
841 do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
843 #define ADD_IMAGE_TYPE(type) \
844 do { Vimage_types = Fcons (type, Vimage_types); } while (0)
846 /* Define a new image type from TYPE. This adds a copy of TYPE to
847 image_types and caches the loading status of TYPE. */
849 static Lisp_Object
850 define_image_type (type, loaded)
851 struct image_type *type;
852 int loaded;
854 Lisp_Object success;
856 if (!loaded)
857 success = Qnil;
858 else
860 /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
861 The initialized data segment is read-only. */
862 struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
863 bcopy (type, p, sizeof *p);
864 p->next = image_types;
865 image_types = p;
866 success = Qt;
869 CACHE_IMAGE_TYPE (*type->type, success);
870 return success;
874 /* Look up image type SYMBOL, and return a pointer to its image_type
875 structure. Value is null if SYMBOL is not a known image type. */
877 static INLINE struct image_type *
878 lookup_image_type (symbol)
879 Lisp_Object symbol;
881 struct image_type *type;
883 /* We must initialize the image-type if it hasn't been already. */
884 if (NILP (Finit_image_library (symbol, Vimage_library_alist)))
885 return 0; /* unimplemented */
887 for (type = image_types; type; type = type->next)
888 if (EQ (symbol, *type->type))
889 break;
891 return type;
895 /* Value is non-zero if OBJECT is a valid Lisp image specification. A
896 valid image specification is a list whose car is the symbol
897 `image', and whose rest is a property list. The property list must
898 contain a value for key `:type'. That value must be the name of a
899 supported image type. The rest of the property list depends on the
900 image type. */
903 valid_image_p (object)
904 Lisp_Object object;
906 int valid_p = 0;
908 if (IMAGEP (object))
910 Lisp_Object tem;
912 for (tem = XCDR (object); CONSP (tem); tem = XCDR (tem))
913 if (EQ (XCAR (tem), QCtype))
915 tem = XCDR (tem);
916 if (CONSP (tem) && SYMBOLP (XCAR (tem)))
918 struct image_type *type;
919 type = lookup_image_type (XCAR (tem));
920 if (type)
921 valid_p = type->valid_p (object);
924 break;
928 return valid_p;
932 /* Log error message with format string FORMAT and argument ARG.
933 Signaling an error, e.g. when an image cannot be loaded, is not a
934 good idea because this would interrupt redisplay, and the error
935 message display would lead to another redisplay. This function
936 therefore simply displays a message. */
938 static void
939 image_error (format, arg1, arg2)
940 char *format;
941 Lisp_Object arg1, arg2;
943 add_to_log (format, arg1, arg2);
948 /***********************************************************************
949 Image specifications
950 ***********************************************************************/
952 enum image_value_type
954 IMAGE_DONT_CHECK_VALUE_TYPE,
955 IMAGE_STRING_VALUE,
956 IMAGE_STRING_OR_NIL_VALUE,
957 IMAGE_SYMBOL_VALUE,
958 IMAGE_POSITIVE_INTEGER_VALUE,
959 IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
960 IMAGE_NON_NEGATIVE_INTEGER_VALUE,
961 IMAGE_ASCENT_VALUE,
962 IMAGE_INTEGER_VALUE,
963 IMAGE_FUNCTION_VALUE,
964 IMAGE_NUMBER_VALUE,
965 IMAGE_BOOL_VALUE
968 /* Structure used when parsing image specifications. */
970 struct image_keyword
972 /* Name of keyword. */
973 char *name;
975 /* The type of value allowed. */
976 enum image_value_type type;
978 /* Non-zero means key must be present. */
979 int mandatory_p;
981 /* Used to recognize duplicate keywords in a property list. */
982 int count;
984 /* The value that was found. */
985 Lisp_Object value;
989 static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
990 int, Lisp_Object));
991 static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
994 /* Parse image spec SPEC according to KEYWORDS. A valid image spec
995 has the format (image KEYWORD VALUE ...). One of the keyword/
996 value pairs must be `:type TYPE'. KEYWORDS is a vector of
997 image_keywords structures of size NKEYWORDS describing other
998 allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
1000 static int
1001 parse_image_spec (spec, keywords, nkeywords, type)
1002 Lisp_Object spec;
1003 struct image_keyword *keywords;
1004 int nkeywords;
1005 Lisp_Object type;
1007 int i;
1008 Lisp_Object plist;
1010 if (!IMAGEP (spec))
1011 return 0;
1013 plist = XCDR (spec);
1014 while (CONSP (plist))
1016 Lisp_Object key, value;
1018 /* First element of a pair must be a symbol. */
1019 key = XCAR (plist);
1020 plist = XCDR (plist);
1021 if (!SYMBOLP (key))
1022 return 0;
1024 /* There must follow a value. */
1025 if (!CONSP (plist))
1026 return 0;
1027 value = XCAR (plist);
1028 plist = XCDR (plist);
1030 /* Find key in KEYWORDS. Error if not found. */
1031 for (i = 0; i < nkeywords; ++i)
1032 if (strcmp (keywords[i].name, SDATA (SYMBOL_NAME (key))) == 0)
1033 break;
1035 if (i == nkeywords)
1036 continue;
1038 /* Record that we recognized the keyword. If a keywords
1039 was found more than once, it's an error. */
1040 keywords[i].value = value;
1041 ++keywords[i].count;
1043 if (keywords[i].count > 1)
1044 return 0;
1046 /* Check type of value against allowed type. */
1047 switch (keywords[i].type)
1049 case IMAGE_STRING_VALUE:
1050 if (!STRINGP (value))
1051 return 0;
1052 break;
1054 case IMAGE_STRING_OR_NIL_VALUE:
1055 if (!STRINGP (value) && !NILP (value))
1056 return 0;
1057 break;
1059 case IMAGE_SYMBOL_VALUE:
1060 if (!SYMBOLP (value))
1061 return 0;
1062 break;
1064 case IMAGE_POSITIVE_INTEGER_VALUE:
1065 if (!INTEGERP (value) || XINT (value) <= 0)
1066 return 0;
1067 break;
1069 case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
1070 if (INTEGERP (value) && XINT (value) >= 0)
1071 break;
1072 if (CONSP (value)
1073 && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
1074 && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
1075 break;
1076 return 0;
1078 case IMAGE_ASCENT_VALUE:
1079 if (SYMBOLP (value) && EQ (value, Qcenter))
1080 break;
1081 else if (INTEGERP (value)
1082 && XINT (value) >= 0
1083 && XINT (value) <= 100)
1084 break;
1085 return 0;
1087 case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
1088 if (!INTEGERP (value) || XINT (value) < 0)
1089 return 0;
1090 break;
1092 case IMAGE_DONT_CHECK_VALUE_TYPE:
1093 break;
1095 case IMAGE_FUNCTION_VALUE:
1096 value = indirect_function (value);
1097 if (SUBRP (value)
1098 || COMPILEDP (value)
1099 || (CONSP (value) && EQ (XCAR (value), Qlambda)))
1100 break;
1101 return 0;
1103 case IMAGE_NUMBER_VALUE:
1104 if (!INTEGERP (value) && !FLOATP (value))
1105 return 0;
1106 break;
1108 case IMAGE_INTEGER_VALUE:
1109 if (!INTEGERP (value))
1110 return 0;
1111 break;
1113 case IMAGE_BOOL_VALUE:
1114 if (!NILP (value) && !EQ (value, Qt))
1115 return 0;
1116 break;
1118 default:
1119 abort ();
1120 break;
1123 if (EQ (key, QCtype) && !EQ (type, value))
1124 return 0;
1127 /* Check that all mandatory fields are present. */
1128 for (i = 0; i < nkeywords; ++i)
1129 if (keywords[i].mandatory_p && keywords[i].count == 0)
1130 return 0;
1132 return NILP (plist);
1136 /* Return the value of KEY in image specification SPEC. Value is nil
1137 if KEY is not present in SPEC. if FOUND is not null, set *FOUND
1138 to 1 if KEY was found in SPEC, set it to 0 otherwise. */
1140 static Lisp_Object
1141 image_spec_value (spec, key, found)
1142 Lisp_Object spec, key;
1143 int *found;
1145 Lisp_Object tail;
1147 xassert (valid_image_p (spec));
1149 for (tail = XCDR (spec);
1150 CONSP (tail) && CONSP (XCDR (tail));
1151 tail = XCDR (XCDR (tail)))
1153 if (EQ (XCAR (tail), key))
1155 if (found)
1156 *found = 1;
1157 return XCAR (XCDR (tail));
1161 if (found)
1162 *found = 0;
1163 return Qnil;
1167 DEFUN ("image-size", Fimage_size, Simage_size, 1, 3, 0,
1168 doc: /* Return the size of image SPEC as pair (WIDTH . HEIGHT).
1169 PIXELS non-nil means return the size in pixels, otherwise return the
1170 size in canonical character units.
1171 FRAME is the frame on which the image will be displayed. FRAME nil
1172 or omitted means use the selected frame. */)
1173 (spec, pixels, frame)
1174 Lisp_Object spec, pixels, frame;
1176 Lisp_Object size;
1178 size = Qnil;
1179 if (valid_image_p (spec))
1181 struct frame *f = check_x_frame (frame);
1182 int id = lookup_image (f, spec);
1183 struct image *img = IMAGE_FROM_ID (f, id);
1184 int width = img->width + 2 * img->hmargin;
1185 int height = img->height + 2 * img->vmargin;
1187 if (NILP (pixels))
1188 size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)),
1189 make_float ((double) height / FRAME_LINE_HEIGHT (f)));
1190 else
1191 size = Fcons (make_number (width), make_number (height));
1193 else
1194 error ("Invalid image specification");
1196 return size;
1200 DEFUN ("image-mask-p", Fimage_mask_p, Simage_mask_p, 1, 2, 0,
1201 doc: /* Return t if image SPEC has a mask bitmap.
1202 FRAME is the frame on which the image will be displayed. FRAME nil
1203 or omitted means use the selected frame. */)
1204 (spec, frame)
1205 Lisp_Object spec, frame;
1207 Lisp_Object mask;
1209 mask = Qnil;
1210 if (valid_image_p (spec))
1212 struct frame *f = check_x_frame (frame);
1213 int id = lookup_image (f, spec);
1214 struct image *img = IMAGE_FROM_ID (f, id);
1215 if (img->mask)
1216 mask = Qt;
1218 else
1219 error ("Invalid image specification");
1221 return mask;
1224 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0,
1225 doc: /* Return extension data for image SPEC.
1226 FRAME is the frame on which the image will be displayed. FRAME nil
1227 or omitted means use the selected frame. */)
1228 (spec, frame)
1229 Lisp_Object spec, frame;
1231 Lisp_Object ext;
1233 ext = Qnil;
1234 if (valid_image_p (spec))
1236 struct frame *f = check_x_frame (frame);
1237 int id = lookup_image (f, spec);
1238 struct image *img = IMAGE_FROM_ID (f, id);
1239 ext = img->data.lisp_val;
1242 return ext;
1246 /***********************************************************************
1247 Image type independent image structures
1248 ***********************************************************************/
1250 static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
1251 static void free_image P_ ((struct frame *f, struct image *img));
1252 static int check_image_size P_ ((struct frame *f, int width, int height));
1254 #define MAX_IMAGE_SIZE 6.0
1255 Lisp_Object Vmax_image_size;
1257 /* Allocate and return a new image structure for image specification
1258 SPEC. SPEC has a hash value of HASH. */
1260 static struct image *
1261 make_image (spec, hash)
1262 Lisp_Object spec;
1263 unsigned hash;
1265 struct image *img = (struct image *) xmalloc (sizeof *img);
1266 Lisp_Object file = image_spec_value (spec, QCfile, NULL);
1268 xassert (valid_image_p (spec));
1269 bzero (img, sizeof *img);
1270 img->dependencies = NILP (file) ? Qnil : list1 (file);
1271 img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
1272 xassert (img->type != NULL);
1273 img->spec = spec;
1274 img->data.lisp_val = Qnil;
1275 img->ascent = DEFAULT_IMAGE_ASCENT;
1276 img->hash = hash;
1277 img->corners[BOT_CORNER] = -1; /* Full image */
1278 return img;
1282 /* Free image IMG which was used on frame F, including its resources. */
1284 static void
1285 free_image (f, img)
1286 struct frame *f;
1287 struct image *img;
1289 if (img)
1291 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1293 /* Remove IMG from the hash table of its cache. */
1294 if (img->prev)
1295 img->prev->next = img->next;
1296 else
1297 c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
1299 if (img->next)
1300 img->next->prev = img->prev;
1302 c->images[img->id] = NULL;
1304 /* Free resources, then free IMG. */
1305 img->type->free (f, img);
1306 xfree (img);
1310 /* Return 1 if the given widths and heights are valid for display;
1311 otherwise, return 0. */
1314 check_image_size (f, width, height)
1315 struct frame *f;
1316 int width;
1317 int height;
1319 int w, h;
1321 if (width <= 0 || height <= 0)
1322 return 0;
1324 if (INTEGERP (Vmax_image_size))
1325 w = h = XINT (Vmax_image_size);
1326 else if (FLOATP (Vmax_image_size))
1328 if (f != NULL)
1330 w = FRAME_PIXEL_WIDTH (f);
1331 h = FRAME_PIXEL_HEIGHT (f);
1333 else
1334 w = h = 1024; /* Arbitrary size for unknown frame. */
1335 w = (int) (XFLOAT_DATA (Vmax_image_size) * w);
1336 h = (int) (XFLOAT_DATA (Vmax_image_size) * h);
1338 else
1339 return 1;
1341 return (width <= w && height <= h);
1344 /* Prepare image IMG for display on frame F. Must be called before
1345 drawing an image. */
1347 void
1348 prepare_image_for_display (f, img)
1349 struct frame *f;
1350 struct image *img;
1352 EMACS_TIME t;
1354 /* We're about to display IMG, so set its timestamp to `now'. */
1355 EMACS_GET_TIME (t);
1356 img->timestamp = EMACS_SECS (t);
1358 /* If IMG doesn't have a pixmap yet, load it now, using the image
1359 type dependent loader function. */
1360 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1361 img->load_failed_p = img->type->load (f, img) == 0;
1363 #if defined (MAC_OS) && USE_CG_DRAWING
1364 if (!img->load_failed_p && img->data.ptr_val == NULL)
1366 img->data.ptr_val = mac_create_cg_image_from_image (f, img);
1367 if (img->data.ptr_val == NULL)
1369 img->load_failed_p = 1;
1370 img->type->free (f, img);
1373 #endif
1377 /* Value is the number of pixels for the ascent of image IMG when
1378 drawn in face FACE. */
1381 image_ascent (img, face, slice)
1382 struct image *img;
1383 struct face *face;
1384 struct glyph_slice *slice;
1386 int height;
1387 int ascent;
1389 if (slice->height == img->height)
1390 height = img->height + img->vmargin;
1391 else if (slice->y == 0)
1392 height = slice->height + img->vmargin;
1393 else
1394 height = slice->height;
1396 if (img->ascent == CENTERED_IMAGE_ASCENT)
1398 if (face->font)
1400 #ifdef HAVE_NTGUI
1401 /* W32 specific version. Why?. ++kfs */
1402 ascent = height / 2 - (FONT_DESCENT (face->font)
1403 - FONT_BASE (face->font)) / 2;
1404 #else
1405 /* This expression is arranged so that if the image can't be
1406 exactly centered, it will be moved slightly up. This is
1407 because a typical font is `top-heavy' (due to the presence
1408 uppercase letters), so the image placement should err towards
1409 being top-heavy too. It also just generally looks better. */
1410 ascent = (height + face->font->ascent - face->font->descent + 1) / 2;
1411 #endif /* HAVE_NTGUI */
1413 else
1414 ascent = height / 2;
1416 else
1417 ascent = (int) (height * img->ascent / 100.0);
1419 return ascent;
1423 /* Image background colors. */
1425 /* Find the "best" corner color of a bitmap.
1426 On W32, XIMG is assumed to a device context with the bitmap selected. */
1428 static RGB_PIXEL_COLOR
1429 four_corners_best (ximg, corners, width, height)
1430 XImagePtr_or_DC ximg;
1431 int *corners;
1432 unsigned long width, height;
1434 RGB_PIXEL_COLOR corner_pixels[4], best;
1435 int i, best_count;
1437 if (corners && corners[BOT_CORNER] >= 0)
1439 /* Get the colors at the corner_pixels of ximg. */
1440 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]);
1441 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]);
1442 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1);
1443 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1);
1445 else
1447 /* Get the colors at the corner_pixels of ximg. */
1448 corner_pixels[0] = GET_PIXEL (ximg, 0, 0);
1449 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0);
1450 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1);
1451 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1);
1453 /* Choose the most frequently found color as background. */
1454 for (i = best_count = 0; i < 4; ++i)
1456 int j, n;
1458 for (j = n = 0; j < 4; ++j)
1459 if (corner_pixels[i] == corner_pixels[j])
1460 ++n;
1462 if (n > best_count)
1463 best = corner_pixels[i], best_count = n;
1466 return best;
1469 /* Portability macros */
1471 #ifdef HAVE_NTGUI
1473 #define Destroy_Image(img_dc, prev) \
1474 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1476 #define Free_Pixmap(display, pixmap) \
1477 DeleteObject (pixmap)
1479 #else
1481 #define Destroy_Image(ximg, dummy) \
1482 XDestroyImage (ximg)
1484 #define Free_Pixmap(display, pixmap) \
1485 XFreePixmap (display, pixmap)
1487 #endif /* HAVE_NTGUI */
1490 /* Return the `background' field of IMG. If IMG doesn't have one yet,
1491 it is guessed heuristically. If non-zero, XIMG is an existing
1492 XImage object (or device context with the image selected on W32) to
1493 use for the heuristic. */
1495 RGB_PIXEL_COLOR
1496 image_background (img, f, ximg)
1497 struct image *img;
1498 struct frame *f;
1499 XImagePtr_or_DC ximg;
1501 if (! img->background_valid)
1502 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1504 int free_ximg = !ximg;
1505 #ifdef HAVE_NTGUI
1506 HGDIOBJ prev;
1507 #endif /* HAVE_NTGUI */
1509 if (free_ximg)
1511 #ifndef HAVE_NTGUI
1512 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1513 0, 0, img->width, img->height, ~0, ZPixmap);
1514 #else
1515 HDC frame_dc = get_frame_dc (f);
1516 ximg = CreateCompatibleDC (frame_dc);
1517 release_frame_dc (f, frame_dc);
1518 prev = SelectObject (ximg, img->pixmap);
1519 #endif /* !HAVE_NTGUI */
1522 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1524 if (free_ximg)
1525 Destroy_Image (ximg, prev);
1527 img->background_valid = 1;
1530 return img->background;
1533 /* Return the `background_transparent' field of IMG. If IMG doesn't
1534 have one yet, it is guessed heuristically. If non-zero, MASK is an
1535 existing XImage object to use for the heuristic. */
1538 image_background_transparent (img, f, mask)
1539 struct image *img;
1540 struct frame *f;
1541 XImagePtr_or_DC mask;
1543 if (! img->background_transparent_valid)
1544 /* IMG doesn't have a background yet, try to guess a reasonable value. */
1546 if (img->mask)
1548 int free_mask = !mask;
1549 #ifdef HAVE_NTGUI
1550 HGDIOBJ prev;
1551 #endif /* HAVE_NTGUI */
1553 if (free_mask)
1555 #ifndef HAVE_NTGUI
1556 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1557 0, 0, img->width, img->height, ~0, ZPixmap);
1558 #else
1559 HDC frame_dc = get_frame_dc (f);
1560 mask = CreateCompatibleDC (frame_dc);
1561 release_frame_dc (f, frame_dc);
1562 prev = SelectObject (mask, img->mask);
1563 #endif /* HAVE_NTGUI */
1566 img->background_transparent
1567 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1569 if (free_mask)
1570 Destroy_Image (mask, prev);
1572 else
1573 img->background_transparent = 0;
1575 img->background_transparent_valid = 1;
1578 return img->background_transparent;
1582 /***********************************************************************
1583 Helper functions for X image types
1584 ***********************************************************************/
1586 static void x_clear_image_1 P_ ((struct frame *, struct image *, int,
1587 int, int));
1588 static void x_clear_image P_ ((struct frame *f, struct image *img));
1589 static unsigned long x_alloc_image_color P_ ((struct frame *f,
1590 struct image *img,
1591 Lisp_Object color_name,
1592 unsigned long dflt));
1595 /* Clear X resources of image IMG on frame F. PIXMAP_P non-zero means
1596 free the pixmap if any. MASK_P non-zero means clear the mask
1597 pixmap if any. COLORS_P non-zero means free colors allocated for
1598 the image, if any. */
1600 static void
1601 x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1602 struct frame *f;
1603 struct image *img;
1604 int pixmap_p, mask_p, colors_p;
1606 if (pixmap_p && img->pixmap)
1608 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1609 img->pixmap = NO_PIXMAP;
1610 img->background_valid = 0;
1613 if (mask_p && img->mask)
1615 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1616 img->mask = NO_PIXMAP;
1617 img->background_transparent_valid = 0;
1620 if (colors_p && img->ncolors)
1622 /* MAC_TODO: color table support. */
1623 /* W32_TODO: color table support. */
1624 #ifdef HAVE_X_WINDOWS
1625 x_free_colors (f, img->colors, img->ncolors);
1626 #endif /* HAVE_X_WINDOWS */
1627 xfree (img->colors);
1628 img->colors = NULL;
1629 img->ncolors = 0;
1632 #if defined (MAC_OS) && USE_CG_DRAWING
1633 if (img->data.ptr_val)
1635 CGImageRelease (img->data.ptr_val);
1636 img->data.ptr_val = NULL;
1638 #endif
1641 /* Free X resources of image IMG which is used on frame F. */
1643 static void
1644 x_clear_image (f, img)
1645 struct frame *f;
1646 struct image *img;
1648 BLOCK_INPUT;
1649 x_clear_image_1 (f, img, 1, 1, 1);
1650 UNBLOCK_INPUT;
1654 /* Allocate color COLOR_NAME for image IMG on frame F. If color
1655 cannot be allocated, use DFLT. Add a newly allocated color to
1656 IMG->colors, so that it can be freed again. Value is the pixel
1657 color. */
1659 static unsigned long
1660 x_alloc_image_color (f, img, color_name, dflt)
1661 struct frame *f;
1662 struct image *img;
1663 Lisp_Object color_name;
1664 unsigned long dflt;
1666 XColor color;
1667 unsigned long result;
1669 xassert (STRINGP (color_name));
1671 if (x_defined_color (f, SDATA (color_name), &color, 1))
1673 /* This isn't called frequently so we get away with simply
1674 reallocating the color vector to the needed size, here. */
1675 ++img->ncolors;
1676 img->colors =
1677 (unsigned long *) xrealloc (img->colors,
1678 img->ncolors * sizeof *img->colors);
1679 img->colors[img->ncolors - 1] = color.pixel;
1680 result = color.pixel;
1682 else
1683 result = dflt;
1685 return result;
1690 /***********************************************************************
1691 Image Cache
1692 ***********************************************************************/
1694 static struct image *search_image_cache P_ ((struct frame *, Lisp_Object, unsigned));
1695 static void cache_image P_ ((struct frame *f, struct image *img));
1696 static void postprocess_image P_ ((struct frame *, struct image *));
1698 /* Return a new, initialized image cache that is allocated from the
1699 heap. Call free_image_cache to free an image cache. */
1701 struct image_cache *
1702 make_image_cache ()
1704 struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
1705 int size;
1707 bzero (c, sizeof *c);
1708 c->size = 50;
1709 c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
1710 size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
1711 c->buckets = (struct image **) xmalloc (size);
1712 bzero (c->buckets, size);
1713 return c;
1717 /* Find an image matching SPEC in the cache, and return it. If no
1718 image is found, return NULL. */
1719 static struct image *
1720 search_image_cache (f, spec, hash)
1721 struct frame *f;
1722 Lisp_Object spec;
1723 unsigned hash;
1725 struct image *img;
1726 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1727 int i = hash % IMAGE_CACHE_BUCKETS_SIZE;
1729 if (!c) return NULL;
1731 /* If the image spec does not specify a background color, the cached
1732 image must have the same background color as the current frame.
1733 The foreground color must also match, for the sake of monochrome
1734 images.
1736 In fact, we could ignore the foreground color matching condition
1737 for color images, or if the image spec specifies :foreground;
1738 similarly we could ignore the background color matching condition
1739 for formats that don't use transparency (such as jpeg), or if the
1740 image spec specifies :background. However, the extra memory
1741 usage is probably negligible in practice, so we don't bother. */
1743 for (img = c->buckets[i]; img; img = img->next)
1744 if (img->hash == hash
1745 && !NILP (Fequal (img->spec, spec))
1746 && img->frame_foreground == FRAME_FOREGROUND_PIXEL (f)
1747 && img->frame_background == FRAME_BACKGROUND_PIXEL (f))
1748 break;
1749 return img;
1753 /* Search frame F for an image with spec SPEC, and free it. */
1755 static void
1756 uncache_image (f, spec)
1757 struct frame *f;
1758 Lisp_Object spec;
1760 struct image *img = search_image_cache (f, spec, sxhash (spec, 0));
1761 if (img)
1762 free_image (f, img);
1766 /* Free image cache of frame F. Be aware that X frames share images
1767 caches. */
1769 void
1770 free_image_cache (f)
1771 struct frame *f;
1773 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1774 if (c)
1776 int i;
1778 /* Cache should not be referenced by any frame when freed. */
1779 xassert (c->refcount == 0);
1781 for (i = 0; i < c->used; ++i)
1782 free_image (f, c->images[i]);
1783 xfree (c->images);
1784 xfree (c->buckets);
1785 xfree (c);
1786 FRAME_IMAGE_CACHE (f) = NULL;
1791 /* Clear image cache of frame F. FILTER=t means free all images.
1792 FILTER=nil means clear only images that haven't been
1793 displayed for some time.
1794 Else, only free the images which have FILTER in their `dependencies'.
1795 Should be called from time to time to reduce the number of loaded images.
1796 If image-cache-eviction-delay is non-nil, this frees images in the cache
1797 which weren't displayed for at least that many seconds. */
1799 void
1800 clear_image_cache (struct frame *f, Lisp_Object filter)
1802 struct image_cache *c = FRAME_IMAGE_CACHE (f);
1804 if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
1806 EMACS_TIME t;
1807 unsigned long old;
1808 int i, nfreed;
1810 EMACS_GET_TIME (t);
1811 old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
1813 /* Block input so that we won't be interrupted by a SIGIO
1814 while being in an inconsistent state. */
1815 BLOCK_INPUT;
1817 for (i = nfreed = 0; i < c->used; ++i)
1819 struct image *img = c->images[i];
1820 if (img != NULL
1821 && (NILP (filter) ? img->timestamp < old
1822 : (EQ (Qt, filter)
1823 || !NILP (Fmember (filter, img->dependencies)))))
1825 free_image (f, img);
1826 ++nfreed;
1830 /* We may be clearing the image cache because, for example,
1831 Emacs was iconified for a longer period of time. In that
1832 case, current matrices may still contain references to
1833 images freed above. So, clear these matrices. */
1834 if (nfreed)
1836 Lisp_Object tail, frame;
1838 FOR_EACH_FRAME (tail, frame)
1840 struct frame *f = XFRAME (frame);
1841 if (FRAME_IMAGE_CACHE (f) == c)
1842 clear_current_matrices (f);
1845 ++windows_or_buffers_changed;
1848 UNBLOCK_INPUT;
1852 void
1853 clear_image_caches (Lisp_Object filter)
1855 /* FIXME: We want to do
1856 * struct terminal *t;
1857 * for (t = terminal_list; t; t = t->next_terminal)
1858 * clear_image_cache (t, filter); */
1859 Lisp_Object tail, frame;
1860 FOR_EACH_FRAME (tail, frame)
1861 if (FRAME_WINDOW_P (XFRAME (frame)))
1862 clear_image_cache (XFRAME (frame), filter);
1865 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
1866 0, 1, 0,
1867 doc: /* Clear the image cache.
1868 FILTER nil or a frame means clear all images in the selected frame.
1869 FILTER t means clear the image caches of all frames.
1870 Anything else, means only clear those images which refer to FILTER,
1871 which is then usually a filename. */)
1872 (filter)
1873 Lisp_Object filter;
1875 if (!(EQ (filter, Qnil) || FRAMEP (filter)))
1876 clear_image_caches (filter);
1877 else
1878 clear_image_cache (check_x_frame (filter), Qt);
1880 return Qnil;
1884 DEFUN ("image-refresh", Fimage_refresh, Simage_refresh,
1885 1, 2, 0,
1886 doc: /* Refresh the image with specification SPEC on frame FRAME.
1887 If SPEC specifies an image file, the displayed image is updated with
1888 the current contents of that file.
1889 FRAME nil or omitted means use the selected frame.
1890 FRAME t means refresh the image on all frames. */)
1891 (spec, frame)
1892 Lisp_Object spec, frame;
1894 if (!valid_image_p (spec))
1895 error ("Invalid image specification");
1897 if (EQ (frame, Qt))
1899 Lisp_Object tail;
1900 FOR_EACH_FRAME (tail, frame)
1902 struct frame *f = XFRAME (frame);
1903 if (FRAME_WINDOW_P (f))
1904 uncache_image (f, spec);
1907 else
1908 uncache_image (check_x_frame (frame), spec);
1910 return Qnil;
1914 /* Compute masks and transform image IMG on frame F, as specified
1915 by the image's specification, */
1917 static void
1918 postprocess_image (f, img)
1919 struct frame *f;
1920 struct image *img;
1922 /* Manipulation of the image's mask. */
1923 if (img->pixmap)
1925 Lisp_Object conversion, spec;
1926 Lisp_Object mask;
1928 spec = img->spec;
1930 /* `:heuristic-mask t'
1931 `:mask heuristic'
1932 means build a mask heuristically.
1933 `:heuristic-mask (R G B)'
1934 `:mask (heuristic (R G B))'
1935 means build a mask from color (R G B) in the
1936 image.
1937 `:mask nil'
1938 means remove a mask, if any. */
1940 mask = image_spec_value (spec, QCheuristic_mask, NULL);
1941 if (!NILP (mask))
1942 x_build_heuristic_mask (f, img, mask);
1943 else
1945 int found_p;
1947 mask = image_spec_value (spec, QCmask, &found_p);
1949 if (EQ (mask, Qheuristic))
1950 x_build_heuristic_mask (f, img, Qt);
1951 else if (CONSP (mask)
1952 && EQ (XCAR (mask), Qheuristic))
1954 if (CONSP (XCDR (mask)))
1955 x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
1956 else
1957 x_build_heuristic_mask (f, img, XCDR (mask));
1959 else if (NILP (mask) && found_p && img->mask)
1961 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1962 img->mask = NO_PIXMAP;
1967 /* Should we apply an image transformation algorithm? */
1968 conversion = image_spec_value (spec, QCconversion, NULL);
1969 if (EQ (conversion, Qdisabled))
1970 x_disable_image (f, img);
1971 else if (EQ (conversion, Qlaplace))
1972 x_laplace (f, img);
1973 else if (EQ (conversion, Qemboss))
1974 x_emboss (f, img);
1975 else if (CONSP (conversion)
1976 && EQ (XCAR (conversion), Qedge_detection))
1978 Lisp_Object tem;
1979 tem = XCDR (conversion);
1980 if (CONSP (tem))
1981 x_edge_detection (f, img,
1982 Fplist_get (tem, QCmatrix),
1983 Fplist_get (tem, QCcolor_adjustment));
1989 /* Return the id of image with Lisp specification SPEC on frame F.
1990 SPEC must be a valid Lisp image specification (see valid_image_p). */
1993 lookup_image (f, spec)
1994 struct frame *f;
1995 Lisp_Object spec;
1997 struct image_cache *c;
1998 struct image *img;
1999 unsigned hash;
2000 struct gcpro gcpro1;
2001 EMACS_TIME now;
2003 /* F must be a window-system frame, and SPEC must be a valid image
2004 specification. */
2005 xassert (FRAME_WINDOW_P (f));
2006 xassert (valid_image_p (spec));
2008 c = FRAME_IMAGE_CACHE (f);
2010 GCPRO1 (spec);
2012 /* Look up SPEC in the hash table of the image cache. */
2013 hash = sxhash (spec, 0);
2014 img = search_image_cache (f, spec, hash);
2015 if (img && img->load_failed_p)
2017 free_image (f, img);
2018 img = NULL;
2021 /* If not found, create a new image and cache it. */
2022 if (img == NULL)
2024 extern Lisp_Object Qpostscript;
2026 BLOCK_INPUT;
2027 img = make_image (spec, hash);
2028 cache_image (f, img);
2029 img->load_failed_p = img->type->load (f, img) == 0;
2030 img->frame_foreground = FRAME_FOREGROUND_PIXEL (f);
2031 img->frame_background = FRAME_BACKGROUND_PIXEL (f);
2033 /* If we can't load the image, and we don't have a width and
2034 height, use some arbitrary width and height so that we can
2035 draw a rectangle for it. */
2036 if (img->load_failed_p)
2038 Lisp_Object value;
2040 value = image_spec_value (spec, QCwidth, NULL);
2041 img->width = (INTEGERP (value)
2042 ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
2043 value = image_spec_value (spec, QCheight, NULL);
2044 img->height = (INTEGERP (value)
2045 ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
2047 else
2049 /* Handle image type independent image attributes
2050 `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF',
2051 `:background COLOR'. */
2052 Lisp_Object ascent, margin, relief, bg;
2054 ascent = image_spec_value (spec, QCascent, NULL);
2055 if (INTEGERP (ascent))
2056 img->ascent = XFASTINT (ascent);
2057 else if (EQ (ascent, Qcenter))
2058 img->ascent = CENTERED_IMAGE_ASCENT;
2060 margin = image_spec_value (spec, QCmargin, NULL);
2061 if (INTEGERP (margin) && XINT (margin) >= 0)
2062 img->vmargin = img->hmargin = XFASTINT (margin);
2063 else if (CONSP (margin) && INTEGERP (XCAR (margin))
2064 && INTEGERP (XCDR (margin)))
2066 if (XINT (XCAR (margin)) > 0)
2067 img->hmargin = XFASTINT (XCAR (margin));
2068 if (XINT (XCDR (margin)) > 0)
2069 img->vmargin = XFASTINT (XCDR (margin));
2072 relief = image_spec_value (spec, QCrelief, NULL);
2073 if (INTEGERP (relief))
2075 img->relief = XINT (relief);
2076 img->hmargin += eabs (img->relief);
2077 img->vmargin += eabs (img->relief);
2080 if (! img->background_valid)
2082 bg = image_spec_value (img->spec, QCbackground, NULL);
2083 if (!NILP (bg))
2085 img->background
2086 = x_alloc_image_color (f, img, bg,
2087 FRAME_BACKGROUND_PIXEL (f));
2088 img->background_valid = 1;
2092 /* Do image transformations and compute masks, unless we
2093 don't have the image yet. */
2094 if (!EQ (*img->type->type, Qpostscript))
2095 postprocess_image (f, img);
2098 UNBLOCK_INPUT;
2101 /* We're using IMG, so set its timestamp to `now'. */
2102 EMACS_GET_TIME (now);
2103 img->timestamp = EMACS_SECS (now);
2105 UNGCPRO;
2107 /* Value is the image id. */
2108 return img->id;
2112 /* Cache image IMG in the image cache of frame F. */
2114 static void
2115 cache_image (f, img)
2116 struct frame *f;
2117 struct image *img;
2119 struct image_cache *c = FRAME_IMAGE_CACHE (f);
2120 int i;
2122 /* Find a free slot in c->images. */
2123 for (i = 0; i < c->used; ++i)
2124 if (c->images[i] == NULL)
2125 break;
2127 /* If no free slot found, maybe enlarge c->images. */
2128 if (i == c->used && c->used == c->size)
2130 c->size *= 2;
2131 c->images = (struct image **) xrealloc (c->images,
2132 c->size * sizeof *c->images);
2135 /* Add IMG to c->images, and assign IMG an id. */
2136 c->images[i] = img;
2137 img->id = i;
2138 if (i == c->used)
2139 ++c->used;
2141 /* Add IMG to the cache's hash table. */
2142 i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
2143 img->next = c->buckets[i];
2144 if (img->next)
2145 img->next->prev = img;
2146 img->prev = NULL;
2147 c->buckets[i] = img;
2151 /* Call FN on every image in the image cache of frame F. Used to mark
2152 Lisp Objects in the image cache. */
2154 /* Mark Lisp objects in image IMG. */
2156 static void
2157 mark_image (img)
2158 struct image *img;
2160 mark_object (img->spec);
2161 mark_object (img->dependencies);
2163 if (!NILP (img->data.lisp_val))
2164 mark_object (img->data.lisp_val);
2168 void
2169 mark_image_cache (struct image_cache *c)
2171 if (c)
2173 int i;
2174 for (i = 0; i < c->used; ++i)
2175 if (c->images[i])
2176 mark_image (c->images[i]);
2182 /***********************************************************************
2183 X / MAC / W32 support code
2184 ***********************************************************************/
2186 #ifdef HAVE_NTGUI
2188 /* Macro for defining functions that will be loaded from image DLLs. */
2189 #define DEF_IMGLIB_FN(func) int (FAR CDECL *fn_##func)()
2191 /* Macro for loading those image functions from the library. */
2192 #define LOAD_IMGLIB_FN(lib,func) { \
2193 fn_##func = (void *) GetProcAddress (lib, #func); \
2194 if (!fn_##func) return 0; \
2197 /* Load a DLL implementing an image type.
2198 The `image-library-alist' variable associates a symbol,
2199 identifying an image type, to a list of possible filenames.
2200 The function returns NULL if no library could be loaded for
2201 the given image type, or if the library was previously loaded;
2202 else the handle of the DLL. */
2203 static HMODULE
2204 w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
2206 HMODULE library = NULL;
2208 if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
2210 Lisp_Object dlls = Fassq (type, libraries);
2212 if (CONSP (dlls))
2213 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
2215 CHECK_STRING_CAR (dlls);
2216 if (library = LoadLibrary (SDATA (XCAR (dlls))))
2217 break;
2221 return library;
2224 #endif /* HAVE_NTGUI */
2226 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
2227 XImagePtr *, Pixmap *));
2228 static void x_destroy_x_image P_ ((XImagePtr));
2229 static void x_put_x_image P_ ((struct frame *, XImagePtr, Pixmap, int, int));
2232 /* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
2233 frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
2234 Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
2235 via xmalloc. Print error messages via image_error if an error
2236 occurs. Value is non-zero if successful.
2238 On W32, a DEPTH of zero signifies a 24 bit image, otherwise DEPTH
2239 should indicate the bit depth of the image. */
2241 static int
2242 x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2243 struct frame *f;
2244 int width, height, depth;
2245 XImagePtr *ximg;
2246 Pixmap *pixmap;
2248 #ifdef HAVE_X_WINDOWS
2249 Display *display = FRAME_X_DISPLAY (f);
2250 Window window = FRAME_X_WINDOW (f);
2251 Screen *screen = FRAME_X_SCREEN (f);
2253 xassert (interrupt_input_blocked);
2255 if (depth <= 0)
2256 depth = DefaultDepthOfScreen (screen);
2257 *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
2258 depth, ZPixmap, 0, NULL, width, height,
2259 depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
2260 if (*ximg == NULL)
2262 image_error ("Unable to allocate X image", Qnil, Qnil);
2263 return 0;
2266 /* Allocate image raster. */
2267 (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
2269 /* Allocate a pixmap of the same size. */
2270 *pixmap = XCreatePixmap (display, window, width, height, depth);
2271 if (*pixmap == NO_PIXMAP)
2273 x_destroy_x_image (*ximg);
2274 *ximg = NULL;
2275 image_error ("Unable to create X pixmap", Qnil, Qnil);
2276 return 0;
2279 return 1;
2280 #endif /* HAVE_X_WINDOWS */
2282 #ifdef HAVE_NTGUI
2284 BITMAPINFOHEADER *header;
2285 HDC hdc;
2286 int scanline_width_bits;
2287 int remainder;
2288 int palette_colors = 0;
2290 if (depth == 0)
2291 depth = 24;
2293 if (depth != 1 && depth != 4 && depth != 8
2294 && depth != 16 && depth != 24 && depth != 32)
2296 image_error ("Invalid image bit depth specified", Qnil, Qnil);
2297 return 0;
2300 scanline_width_bits = width * depth;
2301 remainder = scanline_width_bits % 32;
2303 if (remainder)
2304 scanline_width_bits += 32 - remainder;
2306 /* Bitmaps with a depth less than 16 need a palette. */
2307 /* BITMAPINFO structure already contains the first RGBQUAD. */
2308 if (depth < 16)
2309 palette_colors = 1 << depth - 1;
2311 *ximg = xmalloc (sizeof (XImage) + palette_colors * sizeof (RGBQUAD));
2312 if (*ximg == NULL)
2314 image_error ("Unable to allocate memory for XImage", Qnil, Qnil);
2315 return 0;
2318 header = &((*ximg)->info.bmiHeader);
2319 bzero (&((*ximg)->info), sizeof (BITMAPINFO));
2320 header->biSize = sizeof (*header);
2321 header->biWidth = width;
2322 header->biHeight = -height; /* negative indicates a top-down bitmap. */
2323 header->biPlanes = 1;
2324 header->biBitCount = depth;
2325 header->biCompression = BI_RGB;
2326 header->biClrUsed = palette_colors;
2328 /* TODO: fill in palette. */
2329 if (depth == 1)
2331 (*ximg)->info.bmiColors[0].rgbBlue = 0;
2332 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2333 (*ximg)->info.bmiColors[0].rgbRed = 0;
2334 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2335 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2336 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2337 (*ximg)->info.bmiColors[1].rgbRed = 255;
2338 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2341 hdc = get_frame_dc (f);
2343 /* Create a DIBSection and raster array for the bitmap,
2344 and store its handle in *pixmap. */
2345 *pixmap = CreateDIBSection (hdc, &((*ximg)->info),
2346 (depth < 16) ? DIB_PAL_COLORS : DIB_RGB_COLORS,
2347 /* casting avoids a GCC warning */
2348 (void **)&((*ximg)->data), NULL, 0);
2350 /* Realize display palette and garbage all frames. */
2351 release_frame_dc (f, hdc);
2353 if (*pixmap == NULL)
2355 DWORD err = GetLastError ();
2356 Lisp_Object errcode;
2357 /* All system errors are < 10000, so the following is safe. */
2358 XSETINT (errcode, (int) err);
2359 image_error ("Unable to create bitmap, error code %d", errcode, Qnil);
2360 x_destroy_x_image (*ximg);
2361 return 0;
2364 return 1;
2366 #endif /* HAVE_NTGUI */
2368 #ifdef MAC_OS
2369 Display *display = FRAME_X_DISPLAY (f);
2370 Window window = FRAME_X_WINDOW (f);
2372 xassert (interrupt_input_blocked);
2374 /* Allocate a pixmap of the same size. */
2375 *pixmap = XCreatePixmap (display, window, width, height, depth);
2376 if (*pixmap == NO_PIXMAP)
2378 *ximg = NULL;
2379 image_error ("Unable to create X pixmap", Qnil, Qnil);
2380 return 0;
2383 #if !USE_MAC_IMAGE_IO
2384 LockPixels (GetGWorldPixMap (*pixmap));
2385 #endif
2386 *ximg = *pixmap;
2387 return 1;
2389 #endif /* MAC_OS */
2393 /* Destroy XImage XIMG. Free XIMG->data. */
2395 static void
2396 x_destroy_x_image (ximg)
2397 XImagePtr ximg;
2399 xassert (interrupt_input_blocked);
2400 if (ximg)
2402 #ifdef HAVE_X_WINDOWS
2403 xfree (ximg->data);
2404 ximg->data = NULL;
2405 XDestroyImage (ximg);
2406 #endif /* HAVE_X_WINDOWS */
2407 #ifdef HAVE_NTGUI
2408 /* Data will be freed by DestroyObject. */
2409 ximg->data = NULL;
2410 xfree (ximg);
2411 #endif /* HAVE_NTGUI */
2412 #ifdef MAC_OS
2413 XDestroyImage (ximg);
2414 #endif /* MAC_OS */
2419 /* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
2420 are width and height of both the image and pixmap. */
2422 static void
2423 x_put_x_image (f, ximg, pixmap, width, height)
2424 struct frame *f;
2425 XImagePtr ximg;
2426 Pixmap pixmap;
2427 int width, height;
2429 #ifdef HAVE_X_WINDOWS
2430 GC gc;
2432 xassert (interrupt_input_blocked);
2433 gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
2434 XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
2435 XFreeGC (FRAME_X_DISPLAY (f), gc);
2436 #endif /* HAVE_X_WINDOWS */
2438 #ifdef HAVE_NTGUI
2439 #if 0 /* I don't think this is necessary looking at where it is used. */
2440 HDC hdc = get_frame_dc (f);
2441 SetDIBits (hdc, pixmap, 0, height, ximg->data, &(ximg->info), DIB_RGB_COLORS);
2442 release_frame_dc (f, hdc);
2443 #endif
2444 #endif /* HAVE_NTGUI */
2446 #ifdef MAC_OS
2447 xassert (ximg == pixmap);
2448 #endif /* MAC_OS */
2452 /***********************************************************************
2453 File Handling
2454 ***********************************************************************/
2456 static unsigned char *slurp_file P_ ((char *, int *));
2459 /* Find image file FILE. Look in data-directory/images, then
2460 x-bitmap-file-path. Value is the encoded full name of the file
2461 found, or nil if not found. */
2463 Lisp_Object
2464 x_find_image_file (file)
2465 Lisp_Object file;
2467 Lisp_Object file_found, search_path;
2468 struct gcpro gcpro1, gcpro2;
2469 int fd;
2471 file_found = Qnil;
2472 /* TODO I think this should use something like image-load-path
2473 instead. Unfortunately, that can contain non-string elements. */
2474 search_path = Fcons (Fexpand_file_name (build_string ("images"),
2475 Vdata_directory),
2476 Vx_bitmap_file_path);
2477 GCPRO2 (file_found, search_path);
2479 /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */
2480 fd = openp (search_path, file, Qnil, &file_found, Qnil);
2482 if (fd == -1)
2483 file_found = Qnil;
2484 else
2486 file_found = ENCODE_FILE (file_found);
2487 close (fd);
2490 UNGCPRO;
2491 return file_found;
2495 /* Read FILE into memory. Value is a pointer to a buffer allocated
2496 with xmalloc holding FILE's contents. Value is null if an error
2497 occurred. *SIZE is set to the size of the file. */
2499 static unsigned char *
2500 slurp_file (file, size)
2501 char *file;
2502 int *size;
2504 FILE *fp = NULL;
2505 unsigned char *buf = NULL;
2506 struct stat st;
2508 if (stat (file, &st) == 0
2509 && (fp = fopen (file, "rb")) != NULL
2510 && (buf = (unsigned char *) xmalloc (st.st_size),
2511 fread (buf, 1, st.st_size, fp) == st.st_size))
2513 *size = st.st_size;
2514 fclose (fp);
2516 else
2518 if (fp)
2519 fclose (fp);
2520 if (buf)
2522 xfree (buf);
2523 buf = NULL;
2527 return buf;
2532 #ifdef MAC_OS
2534 /***********************************************************************
2535 MAC Image Load Functions
2536 ***********************************************************************/
2538 #if USE_MAC_IMAGE_IO
2539 static int
2540 image_load_image_io (f, img, type)
2541 struct frame *f;
2542 struct image *img;
2543 CFStringRef type;
2545 CFDictionaryRef options, src_props = NULL, props = NULL;
2546 CFStringRef keys[2];
2547 CFTypeRef values[2];
2548 Lisp_Object specified_file, specified_data;
2549 CGImageSourceRef source = NULL;
2550 size_t count;
2551 CGImageRef image = NULL;
2552 int loop_count = -1;
2553 double delay_time = -1.0;
2554 int width, height;
2555 XImagePtr ximg = NULL;
2556 CGContextRef context;
2557 CGRect rectangle;
2558 int has_alpha_p, gif_p;
2560 gif_p = UTTypeEqual (type, kUTTypeGIF);
2562 keys[0] = kCGImageSourceTypeIdentifierHint;
2563 values[0] = (CFTypeRef) type;
2564 keys[1] = kCGImageSourceShouldCache;
2565 values[1] = (CFTypeRef) kCFBooleanFalse;
2566 options = CFDictionaryCreate (NULL, (const void **) keys,
2567 (const void **) values,
2568 sizeof (keys) / sizeof (keys[0]),
2569 &kCFTypeDictionaryKeyCallBacks,
2570 &kCFTypeDictionaryValueCallBacks);
2571 if (options == NULL)
2573 image_error ("Error creating options for image `%s'", img->spec, Qnil);
2574 return 0;
2577 /* Open the file. */
2578 specified_file = image_spec_value (img->spec, QCfile, NULL);
2579 specified_data = image_spec_value (img->spec, QCdata, NULL);
2581 if (NILP (specified_data))
2583 Lisp_Object file;
2584 CFStringRef path;
2585 CFURLRef url;
2587 file = x_find_image_file (specified_file);
2588 if (!STRINGP (file))
2590 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2591 return 0;
2593 path = cfstring_create_with_utf8_cstring (SDATA (file));
2594 if (path)
2596 url = CFURLCreateWithFileSystemPath (NULL, path,
2597 kCFURLPOSIXPathStyle, 0);
2598 CFRelease (path);
2599 if (url)
2601 source = CGImageSourceCreateWithURL (url, NULL);
2602 CFRelease (url);
2606 else
2608 CFDataRef data = CFDataCreate (NULL, SDATA (specified_data),
2609 SBYTES (specified_data));
2611 if (data)
2613 source = CGImageSourceCreateWithData (data, options);
2614 CFRelease (data);
2617 CFRelease (options);
2619 if (source)
2621 CFStringRef real_type = CGImageSourceGetType (source);
2623 if (real_type && UTTypeEqual (type, real_type))
2624 src_props = CGImageSourceCopyProperties (source, NULL);
2625 if (src_props)
2627 EMACS_INT ino = 0;
2629 count = CGImageSourceGetCount (source);
2630 if (gif_p)
2632 Lisp_Object image = image_spec_value (img->spec, QCindex, NULL);
2634 if (INTEGERP (image))
2635 ino = XFASTINT (image);
2637 if (ino >= 0 && ino < count)
2639 props = CGImageSourceCopyPropertiesAtIndex (source, ino, NULL);
2640 if (props)
2641 image = CGImageSourceCreateImageAtIndex (source, ino, NULL);
2644 CFRelease (source);
2647 if (image == NULL)
2649 if (src_props)
2650 CFRelease (src_props);
2651 if (props)
2652 CFRelease (props);
2653 image_error ("Error reading image `%s'", img->spec, Qnil);
2654 return 0;
2656 else
2658 CFBooleanRef boolean;
2660 if (CFDictionaryGetValueIfPresent (props, kCGImagePropertyHasAlpha,
2661 (const void **) &boolean))
2662 has_alpha_p = CFBooleanGetValue (boolean);
2663 if (gif_p)
2665 CFDictionaryRef dict;
2666 CFNumberRef number;
2668 dict = CFDictionaryGetValue (src_props,
2669 kCGImagePropertyGIFDictionary);
2670 if (dict
2671 && CFDictionaryGetValueIfPresent (dict,
2672 kCGImagePropertyGIFLoopCount,
2673 (const void **) &number))
2674 CFNumberGetValue (number, kCFNumberIntType, &loop_count);
2676 dict = CFDictionaryGetValue (props, kCGImagePropertyGIFDictionary);
2677 if (dict
2678 && CFDictionaryGetValueIfPresent (dict,
2679 kCGImagePropertyGIFDelayTime,
2680 (const void **) &number))
2681 CFNumberGetValue (number, kCFNumberDoubleType, &delay_time);
2683 CFRelease (src_props);
2684 CFRelease (props);
2687 width = img->width = CGImageGetWidth (image);
2688 height = img->height = CGImageGetHeight (image);
2690 if (!check_image_size (f, width, height))
2692 CGImageRelease (image);
2693 image_error ("Invalid image size", Qnil, Qnil);
2694 return 0;
2697 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2699 CGImageRelease (image);
2700 image_error ("Out of memory (%s)", img->spec, Qnil);
2701 return 0;
2703 rectangle = CGRectMake (0, 0, width, height);
2705 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
2706 ximg->bytes_per_line,
2707 mac_cg_color_space_rgb,
2708 kCGImageAlphaNoneSkipFirst
2709 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
2710 | kCGBitmapByteOrder32Host
2711 #endif
2713 if (has_alpha_p)
2715 Lisp_Object specified_bg;
2716 XColor color;
2718 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2719 if (!STRINGP (specified_bg)
2720 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2722 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2723 color.red = RED16_FROM_ULONG (color.pixel);
2724 color.green = GREEN16_FROM_ULONG (color.pixel);
2725 color.blue = BLUE16_FROM_ULONG (color.pixel);
2727 CGContextSetRGBFillColor (context, color.red / 65535.0,
2728 color.green / 65535.0,
2729 color.blue / 65535.0, 1.0);
2730 CGContextFillRect (context, rectangle);
2732 CGContextDrawImage (context, rectangle, image);
2733 CGContextRelease (context);
2734 CGImageRelease (image);
2736 /* Save GIF image extension data for `image-extension-data'.
2737 Format is (count IMAGES
2738 0xff "NETSCAPE2.0" 0x00 DATA_SUB_BLOCK_FOR_LOOP_COUNT
2739 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
2740 if (gif_p)
2742 img->data.lisp_val = Qnil;
2743 if (delay_time >= 0)
2745 Lisp_Object gce = make_uninit_string (4);
2746 int centisec = delay_time * 100.0 + 0.5;
2748 /* Fill the delay time field. */
2749 SSET (gce, 1, centisec & 0xff);
2750 SSET (gce, 2, (centisec >> 8) & 0xff);
2751 /* We don't know about other fields. */
2752 SSET (gce, 0, 0);
2753 SSET (gce, 3, 0);
2754 img->data.lisp_val = Fcons (make_number (0xf9),
2755 Fcons (gce,
2756 img->data.lisp_val));
2758 if (loop_count >= 0)
2760 Lisp_Object data_sub_block = make_uninit_string (3);
2762 SSET (data_sub_block, 0, 0x01);
2763 SSET (data_sub_block, 1, loop_count & 0xff);
2764 SSET (data_sub_block, 2, (loop_count >> 8) & 0xff);
2765 img->data.lisp_val = Fcons (make_number (0),
2766 Fcons (data_sub_block,
2767 img->data.lisp_val));
2768 img->data.lisp_val = Fcons (make_number (0xff),
2769 Fcons (build_string ("NETSCAPE2.0"),
2770 img->data.lisp_val));
2772 if (count > 1)
2773 img->data.lisp_val = Fcons (Qcount,
2774 Fcons (make_number (count),
2775 img->data.lisp_val));
2778 /* Maybe fill in the background field while we have ximg handy. */
2779 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2780 IMAGE_BACKGROUND (img, f, ximg);
2782 /* Put the image into the pixmap. */
2783 x_put_x_image (f, ximg, img->pixmap, width, height);
2784 x_destroy_x_image (ximg);
2785 return 1;
2787 #else /* !USE_MAC_IMAGE_IO */
2788 static int image_load_quicktime P_ ((struct frame *, struct image *img,
2789 OSType));
2790 #ifdef MAC_OSX
2791 static int image_load_quartz2d P_ ((struct frame *, struct image *img, int));
2792 #endif
2794 static OSErr
2795 find_image_fsspec (specified_file, file, fss)
2796 Lisp_Object specified_file, *file;
2797 FSSpec *fss;
2799 OSErr err;
2800 AEDesc desc;
2802 *file = x_find_image_file (specified_file);
2803 if (!STRINGP (*file))
2804 return fnfErr; /* file or directory not found;
2805 incomplete pathname */
2806 /* Try to open the image file. */
2807 err = AECoercePtr (TYPE_FILE_NAME, SDATA (*file),
2808 SBYTES (*file), typeFSS, &desc);
2809 if (err == noErr)
2811 #if TARGET_API_MAC_CARBON
2812 err = AEGetDescData (&desc, fss, sizeof (FSSpec));
2813 #else
2814 *fss = *(FSSpec *)(*(desc.dataHandle));
2815 #endif
2816 AEDisposeDesc (&desc);
2818 return err;
2821 static int
2822 image_load_qt_1 (f, img, type, fss, dh)
2823 struct frame *f;
2824 struct image *img;
2825 OSType type;
2826 const FSSpec *fss;
2827 Handle dh;
2829 ComponentResult err;
2830 GraphicsImportComponent gi;
2831 Rect rect;
2832 int width, height;
2833 ImageDescriptionHandle desc_handle;
2834 short draw_all_pixels;
2835 Lisp_Object specified_bg;
2836 XColor color;
2837 XImagePtr ximg;
2838 RGBColor bg_color;
2840 err = OpenADefaultComponent (GraphicsImporterComponentType, type, &gi);
2841 if (err != noErr)
2843 image_error ("Cannot get importer component for `%s'", img->spec, Qnil);
2844 return 0;
2846 if (dh == NULL)
2848 /* read from file system spec */
2849 err = GraphicsImportSetDataFile (gi, fss);
2850 if (err != noErr)
2852 image_error ("Cannot set fsspec to graphics importer for '%s'",
2853 img->spec, Qnil);
2854 goto error;
2857 else
2859 /* read from data handle */
2860 err = GraphicsImportSetDataHandle (gi, dh);
2861 if (err != noErr)
2863 image_error ("Cannot set data handle to graphics importer for `%s'",
2864 img->spec, Qnil);
2865 goto error;
2868 err = GraphicsImportGetImageDescription (gi, &desc_handle);
2869 if (err != noErr || desc_handle == NULL)
2871 image_error ("Error reading `%s'", img->spec, Qnil);
2872 goto error;
2874 width = img->width = (*desc_handle)->width;
2875 height = img->height = (*desc_handle)->height;
2876 DisposeHandle ((Handle)desc_handle);
2878 if (!check_image_size (f, width, height))
2880 image_error ("Invalid image size", Qnil, Qnil);
2881 goto error;
2884 err = GraphicsImportDoesDrawAllPixels (gi, &draw_all_pixels);
2885 #if 0
2886 /* Don't check the error code here. It may have an undocumented
2887 value -32766. */
2888 if (err != noErr)
2890 image_error ("Error reading `%s'", img->spec, Qnil);
2891 goto error;
2893 #endif
2894 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2896 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
2897 if (!STRINGP (specified_bg) ||
2898 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
2900 color.pixel = FRAME_BACKGROUND_PIXEL (f);
2901 color.red = RED16_FROM_ULONG (color.pixel);
2902 color.green = GREEN16_FROM_ULONG (color.pixel);
2903 color.blue = BLUE16_FROM_ULONG (color.pixel);
2907 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
2908 goto error;
2909 if (draw_all_pixels != graphicsImporterDrawsAllPixels)
2911 CGrafPtr old_port;
2912 GDHandle old_gdh;
2914 GetGWorld (&old_port, &old_gdh);
2915 SetGWorld (ximg, NULL);
2916 bg_color.red = color.red;
2917 bg_color.green = color.green;
2918 bg_color.blue = color.blue;
2919 RGBBackColor (&bg_color);
2920 #if TARGET_API_MAC_CARBON
2921 GetPortBounds (ximg, &rect);
2922 EraseRect (&rect);
2923 #else
2924 EraseRect (&(ximg->portRect));
2925 #endif
2926 SetGWorld (old_port, old_gdh);
2928 GraphicsImportSetGWorld (gi, ximg, NULL);
2929 GraphicsImportDraw (gi);
2930 CloseComponent (gi);
2932 /* Maybe fill in the background field while we have ximg handy. */
2933 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
2934 IMAGE_BACKGROUND (img, f, ximg);
2936 /* Put the image into the pixmap. */
2937 x_put_x_image (f, ximg, img->pixmap, width, height);
2938 x_destroy_x_image (ximg);
2939 return 1;
2941 error:
2942 CloseComponent (gi);
2943 return 0;
2947 /* Load an image using the QuickTime Graphics Importer.
2948 Note: The alpha channel does not work for PNG images. */
2949 static int
2950 image_load_quicktime (f, img, type)
2951 struct frame *f;
2952 struct image *img;
2953 OSType type;
2955 Lisp_Object specified_file;
2956 Lisp_Object specified_data;
2957 OSErr err;
2959 specified_file = image_spec_value (img->spec, QCfile, NULL);
2960 specified_data = image_spec_value (img->spec, QCdata, NULL);
2962 if (NILP (specified_data))
2964 /* Read from a file */
2965 Lisp_Object file;
2966 FSSpec fss;
2968 err = find_image_fsspec (specified_file, &file, &fss);
2969 if (err != noErr)
2971 if (err == fnfErr)
2972 image_error ("Cannot find image file `%s'", specified_file, Qnil);
2973 else
2974 image_error ("Cannot open `%s'", file, Qnil);
2975 return 0;
2977 return image_load_qt_1 (f, img, type, &fss, NULL);
2979 else
2981 /* Memory source! */
2982 int success_p;
2983 Handle dh;
2985 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
2986 if (err != noErr)
2988 image_error ("Cannot allocate data handle for `%s'",
2989 img->spec, Qnil);
2990 return 0;
2992 success_p = image_load_qt_1 (f, img, type, NULL, dh);
2993 DisposeHandle (dh);
2994 return success_p;
2999 #ifdef MAC_OSX
3000 static int
3001 image_load_quartz2d (f, img, png_p)
3002 struct frame *f;
3003 struct image *img;
3004 int png_p;
3006 Lisp_Object file, specified_file;
3007 Lisp_Object specified_data, specified_bg;
3008 struct gcpro gcpro1;
3009 CGDataProviderRef source;
3010 CGImageRef image;
3011 int width, height;
3012 XColor color;
3013 XImagePtr ximg = NULL;
3014 CGContextRef context;
3015 CGRect rectangle;
3017 /* Open the file. */
3018 specified_file = image_spec_value (img->spec, QCfile, NULL);
3019 specified_data = image_spec_value (img->spec, QCdata, NULL);
3021 file = Qnil;
3022 GCPRO1 (file);
3024 if (NILP (specified_data))
3026 CFStringRef path;
3027 CFURLRef url;
3029 file = x_find_image_file (specified_file);
3030 if (!STRINGP (file))
3032 image_error ("Cannot find image file `%s'", specified_file, Qnil);
3033 UNGCPRO;
3034 return 0;
3036 path = cfstring_create_with_utf8_cstring (SDATA (file));
3037 url = CFURLCreateWithFileSystemPath (NULL, path,
3038 kCFURLPOSIXPathStyle, 0);
3039 CFRelease (path);
3040 source = CGDataProviderCreateWithURL (url);
3041 CFRelease (url);
3043 else
3044 source = CGDataProviderCreateWithData (NULL, SDATA (specified_data),
3045 SBYTES (specified_data), NULL);
3047 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
3048 if (png_p)
3049 image = CGImageCreateWithPNGDataProvider (source, NULL, false,
3050 kCGRenderingIntentDefault);
3051 else
3052 #endif
3053 image = CGImageCreateWithJPEGDataProvider (source, NULL, false,
3054 kCGRenderingIntentDefault);
3056 CGDataProviderRelease (source);
3057 if (image == NULL)
3059 UNGCPRO;
3060 image_error ("Error reading image `%s'", img->spec, Qnil);
3061 return 0;
3063 width = img->width = CGImageGetWidth (image);
3064 height = img->height = CGImageGetHeight (image);
3066 if (!check_image_size (f, width, height))
3068 CGImageRelease (image);
3069 UNGCPRO;
3070 image_error ("Invalid image size", Qnil, Qnil);
3071 return 0;
3074 if (png_p)
3076 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
3077 if (!STRINGP (specified_bg) ||
3078 !mac_defined_color (f, SDATA (specified_bg), &color, 0))
3080 color.pixel = FRAME_BACKGROUND_PIXEL (f);
3081 color.red = RED16_FROM_ULONG (color.pixel);
3082 color.green = GREEN16_FROM_ULONG (color.pixel);
3083 color.blue = BLUE16_FROM_ULONG (color.pixel);
3087 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
3089 CGImageRelease (image);
3090 UNGCPRO;
3091 return 0;
3093 rectangle = CGRectMake (0, 0, width, height);
3094 QDBeginCGContext (ximg, &context);
3095 if (png_p)
3097 CGContextSetRGBFillColor (context, color.red / 65535.0,
3098 color.green / 65535.0,
3099 color.blue / 65535.0, 1.0);
3100 CGContextFillRect (context, rectangle);
3102 CGContextDrawImage (context, rectangle, image);
3103 QDEndCGContext (ximg, &context);
3104 CGImageRelease (image);
3106 /* Maybe fill in the background field while we have ximg handy. */
3107 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3108 IMAGE_BACKGROUND (img, f, ximg);
3110 /* Put the image into the pixmap. */
3111 x_put_x_image (f, ximg, img->pixmap, width, height);
3112 x_destroy_x_image (ximg);
3113 UNGCPRO;
3114 return 1;
3116 #endif
3117 #endif /* !USE_MAC_IMAGE_IO */
3119 #endif /* MAC_OS */
3122 /***********************************************************************
3123 XBM images
3124 ***********************************************************************/
3126 static int xbm_scan P_ ((unsigned char **, unsigned char *, char *, int *));
3127 static int xbm_load P_ ((struct frame *f, struct image *img));
3128 static int xbm_load_image P_ ((struct frame *f, struct image *img,
3129 unsigned char *, unsigned char *));
3130 static int xbm_image_p P_ ((Lisp_Object object));
3131 static int xbm_read_bitmap_data P_ ((struct frame *f,
3132 unsigned char *, unsigned char *,
3133 int *, int *, unsigned char **));
3134 static int xbm_file_p P_ ((Lisp_Object));
3137 /* Indices of image specification fields in xbm_format, below. */
3139 enum xbm_keyword_index
3141 XBM_TYPE,
3142 XBM_FILE,
3143 XBM_WIDTH,
3144 XBM_HEIGHT,
3145 XBM_DATA,
3146 XBM_FOREGROUND,
3147 XBM_BACKGROUND,
3148 XBM_ASCENT,
3149 XBM_MARGIN,
3150 XBM_RELIEF,
3151 XBM_ALGORITHM,
3152 XBM_HEURISTIC_MASK,
3153 XBM_MASK,
3154 XBM_LAST
3157 /* Vector of image_keyword structures describing the format
3158 of valid XBM image specifications. */
3160 static struct image_keyword xbm_format[XBM_LAST] =
3162 {":type", IMAGE_SYMBOL_VALUE, 1},
3163 {":file", IMAGE_STRING_VALUE, 0},
3164 {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3165 {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
3166 {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3167 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
3168 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
3169 {":ascent", IMAGE_ASCENT_VALUE, 0},
3170 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3171 {":relief", IMAGE_INTEGER_VALUE, 0},
3172 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3173 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3174 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
3177 /* Structure describing the image type XBM. */
3179 static struct image_type xbm_type =
3181 &Qxbm,
3182 xbm_image_p,
3183 xbm_load,
3184 x_clear_image,
3185 NULL
3188 /* Tokens returned from xbm_scan. */
3190 enum xbm_token
3192 XBM_TK_IDENT = 256,
3193 XBM_TK_NUMBER
3197 /* Return non-zero if OBJECT is a valid XBM-type image specification.
3198 A valid specification is a list starting with the symbol `image'
3199 The rest of the list is a property list which must contain an
3200 entry `:type xbm..
3202 If the specification specifies a file to load, it must contain
3203 an entry `:file FILENAME' where FILENAME is a string.
3205 If the specification is for a bitmap loaded from memory it must
3206 contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
3207 WIDTH and HEIGHT are integers > 0. DATA may be:
3209 1. a string large enough to hold the bitmap data, i.e. it must
3210 have a size >= (WIDTH + 7) / 8 * HEIGHT
3212 2. a bool-vector of size >= WIDTH * HEIGHT
3214 3. a vector of strings or bool-vectors, one for each line of the
3215 bitmap.
3217 4. a string containing an in-memory XBM file. WIDTH and HEIGHT
3218 may not be specified in this case because they are defined in the
3219 XBM file.
3221 Both the file and data forms may contain the additional entries
3222 `:background COLOR' and `:foreground COLOR'. If not present,
3223 foreground and background of the frame on which the image is
3224 displayed is used. */
3226 static int
3227 xbm_image_p (object)
3228 Lisp_Object object;
3230 struct image_keyword kw[XBM_LAST];
3232 bcopy (xbm_format, kw, sizeof kw);
3233 if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
3234 return 0;
3236 xassert (EQ (kw[XBM_TYPE].value, Qxbm));
3238 if (kw[XBM_FILE].count)
3240 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
3241 return 0;
3243 else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value))
3245 /* In-memory XBM file. */
3246 if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count)
3247 return 0;
3249 else
3251 Lisp_Object data;
3252 int width, height;
3254 /* Entries for `:width', `:height' and `:data' must be present. */
3255 if (!kw[XBM_WIDTH].count
3256 || !kw[XBM_HEIGHT].count
3257 || !kw[XBM_DATA].count)
3258 return 0;
3260 data = kw[XBM_DATA].value;
3261 width = XFASTINT (kw[XBM_WIDTH].value);
3262 height = XFASTINT (kw[XBM_HEIGHT].value);
3264 /* Check type of data, and width and height against contents of
3265 data. */
3266 if (VECTORP (data))
3268 int i;
3270 /* Number of elements of the vector must be >= height. */
3271 if (XVECTOR (data)->size < height)
3272 return 0;
3274 /* Each string or bool-vector in data must be large enough
3275 for one line of the image. */
3276 for (i = 0; i < height; ++i)
3278 Lisp_Object elt = XVECTOR (data)->contents[i];
3280 if (STRINGP (elt))
3282 if (SCHARS (elt)
3283 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
3284 return 0;
3286 else if (BOOL_VECTOR_P (elt))
3288 if (XBOOL_VECTOR (elt)->size < width)
3289 return 0;
3291 else
3292 return 0;
3295 else if (STRINGP (data))
3297 if (SCHARS (data)
3298 < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
3299 return 0;
3301 else if (BOOL_VECTOR_P (data))
3303 if (XBOOL_VECTOR (data)->size < width * height)
3304 return 0;
3306 else
3307 return 0;
3310 return 1;
3314 /* Scan a bitmap file. FP is the stream to read from. Value is
3315 either an enumerator from enum xbm_token, or a character for a
3316 single-character token, or 0 at end of file. If scanning an
3317 identifier, store the lexeme of the identifier in SVAL. If
3318 scanning a number, store its value in *IVAL. */
3320 static int
3321 xbm_scan (s, end, sval, ival)
3322 unsigned char **s, *end;
3323 char *sval;
3324 int *ival;
3326 unsigned int c;
3328 loop:
3330 /* Skip white space. */
3331 while (*s < end && (c = *(*s)++, isspace (c)))
3334 if (*s >= end)
3335 c = 0;
3336 else if (isdigit (c))
3338 int value = 0, digit;
3340 if (c == '0' && *s < end)
3342 c = *(*s)++;
3343 if (c == 'x' || c == 'X')
3345 while (*s < end)
3347 c = *(*s)++;
3348 if (isdigit (c))
3349 digit = c - '0';
3350 else if (c >= 'a' && c <= 'f')
3351 digit = c - 'a' + 10;
3352 else if (c >= 'A' && c <= 'F')
3353 digit = c - 'A' + 10;
3354 else
3355 break;
3356 value = 16 * value + digit;
3359 else if (isdigit (c))
3361 value = c - '0';
3362 while (*s < end
3363 && (c = *(*s)++, isdigit (c)))
3364 value = 8 * value + c - '0';
3367 else
3369 value = c - '0';
3370 while (*s < end
3371 && (c = *(*s)++, isdigit (c)))
3372 value = 10 * value + c - '0';
3375 if (*s < end)
3376 *s = *s - 1;
3377 *ival = value;
3378 c = XBM_TK_NUMBER;
3380 else if (isalpha (c) || c == '_')
3382 *sval++ = c;
3383 while (*s < end
3384 && (c = *(*s)++, (isalnum (c) || c == '_')))
3385 *sval++ = c;
3386 *sval = 0;
3387 if (*s < end)
3388 *s = *s - 1;
3389 c = XBM_TK_IDENT;
3391 else if (c == '/' && **s == '*')
3393 /* C-style comment. */
3394 ++*s;
3395 while (**s && (**s != '*' || *(*s + 1) != '/'))
3396 ++*s;
3397 if (**s)
3399 *s += 2;
3400 goto loop;
3404 return c;
3407 #ifdef HAVE_NTGUI
3409 /* Create a Windows bitmap from X bitmap data. */
3410 static HBITMAP
3411 w32_create_pixmap_from_bitmap_data (int width, int height, char *data)
3413 static unsigned char swap_nibble[16]
3414 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
3415 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
3416 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
3417 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
3418 int i, j, w1, w2;
3419 unsigned char *bits, *p;
3420 HBITMAP bmp;
3422 w1 = (width + 7) / 8; /* nb of 8bits elt in X bitmap */
3423 w2 = ((width + 15) / 16) * 2; /* nb of 16bits elt in W32 bitmap */
3424 bits = (unsigned char *) alloca (height * w2);
3425 bzero (bits, height * w2);
3426 for (i = 0; i < height; i++)
3428 p = bits + i*w2;
3429 for (j = 0; j < w1; j++)
3431 /* Bitswap XBM bytes to match how Windows does things. */
3432 unsigned char c = *data++;
3433 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
3434 | (swap_nibble[(c>>4) & 0xf]));
3437 bmp = CreateBitmap (width, height, 1, 1, (char *) bits);
3439 return bmp;
3442 static void
3443 convert_mono_to_color_image (f, img, foreground, background)
3444 struct frame *f;
3445 struct image *img;
3446 COLORREF foreground, background;
3448 HDC hdc, old_img_dc, new_img_dc;
3449 HGDIOBJ old_prev, new_prev;
3450 HBITMAP new_pixmap;
3452 hdc = get_frame_dc (f);
3453 old_img_dc = CreateCompatibleDC (hdc);
3454 new_img_dc = CreateCompatibleDC (hdc);
3455 new_pixmap = CreateCompatibleBitmap (hdc, img->width, img->height);
3456 release_frame_dc (f, hdc);
3457 old_prev = SelectObject (old_img_dc, img->pixmap);
3458 new_prev = SelectObject (new_img_dc, new_pixmap);
3459 /* Windows convention for mono bitmaps is black = background,
3460 white = foreground. */
3461 SetTextColor (new_img_dc, background);
3462 SetBkColor (new_img_dc, foreground);
3464 BitBlt (new_img_dc, 0, 0, img->width, img->height, old_img_dc,
3465 0, 0, SRCCOPY);
3467 SelectObject (old_img_dc, old_prev);
3468 SelectObject (new_img_dc, new_prev);
3469 DeleteDC (old_img_dc);
3470 DeleteDC (new_img_dc);
3471 DeleteObject (img->pixmap);
3472 if (new_pixmap == 0)
3473 fprintf (stderr, "Failed to convert image to color.\n");
3474 else
3475 img->pixmap = new_pixmap;
3478 #define XBM_BIT_SHUFFLE(b) (~(b))
3480 #else
3482 #define XBM_BIT_SHUFFLE(b) (b)
3484 #endif /* HAVE_NTGUI */
3487 static void
3488 Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
3489 struct frame *f;
3490 struct image *img;
3491 char *data;
3492 RGB_PIXEL_COLOR fg, bg;
3493 int non_default_colors;
3495 #ifdef HAVE_NTGUI
3496 img->pixmap
3497 = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
3499 /* If colors were specified, transfer the bitmap to a color one. */
3500 if (non_default_colors)
3501 convert_mono_to_color_image (f, img, fg, bg);
3502 #else
3503 img->pixmap
3504 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
3505 FRAME_X_WINDOW (f),
3506 data,
3507 img->width, img->height,
3508 fg, bg,
3509 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3510 #endif /* HAVE_NTGUI */
3515 /* Replacement for XReadBitmapFileData which isn't available under old
3516 X versions. CONTENTS is a pointer to a buffer to parse; END is the
3517 buffer's end. Set *WIDTH and *HEIGHT to the width and height of
3518 the image. Return in *DATA the bitmap data allocated with xmalloc.
3519 Value is non-zero if successful. DATA null means just test if
3520 CONTENTS looks like an in-memory XBM file. */
3522 static int
3523 xbm_read_bitmap_data (f, contents, end, width, height, data)
3524 struct frame *f;
3525 unsigned char *contents, *end;
3526 int *width, *height;
3527 unsigned char **data;
3529 unsigned char *s = contents;
3530 char buffer[BUFSIZ];
3531 int padding_p = 0;
3532 int v10 = 0;
3533 int bytes_per_line, i, nbytes;
3534 unsigned char *p;
3535 int value;
3536 int LA1;
3538 #define match() \
3539 LA1 = xbm_scan (&s, end, buffer, &value)
3541 #define expect(TOKEN) \
3542 if (LA1 != (TOKEN)) \
3543 goto failure; \
3544 else \
3545 match ()
3547 #define expect_ident(IDENT) \
3548 if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
3549 match (); \
3550 else \
3551 goto failure
3553 *width = *height = -1;
3554 if (data)
3555 *data = NULL;
3556 LA1 = xbm_scan (&s, end, buffer, &value);
3558 /* Parse defines for width, height and hot-spots. */
3559 while (LA1 == '#')
3561 match ();
3562 expect_ident ("define");
3563 expect (XBM_TK_IDENT);
3565 if (LA1 == XBM_TK_NUMBER)
3567 char *p = strrchr (buffer, '_');
3568 p = p ? p + 1 : buffer;
3569 if (strcmp (p, "width") == 0)
3570 *width = value;
3571 else if (strcmp (p, "height") == 0)
3572 *height = value;
3574 expect (XBM_TK_NUMBER);
3577 if (!check_image_size (f, *width, *height))
3578 goto failure;
3579 else if (data == NULL)
3580 goto success;
3582 /* Parse bits. Must start with `static'. */
3583 expect_ident ("static");
3584 if (LA1 == XBM_TK_IDENT)
3586 if (strcmp (buffer, "unsigned") == 0)
3588 match ();
3589 expect_ident ("char");
3591 else if (strcmp (buffer, "short") == 0)
3593 match ();
3594 v10 = 1;
3595 if (*width % 16 && *width % 16 < 9)
3596 padding_p = 1;
3598 else if (strcmp (buffer, "char") == 0)
3599 match ();
3600 else
3601 goto failure;
3603 else
3604 goto failure;
3606 expect (XBM_TK_IDENT);
3607 expect ('[');
3608 expect (']');
3609 expect ('=');
3610 expect ('{');
3612 bytes_per_line = (*width + 7) / 8 + padding_p;
3613 nbytes = bytes_per_line * *height;
3614 p = *data = (unsigned char *) xmalloc (nbytes);
3616 if (v10)
3618 for (i = 0; i < nbytes; i += 2)
3620 int val = value;
3621 expect (XBM_TK_NUMBER);
3623 *p++ = XBM_BIT_SHUFFLE (val);
3624 if (!padding_p || ((i + 2) % bytes_per_line))
3625 *p++ = XBM_BIT_SHUFFLE (value >> 8);
3627 if (LA1 == ',' || LA1 == '}')
3628 match ();
3629 else
3630 goto failure;
3633 else
3635 for (i = 0; i < nbytes; ++i)
3637 int val = value;
3638 expect (XBM_TK_NUMBER);
3640 *p++ = XBM_BIT_SHUFFLE (val);
3642 if (LA1 == ',' || LA1 == '}')
3643 match ();
3644 else
3645 goto failure;
3649 success:
3650 return 1;
3652 failure:
3654 if (data && *data)
3656 xfree (*data);
3657 *data = NULL;
3659 return 0;
3661 #undef match
3662 #undef expect
3663 #undef expect_ident
3667 /* Load XBM image IMG which will be displayed on frame F from buffer
3668 CONTENTS. END is the end of the buffer. Value is non-zero if
3669 successful. */
3671 static int
3672 xbm_load_image (f, img, contents, end)
3673 struct frame *f;
3674 struct image *img;
3675 unsigned char *contents, *end;
3677 int rc;
3678 unsigned char *data;
3679 int success_p = 0;
3681 rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data);
3682 if (rc)
3684 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3685 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3686 int non_default_colors = 0;
3687 Lisp_Object value;
3689 xassert (img->width > 0 && img->height > 0);
3691 /* Get foreground and background colors, maybe allocate colors. */
3692 value = image_spec_value (img->spec, QCforeground, NULL);
3693 if (!NILP (value))
3695 foreground = x_alloc_image_color (f, img, value, foreground);
3696 non_default_colors = 1;
3698 value = image_spec_value (img->spec, QCbackground, NULL);
3699 if (!NILP (value))
3701 background = x_alloc_image_color (f, img, value, background);
3702 img->background = background;
3703 img->background_valid = 1;
3704 non_default_colors = 1;
3707 Create_Pixmap_From_Bitmap_Data (f, img, data,
3708 foreground, background,
3709 non_default_colors);
3710 xfree (data);
3712 if (img->pixmap == NO_PIXMAP)
3714 x_clear_image (f, img);
3715 image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
3717 else
3718 success_p = 1;
3720 else
3721 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3723 return success_p;
3727 /* Value is non-zero if DATA looks like an in-memory XBM file. */
3729 static int
3730 xbm_file_p (data)
3731 Lisp_Object data;
3733 int w, h;
3734 return (STRINGP (data)
3735 && xbm_read_bitmap_data (NULL, SDATA (data),
3736 (SDATA (data)
3737 + SBYTES (data)),
3738 &w, &h, NULL));
3742 /* Fill image IMG which is used on frame F with pixmap data. Value is
3743 non-zero if successful. */
3745 static int
3746 xbm_load (f, img)
3747 struct frame *f;
3748 struct image *img;
3750 int success_p = 0;
3751 Lisp_Object file_name;
3753 xassert (xbm_image_p (img->spec));
3755 /* If IMG->spec specifies a file name, create a non-file spec from it. */
3756 file_name = image_spec_value (img->spec, QCfile, NULL);
3757 if (STRINGP (file_name))
3759 Lisp_Object file;
3760 unsigned char *contents;
3761 int size;
3762 struct gcpro gcpro1;
3764 file = x_find_image_file (file_name);
3765 GCPRO1 (file);
3766 if (!STRINGP (file))
3768 image_error ("Cannot find image file `%s'", file_name, Qnil);
3769 UNGCPRO;
3770 return 0;
3773 contents = slurp_file (SDATA (file), &size);
3774 if (contents == NULL)
3776 image_error ("Error loading XBM image `%s'", img->spec, Qnil);
3777 UNGCPRO;
3778 return 0;
3781 success_p = xbm_load_image (f, img, contents, contents + size);
3782 UNGCPRO;
3784 else
3786 struct image_keyword fmt[XBM_LAST];
3787 Lisp_Object data;
3788 unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
3789 unsigned long background = FRAME_BACKGROUND_PIXEL (f);
3790 int non_default_colors = 0;
3791 char *bits;
3792 int parsed_p;
3793 int in_memory_file_p = 0;
3795 /* See if data looks like an in-memory XBM file. */
3796 data = image_spec_value (img->spec, QCdata, NULL);
3797 in_memory_file_p = xbm_file_p (data);
3799 /* Parse the image specification. */
3800 bcopy (xbm_format, fmt, sizeof fmt);
3801 parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
3802 xassert (parsed_p);
3804 /* Get specified width, and height. */
3805 if (!in_memory_file_p)
3807 img->width = XFASTINT (fmt[XBM_WIDTH].value);
3808 img->height = XFASTINT (fmt[XBM_HEIGHT].value);
3809 xassert (img->width > 0 && img->height > 0);
3812 /* Get foreground and background colors, maybe allocate colors. */
3813 if (fmt[XBM_FOREGROUND].count
3814 && STRINGP (fmt[XBM_FOREGROUND].value))
3816 foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
3817 foreground);
3818 non_default_colors = 1;
3821 if (fmt[XBM_BACKGROUND].count
3822 && STRINGP (fmt[XBM_BACKGROUND].value))
3824 background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
3825 background);
3826 non_default_colors = 1;
3829 if (in_memory_file_p)
3830 success_p = xbm_load_image (f, img, SDATA (data),
3831 (SDATA (data)
3832 + SBYTES (data)));
3833 else
3835 if (VECTORP (data))
3837 int i;
3838 char *p;
3839 int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
3841 p = bits = (char *) alloca (nbytes * img->height);
3842 for (i = 0; i < img->height; ++i, p += nbytes)
3844 Lisp_Object line = XVECTOR (data)->contents[i];
3845 if (STRINGP (line))
3846 bcopy (SDATA (line), p, nbytes);
3847 else
3848 bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
3851 else if (STRINGP (data))
3852 bits = SDATA (data);
3853 else
3854 bits = XBOOL_VECTOR (data)->data;
3856 #ifdef WINDOWSNT
3858 char *invertedBits;
3859 int nbytes, i;
3860 /* Windows mono bitmaps are reversed compared with X. */
3861 invertedBits = bits;
3862 nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR
3863 * img->height;
3864 bits = (char *) alloca(nbytes);
3865 for (i = 0; i < nbytes; i++)
3866 bits[i] = XBM_BIT_SHUFFLE (invertedBits[i]);
3868 #endif
3869 /* Create the pixmap. */
3871 Create_Pixmap_From_Bitmap_Data (f, img, bits,
3872 foreground, background,
3873 non_default_colors);
3874 if (img->pixmap)
3875 success_p = 1;
3876 else
3878 image_error ("Unable to create pixmap for XBM image `%s'",
3879 img->spec, Qnil);
3880 x_clear_image (f, img);
3885 return success_p;
3890 /***********************************************************************
3891 XPM images
3892 ***********************************************************************/
3894 #if defined (HAVE_XPM) || defined (MAC_OS)
3896 static int xpm_image_p P_ ((Lisp_Object object));
3897 static int xpm_load P_ ((struct frame *f, struct image *img));
3898 static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3900 #endif /* HAVE_XPM || MAC_OS */
3902 #ifdef HAVE_XPM
3903 #ifdef HAVE_NTGUI
3904 /* Indicate to xpm.h that we don't have Xlib. */
3905 #define FOR_MSW
3906 /* simx.h in xpm defines XColor and XImage differently than Emacs. */
3907 /* It also defines Display the same way as Emacs, but gcc 3.3 still barfs. */
3908 #define XColor xpm_XColor
3909 #define XImage xpm_XImage
3910 #define Display xpm_Display
3911 #define PIXEL_ALREADY_TYPEDEFED
3912 #include "X11/xpm.h"
3913 #undef FOR_MSW
3914 #undef XColor
3915 #undef XImage
3916 #undef Display
3917 #undef PIXEL_ALREADY_TYPEDEFED
3918 #else
3919 #include "X11/xpm.h"
3920 #endif /* HAVE_NTGUI */
3921 #endif /* HAVE_XPM */
3923 #if defined (HAVE_XPM) || defined (MAC_OS)
3924 /* The symbol `xpm' identifying XPM-format images. */
3926 Lisp_Object Qxpm;
3928 /* Indices of image specification fields in xpm_format, below. */
3930 enum xpm_keyword_index
3932 XPM_TYPE,
3933 XPM_FILE,
3934 XPM_DATA,
3935 XPM_ASCENT,
3936 XPM_MARGIN,
3937 XPM_RELIEF,
3938 XPM_ALGORITHM,
3939 XPM_HEURISTIC_MASK,
3940 XPM_MASK,
3941 XPM_COLOR_SYMBOLS,
3942 XPM_BACKGROUND,
3943 XPM_LAST
3946 /* Vector of image_keyword structures describing the format
3947 of valid XPM image specifications. */
3949 static struct image_keyword xpm_format[XPM_LAST] =
3951 {":type", IMAGE_SYMBOL_VALUE, 1},
3952 {":file", IMAGE_STRING_VALUE, 0},
3953 {":data", IMAGE_STRING_VALUE, 0},
3954 {":ascent", IMAGE_ASCENT_VALUE, 0},
3955 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
3956 {":relief", IMAGE_INTEGER_VALUE, 0},
3957 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3958 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3959 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3960 {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
3961 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
3964 /* Structure describing the image type XPM. */
3966 static struct image_type xpm_type =
3968 &Qxpm,
3969 xpm_image_p,
3970 xpm_load,
3971 x_clear_image,
3972 NULL
3975 #ifdef HAVE_X_WINDOWS
3977 /* Define ALLOC_XPM_COLORS if we can use Emacs' own color allocation
3978 functions for allocating image colors. Our own functions handle
3979 color allocation failures more gracefully than the ones on the XPM
3980 lib. */
3982 #if defined XpmAllocColor && defined XpmFreeColors && defined XpmColorClosure
3983 #define ALLOC_XPM_COLORS
3984 #endif
3985 #endif /* HAVE_X_WINDOWS */
3987 #ifdef ALLOC_XPM_COLORS
3989 static void xpm_init_color_cache P_ ((struct frame *, XpmAttributes *));
3990 static void xpm_free_color_cache P_ ((void));
3991 static int xpm_lookup_color P_ ((struct frame *, char *, XColor *));
3992 static int xpm_color_bucket P_ ((char *));
3993 static struct xpm_cached_color *xpm_cache_color P_ ((struct frame *, char *,
3994 XColor *, int));
3996 /* An entry in a hash table used to cache color definitions of named
3997 colors. This cache is necessary to speed up XPM image loading in
3998 case we do color allocations ourselves. Without it, we would need
3999 a call to XParseColor per pixel in the image. */
4001 struct xpm_cached_color
4003 /* Next in collision chain. */
4004 struct xpm_cached_color *next;
4006 /* Color definition (RGB and pixel color). */
4007 XColor color;
4009 /* Color name. */
4010 char name[1];
4013 /* The hash table used for the color cache, and its bucket vector
4014 size. */
4016 #define XPM_COLOR_CACHE_BUCKETS 1001
4017 struct xpm_cached_color **xpm_color_cache;
4019 /* Initialize the color cache. */
4021 static void
4022 xpm_init_color_cache (f, attrs)
4023 struct frame *f;
4024 XpmAttributes *attrs;
4026 size_t nbytes = XPM_COLOR_CACHE_BUCKETS * sizeof *xpm_color_cache;
4027 xpm_color_cache = (struct xpm_cached_color **) xmalloc (nbytes);
4028 memset (xpm_color_cache, 0, nbytes);
4029 init_color_table ();
4031 if (attrs->valuemask & XpmColorSymbols)
4033 int i;
4034 XColor color;
4036 for (i = 0; i < attrs->numsymbols; ++i)
4037 if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4038 attrs->colorsymbols[i].value, &color))
4040 color.pixel = lookup_rgb_color (f, color.red, color.green,
4041 color.blue);
4042 xpm_cache_color (f, attrs->colorsymbols[i].name, &color, -1);
4047 /* Free the color cache. */
4049 static void
4050 xpm_free_color_cache ()
4052 struct xpm_cached_color *p, *next;
4053 int i;
4055 for (i = 0; i < XPM_COLOR_CACHE_BUCKETS; ++i)
4056 for (p = xpm_color_cache[i]; p; p = next)
4058 next = p->next;
4059 xfree (p);
4062 xfree (xpm_color_cache);
4063 xpm_color_cache = NULL;
4064 free_color_table ();
4067 /* Return the bucket index for color named COLOR_NAME in the color
4068 cache. */
4070 static int
4071 xpm_color_bucket (color_name)
4072 char *color_name;
4074 unsigned h = 0;
4075 char *s;
4077 for (s = color_name; *s; ++s)
4078 h = (h << 2) ^ *s;
4079 return h %= XPM_COLOR_CACHE_BUCKETS;
4083 /* On frame F, cache values COLOR for color with name COLOR_NAME.
4084 BUCKET, if >= 0, is a precomputed bucket index. Value is the cache
4085 entry added. */
4087 static struct xpm_cached_color *
4088 xpm_cache_color (f, color_name, color, bucket)
4089 struct frame *f;
4090 char *color_name;
4091 XColor *color;
4092 int bucket;
4094 size_t nbytes;
4095 struct xpm_cached_color *p;
4097 if (bucket < 0)
4098 bucket = xpm_color_bucket (color_name);
4100 nbytes = sizeof *p + strlen (color_name);
4101 p = (struct xpm_cached_color *) xmalloc (nbytes);
4102 strcpy (p->name, color_name);
4103 p->color = *color;
4104 p->next = xpm_color_cache[bucket];
4105 xpm_color_cache[bucket] = p;
4106 return p;
4109 /* Look up color COLOR_NAME for frame F in the color cache. If found,
4110 return the cached definition in *COLOR. Otherwise, make a new
4111 entry in the cache and allocate the color. Value is zero if color
4112 allocation failed. */
4114 static int
4115 xpm_lookup_color (f, color_name, color)
4116 struct frame *f;
4117 char *color_name;
4118 XColor *color;
4120 struct xpm_cached_color *p;
4121 int h = xpm_color_bucket (color_name);
4123 for (p = xpm_color_cache[h]; p; p = p->next)
4124 if (strcmp (p->name, color_name) == 0)
4125 break;
4127 if (p != NULL)
4128 *color = p->color;
4129 else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
4130 color_name, color))
4132 color->pixel = lookup_rgb_color (f, color->red, color->green,
4133 color->blue);
4134 p = xpm_cache_color (f, color_name, color, h);
4136 /* You get `opaque' at least from ImageMagick converting pbm to xpm
4137 with transparency, and it's useful. */
4138 else if (strcmp ("opaque", color_name) == 0)
4140 bzero (color, sizeof (XColor)); /* Is this necessary/correct? */
4141 color->pixel = FRAME_FOREGROUND_PIXEL (f);
4142 p = xpm_cache_color (f, color_name, color, h);
4145 return p != NULL;
4149 /* Callback for allocating color COLOR_NAME. Called from the XPM lib.
4150 CLOSURE is a pointer to the frame on which we allocate the
4151 color. Return in *COLOR the allocated color. Value is non-zero
4152 if successful. */
4154 static int
4155 xpm_alloc_color (dpy, cmap, color_name, color, closure)
4156 Display *dpy;
4157 Colormap cmap;
4158 char *color_name;
4159 XColor *color;
4160 void *closure;
4162 return xpm_lookup_color ((struct frame *) closure, color_name, color);
4166 /* Callback for freeing NPIXELS colors contained in PIXELS. CLOSURE
4167 is a pointer to the frame on which we allocate the color. Value is
4168 non-zero if successful. */
4170 static int
4171 xpm_free_colors (dpy, cmap, pixels, npixels, closure)
4172 Display *dpy;
4173 Colormap cmap;
4174 Pixel *pixels;
4175 int npixels;
4176 void *closure;
4178 return 1;
4181 #endif /* ALLOC_XPM_COLORS */
4184 #ifdef HAVE_NTGUI
4186 /* XPM library details. */
4188 DEF_IMGLIB_FN (XpmFreeAttributes);
4189 DEF_IMGLIB_FN (XpmCreateImageFromBuffer);
4190 DEF_IMGLIB_FN (XpmReadFileToImage);
4191 DEF_IMGLIB_FN (XImageFree);
4193 static int
4194 init_xpm_functions (Lisp_Object libraries)
4196 HMODULE library;
4198 if (!(library = w32_delayed_load (libraries, Qxpm)))
4199 return 0;
4201 LOAD_IMGLIB_FN (library, XpmFreeAttributes);
4202 LOAD_IMGLIB_FN (library, XpmCreateImageFromBuffer);
4203 LOAD_IMGLIB_FN (library, XpmReadFileToImage);
4204 LOAD_IMGLIB_FN (library, XImageFree);
4205 return 1;
4208 #endif /* HAVE_NTGUI */
4211 /* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
4212 for XPM images. Such a list must consist of conses whose car and
4213 cdr are strings. */
4215 static int
4216 xpm_valid_color_symbols_p (color_symbols)
4217 Lisp_Object color_symbols;
4219 while (CONSP (color_symbols))
4221 Lisp_Object sym = XCAR (color_symbols);
4222 if (!CONSP (sym)
4223 || !STRINGP (XCAR (sym))
4224 || !STRINGP (XCDR (sym)))
4225 break;
4226 color_symbols = XCDR (color_symbols);
4229 return NILP (color_symbols);
4233 /* Value is non-zero if OBJECT is a valid XPM image specification. */
4235 static int
4236 xpm_image_p (object)
4237 Lisp_Object object;
4239 struct image_keyword fmt[XPM_LAST];
4240 bcopy (xpm_format, fmt, sizeof fmt);
4241 return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
4242 /* Either `:file' or `:data' must be present. */
4243 && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
4244 /* Either no `:color-symbols' or it's a list of conses
4245 whose car and cdr are strings. */
4246 && (fmt[XPM_COLOR_SYMBOLS].count == 0
4247 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
4250 #endif /* HAVE_XPM || MAC_OS */
4252 #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4254 x_create_bitmap_from_xpm_data (f, bits)
4255 struct frame *f;
4256 char **bits;
4258 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
4259 int id, rc;
4260 XpmAttributes attrs;
4261 Pixmap bitmap, mask;
4263 bzero (&attrs, sizeof attrs);
4265 attrs.visual = FRAME_X_VISUAL (f);
4266 attrs.colormap = FRAME_X_COLORMAP (f);
4267 attrs.valuemask |= XpmVisual;
4268 attrs.valuemask |= XpmColormap;
4270 rc = XpmCreatePixmapFromData (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4271 bits, &bitmap, &mask, &attrs);
4272 if (rc != XpmSuccess)
4274 XpmFreeAttributes (&attrs);
4275 return -1;
4278 id = x_allocate_bitmap_record (f);
4279 dpyinfo->bitmaps[id - 1].pixmap = bitmap;
4280 dpyinfo->bitmaps[id - 1].have_mask = 1;
4281 dpyinfo->bitmaps[id - 1].mask = mask;
4282 dpyinfo->bitmaps[id - 1].file = NULL;
4283 dpyinfo->bitmaps[id - 1].height = attrs.height;
4284 dpyinfo->bitmaps[id - 1].width = attrs.width;
4285 dpyinfo->bitmaps[id - 1].depth = attrs.depth;
4286 dpyinfo->bitmaps[id - 1].refcount = 1;
4288 XpmFreeAttributes (&attrs);
4289 return id;
4291 #endif /* defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) */
4293 /* Load image IMG which will be displayed on frame F. Value is
4294 non-zero if successful. */
4296 #ifdef HAVE_XPM
4298 static int
4299 xpm_load (f, img)
4300 struct frame *f;
4301 struct image *img;
4303 int rc;
4304 XpmAttributes attrs;
4305 Lisp_Object specified_file, color_symbols;
4306 #ifdef HAVE_NTGUI
4307 HDC hdc;
4308 xpm_XImage * xpm_image = NULL, * xpm_mask = NULL;
4309 #endif /* HAVE_NTGUI */
4311 /* Configure the XPM lib. Use the visual of frame F. Allocate
4312 close colors. Return colors allocated. */
4313 bzero (&attrs, sizeof attrs);
4315 #ifndef HAVE_NTGUI
4316 attrs.visual = FRAME_X_VISUAL (f);
4317 attrs.colormap = FRAME_X_COLORMAP (f);
4318 attrs.valuemask |= XpmVisual;
4319 attrs.valuemask |= XpmColormap;
4320 #endif /* HAVE_NTGUI */
4322 #ifdef ALLOC_XPM_COLORS
4323 /* Allocate colors with our own functions which handle
4324 failing color allocation more gracefully. */
4325 attrs.color_closure = f;
4326 attrs.alloc_color = xpm_alloc_color;
4327 attrs.free_colors = xpm_free_colors;
4328 attrs.valuemask |= XpmAllocColor | XpmFreeColors | XpmColorClosure;
4329 #else /* not ALLOC_XPM_COLORS */
4330 /* Let the XPM lib allocate colors. */
4331 attrs.valuemask |= XpmReturnAllocPixels;
4332 #ifdef XpmAllocCloseColors
4333 attrs.alloc_close_colors = 1;
4334 attrs.valuemask |= XpmAllocCloseColors;
4335 #else /* not XpmAllocCloseColors */
4336 attrs.closeness = 600;
4337 attrs.valuemask |= XpmCloseness;
4338 #endif /* not XpmAllocCloseColors */
4339 #endif /* ALLOC_XPM_COLORS */
4341 /* If image specification contains symbolic color definitions, add
4342 these to `attrs'. */
4343 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4344 if (CONSP (color_symbols))
4346 Lisp_Object tail;
4347 XpmColorSymbol *xpm_syms;
4348 int i, size;
4350 attrs.valuemask |= XpmColorSymbols;
4352 /* Count number of symbols. */
4353 attrs.numsymbols = 0;
4354 for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
4355 ++attrs.numsymbols;
4357 /* Allocate an XpmColorSymbol array. */
4358 size = attrs.numsymbols * sizeof *xpm_syms;
4359 xpm_syms = (XpmColorSymbol *) alloca (size);
4360 bzero (xpm_syms, size);
4361 attrs.colorsymbols = xpm_syms;
4363 /* Fill the color symbol array. */
4364 for (tail = color_symbols, i = 0;
4365 CONSP (tail);
4366 ++i, tail = XCDR (tail))
4368 Lisp_Object name = XCAR (XCAR (tail));
4369 Lisp_Object color = XCDR (XCAR (tail));
4370 xpm_syms[i].name = (char *) alloca (SCHARS (name) + 1);
4371 strcpy (xpm_syms[i].name, SDATA (name));
4372 xpm_syms[i].value = (char *) alloca (SCHARS (color) + 1);
4373 strcpy (xpm_syms[i].value, SDATA (color));
4377 /* Create a pixmap for the image, either from a file, or from a
4378 string buffer containing data in the same format as an XPM file. */
4379 #ifdef ALLOC_XPM_COLORS
4380 xpm_init_color_cache (f, &attrs);
4381 #endif
4383 specified_file = image_spec_value (img->spec, QCfile, NULL);
4385 #ifdef HAVE_NTGUI
4387 HDC frame_dc = get_frame_dc (f);
4388 hdc = CreateCompatibleDC (frame_dc);
4389 release_frame_dc (f, frame_dc);
4391 #endif /* HAVE_NTGUI */
4393 if (STRINGP (specified_file))
4395 Lisp_Object file = x_find_image_file (specified_file);
4396 if (!STRINGP (file))
4398 image_error ("Cannot find image file `%s'", specified_file, Qnil);
4399 return 0;
4402 #ifdef HAVE_NTGUI
4403 /* XpmReadFileToPixmap is not available in the Windows port of
4404 libxpm. But XpmReadFileToImage almost does what we want. */
4405 rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
4406 &xpm_image, &xpm_mask,
4407 &attrs);
4408 #else
4409 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4410 SDATA (file), &img->pixmap, &img->mask,
4411 &attrs);
4412 #endif /* HAVE_NTGUI */
4414 else
4416 Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
4417 #ifdef HAVE_NTGUI
4418 /* XpmCreatePixmapFromBuffer is not available in the Windows port
4419 of libxpm. But XpmCreateImageFromBuffer almost does what we want. */
4420 rc = fn_XpmCreateImageFromBuffer (&hdc, SDATA (buffer),
4421 &xpm_image, &xpm_mask,
4422 &attrs);
4423 #else
4424 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4425 SDATA (buffer),
4426 &img->pixmap, &img->mask,
4427 &attrs);
4428 #endif /* HAVE_NTGUI */
4431 if (rc == XpmSuccess)
4433 #if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
4434 img->colors = colors_in_color_table (&img->ncolors);
4435 #else /* not ALLOC_XPM_COLORS */
4436 int i;
4438 #ifdef HAVE_NTGUI
4439 /* W32 XPM uses XImage to wrap what W32 Emacs calls a Pixmap,
4440 plus some duplicate attributes. */
4441 if (xpm_image && xpm_image->bitmap)
4443 img->pixmap = xpm_image->bitmap;
4444 /* XImageFree in libXpm frees XImage struct without destroying
4445 the bitmap, which is what we want. */
4446 fn_XImageFree (xpm_image);
4448 if (xpm_mask && xpm_mask->bitmap)
4450 /* The mask appears to be inverted compared with what we expect.
4451 TODO: invert our expectations. See other places where we
4452 have to invert bits because our idea of masks is backwards. */
4453 HGDIOBJ old_obj;
4454 old_obj = SelectObject (hdc, xpm_mask->bitmap);
4456 PatBlt (hdc, 0, 0, xpm_mask->width, xpm_mask->height, DSTINVERT);
4457 SelectObject (hdc, old_obj);
4459 img->mask = xpm_mask->bitmap;
4460 fn_XImageFree (xpm_mask);
4461 DeleteDC (hdc);
4464 DeleteDC (hdc);
4465 #endif /* HAVE_NTGUI */
4467 /* Remember allocated colors. */
4468 img->ncolors = attrs.nalloc_pixels;
4469 img->colors = (unsigned long *) xmalloc (img->ncolors
4470 * sizeof *img->colors);
4471 for (i = 0; i < attrs.nalloc_pixels; ++i)
4473 img->colors[i] = attrs.alloc_pixels[i];
4474 #ifdef DEBUG_X_COLORS
4475 register_color (img->colors[i]);
4476 #endif
4478 #endif /* not ALLOC_XPM_COLORS */
4480 img->width = attrs.width;
4481 img->height = attrs.height;
4482 xassert (img->width > 0 && img->height > 0);
4484 /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
4485 #ifdef HAVE_NTGUI
4486 fn_XpmFreeAttributes (&attrs);
4487 #else
4488 XpmFreeAttributes (&attrs);
4489 #endif /* HAVE_NTGUI */
4491 else
4493 #ifdef HAVE_NTGUI
4494 DeleteDC (hdc);
4495 #endif /* HAVE_NTGUI */
4497 switch (rc)
4499 case XpmOpenFailed:
4500 image_error ("Error opening XPM file (%s)", img->spec, Qnil);
4501 break;
4503 case XpmFileInvalid:
4504 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4505 break;
4507 case XpmNoMemory:
4508 image_error ("Out of memory (%s)", img->spec, Qnil);
4509 break;
4511 case XpmColorFailed:
4512 image_error ("Color allocation error (%s)", img->spec, Qnil);
4513 break;
4515 default:
4516 image_error ("Unknown error (%s)", img->spec, Qnil);
4517 break;
4521 #ifdef ALLOC_XPM_COLORS
4522 xpm_free_color_cache ();
4523 #endif
4524 return rc == XpmSuccess;
4527 #endif /* HAVE_XPM */
4529 #ifdef MAC_OS
4531 /* XPM support functions for Mac OS where libxpm is not available.
4532 Only XPM version 3 (without any extensions) is supported. */
4534 static int xpm_scan P_ ((const unsigned char **, const unsigned char *,
4535 const unsigned char **, int *));
4536 static Lisp_Object xpm_make_color_table_v
4537 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4538 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4539 static void xpm_put_color_table_v P_ ((Lisp_Object, const unsigned char *,
4540 int, Lisp_Object));
4541 static Lisp_Object xpm_get_color_table_v P_ ((Lisp_Object,
4542 const unsigned char *, int));
4543 static Lisp_Object xpm_make_color_table_h
4544 P_ ((void (**) (Lisp_Object, const unsigned char *, int, Lisp_Object),
4545 Lisp_Object (**) (Lisp_Object, const unsigned char *, int)));
4546 static void xpm_put_color_table_h P_ ((Lisp_Object, const unsigned char *,
4547 int, Lisp_Object));
4548 static Lisp_Object xpm_get_color_table_h P_ ((Lisp_Object,
4549 const unsigned char *, int));
4550 static int xpm_str_to_color_key P_ ((const char *));
4551 static int xpm_load_image P_ ((struct frame *, struct image *,
4552 const unsigned char *, const unsigned char *));
4554 /* Tokens returned from xpm_scan. */
4556 enum xpm_token
4558 XPM_TK_IDENT = 256,
4559 XPM_TK_STRING,
4560 XPM_TK_EOF
4563 /* Scan an XPM data and return a character (< 256) or a token defined
4564 by enum xpm_token above. *S and END are the start (inclusive) and
4565 the end (exclusive) addresses of the data, respectively. Advance
4566 *S while scanning. If token is either XPM_TK_IDENT or
4567 XPM_TK_STRING, *BEG and *LEN are set to the start address and the
4568 length of the corresponding token, respectively. */
4570 static int
4571 xpm_scan (s, end, beg, len)
4572 const unsigned char **s, *end, **beg;
4573 int *len;
4575 int c;
4577 while (*s < end)
4579 /* Skip white-space. */
4580 while (*s < end && (c = *(*s)++, isspace (c)))
4583 /* gnus-pointer.xpm uses '-' in its identifier.
4584 sb-dir-plus.xpm uses '+' in its identifier. */
4585 if (isalpha (c) || c == '_' || c == '-' || c == '+')
4587 *beg = *s - 1;
4588 while (*s < end
4589 && (c = **s, isalnum (c) || c == '_' || c == '-' || c == '+'))
4590 ++*s;
4591 *len = *s - *beg;
4592 return XPM_TK_IDENT;
4594 else if (c == '"')
4596 *beg = *s;
4597 while (*s < end && **s != '"')
4598 ++*s;
4599 *len = *s - *beg;
4600 if (*s < end)
4601 ++*s;
4602 return XPM_TK_STRING;
4604 else if (c == '/')
4606 if (*s < end && **s == '*')
4608 /* C-style comment. */
4609 ++*s;
4612 while (*s < end && *(*s)++ != '*')
4615 while (*s < end && **s != '/');
4616 if (*s < end)
4617 ++*s;
4619 else
4620 return c;
4622 else
4623 return c;
4626 return XPM_TK_EOF;
4629 /* Functions for color table lookup in XPM data. A key is a string
4630 specifying the color of each pixel in XPM data. A value is either
4631 an integer that specifies a pixel color, Qt that specifies
4632 transparency, or Qnil for the unspecified color. If the length of
4633 the key string is one, a vector is used as a table. Otherwise, a
4634 hash table is used. */
4636 static Lisp_Object
4637 xpm_make_color_table_v (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_v;
4642 *get_func = xpm_get_color_table_v;
4643 return Fmake_vector (make_number (256), Qnil);
4646 static void
4647 xpm_put_color_table_v (color_table, chars_start, chars_len, color)
4648 Lisp_Object color_table;
4649 const unsigned char *chars_start;
4650 int chars_len;
4651 Lisp_Object color;
4653 XVECTOR (color_table)->contents[*chars_start] = color;
4656 static Lisp_Object
4657 xpm_get_color_table_v (color_table, chars_start, chars_len)
4658 Lisp_Object color_table;
4659 const unsigned char *chars_start;
4660 int chars_len;
4662 return XVECTOR (color_table)->contents[*chars_start];
4665 static Lisp_Object
4666 xpm_make_color_table_h (put_func, get_func)
4667 void (**put_func) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4668 Lisp_Object (**get_func) (Lisp_Object, const unsigned char *, int);
4670 *put_func = xpm_put_color_table_h;
4671 *get_func = xpm_get_color_table_h;
4672 return make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
4673 make_float (DEFAULT_REHASH_SIZE),
4674 make_float (DEFAULT_REHASH_THRESHOLD),
4675 Qnil, Qnil, Qnil);
4678 static void
4679 xpm_put_color_table_h (color_table, chars_start, chars_len, color)
4680 Lisp_Object color_table;
4681 const unsigned char *chars_start;
4682 int chars_len;
4683 Lisp_Object color;
4685 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4686 unsigned hash_code;
4687 Lisp_Object chars = make_unibyte_string (chars_start, chars_len);
4689 hash_lookup (table, chars, &hash_code);
4690 hash_put (table, chars, color, hash_code);
4693 static Lisp_Object
4694 xpm_get_color_table_h (color_table, chars_start, chars_len)
4695 Lisp_Object color_table;
4696 const unsigned char *chars_start;
4697 int chars_len;
4699 struct Lisp_Hash_Table *table = XHASH_TABLE (color_table);
4700 int i = hash_lookup (table, make_unibyte_string (chars_start, chars_len),
4701 NULL);
4703 return i >= 0 ? HASH_VALUE (table, i) : Qnil;
4706 enum xpm_color_key {
4707 XPM_COLOR_KEY_S,
4708 XPM_COLOR_KEY_M,
4709 XPM_COLOR_KEY_G4,
4710 XPM_COLOR_KEY_G,
4711 XPM_COLOR_KEY_C
4714 static const char xpm_color_key_strings[][4] = {"s", "m", "g4", "g", "c"};
4716 static int
4717 xpm_str_to_color_key (s)
4718 const char *s;
4720 int i;
4722 for (i = 0;
4723 i < sizeof xpm_color_key_strings / sizeof xpm_color_key_strings[0];
4724 i++)
4725 if (strcmp (xpm_color_key_strings[i], s) == 0)
4726 return i;
4727 return -1;
4730 static int
4731 xpm_load_image (f, img, contents, end)
4732 struct frame *f;
4733 struct image *img;
4734 const unsigned char *contents, *end;
4736 const unsigned char *s = contents, *beg, *str;
4737 unsigned char buffer[BUFSIZ];
4738 int width, height, x, y;
4739 int num_colors, chars_per_pixel;
4740 int len, LA1;
4741 void (*put_color_table) (Lisp_Object, const unsigned char *, int, Lisp_Object);
4742 Lisp_Object (*get_color_table) (Lisp_Object, const unsigned char *, int);
4743 Lisp_Object frame, color_symbols, color_table;
4744 int best_key, have_mask = 0;
4745 XImagePtr ximg = NULL, mask_img = NULL;
4747 #define match() \
4748 LA1 = xpm_scan (&s, end, &beg, &len)
4750 #define expect(TOKEN) \
4751 if (LA1 != (TOKEN)) \
4752 goto failure; \
4753 else \
4754 match ()
4756 #define expect_ident(IDENT) \
4757 if (LA1 == XPM_TK_IDENT \
4758 && strlen ((IDENT)) == len && memcmp ((IDENT), beg, len) == 0) \
4759 match (); \
4760 else \
4761 goto failure
4763 if (!(end - s >= 9 && memcmp (s, "/* XPM */", 9) == 0))
4764 goto failure;
4765 s += 9;
4766 match();
4767 expect_ident ("static");
4768 expect_ident ("char");
4769 expect ('*');
4770 expect (XPM_TK_IDENT);
4771 expect ('[');
4772 expect (']');
4773 expect ('=');
4774 expect ('{');
4775 expect (XPM_TK_STRING);
4776 if (len >= BUFSIZ)
4777 goto failure;
4778 memcpy (buffer, beg, len);
4779 buffer[len] = '\0';
4780 if (sscanf (buffer, "%d %d %d %d", &width, &height,
4781 &num_colors, &chars_per_pixel) != 4
4782 || width <= 0 || height <= 0
4783 || num_colors <= 0 || chars_per_pixel <= 0)
4784 goto failure;
4786 if (!check_image_size (f, width, height))
4788 image_error ("Invalid image size", Qnil, Qnil);
4789 goto failure;
4792 expect (',');
4794 XSETFRAME (frame, f);
4795 if (!NILP (Fxw_display_color_p (frame)))
4796 best_key = XPM_COLOR_KEY_C;
4797 else if (!NILP (Fx_display_grayscale_p (frame)))
4798 best_key = (XFASTINT (Fx_display_planes (frame)) > 2
4799 ? XPM_COLOR_KEY_G : XPM_COLOR_KEY_G4);
4800 else
4801 best_key = XPM_COLOR_KEY_M;
4803 color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
4804 if (chars_per_pixel == 1)
4805 color_table = xpm_make_color_table_v (&put_color_table,
4806 &get_color_table);
4807 else
4808 color_table = xpm_make_color_table_h (&put_color_table,
4809 &get_color_table);
4811 while (num_colors-- > 0)
4813 unsigned char *color, *max_color;
4814 int key, next_key, max_key = 0;
4815 Lisp_Object symbol_color = Qnil, color_val;
4816 XColor cdef;
4818 expect (XPM_TK_STRING);
4819 if (len <= chars_per_pixel || len >= BUFSIZ + chars_per_pixel)
4820 goto failure;
4821 memcpy (buffer, beg + chars_per_pixel, len - chars_per_pixel);
4822 buffer[len - chars_per_pixel] = '\0';
4824 str = strtok (buffer, " \t");
4825 if (str == NULL)
4826 goto failure;
4827 key = xpm_str_to_color_key (str);
4828 if (key < 0)
4829 goto failure;
4832 color = strtok (NULL, " \t");
4833 if (color == NULL)
4834 goto failure;
4836 while ((str = strtok (NULL, " \t")) != NULL)
4838 next_key = xpm_str_to_color_key (str);
4839 if (next_key >= 0)
4840 break;
4841 color[strlen (color)] = ' ';
4844 if (key == XPM_COLOR_KEY_S)
4846 if (NILP (symbol_color))
4847 symbol_color = build_string (color);
4849 else if (max_key < key && key <= best_key)
4851 max_key = key;
4852 max_color = color;
4854 key = next_key;
4856 while (str);
4858 color_val = Qnil;
4859 if (!NILP (color_symbols) && !NILP (symbol_color))
4861 Lisp_Object specified_color = Fassoc (symbol_color, color_symbols);
4863 if (CONSP (specified_color) && STRINGP (XCDR (specified_color)))
4865 if (xstricmp (SDATA (XCDR (specified_color)), "None") == 0)
4866 color_val = Qt;
4867 else if (x_defined_color (f, SDATA (XCDR (specified_color)),
4868 &cdef, 0))
4869 color_val = make_number (cdef.pixel);
4872 if (NILP (color_val) && max_key > 0)
4874 if (xstricmp (max_color, "None") == 0)
4875 color_val = Qt;
4876 else if (x_defined_color (f, max_color, &cdef, 0))
4877 color_val = make_number (cdef.pixel);
4879 if (!NILP (color_val))
4880 (*put_color_table) (color_table, beg, chars_per_pixel, color_val);
4882 expect (',');
4885 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4886 &ximg, &img->pixmap)
4887 || !x_create_x_image_and_pixmap (f, width, height, 1,
4888 &mask_img, &img->mask))
4890 image_error ("Out of memory (%s)", img->spec, Qnil);
4891 goto error;
4894 for (y = 0; y < height; y++)
4896 expect (XPM_TK_STRING);
4897 str = beg;
4898 if (len < width * chars_per_pixel)
4899 goto failure;
4900 for (x = 0; x < width; x++, str += chars_per_pixel)
4902 Lisp_Object color_val =
4903 (*get_color_table) (color_table, str, chars_per_pixel);
4905 XPutPixel (ximg, x, y,
4906 (INTEGERP (color_val) ? XINT (color_val)
4907 : FRAME_FOREGROUND_PIXEL (f)));
4908 XPutPixel (mask_img, x, y,
4909 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4910 : (have_mask = 1, PIX_MASK_RETAIN)));
4912 if (y + 1 < height)
4913 expect (',');
4916 img->width = width;
4917 img->height = height;
4919 /* Maybe fill in the background field while we have ximg handy. */
4920 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
4921 IMAGE_BACKGROUND (img, f, ximg);
4923 x_put_x_image (f, ximg, img->pixmap, width, height);
4924 x_destroy_x_image (ximg);
4925 if (have_mask)
4927 /* Fill in the background_transparent field while we have the
4928 mask handy. */
4929 image_background_transparent (img, f, mask_img);
4931 x_put_x_image (f, mask_img, img->mask, width, height);
4932 x_destroy_x_image (mask_img);
4934 else
4936 x_destroy_x_image (mask_img);
4937 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4938 img->mask = NO_PIXMAP;
4941 return 1;
4943 failure:
4944 image_error ("Invalid XPM file (%s)", img->spec, Qnil);
4945 error:
4946 x_destroy_x_image (ximg);
4947 x_destroy_x_image (mask_img);
4948 x_clear_image (f, img);
4949 return 0;
4951 #undef match
4952 #undef expect
4953 #undef expect_ident
4956 static int
4957 xpm_load (f, img)
4958 struct frame *f;
4959 struct image *img;
4961 int success_p = 0;
4962 Lisp_Object file_name;
4964 /* If IMG->spec specifies a file name, create a non-file spec from it. */
4965 file_name = image_spec_value (img->spec, QCfile, NULL);
4966 if (STRINGP (file_name))
4968 Lisp_Object file;
4969 unsigned char *contents;
4970 int size;
4971 struct gcpro gcpro1;
4973 file = x_find_image_file (file_name);
4974 GCPRO1 (file);
4975 if (!STRINGP (file))
4977 image_error ("Cannot find image file `%s'", file_name, Qnil);
4978 UNGCPRO;
4979 return 0;
4982 contents = slurp_file (SDATA (file), &size);
4983 if (contents == NULL)
4985 image_error ("Error loading XPM image `%s'", img->spec, Qnil);
4986 UNGCPRO;
4987 return 0;
4990 success_p = xpm_load_image (f, img, contents, contents + size);
4991 xfree (contents);
4992 UNGCPRO;
4994 else
4996 Lisp_Object data;
4998 data = image_spec_value (img->spec, QCdata, NULL);
4999 success_p = xpm_load_image (f, img, SDATA (data),
5000 SDATA (data) + SBYTES (data));
5003 return success_p;
5006 #endif /* MAC_OS */
5010 /***********************************************************************
5011 Color table
5012 ***********************************************************************/
5014 #ifdef COLOR_TABLE_SUPPORT
5016 /* An entry in the color table mapping an RGB color to a pixel color. */
5018 struct ct_color
5020 int r, g, b;
5021 unsigned long pixel;
5023 /* Next in color table collision list. */
5024 struct ct_color *next;
5027 /* The bucket vector size to use. Must be prime. */
5029 #define CT_SIZE 101
5031 /* Value is a hash of the RGB color given by R, G, and B. */
5033 #define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
5035 /* The color hash table. */
5037 struct ct_color **ct_table;
5039 /* Number of entries in the color table. */
5041 int ct_colors_allocated;
5043 /* Initialize the color table. */
5045 static void
5046 init_color_table ()
5048 int size = CT_SIZE * sizeof (*ct_table);
5049 ct_table = (struct ct_color **) xmalloc (size);
5050 bzero (ct_table, size);
5051 ct_colors_allocated = 0;
5055 /* Free memory associated with the color table. */
5057 static void
5058 free_color_table ()
5060 int i;
5061 struct ct_color *p, *next;
5063 for (i = 0; i < CT_SIZE; ++i)
5064 for (p = ct_table[i]; p; p = next)
5066 next = p->next;
5067 xfree (p);
5070 xfree (ct_table);
5071 ct_table = NULL;
5075 /* Value is a pixel color for RGB color R, G, B on frame F. If an
5076 entry for that color already is in the color table, return the
5077 pixel color of that entry. Otherwise, allocate a new color for R,
5078 G, B, and make an entry in the color table. */
5080 static unsigned long
5081 lookup_rgb_color (f, r, g, b)
5082 struct frame *f;
5083 int r, g, b;
5085 unsigned hash = CT_HASH_RGB (r, g, b);
5086 int i = hash % CT_SIZE;
5087 struct ct_color *p;
5088 Display_Info *dpyinfo;
5090 /* Handle TrueColor visuals specially, which improves performance by
5091 two orders of magnitude. Freeing colors on TrueColor visuals is
5092 a nop, and pixel colors specify RGB values directly. See also
5093 the Xlib spec, chapter 3.1. */
5094 dpyinfo = FRAME_X_DISPLAY_INFO (f);
5095 if (dpyinfo->red_bits > 0)
5097 unsigned long pr, pg, pb;
5099 /* Apply gamma-correction like normal color allocation does. */
5100 if (f->gamma)
5102 XColor color;
5103 color.red = r, color.green = g, color.blue = b;
5104 gamma_correct (f, &color);
5105 r = color.red, g = color.green, b = color.blue;
5108 /* Scale down RGB values to the visual's bits per RGB, and shift
5109 them to the right position in the pixel color. Note that the
5110 original RGB values are 16-bit values, as usual in X. */
5111 pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset;
5112 pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
5113 pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset;
5115 /* Assemble the pixel color. */
5116 return pr | pg | pb;
5119 for (p = ct_table[i]; p; p = p->next)
5120 if (p->r == r && p->g == g && p->b == b)
5121 break;
5123 if (p == NULL)
5126 #ifdef HAVE_X_WINDOWS
5127 XColor color;
5128 Colormap cmap;
5129 int rc;
5131 color.red = r;
5132 color.green = g;
5133 color.blue = b;
5135 cmap = FRAME_X_COLORMAP (f);
5136 rc = x_alloc_nearest_color (f, cmap, &color);
5137 if (rc)
5139 ++ct_colors_allocated;
5140 p = (struct ct_color *) xmalloc (sizeof *p);
5141 p->r = r;
5142 p->g = g;
5143 p->b = b;
5144 p->pixel = color.pixel;
5145 p->next = ct_table[i];
5146 ct_table[i] = p;
5148 else
5149 return FRAME_FOREGROUND_PIXEL (f);
5151 #else
5152 COLORREF color;
5153 #ifdef HAVE_NTGUI
5154 color = PALETTERGB (r, g, b);
5155 #else
5156 color = RGB_TO_ULONG (r, g, b);
5157 #endif /* HAVE_NTGUI */
5158 ++ct_colors_allocated;
5159 p = (struct ct_color *) xmalloc (sizeof *p);
5160 p->r = r;
5161 p->g = g;
5162 p->b = b;
5163 p->pixel = color;
5164 p->next = ct_table[i];
5165 ct_table[i] = p;
5166 #endif /* HAVE_X_WINDOWS */
5170 return p->pixel;
5174 /* Look up pixel color PIXEL which is used on frame F in the color
5175 table. If not already present, allocate it. Value is PIXEL. */
5177 static unsigned long
5178 lookup_pixel_color (f, pixel)
5179 struct frame *f;
5180 unsigned long pixel;
5182 int i = pixel % CT_SIZE;
5183 struct ct_color *p;
5185 for (p = ct_table[i]; p; p = p->next)
5186 if (p->pixel == pixel)
5187 break;
5189 if (p == NULL)
5191 XColor color;
5192 Colormap cmap;
5193 int rc;
5195 #ifdef HAVE_X_WINDOWS
5196 cmap = FRAME_X_COLORMAP (f);
5197 color.pixel = pixel;
5198 x_query_color (f, &color);
5199 rc = x_alloc_nearest_color (f, cmap, &color);
5200 #else
5201 BLOCK_INPUT;
5202 cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
5203 color.pixel = pixel;
5204 XQueryColor (NULL, cmap, &color);
5205 rc = x_alloc_nearest_color (f, cmap, &color);
5206 UNBLOCK_INPUT;
5207 #endif /* HAVE_X_WINDOWS */
5209 if (rc)
5211 ++ct_colors_allocated;
5213 p = (struct ct_color *) xmalloc (sizeof *p);
5214 p->r = color.red;
5215 p->g = color.green;
5216 p->b = color.blue;
5217 p->pixel = pixel;
5218 p->next = ct_table[i];
5219 ct_table[i] = p;
5221 else
5222 return FRAME_FOREGROUND_PIXEL (f);
5224 return p->pixel;
5228 /* Value is a vector of all pixel colors contained in the color table,
5229 allocated via xmalloc. Set *N to the number of colors. */
5231 static unsigned long *
5232 colors_in_color_table (n)
5233 int *n;
5235 int i, j;
5236 struct ct_color *p;
5237 unsigned long *colors;
5239 if (ct_colors_allocated == 0)
5241 *n = 0;
5242 colors = NULL;
5244 else
5246 colors = (unsigned long *) xmalloc (ct_colors_allocated
5247 * sizeof *colors);
5248 *n = ct_colors_allocated;
5250 for (i = j = 0; i < CT_SIZE; ++i)
5251 for (p = ct_table[i]; p; p = p->next)
5252 colors[j++] = p->pixel;
5255 return colors;
5258 #else /* COLOR_TABLE_SUPPORT */
5260 static unsigned long
5261 lookup_rgb_color (f, r, g, b)
5262 struct frame *f;
5263 int r, g, b;
5265 unsigned long pixel;
5267 #ifdef MAC_OS
5268 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5269 gamma_correct (f, &pixel);
5270 #endif /* MAC_OS */
5272 #ifdef HAVE_NTGUI
5273 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
5274 #endif /* HAVE_NTGUI */
5276 return pixel;
5279 static void
5280 init_color_table ()
5283 #endif /* COLOR_TABLE_SUPPORT */
5286 /***********************************************************************
5287 Algorithms
5288 ***********************************************************************/
5290 static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
5291 static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
5292 static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
5294 #ifdef HAVE_NTGUI
5295 static void XPutPixel (XImagePtr , int, int, COLORREF);
5296 #endif /* HAVE_NTGUI */
5298 /* Non-zero means draw a cross on images having `:conversion
5299 disabled'. */
5301 int cross_disabled_images;
5303 /* Edge detection matrices for different edge-detection
5304 strategies. */
5306 static int emboss_matrix[9] = {
5307 /* x - 1 x x + 1 */
5308 2, -1, 0, /* y - 1 */
5309 -1, 0, 1, /* y */
5310 0, 1, -2 /* y + 1 */
5313 static int laplace_matrix[9] = {
5314 /* x - 1 x x + 1 */
5315 1, 0, 0, /* y - 1 */
5316 0, 0, 0, /* y */
5317 0, 0, -1 /* y + 1 */
5320 /* Value is the intensity of the color whose red/green/blue values
5321 are R, G, and B. */
5323 #define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
5326 /* On frame F, return an array of XColor structures describing image
5327 IMG->pixmap. Each XColor structure has its pixel color set. RGB_P
5328 non-zero means also fill the red/green/blue members of the XColor
5329 structures. Value is a pointer to the array of XColors structures,
5330 allocated with xmalloc; it must be freed by the caller. */
5332 static XColor *
5333 x_to_xcolors (f, img, rgb_p)
5334 struct frame *f;
5335 struct image *img;
5336 int rgb_p;
5338 int x, y;
5339 XColor *colors, *p;
5340 XImagePtr_or_DC ximg;
5341 #ifdef HAVE_NTGUI
5342 HDC hdc;
5343 HGDIOBJ prev;
5344 #endif /* HAVE_NTGUI */
5346 colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
5348 #ifndef HAVE_NTGUI
5349 /* Get the X image IMG->pixmap. */
5350 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
5351 0, 0, img->width, img->height, ~0, ZPixmap);
5352 #else
5353 /* Load the image into a memory device context. */
5354 hdc = get_frame_dc (f);
5355 ximg = CreateCompatibleDC (hdc);
5356 release_frame_dc (f, hdc);
5357 prev = SelectObject (ximg, img->pixmap);
5358 #endif /* HAVE_NTGUI */
5360 /* Fill the `pixel' members of the XColor array. I wished there
5361 were an easy and portable way to circumvent XGetPixel. */
5362 p = colors;
5363 for (y = 0; y < img->height; ++y)
5365 XColor *row = p;
5367 #ifdef HAVE_X_WINDOWS
5368 for (x = 0; x < img->width; ++x, ++p)
5369 p->pixel = XGetPixel (ximg, x, y);
5370 if (rgb_p)
5371 x_query_colors (f, row, img->width);
5373 #else
5375 for (x = 0; x < img->width; ++x, ++p)
5377 /* W32_TODO: palette support needed here? */
5378 p->pixel = GET_PIXEL (ximg, x, y);
5379 if (rgb_p)
5381 #ifdef MAC_OS
5382 p->red = RED16_FROM_ULONG (p->pixel);
5383 p->green = GREEN16_FROM_ULONG (p->pixel);
5384 p->blue = BLUE16_FROM_ULONG (p->pixel);
5385 #endif /* MAC_OS */
5386 #ifdef HAVE_NTGUI
5387 p->red = 256 * GetRValue (p->pixel);
5388 p->green = 256 * GetGValue (p->pixel);
5389 p->blue = 256 * GetBValue (p->pixel);
5390 #endif /* HAVE_NTGUI */
5393 #endif /* HAVE_X_WINDOWS */
5396 Destroy_Image (ximg, prev);
5398 return colors;
5401 #ifdef HAVE_NTGUI
5403 /* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
5404 created with CreateDIBSection, with the pointer to the bit values
5405 stored in ximg->data. */
5407 static void
5408 XPutPixel (ximg, x, y, color)
5409 XImagePtr ximg;
5410 int x, y;
5411 COLORREF color;
5413 int width = ximg->info.bmiHeader.biWidth;
5414 int height = ximg->info.bmiHeader.biHeight;
5415 unsigned char * pixel;
5417 /* True color images. */
5418 if (ximg->info.bmiHeader.biBitCount == 24)
5420 int rowbytes = width * 3;
5421 /* Ensure scanlines are aligned on 4 byte boundaries. */
5422 if (rowbytes % 4)
5423 rowbytes += 4 - (rowbytes % 4);
5425 pixel = ximg->data + y * rowbytes + x * 3;
5426 /* Windows bitmaps are in BGR order. */
5427 *pixel = GetBValue (color);
5428 *(pixel + 1) = GetGValue (color);
5429 *(pixel + 2) = GetRValue (color);
5431 /* Monochrome images. */
5432 else if (ximg->info.bmiHeader.biBitCount == 1)
5434 int rowbytes = width / 8;
5435 /* Ensure scanlines are aligned on 4 byte boundaries. */
5436 if (rowbytes % 4)
5437 rowbytes += 4 - (rowbytes % 4);
5438 pixel = ximg->data + y * rowbytes + x / 8;
5439 /* Filter out palette info. */
5440 if (color & 0x00ffffff)
5441 *pixel = *pixel | (1 << x % 8);
5442 else
5443 *pixel = *pixel & ~(1 << x % 8);
5445 else
5446 image_error ("XPutPixel: palette image not supported", Qnil, Qnil);
5449 #endif /* HAVE_NTGUI */
5451 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
5452 RGB members are set. F is the frame on which this all happens.
5453 COLORS will be freed; an existing IMG->pixmap will be freed, too. */
5455 static void
5456 x_from_xcolors (f, img, colors)
5457 struct frame *f;
5458 struct image *img;
5459 XColor *colors;
5461 int x, y;
5462 XImagePtr oimg;
5463 Pixmap pixmap;
5464 XColor *p;
5466 init_color_table ();
5468 x_create_x_image_and_pixmap (f, img->width, img->height, 0,
5469 &oimg, &pixmap);
5470 p = colors;
5471 for (y = 0; y < img->height; ++y)
5472 for (x = 0; x < img->width; ++x, ++p)
5474 unsigned long pixel;
5475 pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
5476 XPutPixel (oimg, x, y, pixel);
5479 xfree (colors);
5480 x_clear_image_1 (f, img, 1, 0, 1);
5482 x_put_x_image (f, oimg, pixmap, img->width, img->height);
5483 x_destroy_x_image (oimg);
5484 img->pixmap = pixmap;
5485 #ifdef COLOR_TABLE_SUPPORT
5486 img->colors = colors_in_color_table (&img->ncolors);
5487 free_color_table ();
5488 #endif /* COLOR_TABLE_SUPPORT */
5492 /* On frame F, perform edge-detection on image IMG.
5494 MATRIX is a nine-element array specifying the transformation
5495 matrix. See emboss_matrix for an example.
5497 COLOR_ADJUST is a color adjustment added to each pixel of the
5498 outgoing image. */
5500 static void
5501 x_detect_edges (f, img, matrix, color_adjust)
5502 struct frame *f;
5503 struct image *img;
5504 int matrix[9], color_adjust;
5506 XColor *colors = x_to_xcolors (f, img, 1);
5507 XColor *new, *p;
5508 int x, y, i, sum;
5510 for (i = sum = 0; i < 9; ++i)
5511 sum += eabs (matrix[i]);
5513 #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
5515 new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
5517 for (y = 0; y < img->height; ++y)
5519 p = COLOR (new, 0, y);
5520 p->red = p->green = p->blue = 0xffff/2;
5521 p = COLOR (new, img->width - 1, y);
5522 p->red = p->green = p->blue = 0xffff/2;
5525 for (x = 1; x < img->width - 1; ++x)
5527 p = COLOR (new, x, 0);
5528 p->red = p->green = p->blue = 0xffff/2;
5529 p = COLOR (new, x, img->height - 1);
5530 p->red = p->green = p->blue = 0xffff/2;
5533 for (y = 1; y < img->height - 1; ++y)
5535 p = COLOR (new, 1, y);
5537 for (x = 1; x < img->width - 1; ++x, ++p)
5539 int r, g, b, y1, x1;
5541 r = g = b = i = 0;
5542 for (y1 = y - 1; y1 < y + 2; ++y1)
5543 for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
5544 if (matrix[i])
5546 XColor *t = COLOR (colors, x1, y1);
5547 r += matrix[i] * t->red;
5548 g += matrix[i] * t->green;
5549 b += matrix[i] * t->blue;
5552 r = (r / sum + color_adjust) & 0xffff;
5553 g = (g / sum + color_adjust) & 0xffff;
5554 b = (b / sum + color_adjust) & 0xffff;
5555 p->red = p->green = p->blue = COLOR_INTENSITY (r, g, b);
5559 xfree (colors);
5560 x_from_xcolors (f, img, new);
5562 #undef COLOR
5566 /* Perform the pre-defined `emboss' edge-detection on image IMG
5567 on frame F. */
5569 static void
5570 x_emboss (f, img)
5571 struct frame *f;
5572 struct image *img;
5574 x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
5578 /* Transform image IMG which is used on frame F with a Laplace
5579 edge-detection algorithm. The result is an image that can be used
5580 to draw disabled buttons, for example. */
5582 static void
5583 x_laplace (f, img)
5584 struct frame *f;
5585 struct image *img;
5587 x_detect_edges (f, img, laplace_matrix, 45000);
5591 /* Perform edge-detection on image IMG on frame F, with specified
5592 transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
5594 MATRIX must be either
5596 - a list of at least 9 numbers in row-major form
5597 - a vector of at least 9 numbers
5599 COLOR_ADJUST nil means use a default; otherwise it must be a
5600 number. */
5602 static void
5603 x_edge_detection (f, img, matrix, color_adjust)
5604 struct frame *f;
5605 struct image *img;
5606 Lisp_Object matrix, color_adjust;
5608 int i = 0;
5609 int trans[9];
5611 if (CONSP (matrix))
5613 for (i = 0;
5614 i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
5615 ++i, matrix = XCDR (matrix))
5616 trans[i] = XFLOATINT (XCAR (matrix));
5618 else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
5620 for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
5621 trans[i] = XFLOATINT (AREF (matrix, i));
5624 if (NILP (color_adjust))
5625 color_adjust = make_number (0xffff / 2);
5627 if (i == 9 && NUMBERP (color_adjust))
5628 x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
5632 /* Transform image IMG on frame F so that it looks disabled. */
5634 static void
5635 x_disable_image (f, img)
5636 struct frame *f;
5637 struct image *img;
5639 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5640 #ifdef HAVE_NTGUI
5641 int n_planes = dpyinfo->n_planes * dpyinfo->n_cbits;
5642 #else
5643 int n_planes = dpyinfo->n_planes;
5644 #endif /* HAVE_NTGUI */
5646 if (n_planes >= 2)
5648 /* Color (or grayscale). Convert to gray, and equalize. Just
5649 drawing such images with a stipple can look very odd, so
5650 we're using this method instead. */
5651 XColor *colors = x_to_xcolors (f, img, 1);
5652 XColor *p, *end;
5653 const int h = 15000;
5654 const int l = 30000;
5656 for (p = colors, end = colors + img->width * img->height;
5657 p < end;
5658 ++p)
5660 int i = COLOR_INTENSITY (p->red, p->green, p->blue);
5661 int i2 = (0xffff - h - l) * i / 0xffff + l;
5662 p->red = p->green = p->blue = i2;
5665 x_from_xcolors (f, img, colors);
5668 /* Draw a cross over the disabled image, if we must or if we
5669 should. */
5670 if (n_planes < 2 || cross_disabled_images)
5672 #ifndef HAVE_NTGUI
5673 Display *dpy = FRAME_X_DISPLAY (f);
5674 GC gc;
5676 #ifdef MAC_OS
5677 #define MaskForeground(f) PIX_MASK_DRAW
5678 #else
5679 #define MaskForeground(f) WHITE_PIX_DEFAULT (f)
5680 #endif
5682 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
5683 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
5684 XDrawLine (dpy, img->pixmap, gc, 0, 0,
5685 img->width - 1, img->height - 1);
5686 XDrawLine (dpy, img->pixmap, gc, 0, img->height - 1,
5687 img->width - 1, 0);
5688 XFreeGC (dpy, gc);
5690 if (img->mask)
5692 gc = XCreateGC (dpy, img->mask, 0, NULL);
5693 XSetForeground (dpy, gc, MaskForeground (f));
5694 XDrawLine (dpy, img->mask, gc, 0, 0,
5695 img->width - 1, img->height - 1);
5696 XDrawLine (dpy, img->mask, gc, 0, img->height - 1,
5697 img->width - 1, 0);
5698 XFreeGC (dpy, gc);
5700 #else
5701 HDC hdc, bmpdc;
5702 HGDIOBJ prev;
5704 hdc = get_frame_dc (f);
5705 bmpdc = CreateCompatibleDC (hdc);
5706 release_frame_dc (f, hdc);
5708 prev = SelectObject (bmpdc, img->pixmap);
5710 SetTextColor (bmpdc, BLACK_PIX_DEFAULT (f));
5711 MoveToEx (bmpdc, 0, 0, NULL);
5712 LineTo (bmpdc, img->width - 1, img->height - 1);
5713 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5714 LineTo (bmpdc, img->width - 1, 0);
5716 if (img->mask)
5718 SelectObject (bmpdc, img->mask);
5719 SetTextColor (bmpdc, WHITE_PIX_DEFAULT (f));
5720 MoveToEx (bmpdc, 0, 0, NULL);
5721 LineTo (bmpdc, img->width - 1, img->height - 1);
5722 MoveToEx (bmpdc, 0, img->height - 1, NULL);
5723 LineTo (bmpdc, img->width - 1, 0);
5725 SelectObject (bmpdc, prev);
5726 DeleteDC (bmpdc);
5727 #endif /* HAVE_NTGUI */
5732 /* Build a mask for image IMG which is used on frame F. FILE is the
5733 name of an image file, for error messages. HOW determines how to
5734 determine the background color of IMG. If it is a list '(R G B)',
5735 with R, G, and B being integers >= 0, take that as the color of the
5736 background. Otherwise, determine the background color of IMG
5737 heuristically. Value is non-zero if successful. */
5739 static int
5740 x_build_heuristic_mask (f, img, how)
5741 struct frame *f;
5742 struct image *img;
5743 Lisp_Object how;
5745 XImagePtr_or_DC ximg;
5746 #ifndef HAVE_NTGUI
5747 XImagePtr mask_img;
5748 #else
5749 HDC frame_dc;
5750 HGDIOBJ prev;
5751 char *mask_img;
5752 int row_width;
5753 #endif /* HAVE_NTGUI */
5754 int x, y, rc, use_img_background;
5755 unsigned long bg = 0;
5757 if (img->mask)
5759 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
5760 img->mask = NO_PIXMAP;
5761 img->background_transparent_valid = 0;
5764 #ifndef HAVE_NTGUI
5765 /* Create an image and pixmap serving as mask. */
5766 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5767 &mask_img, &img->mask);
5768 if (!rc)
5769 return 0;
5771 /* Get the X image of IMG->pixmap. */
5772 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
5773 img->width, img->height,
5774 ~0, ZPixmap);
5775 #else
5776 /* Create the bit array serving as mask. */
5777 row_width = (img->width + 7) / 8;
5778 mask_img = xmalloc (row_width * img->height);
5779 bzero (mask_img, row_width * img->height);
5781 /* Create a memory device context for IMG->pixmap. */
5782 frame_dc = get_frame_dc (f);
5783 ximg = CreateCompatibleDC (frame_dc);
5784 release_frame_dc (f, frame_dc);
5785 prev = SelectObject (ximg, img->pixmap);
5786 #endif /* HAVE_NTGUI */
5788 /* Determine the background color of ximg. If HOW is `(R G B)'
5789 take that as color. Otherwise, use the image's background color. */
5790 use_img_background = 1;
5792 if (CONSP (how))
5794 int rgb[3], i;
5796 for (i = 0; i < 3 && CONSP (how) && NATNUMP (XCAR (how)); ++i)
5798 rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
5799 how = XCDR (how);
5802 if (i == 3 && NILP (how))
5804 char color_name[30];
5805 sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
5806 bg = (
5807 #ifdef HAVE_NTGUI
5808 0x00ffffff & /* Filter out palette info. */
5809 #endif /* HAVE_NTGUI */
5810 x_alloc_image_color (f, img, build_string (color_name), 0));
5811 use_img_background = 0;
5815 if (use_img_background)
5816 bg = four_corners_best (ximg, img->corners, img->width, img->height);
5818 /* Set all bits in mask_img to 1 whose color in ximg is different
5819 from the background color bg. */
5820 #ifndef HAVE_NTGUI
5821 for (y = 0; y < img->height; ++y)
5822 for (x = 0; x < img->width; ++x)
5823 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5824 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5826 /* Fill in the background_transparent field while we have the mask handy. */
5827 image_background_transparent (img, f, mask_img);
5829 /* Put mask_img into img->mask. */
5830 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5831 x_destroy_x_image (mask_img);
5833 #else
5834 for (y = 0; y < img->height; ++y)
5835 for (x = 0; x < img->width; ++x)
5837 COLORREF p = GetPixel (ximg, x, y);
5838 if (p != bg)
5839 mask_img[y * row_width + x / 8] |= 1 << (x % 8);
5842 /* Create the mask image. */
5843 img->mask = w32_create_pixmap_from_bitmap_data (img->width, img->height,
5844 mask_img);
5845 /* Fill in the background_transparent field while we have the mask handy. */
5846 SelectObject (ximg, img->mask);
5847 image_background_transparent (img, f, ximg);
5849 /* Was: x_destroy_x_image ((XImagePtr )mask_img); which seems bogus ++kfs */
5850 xfree (mask_img);
5851 #endif /* HAVE_NTGUI */
5853 Destroy_Image (ximg, prev);
5855 return 1;
5859 /***********************************************************************
5860 PBM (mono, gray, color)
5861 ***********************************************************************/
5863 static int pbm_image_p P_ ((Lisp_Object object));
5864 static int pbm_load P_ ((struct frame *f, struct image *img));
5865 static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
5867 /* The symbol `pbm' identifying images of this type. */
5869 Lisp_Object Qpbm;
5871 /* Indices of image specification fields in gs_format, below. */
5873 enum pbm_keyword_index
5875 PBM_TYPE,
5876 PBM_FILE,
5877 PBM_DATA,
5878 PBM_ASCENT,
5879 PBM_MARGIN,
5880 PBM_RELIEF,
5881 PBM_ALGORITHM,
5882 PBM_HEURISTIC_MASK,
5883 PBM_MASK,
5884 PBM_FOREGROUND,
5885 PBM_BACKGROUND,
5886 PBM_LAST
5889 /* Vector of image_keyword structures describing the format
5890 of valid user-defined image specifications. */
5892 static struct image_keyword pbm_format[PBM_LAST] =
5894 {":type", IMAGE_SYMBOL_VALUE, 1},
5895 {":file", IMAGE_STRING_VALUE, 0},
5896 {":data", IMAGE_STRING_VALUE, 0},
5897 {":ascent", IMAGE_ASCENT_VALUE, 0},
5898 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
5899 {":relief", IMAGE_INTEGER_VALUE, 0},
5900 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5901 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5902 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
5903 {":foreground", IMAGE_STRING_OR_NIL_VALUE, 0},
5904 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
5907 /* Structure describing the image type `pbm'. */
5909 static struct image_type pbm_type =
5911 &Qpbm,
5912 pbm_image_p,
5913 pbm_load,
5914 x_clear_image,
5915 NULL
5919 /* Return non-zero if OBJECT is a valid PBM image specification. */
5921 static int
5922 pbm_image_p (object)
5923 Lisp_Object object;
5925 struct image_keyword fmt[PBM_LAST];
5927 bcopy (pbm_format, fmt, sizeof fmt);
5929 if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm))
5930 return 0;
5932 /* Must specify either :data or :file. */
5933 return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
5937 /* Scan a decimal number from *S and return it. Advance *S while
5938 reading the number. END is the end of the string. Value is -1 at
5939 end of input. */
5941 static int
5942 pbm_scan_number (s, end)
5943 unsigned char **s, *end;
5945 int c = 0, val = -1;
5947 while (*s < end)
5949 /* Skip white-space. */
5950 while (*s < end && (c = *(*s)++, isspace (c)))
5953 if (c == '#')
5955 /* Skip comment to end of line. */
5956 while (*s < end && (c = *(*s)++, c != '\n'))
5959 else if (isdigit (c))
5961 /* Read decimal number. */
5962 val = c - '0';
5963 while (*s < end && (c = *(*s)++, isdigit (c)))
5964 val = 10 * val + c - '0';
5965 break;
5967 else
5968 break;
5971 return val;
5975 #ifdef HAVE_NTGUI
5976 #if 0 /* Unused. ++kfs */
5978 /* Read FILE into memory. Value is a pointer to a buffer allocated
5979 with xmalloc holding FILE's contents. Value is null if an error
5980 occurred. *SIZE is set to the size of the file. */
5982 static char *
5983 pbm_read_file (file, size)
5984 Lisp_Object file;
5985 int *size;
5987 FILE *fp = NULL;
5988 char *buf = NULL;
5989 struct stat st;
5991 if (stat (SDATA (file), &st) == 0
5992 && (fp = fopen (SDATA (file), "rb")) != NULL
5993 && (buf = (char *) xmalloc (st.st_size),
5994 fread (buf, 1, st.st_size, fp) == st.st_size))
5996 *size = st.st_size;
5997 fclose (fp);
5999 else
6001 if (fp)
6002 fclose (fp);
6003 if (buf)
6005 xfree (buf);
6006 buf = NULL;
6010 return buf;
6012 #endif
6013 #endif /* HAVE_NTGUI */
6015 /* Load PBM image IMG for use on frame F. */
6017 static int
6018 pbm_load (f, img)
6019 struct frame *f;
6020 struct image *img;
6022 int raw_p, x, y;
6023 int width, height, max_color_idx = 0;
6024 XImagePtr ximg;
6025 Lisp_Object file, specified_file;
6026 enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
6027 struct gcpro gcpro1;
6028 unsigned char *contents = NULL;
6029 unsigned char *end, *p;
6030 int size;
6032 specified_file = image_spec_value (img->spec, QCfile, NULL);
6033 file = Qnil;
6034 GCPRO1 (file);
6036 if (STRINGP (specified_file))
6038 file = x_find_image_file (specified_file);
6039 if (!STRINGP (file))
6041 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6042 UNGCPRO;
6043 return 0;
6046 contents = slurp_file (SDATA (file), &size);
6047 if (contents == NULL)
6049 image_error ("Error reading `%s'", file, Qnil);
6050 UNGCPRO;
6051 return 0;
6054 p = contents;
6055 end = contents + size;
6057 else
6059 Lisp_Object data;
6060 data = image_spec_value (img->spec, QCdata, NULL);
6061 p = SDATA (data);
6062 end = p + SBYTES (data);
6065 /* Check magic number. */
6066 if (end - p < 2 || *p++ != 'P')
6068 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6069 error:
6070 xfree (contents);
6071 UNGCPRO;
6072 return 0;
6075 switch (*p++)
6077 case '1':
6078 raw_p = 0, type = PBM_MONO;
6079 break;
6081 case '2':
6082 raw_p = 0, type = PBM_GRAY;
6083 break;
6085 case '3':
6086 raw_p = 0, type = PBM_COLOR;
6087 break;
6089 case '4':
6090 raw_p = 1, type = PBM_MONO;
6091 break;
6093 case '5':
6094 raw_p = 1, type = PBM_GRAY;
6095 break;
6097 case '6':
6098 raw_p = 1, type = PBM_COLOR;
6099 break;
6101 default:
6102 image_error ("Not a PBM image: `%s'", img->spec, Qnil);
6103 goto error;
6106 /* Read width, height, maximum color-component. Characters
6107 starting with `#' up to the end of a line are ignored. */
6108 width = pbm_scan_number (&p, end);
6109 height = pbm_scan_number (&p, end);
6111 if (type != PBM_MONO)
6113 max_color_idx = pbm_scan_number (&p, end);
6114 if (max_color_idx > 65535 || max_color_idx < 0)
6116 image_error ("Unsupported maximum PBM color value", Qnil, Qnil);
6117 goto error;
6121 if (!check_image_size (f, width, height))
6123 image_error ("Invalid image size", Qnil, Qnil);
6124 goto error;
6127 if (!x_create_x_image_and_pixmap (f, width, height, 0,
6128 &ximg, &img->pixmap))
6129 goto error;
6131 /* Initialize the color hash table. */
6132 init_color_table ();
6134 if (type == PBM_MONO)
6136 int c = 0, g;
6137 struct image_keyword fmt[PBM_LAST];
6138 unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
6139 unsigned long bg = FRAME_BACKGROUND_PIXEL (f);
6141 /* Parse the image specification. */
6142 bcopy (pbm_format, fmt, sizeof fmt);
6143 parse_image_spec (img->spec, fmt, PBM_LAST, Qpbm);
6145 /* Get foreground and background colors, maybe allocate colors. */
6146 if (fmt[PBM_FOREGROUND].count
6147 && STRINGP (fmt[PBM_FOREGROUND].value))
6148 fg = x_alloc_image_color (f, img, fmt[PBM_FOREGROUND].value, fg);
6149 if (fmt[PBM_BACKGROUND].count
6150 && STRINGP (fmt[PBM_BACKGROUND].value))
6152 bg = x_alloc_image_color (f, img, fmt[PBM_BACKGROUND].value, bg);
6153 img->background = bg;
6154 img->background_valid = 1;
6157 for (y = 0; y < height; ++y)
6158 for (x = 0; x < width; ++x)
6160 if (raw_p)
6162 if ((x & 7) == 0)
6164 if (p >= end)
6166 x_destroy_x_image (ximg);
6167 x_clear_image (f, img);
6168 image_error ("Invalid image size in image `%s'",
6169 img->spec, Qnil);
6170 goto error;
6172 c = *p++;
6174 g = c & 0x80;
6175 c <<= 1;
6177 else
6178 g = pbm_scan_number (&p, end);
6180 XPutPixel (ximg, x, y, g ? fg : bg);
6183 else
6185 int expected_size = height * width;
6186 if (max_color_idx > 255)
6187 expected_size *= 2;
6188 if (type == PBM_COLOR)
6189 expected_size *= 3;
6191 if (raw_p && p + expected_size > end)
6193 x_destroy_x_image (ximg);
6194 x_clear_image (f, img);
6195 image_error ("Invalid image size in image `%s'",
6196 img->spec, Qnil);
6197 goto error;
6200 for (y = 0; y < height; ++y)
6201 for (x = 0; x < width; ++x)
6203 int r, g, b;
6205 if (type == PBM_GRAY && raw_p)
6207 r = g = b = *p++;
6208 if (max_color_idx > 255)
6209 r = g = b = r * 256 + *p++;
6211 else if (type == PBM_GRAY)
6212 r = g = b = pbm_scan_number (&p, end);
6213 else if (raw_p)
6215 r = *p++;
6216 if (max_color_idx > 255)
6217 r = r * 256 + *p++;
6218 g = *p++;
6219 if (max_color_idx > 255)
6220 g = g * 256 + *p++;
6221 b = *p++;
6222 if (max_color_idx > 255)
6223 b = b * 256 + *p++;
6225 else
6227 r = pbm_scan_number (&p, end);
6228 g = pbm_scan_number (&p, end);
6229 b = pbm_scan_number (&p, end);
6232 if (r < 0 || g < 0 || b < 0)
6234 x_destroy_x_image (ximg);
6235 image_error ("Invalid pixel value in image `%s'",
6236 img->spec, Qnil);
6237 goto error;
6240 /* RGB values are now in the range 0..max_color_idx.
6241 Scale this to the range 0..0xffff supported by X. */
6242 r = (double) r * 65535 / max_color_idx;
6243 g = (double) g * 65535 / max_color_idx;
6244 b = (double) b * 65535 / max_color_idx;
6245 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6249 #ifdef COLOR_TABLE_SUPPORT
6250 /* Store in IMG->colors the colors allocated for the image, and
6251 free the color table. */
6252 img->colors = colors_in_color_table (&img->ncolors);
6253 free_color_table ();
6254 #endif /* COLOR_TABLE_SUPPORT */
6256 img->width = width;
6257 img->height = height;
6259 /* Maybe fill in the background field while we have ximg handy. */
6261 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6262 /* Casting avoids a GCC warning. */
6263 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6265 /* Put the image into a pixmap. */
6266 x_put_x_image (f, ximg, img->pixmap, width, height);
6267 x_destroy_x_image (ximg);
6269 /* X and W32 versions did it here, MAC version above. ++kfs
6270 img->width = width;
6271 img->height = height; */
6273 UNGCPRO;
6274 xfree (contents);
6275 return 1;
6279 /***********************************************************************
6281 ***********************************************************************/
6283 #if defined (HAVE_PNG) || defined (MAC_OS)
6285 /* Function prototypes. */
6287 static int png_image_p P_ ((Lisp_Object object));
6288 static int png_load P_ ((struct frame *f, struct image *img));
6290 /* The symbol `png' identifying images of this type. */
6292 Lisp_Object Qpng;
6294 /* Indices of image specification fields in png_format, below. */
6296 enum png_keyword_index
6298 PNG_TYPE,
6299 PNG_DATA,
6300 PNG_FILE,
6301 PNG_ASCENT,
6302 PNG_MARGIN,
6303 PNG_RELIEF,
6304 PNG_ALGORITHM,
6305 PNG_HEURISTIC_MASK,
6306 PNG_MASK,
6307 PNG_BACKGROUND,
6308 PNG_LAST
6311 /* Vector of image_keyword structures describing the format
6312 of valid user-defined image specifications. */
6314 static struct image_keyword png_format[PNG_LAST] =
6316 {":type", IMAGE_SYMBOL_VALUE, 1},
6317 {":data", IMAGE_STRING_VALUE, 0},
6318 {":file", IMAGE_STRING_VALUE, 0},
6319 {":ascent", IMAGE_ASCENT_VALUE, 0},
6320 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6321 {":relief", IMAGE_INTEGER_VALUE, 0},
6322 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6323 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6324 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6325 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6328 /* Structure describing the image type `png'. */
6330 static struct image_type png_type =
6332 &Qpng,
6333 png_image_p,
6334 png_load,
6335 x_clear_image,
6336 NULL
6339 /* Return non-zero if OBJECT is a valid PNG image specification. */
6341 static int
6342 png_image_p (object)
6343 Lisp_Object object;
6345 struct image_keyword fmt[PNG_LAST];
6346 bcopy (png_format, fmt, sizeof fmt);
6348 if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
6349 return 0;
6351 /* Must specify either the :data or :file keyword. */
6352 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6355 #endif /* HAVE_PNG || MAC_OS */
6358 #ifdef HAVE_PNG
6360 #if defined HAVE_LIBPNG_PNG_H
6361 # include <libpng/png.h>
6362 #else
6363 # include <png.h>
6364 #endif
6366 #ifdef HAVE_NTGUI
6367 /* PNG library details. */
6369 DEF_IMGLIB_FN (png_get_io_ptr);
6370 DEF_IMGLIB_FN (png_check_sig);
6371 DEF_IMGLIB_FN (png_create_read_struct);
6372 DEF_IMGLIB_FN (png_create_info_struct);
6373 DEF_IMGLIB_FN (png_destroy_read_struct);
6374 DEF_IMGLIB_FN (png_set_read_fn);
6375 DEF_IMGLIB_FN (png_set_sig_bytes);
6376 DEF_IMGLIB_FN (png_read_info);
6377 DEF_IMGLIB_FN (png_get_IHDR);
6378 DEF_IMGLIB_FN (png_get_valid);
6379 DEF_IMGLIB_FN (png_set_strip_16);
6380 DEF_IMGLIB_FN (png_set_expand);
6381 DEF_IMGLIB_FN (png_set_gray_to_rgb);
6382 DEF_IMGLIB_FN (png_set_background);
6383 DEF_IMGLIB_FN (png_get_bKGD);
6384 DEF_IMGLIB_FN (png_read_update_info);
6385 DEF_IMGLIB_FN (png_get_channels);
6386 DEF_IMGLIB_FN (png_get_rowbytes);
6387 DEF_IMGLIB_FN (png_read_image);
6388 DEF_IMGLIB_FN (png_read_end);
6389 DEF_IMGLIB_FN (png_error);
6391 static int
6392 init_png_functions (Lisp_Object libraries)
6394 HMODULE library;
6396 /* Try loading libpng under probable names. */
6397 if (!(library = w32_delayed_load (libraries, Qpng)))
6398 return 0;
6400 LOAD_IMGLIB_FN (library, png_get_io_ptr);
6401 LOAD_IMGLIB_FN (library, png_check_sig);
6402 LOAD_IMGLIB_FN (library, png_create_read_struct);
6403 LOAD_IMGLIB_FN (library, png_create_info_struct);
6404 LOAD_IMGLIB_FN (library, png_destroy_read_struct);
6405 LOAD_IMGLIB_FN (library, png_set_read_fn);
6406 LOAD_IMGLIB_FN (library, png_set_sig_bytes);
6407 LOAD_IMGLIB_FN (library, png_read_info);
6408 LOAD_IMGLIB_FN (library, png_get_IHDR);
6409 LOAD_IMGLIB_FN (library, png_get_valid);
6410 LOAD_IMGLIB_FN (library, png_set_strip_16);
6411 LOAD_IMGLIB_FN (library, png_set_expand);
6412 LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
6413 LOAD_IMGLIB_FN (library, png_set_background);
6414 LOAD_IMGLIB_FN (library, png_get_bKGD);
6415 LOAD_IMGLIB_FN (library, png_read_update_info);
6416 LOAD_IMGLIB_FN (library, png_get_channels);
6417 LOAD_IMGLIB_FN (library, png_get_rowbytes);
6418 LOAD_IMGLIB_FN (library, png_read_image);
6419 LOAD_IMGLIB_FN (library, png_read_end);
6420 LOAD_IMGLIB_FN (library, png_error);
6421 return 1;
6423 #else
6425 #define fn_png_get_io_ptr png_get_io_ptr
6426 #define fn_png_check_sig png_check_sig
6427 #define fn_png_create_read_struct png_create_read_struct
6428 #define fn_png_create_info_struct png_create_info_struct
6429 #define fn_png_destroy_read_struct png_destroy_read_struct
6430 #define fn_png_set_read_fn png_set_read_fn
6431 #define fn_png_set_sig_bytes png_set_sig_bytes
6432 #define fn_png_read_info png_read_info
6433 #define fn_png_get_IHDR png_get_IHDR
6434 #define fn_png_get_valid png_get_valid
6435 #define fn_png_set_strip_16 png_set_strip_16
6436 #define fn_png_set_expand png_set_expand
6437 #define fn_png_set_gray_to_rgb png_set_gray_to_rgb
6438 #define fn_png_set_background png_set_background
6439 #define fn_png_get_bKGD png_get_bKGD
6440 #define fn_png_read_update_info png_read_update_info
6441 #define fn_png_get_channels png_get_channels
6442 #define fn_png_get_rowbytes png_get_rowbytes
6443 #define fn_png_read_image png_read_image
6444 #define fn_png_read_end png_read_end
6445 #define fn_png_error png_error
6447 #endif /* HAVE_NTGUI */
6449 /* Error and warning handlers installed when the PNG library
6450 is initialized. */
6452 static void
6453 my_png_error (png_ptr, msg)
6454 png_struct *png_ptr;
6455 char *msg;
6457 xassert (png_ptr != NULL);
6458 image_error ("PNG error: %s", build_string (msg), Qnil);
6459 longjmp (png_ptr->jmpbuf, 1);
6463 static void
6464 my_png_warning (png_ptr, msg)
6465 png_struct *png_ptr;
6466 char *msg;
6468 xassert (png_ptr != NULL);
6469 image_error ("PNG warning: %s", build_string (msg), Qnil);
6472 /* Memory source for PNG decoding. */
6474 struct png_memory_storage
6476 unsigned char *bytes; /* The data */
6477 size_t len; /* How big is it? */
6478 int index; /* Where are we? */
6482 /* Function set as reader function when reading PNG image from memory.
6483 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6484 bytes from the input to DATA. */
6486 static void
6487 png_read_from_memory (png_ptr, data, length)
6488 png_structp png_ptr;
6489 png_bytep data;
6490 png_size_t length;
6492 struct png_memory_storage *tbr
6493 = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
6495 if (length > tbr->len - tbr->index)
6496 fn_png_error (png_ptr, "Read error");
6498 bcopy (tbr->bytes + tbr->index, data, length);
6499 tbr->index = tbr->index + length;
6503 /* Function set as reader function when reading PNG image from a file.
6504 PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
6505 bytes from the input to DATA. */
6507 static void
6508 png_read_from_file (png_ptr, data, length)
6509 png_structp png_ptr;
6510 png_bytep data;
6511 png_size_t length;
6513 FILE *fp = (FILE *) fn_png_get_io_ptr (png_ptr);
6515 if (fread (data, 1, length, fp) < length)
6516 fn_png_error (png_ptr, "Read error");
6520 /* Load PNG image IMG for use on frame F. Value is non-zero if
6521 successful. */
6523 static int
6524 png_load (f, img)
6525 struct frame *f;
6526 struct image *img;
6528 Lisp_Object file, specified_file;
6529 Lisp_Object specified_data;
6530 int x, y, i;
6531 XImagePtr ximg, mask_img = NULL;
6532 struct gcpro gcpro1;
6533 png_struct *png_ptr = NULL;
6534 png_info *info_ptr = NULL, *end_info = NULL;
6535 FILE *volatile fp = NULL;
6536 png_byte sig[8];
6537 png_byte * volatile pixels = NULL;
6538 png_byte ** volatile rows = NULL;
6539 png_uint_32 width, height;
6540 int bit_depth, color_type, interlace_type;
6541 png_byte channels;
6542 png_uint_32 row_bytes;
6543 int transparent_p;
6544 struct png_memory_storage tbr; /* Data to be read */
6546 /* Find out what file to load. */
6547 specified_file = image_spec_value (img->spec, QCfile, NULL);
6548 specified_data = image_spec_value (img->spec, QCdata, NULL);
6549 file = Qnil;
6550 GCPRO1 (file);
6552 if (NILP (specified_data))
6554 file = x_find_image_file (specified_file);
6555 if (!STRINGP (file))
6557 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6558 UNGCPRO;
6559 return 0;
6562 /* Open the image file. */
6563 fp = fopen (SDATA (file), "rb");
6564 if (!fp)
6566 image_error ("Cannot open image file `%s'", file, Qnil);
6567 UNGCPRO;
6568 return 0;
6571 /* Check PNG signature. */
6572 if (fread (sig, 1, sizeof sig, fp) != sizeof sig
6573 || !fn_png_check_sig (sig, sizeof sig))
6575 image_error ("Not a PNG file: `%s'", file, Qnil);
6576 UNGCPRO;
6577 fclose (fp);
6578 return 0;
6581 else
6583 /* Read from memory. */
6584 tbr.bytes = SDATA (specified_data);
6585 tbr.len = SBYTES (specified_data);
6586 tbr.index = 0;
6588 /* Check PNG signature. */
6589 if (tbr.len < sizeof sig
6590 || !fn_png_check_sig (tbr.bytes, sizeof sig))
6592 image_error ("Not a PNG image: `%s'", img->spec, Qnil);
6593 UNGCPRO;
6594 return 0;
6597 /* Need to skip past the signature. */
6598 tbr.bytes += sizeof (sig);
6601 /* Initialize read and info structs for PNG lib. Casting return
6602 value avoids a GCC warning on W32. */
6603 png_ptr = (png_structp)fn_png_create_read_struct (PNG_LIBPNG_VER_STRING,
6604 NULL, my_png_error,
6605 my_png_warning);
6606 if (!png_ptr)
6608 if (fp) fclose (fp);
6609 UNGCPRO;
6610 return 0;
6613 /* Casting return value avoids a GCC warning on W32. */
6614 info_ptr = (png_infop)fn_png_create_info_struct (png_ptr);
6615 if (!info_ptr)
6617 fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
6618 if (fp) fclose (fp);
6619 UNGCPRO;
6620 return 0;
6623 /* Casting return value avoids a GCC warning on W32. */
6624 end_info = (png_infop)fn_png_create_info_struct (png_ptr);
6625 if (!end_info)
6627 fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
6628 if (fp) fclose (fp);
6629 UNGCPRO;
6630 return 0;
6633 /* Set error jump-back. We come back here when the PNG library
6634 detects an error. */
6635 if (setjmp (png_ptr->jmpbuf))
6637 error:
6638 if (png_ptr)
6639 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6640 xfree (pixels);
6641 xfree (rows);
6642 if (fp) fclose (fp);
6643 UNGCPRO;
6644 return 0;
6647 /* Read image info. */
6648 if (!NILP (specified_data))
6649 fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
6650 else
6651 fn_png_set_read_fn (png_ptr, (void *) fp, png_read_from_file);
6653 fn_png_set_sig_bytes (png_ptr, sizeof sig);
6654 fn_png_read_info (png_ptr, info_ptr);
6655 fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
6656 &interlace_type, NULL, NULL);
6658 if (!check_image_size (f, width, height))
6659 goto error;
6661 /* If image contains simply transparency data, we prefer to
6662 construct a clipping mask. */
6663 if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
6664 transparent_p = 1;
6665 else
6666 transparent_p = 0;
6668 /* This function is easier to write if we only have to handle
6669 one data format: RGB or RGBA with 8 bits per channel. Let's
6670 transform other formats into that format. */
6672 /* Strip more than 8 bits per channel. */
6673 if (bit_depth == 16)
6674 fn_png_set_strip_16 (png_ptr);
6676 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
6677 if available. */
6678 fn_png_set_expand (png_ptr);
6680 /* Convert grayscale images to RGB. */
6681 if (color_type == PNG_COLOR_TYPE_GRAY
6682 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6683 fn_png_set_gray_to_rgb (png_ptr);
6685 /* Handle alpha channel by combining the image with a background
6686 color. Do this only if a real alpha channel is supplied. For
6687 simple transparency, we prefer a clipping mask. */
6688 if (!transparent_p)
6690 /* png_color_16 *image_bg; */
6691 Lisp_Object specified_bg
6692 = image_spec_value (img->spec, QCbackground, NULL);
6693 int shift = (bit_depth == 16) ? 0 : 8;
6695 if (STRINGP (specified_bg))
6696 /* The user specified `:background', use that. */
6698 /* W32 version incorrectly used COLORREF here!! ++kfs */
6699 XColor color;
6700 if (x_defined_color (f, SDATA (specified_bg), &color, 0))
6702 png_color_16 user_bg;
6704 bzero (&user_bg, sizeof user_bg);
6705 user_bg.red = color.red >> shift;
6706 user_bg.green = color.green >> shift;
6707 user_bg.blue = color.blue >> shift;
6709 fn_png_set_background (png_ptr, &user_bg,
6710 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6713 else
6715 /* We use the current frame background, ignoring any default
6716 background color set by the image. */
6717 #ifdef HAVE_X_WINDOWS
6718 XColor color;
6719 png_color_16 frame_background;
6721 color.pixel = FRAME_BACKGROUND_PIXEL (f);
6722 x_query_color (f, &color);
6724 bzero (&frame_background, sizeof frame_background);
6725 frame_background.red = color.red >> shift;
6726 frame_background.green = color.green >> shift;
6727 frame_background.blue = color.blue >> shift;
6728 #endif /* HAVE_X_WINDOWS */
6730 #ifdef HAVE_NTGUI
6731 COLORREF color;
6732 png_color_16 frame_background;
6733 color = FRAME_BACKGROUND_PIXEL (f);
6734 #if 0 /* W32 TODO : Colormap support. */
6735 x_query_color (f, &color);
6736 #endif
6737 bzero (&frame_background, sizeof frame_background);
6738 frame_background.red = GetRValue (color);
6739 frame_background.green = GetGValue (color);
6740 frame_background.blue = GetBValue (color);
6741 #endif /* HAVE_NTGUI */
6743 #ifdef MAC_OS
6744 unsigned long color;
6745 png_color_16 frame_background;
6746 color = FRAME_BACKGROUND_PIXEL (f);
6747 #if 0 /* MAC/W32 TODO : Colormap support. */
6748 x_query_color (f, &color);
6749 #endif
6750 bzero (&frame_background, sizeof frame_background);
6751 frame_background.red = RED_FROM_ULONG (color);
6752 frame_background.green = GREEN_FROM_ULONG (color);
6753 frame_background.blue = BLUE_FROM_ULONG (color);
6754 #endif /* MAC_OS */
6756 fn_png_set_background (png_ptr, &frame_background,
6757 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
6761 /* Update info structure. */
6762 fn_png_read_update_info (png_ptr, info_ptr);
6764 /* Get number of channels. Valid values are 1 for grayscale images
6765 and images with a palette, 2 for grayscale images with transparency
6766 information (alpha channel), 3 for RGB images, and 4 for RGB
6767 images with alpha channel, i.e. RGBA. If conversions above were
6768 sufficient we should only have 3 or 4 channels here. */
6769 channels = fn_png_get_channels (png_ptr, info_ptr);
6770 xassert (channels == 3 || channels == 4);
6772 /* Number of bytes needed for one row of the image. */
6773 row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
6775 /* Allocate memory for the image. */
6776 pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
6777 rows = (png_byte **) xmalloc (height * sizeof *rows);
6778 for (i = 0; i < height; ++i)
6779 rows[i] = pixels + i * row_bytes;
6781 /* Read the entire image. */
6782 fn_png_read_image (png_ptr, rows);
6783 fn_png_read_end (png_ptr, info_ptr);
6784 if (fp)
6786 fclose (fp);
6787 fp = NULL;
6790 /* Create the X image and pixmap. */
6791 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
6792 &img->pixmap))
6793 goto error;
6795 /* Create an image and pixmap serving as mask if the PNG image
6796 contains an alpha channel. */
6797 if (channels == 4
6798 && !transparent_p
6799 && !x_create_x_image_and_pixmap (f, width, height, 1,
6800 &mask_img, &img->mask))
6802 x_destroy_x_image (ximg);
6803 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
6804 img->pixmap = NO_PIXMAP;
6805 goto error;
6808 /* Fill the X image and mask from PNG data. */
6809 init_color_table ();
6811 for (y = 0; y < height; ++y)
6813 png_byte *p = rows[y];
6815 for (x = 0; x < width; ++x)
6817 unsigned r, g, b;
6819 r = *p++ << 8;
6820 g = *p++ << 8;
6821 b = *p++ << 8;
6822 XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
6823 /* An alpha channel, aka mask channel, associates variable
6824 transparency with an image. Where other image formats
6825 support binary transparency---fully transparent or fully
6826 opaque---PNG allows up to 254 levels of partial transparency.
6827 The PNG library implements partial transparency by combining
6828 the image with a specified background color.
6830 I'm not sure how to handle this here nicely: because the
6831 background on which the image is displayed may change, for
6832 real alpha channel support, it would be necessary to create
6833 a new image for each possible background.
6835 What I'm doing now is that a mask is created if we have
6836 boolean transparency information. Otherwise I'm using
6837 the frame's background color to combine the image with. */
6839 if (channels == 4)
6841 if (mask_img)
6842 XPutPixel (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
6843 ++p;
6848 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
6849 /* Set IMG's background color from the PNG image, unless the user
6850 overrode it. */
6852 png_color_16 *bg;
6853 if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
6855 img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
6856 img->background_valid = 1;
6860 #ifdef COLOR_TABLE_SUPPORT
6861 /* Remember colors allocated for this image. */
6862 img->colors = colors_in_color_table (&img->ncolors);
6863 free_color_table ();
6864 #endif /* COLOR_TABLE_SUPPORT */
6866 /* Clean up. */
6867 fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
6868 xfree (rows);
6869 xfree (pixels);
6871 img->width = width;
6872 img->height = height;
6874 /* Maybe fill in the background field while we have ximg handy.
6875 Casting avoids a GCC warning. */
6876 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6878 /* Put the image into the pixmap, then free the X image and its buffer. */
6879 x_put_x_image (f, ximg, img->pixmap, width, height);
6880 x_destroy_x_image (ximg);
6882 /* Same for the mask. */
6883 if (mask_img)
6885 /* Fill in the background_transparent field while we have the
6886 mask handy. Casting avoids a GCC warning. */
6887 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
6889 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
6890 x_destroy_x_image (mask_img);
6893 UNGCPRO;
6894 return 1;
6897 #else /* HAVE_PNG */
6899 #ifdef MAC_OS
6900 static int
6901 png_load (f, img)
6902 struct frame *f;
6903 struct image *img;
6905 #if USE_MAC_IMAGE_IO
6906 return image_load_image_io (f, img, kUTTypePNG);
6907 #elif MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6908 return image_load_quartz2d (f, img, 1);
6909 #else
6910 return image_load_quicktime (f, img, kQTFileTypePNG);
6911 #endif
6913 #endif /* MAC_OS */
6915 #endif /* !HAVE_PNG */
6919 /***********************************************************************
6920 JPEG
6921 ***********************************************************************/
6923 #if defined (HAVE_JPEG) || defined (MAC_OS)
6925 static int jpeg_image_p P_ ((Lisp_Object object));
6926 static int jpeg_load P_ ((struct frame *f, struct image *img));
6928 /* The symbol `jpeg' identifying images of this type. */
6930 Lisp_Object Qjpeg;
6932 /* Indices of image specification fields in gs_format, below. */
6934 enum jpeg_keyword_index
6936 JPEG_TYPE,
6937 JPEG_DATA,
6938 JPEG_FILE,
6939 JPEG_ASCENT,
6940 JPEG_MARGIN,
6941 JPEG_RELIEF,
6942 JPEG_ALGORITHM,
6943 JPEG_HEURISTIC_MASK,
6944 JPEG_MASK,
6945 JPEG_BACKGROUND,
6946 JPEG_LAST
6949 /* Vector of image_keyword structures describing the format
6950 of valid user-defined image specifications. */
6952 static struct image_keyword jpeg_format[JPEG_LAST] =
6954 {":type", IMAGE_SYMBOL_VALUE, 1},
6955 {":data", IMAGE_STRING_VALUE, 0},
6956 {":file", IMAGE_STRING_VALUE, 0},
6957 {":ascent", IMAGE_ASCENT_VALUE, 0},
6958 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
6959 {":relief", IMAGE_INTEGER_VALUE, 0},
6960 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6961 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6962 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
6963 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
6966 /* Structure describing the image type `jpeg'. */
6968 static struct image_type jpeg_type =
6970 &Qjpeg,
6971 jpeg_image_p,
6972 jpeg_load,
6973 x_clear_image,
6974 NULL
6977 /* Return non-zero if OBJECT is a valid JPEG image specification. */
6979 static int
6980 jpeg_image_p (object)
6981 Lisp_Object object;
6983 struct image_keyword fmt[JPEG_LAST];
6985 bcopy (jpeg_format, fmt, sizeof fmt);
6987 if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg))
6988 return 0;
6990 /* Must specify either the :data or :file keyword. */
6991 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6994 #endif /* HAVE_JPEG || MAC_OS */
6996 #ifdef HAVE_JPEG
6998 /* Work around a warning about HAVE_STDLIB_H being redefined in
6999 jconfig.h. */
7000 #ifdef HAVE_STDLIB_H
7001 #define HAVE_STDLIB_H_1
7002 #undef HAVE_STDLIB_H
7003 #endif /* HAVE_STLIB_H */
7005 #if defined (HAVE_NTGUI) && !defined (__WIN32__)
7006 /* In older releases of the jpeg library, jpeglib.h will define boolean
7007 differently depending on __WIN32__, so make sure it is defined. */
7008 #define __WIN32__ 1
7009 #endif
7011 #include <jpeglib.h>
7012 #include <jerror.h>
7013 #include <setjmp.h>
7015 #ifdef HAVE_STLIB_H_1
7016 #define HAVE_STDLIB_H 1
7017 #endif
7019 #ifdef HAVE_NTGUI
7021 /* JPEG library details. */
7022 DEF_IMGLIB_FN (jpeg_CreateDecompress);
7023 DEF_IMGLIB_FN (jpeg_start_decompress);
7024 DEF_IMGLIB_FN (jpeg_finish_decompress);
7025 DEF_IMGLIB_FN (jpeg_destroy_decompress);
7026 DEF_IMGLIB_FN (jpeg_read_header);
7027 DEF_IMGLIB_FN (jpeg_read_scanlines);
7028 DEF_IMGLIB_FN (jpeg_std_error);
7029 DEF_IMGLIB_FN (jpeg_resync_to_restart);
7031 static int
7032 init_jpeg_functions (Lisp_Object libraries)
7034 HMODULE library;
7036 if (!(library = w32_delayed_load (libraries, Qjpeg)))
7037 return 0;
7039 LOAD_IMGLIB_FN (library, jpeg_finish_decompress);
7040 LOAD_IMGLIB_FN (library, jpeg_read_scanlines);
7041 LOAD_IMGLIB_FN (library, jpeg_start_decompress);
7042 LOAD_IMGLIB_FN (library, jpeg_read_header);
7043 LOAD_IMGLIB_FN (library, jpeg_CreateDecompress);
7044 LOAD_IMGLIB_FN (library, jpeg_destroy_decompress);
7045 LOAD_IMGLIB_FN (library, jpeg_std_error);
7046 LOAD_IMGLIB_FN (library, jpeg_resync_to_restart);
7047 return 1;
7050 /* Wrapper since we can't directly assign the function pointer
7051 to another function pointer that was declared more completely easily. */
7052 static boolean
7053 jpeg_resync_to_restart_wrapper (cinfo, desired)
7054 j_decompress_ptr cinfo;
7055 int desired;
7057 return fn_jpeg_resync_to_restart (cinfo, desired);
7060 #else
7062 #define fn_jpeg_CreateDecompress(a,b,c) jpeg_create_decompress(a)
7063 #define fn_jpeg_start_decompress jpeg_start_decompress
7064 #define fn_jpeg_finish_decompress jpeg_finish_decompress
7065 #define fn_jpeg_destroy_decompress jpeg_destroy_decompress
7066 #define fn_jpeg_read_header jpeg_read_header
7067 #define fn_jpeg_read_scanlines jpeg_read_scanlines
7068 #define fn_jpeg_std_error jpeg_std_error
7069 #define jpeg_resync_to_restart_wrapper jpeg_resync_to_restart
7071 #endif /* HAVE_NTGUI */
7073 struct my_jpeg_error_mgr
7075 struct jpeg_error_mgr pub;
7076 jmp_buf setjmp_buffer;
7080 static void
7081 my_error_exit (cinfo)
7082 j_common_ptr cinfo;
7084 struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
7085 longjmp (mgr->setjmp_buffer, 1);
7089 /* Init source method for JPEG data source manager. Called by
7090 jpeg_read_header() before any data is actually read. See
7091 libjpeg.doc from the JPEG lib distribution. */
7093 static void
7094 our_common_init_source (cinfo)
7095 j_decompress_ptr cinfo;
7100 /* Method to terminate data source. Called by
7101 jpeg_finish_decompress() after all data has been processed. */
7103 static void
7104 our_common_term_source (cinfo)
7105 j_decompress_ptr cinfo;
7110 /* Fill input buffer method for JPEG data source manager. Called
7111 whenever more data is needed. We read the whole image in one step,
7112 so this only adds a fake end of input marker at the end. */
7114 static JOCTET our_memory_buffer[2];
7116 static boolean
7117 our_memory_fill_input_buffer (cinfo)
7118 j_decompress_ptr cinfo;
7120 /* Insert a fake EOI marker. */
7121 struct jpeg_source_mgr *src = cinfo->src;
7123 our_memory_buffer[0] = (JOCTET) 0xFF;
7124 our_memory_buffer[1] = (JOCTET) JPEG_EOI;
7126 src->next_input_byte = our_memory_buffer;
7127 src->bytes_in_buffer = 2;
7128 return 1;
7132 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7133 is the JPEG data source manager. */
7135 static void
7136 our_memory_skip_input_data (cinfo, num_bytes)
7137 j_decompress_ptr cinfo;
7138 long num_bytes;
7140 struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
7142 if (src)
7144 if (num_bytes > src->bytes_in_buffer)
7145 ERREXIT (cinfo, JERR_INPUT_EOF);
7147 src->bytes_in_buffer -= num_bytes;
7148 src->next_input_byte += num_bytes;
7153 /* Set up the JPEG lib for reading an image from DATA which contains
7154 LEN bytes. CINFO is the decompression info structure created for
7155 reading the image. */
7157 static void
7158 jpeg_memory_src (cinfo, data, len)
7159 j_decompress_ptr cinfo;
7160 JOCTET *data;
7161 unsigned int len;
7163 struct jpeg_source_mgr *src;
7165 if (cinfo->src == NULL)
7167 /* First time for this JPEG object? */
7168 cinfo->src = (struct jpeg_source_mgr *)
7169 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7170 sizeof (struct jpeg_source_mgr));
7171 src = (struct jpeg_source_mgr *) cinfo->src;
7172 src->next_input_byte = data;
7175 src = (struct jpeg_source_mgr *) cinfo->src;
7176 src->init_source = our_common_init_source;
7177 src->fill_input_buffer = our_memory_fill_input_buffer;
7178 src->skip_input_data = our_memory_skip_input_data;
7179 src->resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7180 src->term_source = our_common_term_source;
7181 src->bytes_in_buffer = len;
7182 src->next_input_byte = data;
7186 struct jpeg_stdio_mgr
7188 struct jpeg_source_mgr mgr;
7189 boolean finished;
7190 FILE *file;
7191 JOCTET *buffer;
7195 /* Size of buffer to read JPEG from file.
7196 Not too big, as we want to use alloc_small. */
7197 #define JPEG_STDIO_BUFFER_SIZE 8192
7200 /* Fill input buffer method for JPEG data source manager. Called
7201 whenever more data is needed. The data is read from a FILE *. */
7203 static boolean
7204 our_stdio_fill_input_buffer (cinfo)
7205 j_decompress_ptr cinfo;
7207 struct jpeg_stdio_mgr *src;
7209 src = (struct jpeg_stdio_mgr *) cinfo->src;
7210 if (!src->finished)
7212 size_t bytes;
7214 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file);
7215 if (bytes > 0)
7216 src->mgr.bytes_in_buffer = bytes;
7217 else
7219 WARNMS (cinfo, JWRN_JPEG_EOF);
7220 src->finished = 1;
7221 src->buffer[0] = (JOCTET) 0xFF;
7222 src->buffer[1] = (JOCTET) JPEG_EOI;
7223 src->mgr.bytes_in_buffer = 2;
7225 src->mgr.next_input_byte = src->buffer;
7228 return 1;
7232 /* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
7233 is the JPEG data source manager. */
7235 static void
7236 our_stdio_skip_input_data (cinfo, num_bytes)
7237 j_decompress_ptr cinfo;
7238 long num_bytes;
7240 struct jpeg_stdio_mgr *src;
7241 src = (struct jpeg_stdio_mgr *) cinfo->src;
7243 while (num_bytes > 0 && !src->finished)
7245 if (num_bytes <= src->mgr.bytes_in_buffer)
7247 src->mgr.bytes_in_buffer -= num_bytes;
7248 src->mgr.next_input_byte += num_bytes;
7249 break;
7251 else
7253 num_bytes -= src->mgr.bytes_in_buffer;
7254 src->mgr.bytes_in_buffer = 0;
7255 src->mgr.next_input_byte = NULL;
7257 our_stdio_fill_input_buffer (cinfo);
7263 /* Set up the JPEG lib for reading an image from a FILE *.
7264 CINFO is the decompression info structure created for
7265 reading the image. */
7267 static void
7268 jpeg_file_src (cinfo, fp)
7269 j_decompress_ptr cinfo;
7270 FILE *fp;
7272 struct jpeg_stdio_mgr *src;
7274 if (cinfo->src != NULL)
7275 src = (struct jpeg_stdio_mgr *) cinfo->src;
7276 else
7278 /* First time for this JPEG object? */
7279 cinfo->src = (struct jpeg_source_mgr *)
7280 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7281 sizeof (struct jpeg_stdio_mgr));
7282 src = (struct jpeg_stdio_mgr *) cinfo->src;
7283 src->buffer = (JOCTET *)
7284 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
7285 JPEG_STDIO_BUFFER_SIZE);
7288 src->file = fp;
7289 src->finished = 0;
7290 src->mgr.init_source = our_common_init_source;
7291 src->mgr.fill_input_buffer = our_stdio_fill_input_buffer;
7292 src->mgr.skip_input_data = our_stdio_skip_input_data;
7293 src->mgr.resync_to_restart = jpeg_resync_to_restart_wrapper; /* Use default method. */
7294 src->mgr.term_source = our_common_term_source;
7295 src->mgr.bytes_in_buffer = 0;
7296 src->mgr.next_input_byte = NULL;
7300 /* Load image IMG for use on frame F. Patterned after example.c
7301 from the JPEG lib. */
7303 static int
7304 jpeg_load (f, img)
7305 struct frame *f;
7306 struct image *img;
7308 struct jpeg_decompress_struct cinfo;
7309 struct my_jpeg_error_mgr mgr;
7310 Lisp_Object file, specified_file;
7311 Lisp_Object specified_data;
7312 FILE * volatile fp = NULL;
7313 JSAMPARRAY buffer;
7314 int row_stride, x, y;
7315 XImagePtr ximg = NULL;
7316 int rc;
7317 unsigned long *colors;
7318 int width, height;
7319 struct gcpro gcpro1;
7321 /* Open the JPEG file. */
7322 specified_file = image_spec_value (img->spec, QCfile, NULL);
7323 specified_data = image_spec_value (img->spec, QCdata, NULL);
7324 file = Qnil;
7325 GCPRO1 (file);
7327 if (NILP (specified_data))
7329 file = x_find_image_file (specified_file);
7330 if (!STRINGP (file))
7332 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7333 UNGCPRO;
7334 return 0;
7337 fp = fopen (SDATA (file), "rb");
7338 if (fp == NULL)
7340 image_error ("Cannot open `%s'", file, Qnil);
7341 UNGCPRO;
7342 return 0;
7346 /* Customize libjpeg's error handling to call my_error_exit when an
7347 error is detected. This function will perform a longjmp.
7348 Casting return value avoids a GCC warning on W32. */
7349 cinfo.err = (struct jpeg_error_mgr *)fn_jpeg_std_error (&mgr.pub);
7350 mgr.pub.error_exit = my_error_exit;
7352 if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
7354 if (rc == 1)
7356 /* Called from my_error_exit. Display a JPEG error. */
7357 char buffer[JMSG_LENGTH_MAX];
7358 cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
7359 image_error ("Error reading JPEG image `%s': %s", img->spec,
7360 build_string (buffer));
7363 /* Close the input file and destroy the JPEG object. */
7364 if (fp)
7365 fclose ((FILE *) fp);
7366 fn_jpeg_destroy_decompress (&cinfo);
7368 /* If we already have an XImage, free that. */
7369 x_destroy_x_image (ximg);
7371 /* Free pixmap and colors. */
7372 x_clear_image (f, img);
7374 UNGCPRO;
7375 return 0;
7378 /* Create the JPEG decompression object. Let it read from fp.
7379 Read the JPEG image header. */
7380 fn_jpeg_CreateDecompress (&cinfo, JPEG_LIB_VERSION, sizeof (cinfo));
7382 if (NILP (specified_data))
7383 jpeg_file_src (&cinfo, (FILE *) fp);
7384 else
7385 jpeg_memory_src (&cinfo, SDATA (specified_data),
7386 SBYTES (specified_data));
7388 fn_jpeg_read_header (&cinfo, 1);
7390 /* Customize decompression so that color quantization will be used.
7391 Start decompression. */
7392 cinfo.quantize_colors = 1;
7393 fn_jpeg_start_decompress (&cinfo);
7394 width = img->width = cinfo.output_width;
7395 height = img->height = cinfo.output_height;
7397 if (!check_image_size (f, width, height))
7399 image_error ("Invalid image size", Qnil, Qnil);
7400 longjmp (mgr.setjmp_buffer, 2);
7403 /* Create X image and pixmap. */
7404 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7405 longjmp (mgr.setjmp_buffer, 2);
7407 /* Allocate colors. When color quantization is used,
7408 cinfo.actual_number_of_colors has been set with the number of
7409 colors generated, and cinfo.colormap is a two-dimensional array
7410 of color indices in the range 0..cinfo.actual_number_of_colors.
7411 No more than 255 colors will be generated. */
7413 int i, ir, ig, ib;
7415 if (cinfo.out_color_components > 2)
7416 ir = 0, ig = 1, ib = 2;
7417 else if (cinfo.out_color_components > 1)
7418 ir = 0, ig = 1, ib = 0;
7419 else
7420 ir = 0, ig = 0, ib = 0;
7422 /* Use the color table mechanism because it handles colors that
7423 cannot be allocated nicely. Such colors will be replaced with
7424 a default color, and we don't have to care about which colors
7425 can be freed safely, and which can't. */
7426 init_color_table ();
7427 colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
7428 * sizeof *colors);
7430 for (i = 0; i < cinfo.actual_number_of_colors; ++i)
7432 /* Multiply RGB values with 255 because X expects RGB values
7433 in the range 0..0xffff. */
7434 int r = cinfo.colormap[ir][i] << 8;
7435 int g = cinfo.colormap[ig][i] << 8;
7436 int b = cinfo.colormap[ib][i] << 8;
7437 colors[i] = lookup_rgb_color (f, r, g, b);
7440 #ifdef COLOR_TABLE_SUPPORT
7441 /* Remember those colors actually allocated. */
7442 img->colors = colors_in_color_table (&img->ncolors);
7443 free_color_table ();
7444 #endif /* COLOR_TABLE_SUPPORT */
7447 /* Read pixels. */
7448 row_stride = width * cinfo.output_components;
7449 buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
7450 row_stride, 1);
7451 for (y = 0; y < height; ++y)
7453 fn_jpeg_read_scanlines (&cinfo, buffer, 1);
7454 for (x = 0; x < cinfo.output_width; ++x)
7455 XPutPixel (ximg, x, y, colors[buffer[0][x]]);
7458 /* Clean up. */
7459 fn_jpeg_finish_decompress (&cinfo);
7460 fn_jpeg_destroy_decompress (&cinfo);
7461 if (fp)
7462 fclose ((FILE *) fp);
7464 /* Maybe fill in the background field while we have ximg handy. */
7465 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7466 /* Casting avoids a GCC warning. */
7467 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7469 /* Put the image into the pixmap. */
7470 x_put_x_image (f, ximg, img->pixmap, width, height);
7471 x_destroy_x_image (ximg);
7472 UNGCPRO;
7473 return 1;
7476 #else /* HAVE_JPEG */
7478 #ifdef MAC_OS
7479 static int
7480 jpeg_load (f, img)
7481 struct frame *f;
7482 struct image *img;
7484 #if USE_MAC_IMAGE_IO
7485 return image_load_image_io (f, img, kUTTypeJPEG);
7486 #elif defined (MAC_OSX)
7487 return image_load_quartz2d (f, img, 0);
7488 #else
7489 return image_load_quicktime (f, img, kQTFileTypeJPEG);
7490 #endif
7492 #endif /* MAC_OS */
7494 #endif /* !HAVE_JPEG */
7498 /***********************************************************************
7499 TIFF
7500 ***********************************************************************/
7502 #if defined (HAVE_TIFF) || defined (MAC_OS)
7504 static int tiff_image_p P_ ((Lisp_Object object));
7505 static int tiff_load P_ ((struct frame *f, struct image *img));
7507 /* The symbol `tiff' identifying images of this type. */
7509 Lisp_Object Qtiff;
7511 /* Indices of image specification fields in tiff_format, below. */
7513 enum tiff_keyword_index
7515 TIFF_TYPE,
7516 TIFF_DATA,
7517 TIFF_FILE,
7518 TIFF_ASCENT,
7519 TIFF_MARGIN,
7520 TIFF_RELIEF,
7521 TIFF_ALGORITHM,
7522 TIFF_HEURISTIC_MASK,
7523 TIFF_MASK,
7524 TIFF_BACKGROUND,
7525 TIFF_LAST
7528 /* Vector of image_keyword structures describing the format
7529 of valid user-defined image specifications. */
7531 static struct image_keyword tiff_format[TIFF_LAST] =
7533 {":type", IMAGE_SYMBOL_VALUE, 1},
7534 {":data", IMAGE_STRING_VALUE, 0},
7535 {":file", IMAGE_STRING_VALUE, 0},
7536 {":ascent", IMAGE_ASCENT_VALUE, 0},
7537 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7538 {":relief", IMAGE_INTEGER_VALUE, 0},
7539 {":conversions", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7540 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7541 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7542 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7545 /* Structure describing the image type `tiff'. */
7547 static struct image_type tiff_type =
7549 &Qtiff,
7550 tiff_image_p,
7551 tiff_load,
7552 x_clear_image,
7553 NULL
7556 /* Return non-zero if OBJECT is a valid TIFF image specification. */
7558 static int
7559 tiff_image_p (object)
7560 Lisp_Object object;
7562 struct image_keyword fmt[TIFF_LAST];
7563 bcopy (tiff_format, fmt, sizeof fmt);
7565 if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff))
7566 return 0;
7568 /* Must specify either the :data or :file keyword. */
7569 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7572 #endif /* HAVE_TIFF || MAC_OS */
7574 #ifdef HAVE_TIFF
7576 #include <tiffio.h>
7578 #ifdef HAVE_NTGUI
7580 /* TIFF library details. */
7581 DEF_IMGLIB_FN (TIFFSetErrorHandler);
7582 DEF_IMGLIB_FN (TIFFSetWarningHandler);
7583 DEF_IMGLIB_FN (TIFFOpen);
7584 DEF_IMGLIB_FN (TIFFClientOpen);
7585 DEF_IMGLIB_FN (TIFFGetField);
7586 DEF_IMGLIB_FN (TIFFReadRGBAImage);
7587 DEF_IMGLIB_FN (TIFFClose);
7589 static int
7590 init_tiff_functions (Lisp_Object libraries)
7592 HMODULE library;
7594 if (!(library = w32_delayed_load (libraries, Qtiff)))
7595 return 0;
7597 LOAD_IMGLIB_FN (library, TIFFSetErrorHandler);
7598 LOAD_IMGLIB_FN (library, TIFFSetWarningHandler);
7599 LOAD_IMGLIB_FN (library, TIFFOpen);
7600 LOAD_IMGLIB_FN (library, TIFFClientOpen);
7601 LOAD_IMGLIB_FN (library, TIFFGetField);
7602 LOAD_IMGLIB_FN (library, TIFFReadRGBAImage);
7603 LOAD_IMGLIB_FN (library, TIFFClose);
7604 return 1;
7607 #else
7609 #define fn_TIFFSetErrorHandler TIFFSetErrorHandler
7610 #define fn_TIFFSetWarningHandler TIFFSetWarningHandler
7611 #define fn_TIFFOpen TIFFOpen
7612 #define fn_TIFFClientOpen TIFFClientOpen
7613 #define fn_TIFFGetField TIFFGetField
7614 #define fn_TIFFReadRGBAImage TIFFReadRGBAImage
7615 #define fn_TIFFClose TIFFClose
7617 #endif /* HAVE_NTGUI */
7620 /* Reading from a memory buffer for TIFF images Based on the PNG
7621 memory source, but we have to provide a lot of extra functions.
7622 Blah.
7624 We really only need to implement read and seek, but I am not
7625 convinced that the TIFF library is smart enough not to destroy
7626 itself if we only hand it the function pointers we need to
7627 override. */
7629 typedef struct
7631 unsigned char *bytes;
7632 size_t len;
7633 int index;
7635 tiff_memory_source;
7637 static size_t
7638 tiff_read_from_memory (data, buf, size)
7639 thandle_t data;
7640 tdata_t buf;
7641 tsize_t size;
7643 tiff_memory_source *src = (tiff_memory_source *) data;
7645 if (size > src->len - src->index)
7646 return (size_t) -1;
7647 bcopy (src->bytes + src->index, buf, size);
7648 src->index += size;
7649 return size;
7652 static size_t
7653 tiff_write_from_memory (data, buf, size)
7654 thandle_t data;
7655 tdata_t buf;
7656 tsize_t size;
7658 return (size_t) -1;
7661 static toff_t
7662 tiff_seek_in_memory (data, off, whence)
7663 thandle_t data;
7664 toff_t off;
7665 int whence;
7667 tiff_memory_source *src = (tiff_memory_source *) data;
7668 int idx;
7670 switch (whence)
7672 case SEEK_SET: /* Go from beginning of source. */
7673 idx = off;
7674 break;
7676 case SEEK_END: /* Go from end of source. */
7677 idx = src->len + off;
7678 break;
7680 case SEEK_CUR: /* Go from current position. */
7681 idx = src->index + off;
7682 break;
7684 default: /* Invalid `whence'. */
7685 return -1;
7688 if (idx > src->len || idx < 0)
7689 return -1;
7691 src->index = idx;
7692 return src->index;
7695 static int
7696 tiff_close_memory (data)
7697 thandle_t data;
7699 /* NOOP */
7700 return 0;
7703 static int
7704 tiff_mmap_memory (data, pbase, psize)
7705 thandle_t data;
7706 tdata_t *pbase;
7707 toff_t *psize;
7709 /* It is already _IN_ memory. */
7710 return 0;
7713 static void
7714 tiff_unmap_memory (data, base, size)
7715 thandle_t data;
7716 tdata_t base;
7717 toff_t size;
7719 /* We don't need to do this. */
7722 static toff_t
7723 tiff_size_of_memory (data)
7724 thandle_t data;
7726 return ((tiff_memory_source *) data)->len;
7730 static void
7731 tiff_error_handler (title, format, ap)
7732 const char *title, *format;
7733 va_list ap;
7735 char buf[512];
7736 int len;
7738 len = sprintf (buf, "TIFF error: %s ", title);
7739 vsprintf (buf + len, format, ap);
7740 add_to_log (buf, Qnil, Qnil);
7744 static void
7745 tiff_warning_handler (title, format, ap)
7746 const char *title, *format;
7747 va_list ap;
7749 char buf[512];
7750 int len;
7752 len = sprintf (buf, "TIFF warning: %s ", title);
7753 vsprintf (buf + len, format, ap);
7754 add_to_log (buf, Qnil, Qnil);
7758 /* Load TIFF image IMG for use on frame F. Value is non-zero if
7759 successful. */
7761 static int
7762 tiff_load (f, img)
7763 struct frame *f;
7764 struct image *img;
7766 Lisp_Object file, specified_file;
7767 Lisp_Object specified_data;
7768 TIFF *tiff;
7769 int width, height, x, y;
7770 uint32 *buf;
7771 int rc;
7772 XImagePtr ximg;
7773 struct gcpro gcpro1;
7774 tiff_memory_source memsrc;
7776 specified_file = image_spec_value (img->spec, QCfile, NULL);
7777 specified_data = image_spec_value (img->spec, QCdata, NULL);
7778 file = Qnil;
7779 GCPRO1 (file);
7781 fn_TIFFSetErrorHandler (tiff_error_handler);
7782 fn_TIFFSetWarningHandler (tiff_warning_handler);
7784 if (NILP (specified_data))
7786 /* Read from a file */
7787 file = x_find_image_file (specified_file);
7788 if (!STRINGP (file))
7790 image_error ("Cannot find image file `%s'", specified_file, Qnil);
7791 UNGCPRO;
7792 return 0;
7795 /* Try to open the image file. Casting return value avoids a
7796 GCC warning on W32. */
7797 tiff = (TIFF *)fn_TIFFOpen (SDATA (file), "r");
7798 if (tiff == NULL)
7800 image_error ("Cannot open `%s'", file, Qnil);
7801 UNGCPRO;
7802 return 0;
7805 else
7807 /* Memory source! */
7808 memsrc.bytes = SDATA (specified_data);
7809 memsrc.len = SBYTES (specified_data);
7810 memsrc.index = 0;
7812 /* Casting return value avoids a GCC warning on W32. */
7813 tiff = (TIFF *)fn_TIFFClientOpen ("memory_source", "r", &memsrc,
7814 (TIFFReadWriteProc) tiff_read_from_memory,
7815 (TIFFReadWriteProc) tiff_write_from_memory,
7816 tiff_seek_in_memory,
7817 tiff_close_memory,
7818 tiff_size_of_memory,
7819 tiff_mmap_memory,
7820 tiff_unmap_memory);
7822 if (!tiff)
7824 image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
7825 UNGCPRO;
7826 return 0;
7830 /* Get width and height of the image, and allocate a raster buffer
7831 of width x height 32-bit values. */
7832 fn_TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
7833 fn_TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
7835 if (!check_image_size (f, width, height))
7837 image_error ("Invalid image size", Qnil, Qnil);
7838 UNGCPRO;
7839 return 0;
7842 buf = (uint32 *) xmalloc (width * height * sizeof *buf);
7844 rc = fn_TIFFReadRGBAImage (tiff, width, height, buf, 0);
7845 fn_TIFFClose (tiff);
7846 if (!rc)
7848 image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
7849 xfree (buf);
7850 UNGCPRO;
7851 return 0;
7854 /* Create the X image and pixmap. */
7855 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
7857 xfree (buf);
7858 UNGCPRO;
7859 return 0;
7862 /* Initialize the color table. */
7863 init_color_table ();
7865 /* Process the pixel raster. Origin is in the lower-left corner. */
7866 for (y = 0; y < height; ++y)
7868 uint32 *row = buf + y * width;
7870 for (x = 0; x < width; ++x)
7872 uint32 abgr = row[x];
7873 int r = TIFFGetR (abgr) << 8;
7874 int g = TIFFGetG (abgr) << 8;
7875 int b = TIFFGetB (abgr) << 8;
7876 XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
7880 #ifdef COLOR_TABLE_SUPPORT
7881 /* Remember the colors allocated for the image. Free the color table. */
7882 img->colors = colors_in_color_table (&img->ncolors);
7883 free_color_table ();
7884 #endif /* COLOR_TABLE_SUPPORT */
7886 img->width = width;
7887 img->height = height;
7889 /* Maybe fill in the background field while we have ximg handy. */
7890 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
7891 /* Casting avoids a GCC warning on W32. */
7892 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7894 /* Put the image into the pixmap, then free the X image and its buffer. */
7895 x_put_x_image (f, ximg, img->pixmap, width, height);
7896 x_destroy_x_image (ximg);
7897 xfree (buf);
7899 UNGCPRO;
7900 return 1;
7903 #else /* HAVE_TIFF */
7905 #ifdef MAC_OS
7906 static int
7907 tiff_load (f, img)
7908 struct frame *f;
7909 struct image *img;
7911 #if USE_MAC_IMAGE_IO
7912 return image_load_image_io (f, img, kUTTypeTIFF);
7913 #else
7914 return image_load_quicktime (f, img, kQTFileTypeTIFF);
7915 #endif
7917 #endif /* MAC_OS */
7919 #endif /* !HAVE_TIFF */
7923 /***********************************************************************
7925 ***********************************************************************/
7927 #if defined (HAVE_GIF) || defined (MAC_OS)
7929 static int gif_image_p P_ ((Lisp_Object object));
7930 static int gif_load P_ ((struct frame *f, struct image *img));
7931 static void gif_clear_image P_ ((struct frame *f, struct image *img));
7933 /* The symbol `gif' identifying images of this type. */
7935 Lisp_Object Qgif;
7937 /* Indices of image specification fields in gif_format, below. */
7939 enum gif_keyword_index
7941 GIF_TYPE,
7942 GIF_DATA,
7943 GIF_FILE,
7944 GIF_ASCENT,
7945 GIF_MARGIN,
7946 GIF_RELIEF,
7947 GIF_ALGORITHM,
7948 GIF_HEURISTIC_MASK,
7949 GIF_MASK,
7950 GIF_IMAGE,
7951 GIF_BACKGROUND,
7952 GIF_LAST
7955 /* Vector of image_keyword structures describing the format
7956 of valid user-defined image specifications. */
7958 static struct image_keyword gif_format[GIF_LAST] =
7960 {":type", IMAGE_SYMBOL_VALUE, 1},
7961 {":data", IMAGE_STRING_VALUE, 0},
7962 {":file", IMAGE_STRING_VALUE, 0},
7963 {":ascent", IMAGE_ASCENT_VALUE, 0},
7964 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
7965 {":relief", IMAGE_INTEGER_VALUE, 0},
7966 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7967 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7968 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
7969 {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
7970 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
7973 /* Structure describing the image type `gif'. */
7975 static struct image_type gif_type =
7977 &Qgif,
7978 gif_image_p,
7979 gif_load,
7980 gif_clear_image,
7981 NULL
7984 /* Free X resources of GIF image IMG which is used on frame F. */
7986 static void
7987 gif_clear_image (f, img)
7988 struct frame *f;
7989 struct image *img;
7991 /* IMG->data.ptr_val may contain extension data. */
7992 img->data.lisp_val = Qnil;
7993 x_clear_image (f, img);
7996 /* Return non-zero if OBJECT is a valid GIF image specification. */
7998 static int
7999 gif_image_p (object)
8000 Lisp_Object object;
8002 struct image_keyword fmt[GIF_LAST];
8003 bcopy (gif_format, fmt, sizeof fmt);
8005 if (!parse_image_spec (object, fmt, GIF_LAST, Qgif))
8006 return 0;
8008 /* Must specify either the :data or :file keyword. */
8009 return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
8012 #endif /* HAVE_GIF || MAC_OS */
8014 #ifdef HAVE_GIF
8016 #if defined (HAVE_NTGUI) || defined (MAC_OS)
8017 /* winuser.h might define DrawText to DrawTextA or DrawTextW.
8018 Undefine before redefining to avoid a preprocessor warning. */
8019 #ifdef DrawText
8020 #undef DrawText
8021 #endif
8022 /* avoid conflict with QuickdrawText.h */
8023 #define DrawText gif_DrawText
8024 #include <gif_lib.h>
8025 #undef DrawText
8027 #else /* HAVE_NTGUI || MAC_OS */
8029 #include <gif_lib.h>
8031 #endif /* HAVE_NTGUI || MAC_OS */
8034 #ifdef HAVE_NTGUI
8036 /* GIF library details. */
8037 DEF_IMGLIB_FN (DGifCloseFile);
8038 DEF_IMGLIB_FN (DGifSlurp);
8039 DEF_IMGLIB_FN (DGifOpen);
8040 DEF_IMGLIB_FN (DGifOpenFileName);
8042 static int
8043 init_gif_functions (Lisp_Object libraries)
8045 HMODULE library;
8047 if (!(library = w32_delayed_load (libraries, Qgif)))
8048 return 0;
8050 LOAD_IMGLIB_FN (library, DGifCloseFile);
8051 LOAD_IMGLIB_FN (library, DGifSlurp);
8052 LOAD_IMGLIB_FN (library, DGifOpen);
8053 LOAD_IMGLIB_FN (library, DGifOpenFileName);
8054 return 1;
8057 #else
8059 #define fn_DGifCloseFile DGifCloseFile
8060 #define fn_DGifSlurp DGifSlurp
8061 #define fn_DGifOpen DGifOpen
8062 #define fn_DGifOpenFileName DGifOpenFileName
8064 #endif /* HAVE_NTGUI */
8066 /* Reading a GIF image from memory
8067 Based on the PNG memory stuff to a certain extent. */
8069 typedef struct
8071 unsigned char *bytes;
8072 size_t len;
8073 int index;
8075 gif_memory_source;
8077 /* Make the current memory source available to gif_read_from_memory.
8078 It's done this way because not all versions of libungif support
8079 a UserData field in the GifFileType structure. */
8080 static gif_memory_source *current_gif_memory_src;
8082 static int
8083 gif_read_from_memory (file, buf, len)
8084 GifFileType *file;
8085 GifByteType *buf;
8086 int len;
8088 gif_memory_source *src = current_gif_memory_src;
8090 if (len > src->len - src->index)
8091 return -1;
8093 bcopy (src->bytes + src->index, buf, len);
8094 src->index += len;
8095 return len;
8099 /* Load GIF image IMG for use on frame F. Value is non-zero if
8100 successful. */
8102 static int interlace_start[] = {0, 4, 2, 1};
8103 static int interlace_increment[] = {8, 8, 4, 2};
8105 static int
8106 gif_load (f, img)
8107 struct frame *f;
8108 struct image *img;
8110 Lisp_Object file, specified_file;
8111 Lisp_Object specified_data;
8112 int rc, width, height, x, y, i;
8113 XImagePtr ximg;
8114 ColorMapObject *gif_color_map;
8115 unsigned long pixel_colors[256];
8116 GifFileType *gif;
8117 struct gcpro gcpro1;
8118 Lisp_Object image;
8119 int ino, image_height, image_width;
8120 gif_memory_source memsrc;
8121 unsigned char *raster;
8123 specified_file = image_spec_value (img->spec, QCfile, NULL);
8124 specified_data = image_spec_value (img->spec, QCdata, NULL);
8125 file = Qnil;
8126 GCPRO1 (file);
8128 if (NILP (specified_data))
8130 file = x_find_image_file (specified_file);
8131 if (!STRINGP (file))
8133 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8134 UNGCPRO;
8135 return 0;
8138 /* Open the GIF file. Casting return value avoids a GCC warning
8139 on W32. */
8140 gif = (GifFileType *)fn_DGifOpenFileName (SDATA (file));
8141 if (gif == NULL)
8143 image_error ("Cannot open `%s'", file, Qnil);
8144 UNGCPRO;
8145 return 0;
8148 else
8150 /* Read from memory! */
8151 current_gif_memory_src = &memsrc;
8152 memsrc.bytes = SDATA (specified_data);
8153 memsrc.len = SBYTES (specified_data);
8154 memsrc.index = 0;
8156 /* Casting return value avoids a GCC warning on W32. */
8157 gif = (GifFileType *) fn_DGifOpen (&memsrc, gif_read_from_memory);
8158 if (!gif)
8160 image_error ("Cannot open memory source `%s'", img->spec, Qnil);
8161 UNGCPRO;
8162 return 0;
8166 /* Before reading entire contents, check the declared image size. */
8167 if (!check_image_size (f, gif->SWidth, gif->SHeight))
8169 image_error ("Invalid image size", Qnil, Qnil);
8170 fn_DGifCloseFile (gif);
8171 UNGCPRO;
8172 return 0;
8175 /* Read entire contents. */
8176 rc = fn_DGifSlurp (gif);
8177 if (rc == GIF_ERROR)
8179 image_error ("Error reading `%s'", img->spec, Qnil);
8180 fn_DGifCloseFile (gif);
8181 UNGCPRO;
8182 return 0;
8185 image = image_spec_value (img->spec, QCindex, NULL);
8186 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8187 if (ino >= gif->ImageCount)
8189 image_error ("Invalid image number `%s' in image `%s'",
8190 image, img->spec);
8191 fn_DGifCloseFile (gif);
8192 UNGCPRO;
8193 return 0;
8196 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top;
8197 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left;
8198 image_height = gif->SavedImages[ino].ImageDesc.Height;
8199 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height;
8200 image_width = gif->SavedImages[ino].ImageDesc.Width;
8201 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width;
8203 width = img->width = max (gif->SWidth,
8204 max (gif->Image.Left + gif->Image.Width,
8205 img->corners[RIGHT_CORNER]));
8206 height = img->height = max (gif->SHeight,
8207 max (gif->Image.Top + gif->Image.Height,
8208 img->corners[BOT_CORNER]));
8210 if (!check_image_size (f, width, height))
8212 image_error ("Invalid image size", Qnil, Qnil);
8213 fn_DGifCloseFile (gif);
8214 UNGCPRO;
8215 return 0;
8218 /* Create the X image and pixmap. */
8219 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8221 fn_DGifCloseFile (gif);
8222 UNGCPRO;
8223 return 0;
8226 /* Allocate colors. */
8227 gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
8228 if (!gif_color_map)
8229 gif_color_map = gif->SColorMap;
8230 init_color_table ();
8231 bzero (pixel_colors, sizeof pixel_colors);
8233 if (gif_color_map)
8234 for (i = 0; i < gif_color_map->ColorCount; ++i)
8236 int r = gif_color_map->Colors[i].Red << 8;
8237 int g = gif_color_map->Colors[i].Green << 8;
8238 int b = gif_color_map->Colors[i].Blue << 8;
8239 pixel_colors[i] = lookup_rgb_color (f, r, g, b);
8242 #ifdef COLOR_TABLE_SUPPORT
8243 img->colors = colors_in_color_table (&img->ncolors);
8244 free_color_table ();
8245 #endif /* COLOR_TABLE_SUPPORT */
8247 /* Clear the part of the screen image that are not covered by
8248 the image from the GIF file. Full animated GIF support
8249 requires more than can be done here (see the gif89 spec,
8250 disposal methods). Let's simply assume that the part
8251 not covered by a sub-image is in the frame's background color. */
8252 for (y = 0; y < img->corners[TOP_CORNER]; ++y)
8253 for (x = 0; x < width; ++x)
8254 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8256 for (y = img->corners[BOT_CORNER]; y < height; ++y)
8257 for (x = 0; x < width; ++x)
8258 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8260 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y)
8262 for (x = 0; x < img->corners[LEFT_CORNER]; ++x)
8263 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8264 for (x = img->corners[RIGHT_CORNER]; x < width; ++x)
8265 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
8268 /* Read the GIF image into the X image. We use a local variable
8269 `raster' here because RasterBits below is a char *, and invites
8270 problems with bytes >= 0x80. */
8271 raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
8273 if (gif->SavedImages[ino].ImageDesc.Interlace)
8275 int pass;
8276 int row = interlace_start[0];
8278 pass = 0;
8280 for (y = 0; y < image_height; y++)
8282 if (row >= image_height)
8284 row = interlace_start[++pass];
8285 while (row >= image_height)
8286 row = interlace_start[++pass];
8289 for (x = 0; x < image_width; x++)
8291 int i = raster[(y * image_width) + x];
8292 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8293 row + img->corners[TOP_CORNER], pixel_colors[i]);
8296 row += interlace_increment[pass];
8299 else
8301 for (y = 0; y < image_height; ++y)
8302 for (x = 0; x < image_width; ++x)
8304 int i = raster[y * image_width + x];
8305 XPutPixel (ximg, x + img->corners[LEFT_CORNER],
8306 y + img->corners[TOP_CORNER], pixel_colors[i]);
8310 /* Save GIF image extension data for `image-extension-data'.
8311 Format is (count IMAGES FUNCTION "BYTES" ...). */
8312 img->data.lisp_val = Qnil;
8313 if (gif->SavedImages[ino].ExtensionBlockCount > 0)
8315 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks;
8316 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++)
8317 /* Append (... FUNCTION "BYTES") */
8318 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount),
8319 Fcons (make_number (ext->Function),
8320 img->data.lisp_val));
8321 img->data.lisp_val = Fnreverse (img->data.lisp_val);
8323 if (gif->ImageCount > 1)
8324 img->data.lisp_val = Fcons (Qcount,
8325 Fcons (make_number (gif->ImageCount),
8326 img->data.lisp_val));
8328 fn_DGifCloseFile (gif);
8330 /* Maybe fill in the background field while we have ximg handy. */
8331 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8332 /* Casting avoids a GCC warning. */
8333 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8335 /* Put the image into the pixmap, then free the X image and its buffer. */
8336 x_put_x_image (f, ximg, img->pixmap, width, height);
8337 x_destroy_x_image (ximg);
8339 UNGCPRO;
8340 return 1;
8343 #else /* !HAVE_GIF */
8345 #ifdef MAC_OS
8346 static int
8347 gif_load (f, img)
8348 struct frame *f;
8349 struct image *img;
8351 #if USE_MAC_IMAGE_IO
8352 return image_load_image_io (f, img, kUTTypeGIF);
8353 #else /* !USE_MAC_IMAGE_IO */
8354 Lisp_Object specified_file, file;
8355 Lisp_Object specified_data;
8356 OSErr err;
8357 Boolean graphic_p, movie_p, prefer_graphic_p;
8358 Handle dh = NULL;
8359 Movie movie = NULL;
8360 Lisp_Object image;
8361 Track track = NULL;
8362 Media media = NULL;
8363 long nsamples;
8364 Rect rect;
8365 Lisp_Object specified_bg;
8366 XColor color;
8367 RGBColor bg_color;
8368 int width, height;
8369 XImagePtr ximg;
8370 TimeScale time_scale;
8371 TimeValue time, duration;
8372 int ino;
8373 CGrafPtr old_port;
8374 GDHandle old_gdh;
8376 specified_file = image_spec_value (img->spec, QCfile, NULL);
8377 specified_data = image_spec_value (img->spec, QCdata, NULL);
8379 /* Animated gifs use QuickTime Movie Toolbox. So initialize it here. */
8380 EnterMovies ();
8382 if (NILP (specified_data))
8384 /* Read from a file */
8385 FSSpec fss;
8386 short refnum;
8388 err = find_image_fsspec (specified_file, &file, &fss);
8389 if (err != noErr)
8391 if (err == fnfErr)
8392 image_error ("Cannot find image file `%s'", specified_file, Qnil);
8393 else
8394 goto open_error;
8397 err = CanQuickTimeOpenFile (&fss, kQTFileTypeGIF, 0,
8398 &graphic_p, &movie_p, &prefer_graphic_p, 0);
8399 if (err != noErr)
8400 goto open_error;
8402 if (!graphic_p && !movie_p)
8403 goto open_error;
8404 if (prefer_graphic_p)
8405 return image_load_qt_1 (f, img, kQTFileTypeGIF, &fss, NULL);
8406 err = OpenMovieFile (&fss, &refnum, fsRdPerm);
8407 if (err != noErr)
8408 goto open_error;
8409 err = NewMovieFromFile (&movie, refnum, NULL, NULL, 0, NULL);
8410 CloseMovieFile (refnum);
8411 if (err != noErr)
8413 image_error ("Error reading `%s'", file, Qnil);
8414 return 0;
8417 else
8419 /* Memory source! */
8420 Handle dref = NULL;
8421 long file_type_atom[3];
8423 err = PtrToHand (SDATA (specified_data), &dh, SBYTES (specified_data));
8424 if (err != noErr)
8426 image_error ("Cannot allocate data handle for `%s'",
8427 img->spec, Qnil);
8428 goto error;
8431 file_type_atom[0] = EndianU32_NtoB (sizeof (long) * 3);
8432 file_type_atom[1] = EndianU32_NtoB (kDataRefExtensionMacOSFileType);
8433 file_type_atom[2] = EndianU32_NtoB (kQTFileTypeGIF);
8434 err = PtrToHand (&dh, &dref, sizeof (Handle));
8435 if (err == noErr)
8436 /* no file name */
8437 err = PtrAndHand ("\p", dref, 1);
8438 if (err == noErr)
8439 err = PtrAndHand (file_type_atom, dref, sizeof (long) * 3);
8440 if (err != noErr)
8442 image_error ("Cannot allocate handle data ref for `%s'", img->spec, Qnil);
8443 goto error;
8445 err = CanQuickTimeOpenDataRef (dref, HandleDataHandlerSubType, &graphic_p,
8446 &movie_p, &prefer_graphic_p, 0);
8447 if (err != noErr)
8448 goto open_error;
8450 if (!graphic_p && !movie_p)
8451 goto open_error;
8452 if (prefer_graphic_p)
8454 int success_p;
8456 DisposeHandle (dref);
8457 success_p = image_load_qt_1 (f, img, kQTFileTypeGIF, NULL, dh);
8458 DisposeHandle (dh);
8459 return success_p;
8461 err = NewMovieFromDataRef (&movie, 0, NULL, dref,
8462 HandleDataHandlerSubType);
8463 DisposeHandle (dref);
8464 if (err != noErr)
8465 goto open_error;
8468 image = image_spec_value (img->spec, QCindex, NULL);
8469 ino = INTEGERP (image) ? XFASTINT (image) : 0;
8470 track = GetMovieIndTrack (movie, 1);
8471 media = GetTrackMedia (track);
8472 nsamples = GetMediaSampleCount (media);
8473 if (ino >= nsamples)
8475 image_error ("Invalid image number `%s' in image `%s'",
8476 image, img->spec);
8477 goto error;
8479 time_scale = GetMediaTimeScale (media);
8481 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8482 if (!STRINGP (specified_bg)
8483 || !mac_defined_color (f, SDATA (specified_bg), &color, 0))
8485 color.pixel = FRAME_BACKGROUND_PIXEL (f);
8486 color.red = RED16_FROM_ULONG (color.pixel);
8487 color.green = GREEN16_FROM_ULONG (color.pixel);
8488 color.blue = BLUE16_FROM_ULONG (color.pixel);
8490 GetMovieBox (movie, &rect);
8491 width = img->width = rect.right - rect.left;
8492 height = img->height = rect.bottom - rect.top;
8493 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8494 goto error;
8496 GetGWorld (&old_port, &old_gdh);
8497 SetGWorld (ximg, NULL);
8498 bg_color.red = color.red;
8499 bg_color.green = color.green;
8500 bg_color.blue = color.blue;
8501 RGBBackColor (&bg_color);
8502 SetGWorld (old_port, old_gdh);
8503 SetMovieActive (movie, 1);
8504 SetMovieGWorld (movie, ximg, NULL);
8505 SampleNumToMediaTime (media, ino + 1, &time, &duration);
8506 SetMovieTimeValue (movie, time);
8507 MoviesTask (movie, 0L);
8508 DisposeTrackMedia (media);
8509 DisposeMovieTrack (track);
8510 DisposeMovie (movie);
8511 if (dh)
8512 DisposeHandle (dh);
8514 /* Save GIF image extension data for `image-extension-data'.
8515 Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */
8517 Lisp_Object gce = make_uninit_string (4);
8518 int centisec = ((float)duration / time_scale) * 100.0f + 0.5f;
8520 /* Fill the delay time field. */
8521 SSET (gce, 1, centisec & 0xff);
8522 SSET (gce, 2, (centisec >> 8) & 0xff);
8523 /* We don't know about other fields. */
8524 SSET (gce, 0, 0);
8525 SSET (gce, 3, 0);
8527 img->data.lisp_val = list4 (Qcount, make_number (nsamples),
8528 make_number (0xf9), gce);
8531 /* Maybe fill in the background field while we have ximg handy. */
8532 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
8533 IMAGE_BACKGROUND (img, f, ximg);
8535 /* Put the image into the pixmap. */
8536 x_put_x_image (f, ximg, img->pixmap, width, height);
8537 x_destroy_x_image (ximg);
8538 return 1;
8540 open_error:
8541 image_error ("Cannot open `%s'", file, Qnil);
8542 error:
8543 if (media)
8544 DisposeTrackMedia (media);
8545 if (track)
8546 DisposeMovieTrack (track);
8547 if (movie)
8548 DisposeMovie (movie);
8549 if (dh)
8550 DisposeHandle (dh);
8551 return 0;
8552 #endif /* !USE_MAC_IMAGE_IO */
8554 #endif /* MAC_OS */
8556 #endif /* HAVE_GIF */
8560 /***********************************************************************
8562 ***********************************************************************/
8564 #if defined (HAVE_RSVG)
8566 /* Function prototypes. */
8568 static int svg_image_p P_ ((Lisp_Object object));
8569 static int svg_load P_ ((struct frame *f, struct image *img));
8571 static int svg_load_image P_ ((struct frame *, struct image *,
8572 unsigned char *, unsigned int));
8574 /* The symbol `svg' identifying images of this type. */
8576 Lisp_Object Qsvg;
8578 /* Indices of image specification fields in svg_format, below. */
8580 enum svg_keyword_index
8582 SVG_TYPE,
8583 SVG_DATA,
8584 SVG_FILE,
8585 SVG_ASCENT,
8586 SVG_MARGIN,
8587 SVG_RELIEF,
8588 SVG_ALGORITHM,
8589 SVG_HEURISTIC_MASK,
8590 SVG_MASK,
8591 SVG_BACKGROUND,
8592 SVG_LAST
8595 /* Vector of image_keyword structures describing the format
8596 of valid user-defined image specifications. */
8598 static struct image_keyword svg_format[SVG_LAST] =
8600 {":type", IMAGE_SYMBOL_VALUE, 1},
8601 {":data", IMAGE_STRING_VALUE, 0},
8602 {":file", IMAGE_STRING_VALUE, 0},
8603 {":ascent", IMAGE_ASCENT_VALUE, 0},
8604 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
8605 {":relief", IMAGE_INTEGER_VALUE, 0},
8606 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8607 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8608 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
8609 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
8612 /* Structure describing the image type `svg'. Its the same type of
8613 structure defined for all image formats, handled by emacs image
8614 functions. See struct image_type in dispextern.h. */
8616 static struct image_type svg_type =
8618 /* An identifier showing that this is an image structure for the SVG format. */
8619 &Qsvg,
8620 /* Handle to a function that can be used to identify a SVG file. */
8621 svg_image_p,
8622 /* Handle to function used to load a SVG file. */
8623 svg_load,
8624 /* Handle to function to free sresources for SVG. */
8625 x_clear_image,
8626 /* An internal field to link to the next image type in a list of
8627 image types, will be filled in when registering the format. */
8628 NULL
8632 /* Return non-zero if OBJECT is a valid SVG image specification. Do
8633 this by calling parse_image_spec and supplying the keywords that
8634 identify the SVG format. */
8636 static int
8637 svg_image_p (object)
8638 Lisp_Object object;
8640 struct image_keyword fmt[SVG_LAST];
8641 bcopy (svg_format, fmt, sizeof fmt);
8643 if (!parse_image_spec (object, fmt, SVG_LAST, Qsvg))
8644 return 0;
8646 /* Must specify either the :data or :file keyword. */
8647 return fmt[SVG_FILE].count + fmt[SVG_DATA].count == 1;
8650 #include <librsvg/rsvg.h>
8652 #ifdef HAVE_NTGUI
8654 /* SVG library functions. */
8655 DEF_IMGLIB_FN (rsvg_handle_new);
8656 DEF_IMGLIB_FN (rsvg_handle_set_size_callback);
8657 DEF_IMGLIB_FN (rsvg_handle_write);
8658 DEF_IMGLIB_FN (rsvg_handle_close);
8659 DEF_IMGLIB_FN (rsvg_handle_get_pixbuf);
8660 DEF_IMGLIB_FN (rsvg_handle_free);
8662 DEF_IMGLIB_FN (gdk_pixbuf_get_width);
8663 DEF_IMGLIB_FN (gdk_pixbuf_get_height);
8664 DEF_IMGLIB_FN (gdk_pixbuf_get_pixels);
8665 DEF_IMGLIB_FN (gdk_pixbuf_get_rowstride);
8666 DEF_IMGLIB_FN (gdk_pixbuf_get_colorspace);
8667 DEF_IMGLIB_FN (gdk_pixbuf_get_n_channels);
8668 DEF_IMGLIB_FN (gdk_pixbuf_get_has_alpha);
8669 DEF_IMGLIB_FN (gdk_pixbuf_get_bits_per_sample);
8671 DEF_IMGLIB_FN (g_type_init);
8672 DEF_IMGLIB_FN (g_object_unref);
8673 DEF_IMGLIB_FN (g_error_free);
8675 Lisp_Object Qgdk_pixbuf, Qglib;
8677 static int
8678 init_svg_functions (Lisp_Object libraries)
8680 HMODULE library, gdklib, glib;
8682 if (!(glib = w32_delayed_load (libraries, Qglib))
8683 || !(gdklib = w32_delayed_load (libraries, Qgdk_pixbuf))
8684 || !(library = w32_delayed_load (libraries, Qsvg)))
8685 return 0;
8687 LOAD_IMGLIB_FN (library, rsvg_handle_new);
8688 LOAD_IMGLIB_FN (library, rsvg_handle_set_size_callback);
8689 LOAD_IMGLIB_FN (library, rsvg_handle_write);
8690 LOAD_IMGLIB_FN (library, rsvg_handle_close);
8691 LOAD_IMGLIB_FN (library, rsvg_handle_get_pixbuf);
8692 LOAD_IMGLIB_FN (library, rsvg_handle_free);
8694 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_width);
8695 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_height);
8696 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_pixels);
8697 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_rowstride);
8698 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_colorspace);
8699 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_n_channels);
8700 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_has_alpha);
8701 LOAD_IMGLIB_FN (gdklib, gdk_pixbuf_get_bits_per_sample);
8703 LOAD_IMGLIB_FN (glib, g_type_init);
8704 LOAD_IMGLIB_FN (glib, g_object_unref);
8705 LOAD_IMGLIB_FN (glib, g_error_free);
8706 return 1;
8709 #else
8710 /* The following aliases for library functions allow dynamic loading
8711 to be used on some platforms. */
8712 #define fn_rsvg_handle_new rsvg_handle_new
8713 #define fn_rsvg_handle_set_size_callback rsvg_handle_set_size_callback
8714 #define fn_rsvg_handle_write rsvg_handle_write
8715 #define fn_rsvg_handle_close rsvg_handle_close
8716 #define fn_rsvg_handle_get_pixbuf rsvg_handle_get_pixbuf
8717 #define fn_rsvg_handle_free rsvg_handle_free
8719 #define fn_gdk_pixbuf_get_width gdk_pixbuf_get_width
8720 #define fn_gdk_pixbuf_get_height gdk_pixbuf_get_height
8721 #define fn_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels
8722 #define fn_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride
8723 #define fn_gdk_pixbuf_get_colorspace gdk_pixbuf_get_colorspace
8724 #define fn_gdk_pixbuf_get_n_channels gdk_pixbuf_get_n_channels
8725 #define fn_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha
8726 #define fn_gdk_pixbuf_get_bits_per_sample gdk_pixbuf_get_bits_per_sample
8728 #define fn_g_type_init g_type_init
8729 #define fn_g_object_unref g_object_unref
8730 #define fn_g_error_free g_error_free
8731 #endif /* !HAVE_NTGUI */
8733 /* Load SVG image IMG for use on frame F. Value is non-zero if
8734 successful. this function will go into the svg_type structure, and
8735 the prototype thus needs to be compatible with that structure. */
8737 static int
8738 svg_load (f, img)
8739 struct frame *f;
8740 struct image *img;
8742 int success_p = 0;
8743 Lisp_Object file_name;
8745 /* If IMG->spec specifies a file name, create a non-file spec from it. */
8746 file_name = image_spec_value (img->spec, QCfile, NULL);
8747 if (STRINGP (file_name))
8749 Lisp_Object file;
8750 unsigned char *contents;
8751 int size;
8752 struct gcpro gcpro1;
8754 file = x_find_image_file (file_name);
8755 GCPRO1 (file);
8756 if (!STRINGP (file))
8758 image_error ("Cannot find image file `%s'", file_name, Qnil);
8759 UNGCPRO;
8760 return 0;
8763 /* Read the entire file into memory. */
8764 contents = slurp_file (SDATA (file), &size);
8765 if (contents == NULL)
8767 image_error ("Error loading SVG image `%s'", img->spec, Qnil);
8768 UNGCPRO;
8769 return 0;
8771 /* If the file was slurped into memory properly, parse it. */
8772 success_p = svg_load_image (f, img, contents, size);
8773 xfree (contents);
8774 UNGCPRO;
8776 /* Else its not a file, its a lisp object. Load the image from a
8777 lisp object rather than a file. */
8778 else
8780 Lisp_Object data;
8782 data = image_spec_value (img->spec, QCdata, NULL);
8783 success_p = svg_load_image (f, img, SDATA (data), SBYTES (data));
8786 return success_p;
8789 /* svg_load_image is a helper function for svg_load, which does the
8790 actual loading given contents and size, apart from frame and image
8791 structures, passed from svg_load.
8793 Uses librsvg to do most of the image processing.
8795 Returns non-zero when successful. */
8796 static int
8797 svg_load_image (f, img, contents, size)
8798 /* Pointer to emacs frame structure. */
8799 struct frame *f;
8800 /* Pointer to emacs image structure. */
8801 struct image *img;
8802 /* String containing the SVG XML data to be parsed. */
8803 unsigned char *contents;
8804 /* Size of data in bytes. */
8805 unsigned int size;
8807 RsvgHandle *rsvg_handle;
8808 GError *error = NULL;
8809 GdkPixbuf *pixbuf;
8810 int width;
8811 int height;
8812 const guint8 *pixels;
8813 int rowstride;
8814 XImagePtr ximg;
8815 Lisp_Object specified_bg;
8816 XColor background;
8817 int x;
8818 int y;
8820 /* g_type_init is a glib function that must be called prior to using
8821 gnome type library functions. */
8822 fn_g_type_init ();
8823 /* Make a handle to a new rsvg object. */
8824 rsvg_handle = fn_rsvg_handle_new ();
8826 /* Parse the contents argument and fill in the rsvg_handle. */
8827 fn_rsvg_handle_write (rsvg_handle, contents, size, &error);
8828 if (error)
8829 goto rsvg_error;
8831 /* The parsing is complete, rsvg_handle is ready to used, close it
8832 for further writes. */
8833 fn_rsvg_handle_close (rsvg_handle, &error);
8834 if (error)
8835 goto rsvg_error;
8836 /* We can now get a valid pixel buffer from the svg file, if all
8837 went ok. */
8838 pixbuf = fn_rsvg_handle_get_pixbuf (rsvg_handle);
8839 eassert (pixbuf);
8841 /* Extract some meta data from the svg handle. */
8842 width = fn_gdk_pixbuf_get_width (pixbuf);
8843 height = fn_gdk_pixbuf_get_height (pixbuf);
8844 pixels = fn_gdk_pixbuf_get_pixels (pixbuf);
8845 rowstride = fn_gdk_pixbuf_get_rowstride (pixbuf);
8847 /* Validate the svg meta data. */
8848 eassert (fn_gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
8849 eassert (fn_gdk_pixbuf_get_n_channels (pixbuf) == 4);
8850 eassert (fn_gdk_pixbuf_get_has_alpha (pixbuf));
8851 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8853 /* Try to create a x pixmap to hold the svg pixmap. */
8854 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
8856 fn_g_object_unref (pixbuf);
8857 return 0;
8860 init_color_table ();
8862 /* Handle alpha channel by combining the image with a background
8863 color. */
8864 specified_bg = image_spec_value (img->spec, QCbackground, NULL);
8865 if (STRINGP (specified_bg)
8866 && x_defined_color (f, SDATA (specified_bg), &background, 0))
8868 background.red >>= 8;
8869 background.green >>= 8;
8870 background.blue >>= 8;
8872 else
8874 #ifdef HAVE_X_WINDOWS
8875 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8876 x_query_color (f, &background);
8878 /* SVG pixmaps specify transparency in the last byte, so right
8879 shift 8 bits to get rid of it, since emacs doesn't support
8880 transparency. */
8881 background.red >>= 8;
8882 background.green >>= 8;
8883 background.blue >>= 8;
8884 #elif defined (MAC_OS)
8885 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8886 background.red = RED_FROM_ULONG (background.pixel);
8887 background.green = GREEN_FROM_ULONG (background.pixel);
8888 background.blue = BLUE_FROM_ULONG (background.pixel);
8889 #elif defined (HAVE_NTGUI)
8890 background.pixel = FRAME_BACKGROUND_PIXEL (f);
8891 #if 0 /* W32 TODO : Colormap support. */
8892 x_query_color (f, &background);
8893 #endif
8895 /* SVG pixmaps specify transparency in the last byte, so right
8896 shift 8 bits to get rid of it, since emacs doesn't support
8897 transparency. */
8898 background.red >>= 8;
8899 background.green >>= 8;
8900 background.blue >>= 8;
8901 #else /* not HAVE_X_WINDOWS && not MAC_OS*/
8902 #error FIXME
8903 #endif
8906 /* This loop handles opacity values, since Emacs assumes
8907 non-transparent images. Each pixel must be "flattened" by
8908 calculating the resulting color, given the transparency of the
8909 pixel, and the image background color. */
8910 for (y = 0; y < height; ++y)
8912 for (x = 0; x < width; ++x)
8914 unsigned red;
8915 unsigned green;
8916 unsigned blue;
8917 unsigned opacity;
8919 red = *pixels++;
8920 green = *pixels++;
8921 blue = *pixels++;
8922 opacity = *pixels++;
8924 red = ((red * opacity)
8925 + (background.red * ((1 << 8) - opacity)));
8926 green = ((green * opacity)
8927 + (background.green * ((1 << 8) - opacity)));
8928 blue = ((blue * opacity)
8929 + (background.blue * ((1 << 8) - opacity)));
8931 XPutPixel (ximg, x, y, lookup_rgb_color (f, red, green, blue));
8934 pixels += rowstride - 4 * width;
8937 #ifdef COLOR_TABLE_SUPPORT
8938 /* Remember colors allocated for this image. */
8939 img->colors = colors_in_color_table (&img->ncolors);
8940 free_color_table ();
8941 #endif /* COLOR_TABLE_SUPPORT */
8943 fn_g_object_unref (pixbuf);
8945 img->width = width;
8946 img->height = height;
8948 /* Maybe fill in the background field while we have ximg handy.
8949 Casting avoids a GCC warning. */
8950 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8952 /* Put the image into the pixmap, then free the X image and its
8953 buffer. */
8954 x_put_x_image (f, ximg, img->pixmap, width, height);
8955 x_destroy_x_image (ximg);
8957 return 1;
8959 rsvg_error:
8960 /* FIXME: Use error->message so the user knows what is the actual
8961 problem with the image. */
8962 image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
8963 fn_g_error_free (error);
8964 return 0;
8967 #endif /* defined (HAVE_RSVG) */
8972 /***********************************************************************
8973 Ghostscript
8974 ***********************************************************************/
8976 #ifdef HAVE_X_WINDOWS
8977 #define HAVE_GHOSTSCRIPT 1
8978 #endif /* HAVE_X_WINDOWS */
8980 /* The symbol `postscript' identifying images of this type. */
8982 Lisp_Object Qpostscript;
8984 #ifdef HAVE_GHOSTSCRIPT
8986 static int gs_image_p P_ ((Lisp_Object object));
8987 static int gs_load P_ ((struct frame *f, struct image *img));
8988 static void gs_clear_image P_ ((struct frame *f, struct image *img));
8990 /* Keyword symbols. */
8992 Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
8994 /* Indices of image specification fields in gs_format, below. */
8996 enum gs_keyword_index
8998 GS_TYPE,
8999 GS_PT_WIDTH,
9000 GS_PT_HEIGHT,
9001 GS_FILE,
9002 GS_LOADER,
9003 GS_BOUNDING_BOX,
9004 GS_ASCENT,
9005 GS_MARGIN,
9006 GS_RELIEF,
9007 GS_ALGORITHM,
9008 GS_HEURISTIC_MASK,
9009 GS_MASK,
9010 GS_BACKGROUND,
9011 GS_LAST
9014 /* Vector of image_keyword structures describing the format
9015 of valid user-defined image specifications. */
9017 static struct image_keyword gs_format[GS_LAST] =
9019 {":type", IMAGE_SYMBOL_VALUE, 1},
9020 {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9021 {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
9022 {":file", IMAGE_STRING_VALUE, 1},
9023 {":loader", IMAGE_FUNCTION_VALUE, 0},
9024 {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
9025 {":ascent", IMAGE_ASCENT_VALUE, 0},
9026 {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
9027 {":relief", IMAGE_INTEGER_VALUE, 0},
9028 {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9029 {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9030 {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
9031 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}
9034 /* Structure describing the image type `ghostscript'. */
9036 static struct image_type gs_type =
9038 &Qpostscript,
9039 gs_image_p,
9040 gs_load,
9041 gs_clear_image,
9042 NULL
9046 /* Free X resources of Ghostscript image IMG which is used on frame F. */
9048 static void
9049 gs_clear_image (f, img)
9050 struct frame *f;
9051 struct image *img;
9053 /* IMG->data.ptr_val may contain a recorded colormap. */
9054 xfree (img->data.ptr_val);
9055 x_clear_image (f, img);
9059 /* Return non-zero if OBJECT is a valid Ghostscript image
9060 specification. */
9062 static int
9063 gs_image_p (object)
9064 Lisp_Object object;
9066 struct image_keyword fmt[GS_LAST];
9067 Lisp_Object tem;
9068 int i;
9070 bcopy (gs_format, fmt, sizeof fmt);
9072 if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript))
9073 return 0;
9075 /* Bounding box must be a list or vector containing 4 integers. */
9076 tem = fmt[GS_BOUNDING_BOX].value;
9077 if (CONSP (tem))
9079 for (i = 0; i < 4; ++i, tem = XCDR (tem))
9080 if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
9081 return 0;
9082 if (!NILP (tem))
9083 return 0;
9085 else if (VECTORP (tem))
9087 if (XVECTOR (tem)->size != 4)
9088 return 0;
9089 for (i = 0; i < 4; ++i)
9090 if (!INTEGERP (XVECTOR (tem)->contents[i]))
9091 return 0;
9093 else
9094 return 0;
9096 return 1;
9100 /* Load Ghostscript image IMG for use on frame F. Value is non-zero
9101 if successful. */
9103 static int
9104 gs_load (f, img)
9105 struct frame *f;
9106 struct image *img;
9108 char buffer[100];
9109 Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
9110 struct gcpro gcpro1, gcpro2;
9111 Lisp_Object frame;
9112 double in_width, in_height;
9113 Lisp_Object pixel_colors = Qnil;
9115 /* Compute pixel size of pixmap needed from the given size in the
9116 image specification. Sizes in the specification are in pt. 1 pt
9117 = 1/72 in, xdpi and ydpi are stored in the frame's X display
9118 info. */
9119 pt_width = image_spec_value (img->spec, QCpt_width, NULL);
9120 in_width = XFASTINT (pt_width) / 72.0;
9121 img->width = in_width * FRAME_X_DISPLAY_INFO (f)->resx;
9122 pt_height = image_spec_value (img->spec, QCpt_height, NULL);
9123 in_height = XFASTINT (pt_height) / 72.0;
9124 img->height = in_height * FRAME_X_DISPLAY_INFO (f)->resy;
9126 if (!check_image_size (f, img->width, img->height))
9128 image_error ("Invalid image size", Qnil, Qnil);
9129 return 0;
9132 /* Create the pixmap. */
9133 xassert (img->pixmap == NO_PIXMAP);
9135 /* Only W32 version did BLOCK_INPUT here. ++kfs */
9136 BLOCK_INPUT;
9137 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9138 img->width, img->height,
9139 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
9140 UNBLOCK_INPUT;
9142 if (!img->pixmap)
9144 image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
9145 return 0;
9148 /* Call the loader to fill the pixmap. It returns a process object
9149 if successful. We do not record_unwind_protect here because
9150 other places in redisplay like calling window scroll functions
9151 don't either. Let the Lisp loader use `unwind-protect' instead. */
9152 GCPRO2 (window_and_pixmap_id, pixel_colors);
9154 sprintf (buffer, "%lu %lu",
9155 (unsigned long) FRAME_X_WINDOW (f),
9156 (unsigned long) img->pixmap);
9157 window_and_pixmap_id = build_string (buffer);
9159 sprintf (buffer, "%lu %lu",
9160 FRAME_FOREGROUND_PIXEL (f),
9161 FRAME_BACKGROUND_PIXEL (f));
9162 pixel_colors = build_string (buffer);
9164 XSETFRAME (frame, f);
9165 loader = image_spec_value (img->spec, QCloader, NULL);
9166 if (NILP (loader))
9167 loader = intern ("gs-load-image");
9169 img->data.lisp_val = call6 (loader, frame, img->spec,
9170 make_number (img->width),
9171 make_number (img->height),
9172 window_and_pixmap_id,
9173 pixel_colors);
9174 UNGCPRO;
9175 return PROCESSP (img->data.lisp_val);
9179 /* Kill the Ghostscript process that was started to fill PIXMAP on
9180 frame F. Called from XTread_socket when receiving an event
9181 telling Emacs that Ghostscript has finished drawing. */
9183 void
9184 x_kill_gs_process (pixmap, f)
9185 Pixmap pixmap;
9186 struct frame *f;
9188 struct image_cache *c = FRAME_IMAGE_CACHE (f);
9189 int class, i;
9190 struct image *img;
9192 /* Find the image containing PIXMAP. */
9193 for (i = 0; i < c->used; ++i)
9194 if (c->images[i]->pixmap == pixmap)
9195 break;
9197 /* Should someone in between have cleared the image cache, for
9198 instance, give up. */
9199 if (i == c->used)
9200 return;
9202 /* Kill the GS process. We should have found PIXMAP in the image
9203 cache and its image should contain a process object. */
9204 img = c->images[i];
9205 xassert (PROCESSP (img->data.lisp_val));
9206 Fkill_process (img->data.lisp_val, Qnil);
9207 img->data.lisp_val = Qnil;
9209 #if defined (HAVE_X_WINDOWS)
9211 /* On displays with a mutable colormap, figure out the colors
9212 allocated for the image by looking at the pixels of an XImage for
9213 img->pixmap. */
9214 class = FRAME_X_VISUAL (f)->class;
9215 if (class != StaticColor && class != StaticGray && class != TrueColor)
9217 XImagePtr ximg;
9219 BLOCK_INPUT;
9221 /* Try to get an XImage for img->pixmep. */
9222 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
9223 0, 0, img->width, img->height, ~0, ZPixmap);
9224 if (ximg)
9226 int x, y;
9228 /* Initialize the color table. */
9229 init_color_table ();
9231 /* For each pixel of the image, look its color up in the
9232 color table. After having done so, the color table will
9233 contain an entry for each color used by the image. */
9234 for (y = 0; y < img->height; ++y)
9235 for (x = 0; x < img->width; ++x)
9237 unsigned long pixel = XGetPixel (ximg, x, y);
9238 lookup_pixel_color (f, pixel);
9241 /* Record colors in the image. Free color table and XImage. */
9242 #ifdef COLOR_TABLE_SUPPORT
9243 img->colors = colors_in_color_table (&img->ncolors);
9244 free_color_table ();
9245 #endif
9246 XDestroyImage (ximg);
9248 #if 0 /* This doesn't seem to be the case. If we free the colors
9249 here, we get a BadAccess later in x_clear_image when
9250 freeing the colors. */
9251 /* We have allocated colors once, but Ghostscript has also
9252 allocated colors on behalf of us. So, to get the
9253 reference counts right, free them once. */
9254 if (img->ncolors)
9255 x_free_colors (f, img->colors, img->ncolors);
9256 #endif
9258 else
9259 image_error ("Cannot get X image of `%s'; colors will not be freed",
9260 img->spec, Qnil);
9262 UNBLOCK_INPUT;
9264 #endif /* HAVE_X_WINDOWS */
9266 /* Now that we have the pixmap, compute mask and transform the
9267 image if requested. */
9268 BLOCK_INPUT;
9269 postprocess_image (f, img);
9270 UNBLOCK_INPUT;
9273 #endif /* HAVE_GHOSTSCRIPT */
9276 /***********************************************************************
9277 Tests
9278 ***********************************************************************/
9280 #if GLYPH_DEBUG
9282 DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
9283 doc: /* Value is non-nil if SPEC is a valid image specification. */)
9284 (spec)
9285 Lisp_Object spec;
9287 return valid_image_p (spec) ? Qt : Qnil;
9291 DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
9292 (spec)
9293 Lisp_Object spec;
9295 int id = -1;
9297 if (valid_image_p (spec))
9298 id = lookup_image (SELECTED_FRAME (), spec);
9300 debug_print (spec);
9301 return make_number (id);
9304 #endif /* GLYPH_DEBUG != 0 */
9307 /***********************************************************************
9308 Initialization
9309 ***********************************************************************/
9311 #ifdef HAVE_NTGUI
9312 /* Image types that rely on external libraries are loaded dynamically
9313 if the library is available. */
9314 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9315 define_image_type (image_type, init_lib_fn (libraries))
9316 #else
9317 #define CHECK_LIB_AVAILABLE(image_type, init_lib_fn, libraries) \
9318 define_image_type (image_type, 1)
9319 #endif /* HAVE_NTGUI */
9321 DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0,
9322 doc: /* Initialize image library implementing image type TYPE.
9323 Return non-nil if TYPE is a supported image type.
9325 Image types pbm and xbm are prebuilt; other types are loaded here.
9326 Libraries to load are specified in alist LIBRARIES (usually, the value
9327 of `image-library-alist', which see). */)
9328 (type, libraries)
9329 Lisp_Object type, libraries;
9331 Lisp_Object tested;
9333 /* Don't try to reload the library. */
9334 tested = Fassq (type, Vimage_type_cache);
9335 if (CONSP (tested))
9336 return XCDR (tested);
9338 #if defined (HAVE_XPM) || defined (MAC_OS)
9339 if (EQ (type, Qxpm))
9340 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
9341 #endif
9343 #if defined (HAVE_JPEG) || defined (MAC_OS)
9344 if (EQ (type, Qjpeg))
9345 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
9346 #endif
9348 #if defined (HAVE_TIFF) || defined (MAC_OS)
9349 if (EQ (type, Qtiff))
9350 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
9351 #endif
9353 #if defined (HAVE_GIF) || defined (MAC_OS)
9354 if (EQ (type, Qgif))
9355 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
9356 #endif
9358 #if defined (HAVE_PNG) || defined (MAC_OS)
9359 if (EQ (type, Qpng))
9360 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
9361 #endif
9363 #if defined (HAVE_RSVG)
9364 if (EQ (type, Qsvg))
9365 return CHECK_LIB_AVAILABLE (&svg_type, init_svg_functions, libraries);
9366 #endif
9368 #ifdef HAVE_GHOSTSCRIPT
9369 if (EQ (type, Qpostscript))
9370 return CHECK_LIB_AVAILABLE (&gs_type, init_gs_functions, libraries);
9371 #endif
9373 /* If the type is not recognized, avoid testing it ever again. */
9374 CACHE_IMAGE_TYPE (type, Qnil);
9375 return Qnil;
9378 void
9379 syms_of_image ()
9381 extern Lisp_Object Qrisky_local_variable; /* Syms_of_xdisp has already run. */
9383 /* Initialize this only once, since that's what we do with Vimage_types
9384 and they are supposed to be in sync. Initializing here gives correct
9385 operation on GNU/Linux of calling dump-emacs after loading some images. */
9386 image_types = NULL;
9388 /* Must be defined now becase we're going to update it below, while
9389 defining the supported image types. */
9390 DEFVAR_LISP ("image-types", &Vimage_types,
9391 doc: /* List of potentially supported image types.
9392 Each element of the list is a symbol for an image type, like 'jpeg or 'png.
9393 To check whether it is really supported, use `image-type-available-p'. */);
9394 Vimage_types = Qnil;
9396 DEFVAR_LISP ("image-library-alist", &Vimage_library_alist,
9397 doc: /* Alist of image types vs external libraries needed to display them.
9399 Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol
9400 representing a supported image type, and the rest are strings giving
9401 alternate filenames for the corresponding external libraries.
9403 Emacs tries to load the libraries in the order they appear on the
9404 list; if none is loaded, the running session of Emacs won't
9405 support the image type. Types 'pbm and 'xbm don't need to be
9406 listed; they are always supported. */);
9407 Vimage_library_alist = Qnil;
9408 Fput (intern ("image-library-alist"), Qrisky_local_variable, Qt);
9410 DEFVAR_LISP ("max-image-size", &Vmax_image_size,
9411 doc: /* Maximum size of images.
9412 Emacs will not load an image into memory if its pixel width or
9413 pixel height exceeds this limit.
9415 If the value is an integer, it directly specifies the maximum
9416 image height and width, measured in pixels. If it is a floating
9417 point number, it specifies the maximum image height and width
9418 as a ratio to the frame height and width. If the value is
9419 non-numeric, there is no explicit limit on the size of images. */);
9420 Vmax_image_size = make_float (MAX_IMAGE_SIZE);
9422 Vimage_type_cache = Qnil;
9423 staticpro (&Vimage_type_cache);
9425 Qpbm = intern ("pbm");
9426 staticpro (&Qpbm);
9427 ADD_IMAGE_TYPE (Qpbm);
9429 Qxbm = intern ("xbm");
9430 staticpro (&Qxbm);
9431 ADD_IMAGE_TYPE (Qxbm);
9433 define_image_type (&xbm_type, 1);
9434 define_image_type (&pbm_type, 1);
9436 Qcount = intern ("count");
9437 staticpro (&Qcount);
9439 QCascent = intern (":ascent");
9440 staticpro (&QCascent);
9441 QCmargin = intern (":margin");
9442 staticpro (&QCmargin);
9443 QCrelief = intern (":relief");
9444 staticpro (&QCrelief);
9445 QCconversion = intern (":conversion");
9446 staticpro (&QCconversion);
9447 QCcolor_symbols = intern (":color-symbols");
9448 staticpro (&QCcolor_symbols);
9449 QCheuristic_mask = intern (":heuristic-mask");
9450 staticpro (&QCheuristic_mask);
9451 QCindex = intern (":index");
9452 staticpro (&QCindex);
9453 QCmatrix = intern (":matrix");
9454 staticpro (&QCmatrix);
9455 QCcolor_adjustment = intern (":color-adjustment");
9456 staticpro (&QCcolor_adjustment);
9457 QCmask = intern (":mask");
9458 staticpro (&QCmask);
9460 Qlaplace = intern ("laplace");
9461 staticpro (&Qlaplace);
9462 Qemboss = intern ("emboss");
9463 staticpro (&Qemboss);
9464 Qedge_detection = intern ("edge-detection");
9465 staticpro (&Qedge_detection);
9466 Qheuristic = intern ("heuristic");
9467 staticpro (&Qheuristic);
9469 Qpostscript = intern ("postscript");
9470 staticpro (&Qpostscript);
9471 #ifdef HAVE_GHOSTSCRIPT
9472 ADD_IMAGE_TYPE (Qpostscript);
9473 QCloader = intern (":loader");
9474 staticpro (&QCloader);
9475 QCbounding_box = intern (":bounding-box");
9476 staticpro (&QCbounding_box);
9477 QCpt_width = intern (":pt-width");
9478 staticpro (&QCpt_width);
9479 QCpt_height = intern (":pt-height");
9480 staticpro (&QCpt_height);
9481 #endif /* HAVE_GHOSTSCRIPT */
9483 #if defined (HAVE_XPM) || defined (MAC_OS)
9484 Qxpm = intern ("xpm");
9485 staticpro (&Qxpm);
9486 ADD_IMAGE_TYPE (Qxpm);
9487 #endif
9489 #if defined (HAVE_JPEG) || defined (MAC_OS)
9490 Qjpeg = intern ("jpeg");
9491 staticpro (&Qjpeg);
9492 ADD_IMAGE_TYPE (Qjpeg);
9493 #endif
9495 #if defined (HAVE_TIFF) || defined (MAC_OS)
9496 Qtiff = intern ("tiff");
9497 staticpro (&Qtiff);
9498 ADD_IMAGE_TYPE (Qtiff);
9499 #endif
9501 #if defined (HAVE_GIF) || defined (MAC_OS)
9502 Qgif = intern ("gif");
9503 staticpro (&Qgif);
9504 ADD_IMAGE_TYPE (Qgif);
9505 #endif
9507 #if defined (HAVE_PNG) || defined (MAC_OS)
9508 Qpng = intern ("png");
9509 staticpro (&Qpng);
9510 ADD_IMAGE_TYPE (Qpng);
9511 #endif
9513 #if defined (HAVE_RSVG)
9514 Qsvg = intern ("svg");
9515 staticpro (&Qsvg);
9516 ADD_IMAGE_TYPE (Qsvg);
9517 #ifdef HAVE_NTGUI
9518 Qgdk_pixbuf = intern ("gdk-pixbuf");
9519 staticpro (&Qgdk_pixbuf);
9520 Qglib = intern ("glib");
9521 staticpro (&Qglib);
9522 #endif /* HAVE_NTGUI */
9523 #endif /* HAVE_RSVG */
9525 defsubr (&Sinit_image_library);
9526 defsubr (&Sclear_image_cache);
9527 defsubr (&Simage_refresh);
9528 defsubr (&Simage_size);
9529 defsubr (&Simage_mask_p);
9530 defsubr (&Simage_extension_data);
9532 #if GLYPH_DEBUG
9533 defsubr (&Simagep);
9534 defsubr (&Slookup_image);
9535 #endif
9537 DEFVAR_BOOL ("cross-disabled-images", &cross_disabled_images,
9538 doc: /* Non-nil means always draw a cross over disabled images.
9539 Disabled images are those having a `:conversion disabled' property.
9540 A cross is always drawn on black & white displays. */);
9541 cross_disabled_images = 0;
9543 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
9544 doc: /* List of directories to search for window system bitmap files. */);
9545 Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS);
9547 DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
9548 doc: /* Time after which cached images are removed from the cache.
9549 When an image has not been displayed this many seconds, remove it
9550 from the image cache. Value must be an integer or nil with nil
9551 meaning don't clear the cache. */);
9552 Vimage_cache_eviction_delay = make_number (30 * 60);
9555 void
9556 init_image ()
9560 /* arch-tag: 123c2a5e-14a8-4c53-ab95-af47d7db49b9
9561 (do not change this comment) */